電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學(xué)習在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區
創(chuàng )作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內不再提示
創(chuàng )作
電子發(fā)燒友網(wǎng)>電子資料下載>電子資料>機器人割草機開(kāi)源分享

機器人割草機開(kāi)源分享

2023-06-15 | zip | 0.00 MB | 次下載 | 免費

資料介紹

描述

概述

讓你的草坪在夏日的陽(yáng)光下煥然一新對于房主來(lái)說(shuō)通常是一件可怕的家務(wù)事。機器人割草機可以消除夏季最令人生畏的家務(wù)之一。它看起來(lái)類(lèi)似于機器人吸塵器。你可以看著(zhù)它在你的草坪上飛來(lái)飛去,讓你的草坪保持最佳狀態(tài)。為割草機配備支持物聯(lián)網(wǎng)的功能,例如藍牙Wi-Fi 連接、GPS 導航和靈活的調度功能,可以讓您在任何地方使用移動(dòng)應用程序控制割草機并跟蹤割草進(jìn)度。

特征

  • 割草機由鋰電池供電,非常安靜,可以發(fā)送低電量警報。
  • 測量割草路徑。
  • 調整切割高度。
  • 自動(dòng)路線(xiàn)規劃。
  • 使用移動(dòng)應用程序進(jìn)行遠程控制。

?

腳步

第 1 步:硬件設計

割草機包括四個(gè)硬件部件。

  • 無(wú)線(xiàn)連接系統:涂鴉的網(wǎng)絡(luò )模塊允許在任何地方在移動(dòng)應用程序上遠程控制和查看割草機狀態(tài)。
  • 動(dòng)力系統:12V鋰電池組配合減速電機推動(dòng)橡膠輪胎車(chē)輪前進(jìn)。
  • 割草控制系統:兩個(gè)伺服系統可調節切割高度,切割刀片和驅動(dòng)輪采用無(wú)刷直流電機。
  • 定位導航系統:集成GNSS模塊和磁傳感器,實(shí)現導航定位能力。

無(wú)線(xiàn)連接系統

將您的 MCU 與涂鴉的網(wǎng)絡(luò )模塊對接,讓您的產(chǎn)品支持物聯(lián)網(wǎng)并連接到云端。

涂鴉提供一站式物聯(lián)網(wǎng)開(kāi)發(fā)服務(wù),包括典型物聯(lián)網(wǎng)產(chǎn)品的三大要素,即網(wǎng)絡(luò )模塊、移動(dòng)應用和云服務(wù)。借助涂鴉MCU SDK、一體機APP和控制面板,您可以輕松專(zhuān)注于應用開(kāi)發(fā),輕松將您的產(chǎn)品接入涂鴉IoT平臺,快速享受云服務(wù)。

MCU SDK 是根據您在涂鴉物聯(lián)網(wǎng)平臺上定義的產(chǎn)品特性自動(dòng)生成的。為了方便與協(xié)議的接口,MCU SDK 內置了對通信和協(xié)議解析的支持。您可以將此 SDK 添加到現有項目中并完成所需的配置以實(shí)現 MCU 程序開(kāi)發(fā)。

pYYBAGNodJeAVc-RAABpxyjY7sU261.png
?

硬件資源要求

MCU 的 SDK 要求如下。如果你的 MCU 沒(méi)有足夠的資源,你可以參考 SDK 中的函數來(lái)對接涂鴉的協(xié)議。

  • 內存:4 KB
  • RAM:需要大約 100 字節的 RAM,具體取決于數據點(diǎn) (DP) 的數據長(cháng)度。如果啟用 OTA 更新,它必須大于 260 字節。
  • 嵌套函數:9 級。

選擇網(wǎng)絡(luò )模塊

涂鴉針對物聯(lián)網(wǎng)項目的各種需求,提供了一系列不同協(xié)議的模塊,如Wi-Fi 模塊、Wi-Fi 和藍牙 LE 模塊。

為了簡(jiǎn)化開(kāi)發(fā)過(guò)程,您可以選擇涂鴉三明治評估套件。

電源系統

電源

通常,市場(chǎng)上的割草機由氣體或電池供電。

燃氣割草機只要有足夠的燃料并且比電池供電的割草機更強大,就可以跑很遠。然而,它比電池選項產(chǎn)生更多的噪音,并在整個(gè)氣體燃燒過(guò)程中產(chǎn)生排放。

我們選擇環(huán)保鋰電池組為我們的割草機供電,以減輕噪音和污染影響。

電池

建議使用 3S 或 4S 12V 鋰離子電池。鋰離子電池的充放電倍率可以達到15C甚至超過(guò)20C,保證了強大的動(dòng)力推動(dòng)車(chē)輪前進(jìn)。如果您不選擇鋰離子電池,請選擇使用壽命長(cháng)且最大輸出電流大于 5A 的電池。

pYYBAGNodJuAPMdOAADJTE7zzPI096.png
?

降壓轉換器

我們需要一個(gè)降壓轉換器來(lái)為不同的系統提供輸出電壓。

降壓轉換器LM2596提供 3.3V、5V、12V 的固定輸出電壓和可調輸出版本。它具有以下特點(diǎn)。

  • 輸入電壓范圍高達 40 V。
  • 可調版本輸出電壓范圍:在線(xiàn)路和負載條件下最大為 1.2V 至 37V ±4%。
  • 3A 輸出負載電流。
  • 高效率。
  • 熱關(guān)斷和限流保護。
poYBAGNodJ6AKBULAABxTV0hKDY081.png
?

齒輪馬達

減速電機可以定義為直流電機的延伸。它有一個(gè)連接到電機的齒輪組件,以增加扭矩并降低速度。

減速電機的額定電壓必須與電池的額定電壓相匹配。12V 電機的電源電壓范圍為 11V 至 16V。

我們選用MG513直流12V減速電機,額定輸出電流0.36A。其減速比為1/60,空載轉速為183 RPM。電機可提供 2 kgf.cm 的扭矩和 6 kg 的最大負載。使用 65 mm 橡膠輪,割草機的速度可以達到 0.5 m/s。

電機具有內置霍爾效應傳感器。基于磁感應,我們可以得到電機的轉速,然后測量所經(jīng)過(guò)的速度和距離。

poYBAGNodKGAeSzkAAA3VZotJyc396.png
?

電機驅動(dòng)器

東芝TB6612FNG驅動(dòng)器是一款基于 MOSFET 的雙通道 H 橋集成電路。它具有以下特點(diǎn)。

  • 電源電壓:VM = 15V(最大值)。
  • 輸出電流:I = 1.2A(平均)/3.2A(峰值)。
  • 輸出低導通電阻:0.5Ω。
  • 內置熱關(guān)斷電路和低電壓檢測電路。
  • PWM信號的開(kāi)關(guān)頻率:100 kHz。

TB6612FNG 不需要散熱器,因為它比基于雙極結型晶體管 (BJT) 的驅動(dòng)器(如 L298N)效率更高。外圍電路簡(jiǎn)單,加電源濾波電容即可驅動(dòng)電機。

TB6612FNG有一對驅動(dòng)器,可以獨立控制兩個(gè)電機。因此,四個(gè)電機只需要兩個(gè) TB6612FNG IC。

STBY引腳為高電平時(shí),兩個(gè)輸入信號IN1IN2可以是順時(shí)針(CW)、逆時(shí)針(CCW)、短制動(dòng)和停止模式等四種模式之一。

pYYBAGNodKOAWoS5AAAPMg_kloQ958.png
?

示意圖如下。

?
pYYBAGNodKaAFmJYAACYo1T2mgM831.png
?

割草控制系統

割草控制系統可以調節割草高度并控制割草操作。

無(wú)刷直流電機

無(wú)刷電機沒(méi)有電刷,因此在有刷電機運行時(shí)不會(huì )產(chǎn)生電火花,大大降低了電火花對射頻遙控設備的干擾。無(wú)刷,運行時(shí)摩擦力大大降低,運行平穩,噪音低很多。這一優(yōu)勢是對穩定性和長(cháng)使用壽命的巨大支持。

pYYBAGNodKmAXezxAACUe9_bq7M652.png
?

我們使用 900 Kv 的無(wú)刷電機。選擇電機時(shí),請考慮 Kv 額定值和扭矩兩個(gè)因素。無(wú)刷電機的 Kv 額定值是電機的空載轉速與連接到線(xiàn)圈的導線(xiàn)上的峰值電壓之比。一般來(lái)說(shuō),電機的Kv越大,電機所能產(chǎn)生的扭矩就越小。

尺寸方面,推薦使用2212電機。

電子速度控制器 (ESC)

電子速度控制器 (ESC) 是一種控制和調節電動(dòng)機速度的電子電路。

poYBAGNodKuARHZkAAAiNAVxQ70403.png
?

我們使用 20A 電調。確保 ESC 的輸出電流與無(wú)刷電機的輸出電流匹配。

它具有以下特點(diǎn)。

  • 用于多旋翼控制器的特殊核心程序大大提高了油門(mén)響應。
  • 特別優(yōu)化的軟件,與盤(pán)式電機具有出色的兼容性。
  • 除定時(shí)外的所有設置都是預設的,使用簡(jiǎn)單,高度智能,自適應。
  • 油門(mén)信號線(xiàn)采用雙絞線(xiàn)設計,有效降低信號傳輸中產(chǎn)生的串擾,使飛行更加平穩。
  • 專(zhuān)用驅動(dòng)芯片的MOSFET驅動(dòng)效果比由分立元件組成的普通驅動(dòng)電路要好得多。
  • 具有超低電阻的 MOSFET 帶來(lái)高性能和大電流耐受性。

伺服

伺服系統包含直流電機、控制電路、減速器、反饋機構和其他電路。它可以根據輸入信號轉到特定位置。其內部的電位器或角度傳感器可以感應輸出軸的位置,從而使控制板據此準確控制輸出軸的轉動(dòng)。

pYYBAGNodK2AM13XAACAB4HnkVs428.png
?

通常,舵機有三根線(xiàn):棕色或黑色一根是地線(xiàn),紅色一根是電源線(xiàn),橙色或白色一根是信號線(xiàn)。

舵機可以工作在 4V 到 6V 之間,推薦使用 5V 電壓。伺服旋轉的角度是通過(guò)調整PWM信號的占空比來(lái)實(shí)現的。標準 PWM 信號的周期固定為 20 ms (50 Hz)。脈沖寬度在 0.5 ms 到 2.5 ms 之間,對應伺服旋轉角度 0° 到 180°。

兩個(gè)舵機和一些金屬圓盤(pán)組成一個(gè)升降結構來(lái)調整切割高度。

pYYBAGNodLCAMqjPAAFt5YBzXds574.png
?

定位導航系統

定位導航系統可實(shí)現定位和定向。

全球導航衛星系統定位

全球導航衛星系統 (GNSS) 是一個(gè)衛星網(wǎng)絡(luò ),用于廣播時(shí)間和軌道信息,用于導航和定位測量。目前,美國的全球定位系統(GPS)、俄羅斯的全球導航衛星系統(GLONASS)、中國的北斗衛星導航系統(BDS)和歐盟的伽利略系統都是全面運行的全球導航衛星系統。

pYYBAGNodLOAaJvPAACwouzwh6M259.png
?

我們使用涂鴉的GUC300 GNSS 模塊進(jìn)行定位和導航。

  • GUC300由高度集成的GNSS芯片UFirebird-UC6226NIS和外圍電路組成。它具有內置SAW濾波器、低噪聲放大器(LNA)、26 MHz溫度補償晶體振蕩器(TCXO)等元件。它同時(shí)支持 GPS 和 BDS 衛星導航系統。

GUC300 具有以下特點(diǎn)。

  • 定位引擎:

64個(gè)同步跟蹤通道

熱啟動(dòng)時(shí)間:<1.2秒

冷啟動(dòng)靈敏度:-145 dBm。跟蹤靈敏度:-158 dBm

數據更新率:高達 10 Hz

  • 定位引擎:

RF子系統采用寬帶設計。輸入信號的中心頻率約為 1575 MHz。

接收和跟蹤 GPS 的 1575.42 MHz L1 信號

接收和跟蹤北斗衛星導航系統1561.098 MHz B1信號

GUC300默認接收GPS和BDS信號,可定制為GPS+BDS、GPS+GLONASS或單GNSS系統。您可以提交服務(wù)單以請求所需的 GNSS 固件。

poYBAGNodLWAf5W-AABXjI-kJu0940.png
?

GUC300 默認每秒輸出$GNRMC, $GNGGA, 和$GPGSV句子。串口波特率為9600。我們可以解析$GNGGA句子。

$GNGGA,071520.00,3018.12971,N,12003.84423,E,1,20,1.47,60.5,M,,M,,\*61

上述句子的字段描述如下。$GNGGA, <1>, <2>, <3>, <4>, <5>, <6>, <7>, <8>, <9>, M, <10>, M, <11> , <12>*xx

  • \$GNGGA:句子類(lèi)型標識符。此示例指示 GGA 協(xié)議頭。
  • <1>:UTC時(shí)間,格式為hhmmss.sss.
  • <2>:緯度,格式為ddmm.mmmm. 插入前導零。
  • <3>:緯度半球,N或S(北緯或南緯)。
  • <4>:經(jīng)度,格式為dddmm.mmmm. 插入前導零。
  • <5>:半球經(jīng)度,E或W(東經(jīng)或西經(jīng))。
  • <6>:GPS定位狀態(tài)。0: 初始化。1: 單點(diǎn)定位。2: 差別。3: 無(wú)效的 PPS。4: 固定解決方案。5: 浮點(diǎn)解。6: 估計。7:手動(dòng)輸入的固定值。8模擬模式。9: WAAS different.xx: 從$to開(kāi)始的所有 ASCII 字符的 XOR 校驗值\*。
  • <7>:使用的衛星數,范圍從00到12。插入前導零。
  • <8>:水平精度稀釋度(HDOP),范圍從0.5到99.9。HDOP越小,衛星分布越好。
  • <9>:海平面高度,范圍從-9999.9到9999.9。
  • 以米為單位。
  • <10>:地球橢球體相對于大地水準面的高度,范圍從-9999.9到9999.9。
  • 以米為單位。
  • <11>:距離上次接收到差分 GPS 信號的秒數。如果不采用差分定位,則該字段為空。
  • <12>:差分參考基站標簽,范圍從0000到1023。插入前導零。
  • :回車(chē),結束標記。
  • :換行,結束標簽。

電路原理

GUC300原理圖

GUC300 電路板

電子羅盤(pán)傳感器

我們選擇了 3 軸電子羅盤(pán)傳感器QMC5883L 。

poYBAGNodLmAYom1AADxNKn769Y336.png
?

電子羅盤(pán)由一個(gè) 3D 磁阻傳感器、一個(gè) 2 軸傾角儀和一個(gè) MCU 組成。3D磁阻傳感器用于監測地磁場(chǎng)的變化,傾角儀可以測量感應方向與地平面之間的角度(相對于重力)。MCU 處理輸入信號并輸出??數據以補償硬鐵和軟鐵失真。磁力計包括 x、y 和 z 方向的三個(gè)磁阻傳感器,以相應地測量地磁場(chǎng)強度。傳感器在每個(gè)方向上的靈敏度已根據地磁場(chǎng)矢量進(jìn)行了最佳校準。交叉軸靈敏度已降至最低。來(lái)自傳感器的模擬輸出信號將被放大,然后發(fā)送到 MCU 進(jìn)行處理。

我們可以使用下面的公式來(lái)計算方向。

方向.x=atan2((double)Mag_data.y, (double)Mag_data.x)*57.3+180;

Mag_data.x分別是 X 軸和Mag_data.yY 軸的數據。atan2是平面的正 x 軸與其上坐標 (x, y) 給定的點(diǎn)之間的弧度角。將弧度值乘以 57.3 以將弧度轉換為度數。最后,將轉換后的值加上 180 度。

對于計算結果,真南為0或360,西為90,北為180,東為270。

組裝設備

設計一個(gè)安裝輪子、伺服系統和其他組件的底板。下載底板結構文件。

pYYBAGNodLuAU-AJAABRjS-tIKA936.png
?

整個(gè)組件看起來(lái)像這樣。

我們需要設計一個(gè)PCB布局來(lái)放置電機驅動(dòng)器和電源等組件。確保為舵機、電機和電子羅盤(pán)的接口預留空間,以保持項目整潔。您還可以添加一些功能,例如用于警報的蜂鳴器和用于信號的 LED。

?
poYBAGNodL6AIN3hAAGfAKx2X5Y814.png
?

電路原理圖

原理圖,示意圖

印刷電路板

最后,將 GPS、微控制器和電源單元安裝在 PCB 上,PCB 組裝完成。

第 2 步:創(chuàng )建產(chǎn)品

1.登錄涂鴉IoT平臺。

2.點(diǎn)擊創(chuàng )建。

?
pYYBAGNodMCABRgEAABn9EEWG-Q831.png
?

3.向下滾動(dòng)頁(yè)面并單擊找不到類(lèi)別?在左下角。

4.填寫(xiě)所需信息并點(diǎn)擊創(chuàng )建。

  • Product Name 、Product DescriptionProduct Model是用戶(hù)定義的。
  • 選擇Wi-Fi-Bluetooth作為協(xié)議,然后單擊Create 。
?
poYBAGNodMSAHpPtAACLHM8oWb4237.png
?

5.在自定義函數部分,單擊添加以創(chuàng )建所需的函數。函數定義步驟中,您可以根據需要添加標準函數或創(chuàng )建自定義函數。

我們設置了以下功能。

  • 標準功能:方向控制
  • 自定義功能:刀片位置、刀片轉速、切割長(cháng)度、切割寬度、鋸齒割草模式。
?
poYBAGNodMaAHVzsAABFhZkGQdM639.png
?

6. 在設備面板選項卡的第二步中,選擇所需的面板。在設備面板的第二步,可以選擇調試友好的DIY風(fēng)格面板。

7.在硬件開(kāi)發(fā)的第三步,選擇涂鴉標準模塊SDK 。

?
pYYBAGNodMmALx2fAABrSbjvILs361.png
?

8.向下滾動(dòng)頁(yè)面并找到下載文檔。點(diǎn)擊全部下載,下載MCU SDK開(kāi)發(fā)所需的全部文件。

?
poYBAGNodMuAJO6QAAA3lMfN09k784.png
?
  • 平臺上的操作就完成了。您可以使用涂鴉智能 App 使用虛擬設備進(jìn)行遠程控制。
?
pYYBAGNodM-AcYnyAAA3oEDeWFw109.png
?

第 3 步:固件開(kāi)發(fā)

在應用程序開(kāi)發(fā)之前,您需要將 MCU SDK 移植到您的項目中。

然后將通用固件和涂鴉的授權刷入網(wǎng)絡(luò )模塊。這樣,割草機就可以與云進(jìn)行通信。

演示例程還包括 FreeRTOS,以方便您的開(kāi)發(fā)。

以上準備工作完成后,就可以進(jìn)行應用開(kāi)發(fā)了。

下載示例代碼:tuya-iotos-embeded-mcu-demo-wifi-ble-samrt-lawn-mower

電機、伺服和電調驅動(dòng)器

將四個(gè)電機連接到每個(gè)車(chē)輪以進(jìn)行運動(dòng)。兩個(gè)舵機用于控制 ESC 以及連接到 ESC 的刀片的位置。ESC 控制和調節刀片旋轉的速度。

編寫(xiě)上述組件的初始化程序,在servo_motor.c.

  • 為輸出 GPIO 定義宏。
#define MOTOR_PORT_1                        GPIOA
#define MOTOR_PIN_1                         GPIO_PIN_15
#define MOTOR_PORT_1_P                      GPIOD
#define MOTOR_PIN_1_P                       GPIO_PIN_0
#define MOTOR_PORT_1_N                      GPIOD
#define MOTOR_PIN_1_N                       GPIO_PIN_7
#define MOTOR_PORT_2                        GPIOB
#define MOTOR_PIN_2                         GPIO_PIN_9
#define MOTOR_PORT_2_P                      GPIOD
#define MOTOR_PIN_2_P                       GPIO_PIN_1
#define MOTOR_PORT_2_N                      GPIOD
#define MOTOR_PIN_2_N                       GPIO_PIN_2
#define MOTOR_PORT_3                        GPIOB
#define MOTOR_PIN_3                         GPIO_PIN_10
#define MOTOR_PORT_3_P                      GPIOD
#define MOTOR_PIN_3_P                       GPIO_PIN_3
#define MOTOR_PORT_3_N                      GPIOD
#define MOTOR_PIN_3_N                       GPIO_PIN_4
#define MOTOR_PORT_4                        GPIOB
#define MOTOR_PIN_4                         GPIO_PIN_11
#define MOTOR_PORT_4_P                      GPIOD
#define MOTOR_PIN_4_P                       GPIO_PIN_8
#define MOTOR_PORT_4_N                      GPIOD
#define MOTOR_PIN_4_N                       GPIO_PIN_9
#define MOTOR_CHANNEL_1                     TIMER_CH_0
#define MOTOR_CHANNEL_2                     TIMER_CH_1
#define MOTOR_CHANNEL_3                     TIMER_CH_2
#define MOTOR_CHANNEL_4                     TIMER_CH_3
#define SERVO_PORT_1                        GPIOC
#define SERVO_PIN_1                         GPIO_PIN_6
#define SERVO_PORT_2                        GPIOC
#define SERVO_PIN_2                         GPIO_PIN_7
#define BLADE_MOTOR_PORT                    GPIOC
#define BLADE_MOTOR_PIN                     GPIO_PIN_8
  • 調用初始化接口開(kāi)啟GPIO時(shí)鐘,指定輸出GPIO為普通模式或PWM模式。然后,調用timer_config設置 PWM 參數。
void servo_motor_init(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);

/*Configure PD1~8 Output motor Positive and Negative pin to drive wheels_1~4*/
gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, MOTOR_PIN_1_P | MOTOR_PIN_1_N | MOTOR_PIN_2_P | MOTOR_PIN_2_N | MOTOR_PIN_3_P | MOTOR_PIN_3_N | MOTOR_PIN_4_P | MOTOR_PIN_4_N);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_1_P | MOTOR_PIN_1_N | MOTOR_PIN_2_P | MOTOR_PIN_2_N | MOTOR_PIN_3_P | MOTOR_PIN_3_N | MOTOR_PIN_4_P | MOTOR_PIN_4_N);
gpio_bit_reset(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_1_N | MOTOR_PIN_2_P | MOTOR_PIN_2_N | MOTOR_PIN_3_P | MOTOR_PIN_3_N | MOTOR_PIN_4_P | MOTOR_PIN_4_N);

/*Configure PA15(TIMER1_CH0) Output PWM pulse to drive wheels_1*/
gpio_mode_set(MOTOR_PORT_1, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_1);
gpio_output_options_set(MOTOR_PORT_1, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_1);
gpio_af_set(MOTOR_PORT_1, GPIO_AF_1, MOTOR_PIN_1);
/*Configure PB9(TIMER1_CH1) Output PWM pulse to drive wheels_2*/
gpio_mode_set(MOTOR_PORT_2, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_2);
gpio_output_options_set(MOTOR_PORT_2, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_2);
gpio_af_set(MOTOR_PORT_2, GPIO_AF_1, MOTOR_PIN_2);
/*Configure PB10(TIMER1_CH2) Output PWM pulse to drive wheels_3*/
gpio_mode_set(MOTOR_PORT_3, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_3);
gpio_output_options_set(MOTOR_PORT_3, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_3);
gpio_af_set(MOTOR_PORT_3, GPIO_AF_1, MOTOR_PIN_3);
/*Configure PB11(TIMER1_CH3) Output PWM pulse to drive wheels_4*/
gpio_mode_set(MOTOR_PORT_4, GPIO_MODE_AF, GPIO_PUPD_NONE, MOTOR_PIN_4);
gpio_output_options_set(MOTOR_PORT_4, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,MOTOR_PIN_4);
gpio_af_set(MOTOR_PORT_4, GPIO_AF_1, MOTOR_PIN_4);
/*Configure PC6(TIMER2_CH0) Output PWM pulse to drive servo no.1*/
gpio_mode_set(SERVO_PORT_1, GPIO_MODE_AF, GPIO_PUPD_NONE, SERVO_PIN_1);
gpio_output_options_set(SERVO_PORT_1, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SERVO_PIN_1);
gpio_af_set(SERVO_PORT_1, GPIO_AF_2, SERVO_PIN_1);

/*Configure PC7(TIMER2_CH1) Output PWM pulse to drive servo no.2*/
gpio_mode_set(SERVO_PORT_2, GPIO_MODE_AF, GPIO_PUPD_NONE, SERVO_PIN_2);
gpio_output_options_set(SERVO_PORT_2, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SERVO_PIN_2);
gpio_af_set(SERVO_PORT_2, GPIO_AF_2, SERVO_PIN_2);

/*Configure PC8(TIMER2_CH2) Output PWM pulse to drive blade motor*/
gpio_mode_set(BLADE_MOTOR_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, BLADE_MOTOR_PIN);
gpio_output_options_set(BLADE_MOTOR_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,BLADE_MOTOR_PIN);
gpio_af_set(BLADE_MOTOR_PORT, GPIO_AF_2, BLADE_MOTOR_PIN);

timer_config();
}
void timer_config(void)
{
uint16_t i = 0;

/* TIMER1 configuration: generate PWM signals with different duty cycles:
TIMER1CLK = SystemCoreClock / 120 = 1MHz */
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER1);
rcu_periph_clock_enable(RCU_TIMER2);
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
timer_struct_para_init(&timer_initpara);
timer_deinit(TIMER1);
timer_deinit(TIMER2);
/* TIMER1 configuration */
timer_initpara.prescaler         = 119;
timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection  = TIMER_COUNTER_UP;
timer_initpara.period            = 500; /* 500*(1/1MHZ) = 500us */
timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER1,&timer_initpara);
/* TIMER2 configuration */
timer_initpara.prescaler         = 119;
timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection  = TIMER_COUNTER_UP;
timer_initpara.period            = 20000; /* 20000*(1/1MHZ) = 20ms */
timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER2,&timer_initpara);
timer_channel_output_struct_para_init(&timer_ocintpara);
timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
timer_ocintpara.ocidlestate  = TIMER_OC_IDLE_STATE_LOW;
timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
for(i = 0; i < 4; i++) {

timer_channel_output_config(TIMER1,i,&timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER1,i,0);
timer_channel_output_mode_config(TIMER1,i,TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER1,i,TIMER_OC_SHADOW_DISABLE);
}
for(i = 0; i < 3; i++) {

timer_channel_output_config(TIMER2,i,&timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER2,i,0);
timer_channel_output_mode_config(TIMER2,i,TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER2,i,TIMER_OC_SHADOW_DISABLE);
}
/* auto-reload preload enable */
timer_auto_reload_shadow_enable(TIMER1);
timer_auto_reload_shadow_enable(TIMER2);
/* TIMER enable */
timer_enable(TIMER1);
timer_enable(TIMER2);
}
  • 調整電機和舵機的PWM占空比,將占空比調整的操作封裝為通用接口。以連接到車(chē)輪的電機為例。car_moving用于根據輸入方向和速度調整正負電平和占空比,從而控制車(chē)輪。
void car_moving(MOVING_DIRECTION direction, uint16_t speed_value)
{
uint8_t i;
switch(direction) {

case forward:

gpio_bit_set(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);

for(i = 0; i < 4; i++) {
timer_channel_output_pulse_value_config(TIMER1,i,speed_value);
}
break;
case right:

gpio_bit_set(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);

//Since the two sets of wheels on the right are always faster than the left in the actual commissioning process, 60 is added to compensate
timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_1,speed_value + 60);
timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_3,speed_value + 60);

timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_2,speed_value);
timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_4,speed_value);
break;
case left:

gpio_bit_set(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);
timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_1,speed_value);
timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_3,speed_value);

timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_2,speed_value + 50);
timer_channel_output_pulse_value_config(TIMER1,MOTOR_CHANNEL_4,speed_value + 50);
break;
case backward:

gpio_bit_reset(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
gpio_bit_set(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);

for(i = 0; i < 4; i++) {
timer_channel_output_pulse_value_config(TIMER1,i,speed_value);
}
break;
case stop:

gpio_bit_reset(GPIOD, MOTOR_PIN_1_P | MOTOR_PIN_2_P | MOTOR_PIN_3_P | MOTOR_PIN_4_P);
gpio_bit_reset(GPIOD, MOTOR_PIN_1_N | MOTOR_PIN_2_N | MOTOR_PIN_3_N | MOTOR_PIN_4_N);

for(i = 0; i < 4; i++) {
timer_channel_output_pulse_value_config(TIMER1,i,speed_value);
}
break;
default:
break;
}
}

用于線(xiàn)性運動(dòng)校正的比例積分微分 (PID) 算法

由于四個(gè)輪子由獨立的電機控制,即使 PWM 輸出設置為相同的占空比,錯誤和其他因素也會(huì )導致割草機偏離線(xiàn)性運動(dòng)。因此,我們使用PID算法來(lái)動(dòng)態(tài)調整每個(gè)車(chē)輪的實(shí)際轉速。直線(xiàn)運動(dòng)表示四個(gè)輪子同時(shí)移動(dòng)相同的距離。由于四個(gè)輪子的直徑相同,因此每個(gè)輪子的轉速應該相同。因為電機轉速直接決定了電機編碼器輸出的脈沖數,所以我們以電機編碼器單位時(shí)間內實(shí)時(shí)輸出的脈沖數作為PID算法的輸入,占空比增量作為控制對象。我們可以不斷微調脈沖,使四個(gè)電機達到相同的值。

  • 通過(guò)外部中斷對脈沖進(jìn)行計數,收集電機編碼器輸出脈沖的單位時(shí)間增量。中的movement_system_init()函數movement.c包括外部中斷的配置。
void movement_system_init(void)
{
rcu_periph_clock_enable(RCU_SYSCFG);

gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
nvic_irq_enable(EXTI0_IRQn, 2U, 0U);
syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN0);
exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_RISING);
exti_interrupt_flag_clear(EXTI_0);

gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_1);
nvic_irq_enable(EXTI1_IRQn, 2U, 0U);
syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN1);
exti_init(EXTI_1, EXTI_INTERRUPT, EXTI_TRIG_RISING);
exti_interrupt_flag_clear(EXTI_1);
gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_2);
nvic_irq_enable(EXTI2_IRQn, 2U, 0U);
syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN2);
exti_init(EXTI_2, EXTI_INTERRUPT, EXTI_TRIG_RISING);
exti_interrupt_flag_clear(EXTI_2);

gpio_mode_set(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_3);
nvic_irq_enable(EXTI3_IRQn, 2U, 0U);
syscfg_exti_line_config(EXTI_SOURCE_GPIOC, EXTI_SOURCE_PIN3);
exti_init(EXTI_3, EXTI_INTERRUPT, EXTI_TRIG_RISING);
exti_interrupt_flag_clear(EXTI_3);
}

void EXTI0_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_0)){
move_state.encoder_pulse[0]++;
}
exti_interrupt_flag_clear(EXTI_0);
}
void EXTI1_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_1)){
move_state.encoder_pulse[1]++;
}
exti_interrupt_flag_clear(EXTI_1);
}
void EXTI2_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_2)){
move_state.encoder_pulse[2]++;
}
exti_interrupt_flag_clear(EXTI_2);
}
void EXTI3_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_3)){
move_state.encoder_pulse[3]++;
}
exti_interrupt_flag_clear(EXTI_3);
}
  • 實(shí)現forward_correction()接口,將收集到的脈沖pulse_num、最后一個(gè)脈沖pulse_num_old和所需的脈沖增量standard_increment傳遞給 PID 控制函數。調用single_motor_speed_set()根據計算結果調整各電機的PWM占空比。
int e[4]={0},e1[4]={0},e2[4]={0}; // PID offset
float uk[4]={0.0},uk1[4]={0.0},duk[4]={0.0}; // PID output
float Kp=0.8,Ki=0.3,Kd=0.9; // PID control factors.
int out[4] = {0};
static void forward_correction(uint32_t *pulse_num, uint32_t *pulse_num_old, uint32_t standard_increment)
{
uint8_t i = 0;

for(i = 0;i < 4;i++) {
e[i] = standard_increment - (pulse_num[i] - pulse_num_old[i]);
duk[i] = (Kp*(e[i]-e1[i])+Ki*e[i])/100;
uk[i] = uk1[i] + duk[i];
out[i] = (int)uk[i];
uk1[i] = uk[i];
e2[i] = e1[i];
e1[i] = e[i];
single_motor_speed_set(i, (uint16_t)(200+(out[i]*5)));
}
return;
}
  • 當運動(dòng)輪詢(xún)處理程序進(jìn)入switch直線(xiàn)運動(dòng)的分支時(shí),您可以調用forward_correction()來(lái)調整電機速度,然后將 分配encoder_pulseencoder_pulse_old。
void movement_logic_handle(void)
{
MOVE_STATE_T *p = NULL;
p = &move_state;
uint8_t i = 0;
MOVING_DIRECTION turning_state;

switch(p->todo_type) {

......
case on_the_move:

if(forward_sampling_time_flag == 20) { //20*20ms = 400ms
for(i = 0;i < 4;i++) {
pulse_test[i] = p->encoder_pulse[i]-p->encoder_pulse_old[i];
}
forward_correction(p->encoder_pulse,p->encoder_pulse_old,390);

for(i = 0;i < 4;i++) {
p->encoder_pulse_old[i] = p->encoder_pulse[i];
}
forward_sampling_time_flag = 0;
}
forward_sampling_time_flag++;

todo_judge();

break;
......
default:
break;
}

}

讓割草機旋轉 90 度

以之字形割草模式為例。當割草機到達直線(xiàn)運動(dòng)的終點(diǎn)時(shí),它必須轉動(dòng) 90 度。todo_judge功能用于確定旋轉運動(dòng),該運動(dòng)也基于來(lái)自電機編碼器的脈沖數。將長(cháng)度轉換為脈沖數。當脈沖達到規定值時(shí),割草機將轉動(dòng) 90 度。割草機需要確定從長(cháng)邊或寬邊轉向以及向左或向右轉向。todo_judge()函數有判斷switch。分支指示割草機是case從長(cháng)邊轉向還是從寬邊轉向。case用于判斷直線(xiàn)運動(dòng)中的割草機是否應轉彎。如果是,則轉彎狀態(tài)將更改(change_to_do(turning);),并且案例分支p->run_step_flag = width_right;將在割草機在下一個(gè)行駛階段進(jìn)入此功能時(shí)更改。如果寬度達到規定值,則表明曲折割草作業(yè)完成。

static void todo_judge(void)
{
MOVE_STATE_T *p = NULL;
p = &move_state;

switch(p->run_step_flag) {

case length_right:
if(pulse_to_distance(p->encoder_pulse[0]) >= (p->range_length_mm - 10)) {
if((p->current_angle + 900) > 3600) {
p->target_angle = p->current_angle + 900 - 3600;
}else{
p->target_angle = p->current_angle + 900;
}
change_to_do(turning);
p->run_step_flag = width_right;
}
break;
case width_right:
if(pulse_to_distance(p->encoder_pulse[0]) >= 100) {
if((p->current_angle + 900) > 3600) {
p->target_angle = p->current_angle + 900 - 3600;
}else{
p->target_angle = p->current_angle + 900;
}
change_to_do(turning);
p->run_step_flag = length_left;
width_remain_mm -= 100;
}
break;
case length_left:
if(pulse_to_distance(p->encoder_pulse[0]) >= (p->range_length_mm - 10)) {
if(p->current_angle < 900) {
p->target_angle = 3600 - (900 - p->current_angle);
}else{
p->target_angle = p->current_angle - 900;
}
change_to_do(turning);
p->run_step_flag = width_left;
}
break;
case width_left:
if(pulse_to_distance(p->encoder_pulse[0]) >= 100) {
if(p->current_angle < 900) {
p->target_angle = 3600 - (900 - p->current_angle);
}else{
p->target_angle = p->current_angle - 900;
}
change_to_do(turning);
p->run_step_flag = length_right;
width_remain_mm -= 100;

}
break;
default:
break;
}

if(width_remain_mm <= 0) {
change_to_do(to_stop);
move_state.bow_mode_switch = pdFALSE;
}
}
  • 上述例程中,p->target_angle是目標方位角,p->current_angle是當前方位角,用于控制割草機的轉向角。目標方位角是割草機即將轉彎時(shí)的方位角加減90度得到的。并且當前方位角是根據地磁傳感器的數據計算得出的。QMC5883L.c文件包含 I2C QMC5883L 的驅動(dòng)程序代碼。在這里,我們使用QMC5883L_GetAngle()來(lái)獲取當前方位角。
void move_control_task(void *pvParameters)
{
float_xyz Mag_angle;
uint8_t test_flag = 50;
vTaskDelay(200);
QMC_Init();
QMC5883L_GetAngle(&Mag_angle);
move_state.current_angle = (int16_t)Mag_angle.x;
vTaskDelay(500);
while(1) {

if(test_flag){
vTaskDelay(20);
test_flag--;
}else if(test_flag == 0) {
vTaskDelay(20);
movement_logic_handle();
}
QMC5883L_GetAngle(&Mag_angle);
move_state.current_angle = (int16_t)Mag_angle.x;
}
}
  • 方位角可用于確定轉彎操作。angle_correction()界面可以確定割草機應該左轉還是右轉或直行。angle_correction()接口在移動(dòng)輪詢(xún)處理程序turningcase分支中調用。
static MOVING_DIRECTION angle_correction(void)
{
int16_t target,current = 0;
target = move_state.target_angle;
current = move_state.current_angle;
if(target < current) {
if(current - target <= 20) {
return forward;
}
if(current - target <= 1800) {
return left;
}else{
return right;
}
}else if(target > current) {
if(target - current <= 20) {
return forward;
}
if(target - current <= 1800) {
return right;
}else{
return left;
}
}else if(current == target) {
return forward;
}
}
void movement_logic_handle(void)
{
MOVE_STATE_T *p = NULL;
p = &move_state;
uint8_t i = 0;
MOVING_DIRECTION turning_state;

switch(p->todo_type) {

......
case on_the_move:

if(forward_sampling_time_flag == 20) { //20*20ms = 400ms
for(i = 0;i < 4;i++) {
pulse_test[i] = p->encoder_pulse[i]-p->encoder_pulse_old[i];
}
forward_correction(p->encoder_pulse,p->encoder_pulse_old,390);

for(i = 0;i < 4;i++) {
p->encoder_pulse_old[i] = p->encoder_pulse[i];
}
forward_sampling_time_flag = 0;
}
forward_sampling_time_flag++;

todo_judge();

break;
case turning:

turning_state = angle_correction();
if(turning_state == right) {
car_full_turn(right,150);
turning_sampling_time_flag = 0;
}else if(turning_state == left) {
car_full_turn(left,150);
turning_sampling_time_flag = 0;
}else if(turning_state == forward) {
car_moving(stop,0);
turning_sampling_time_flag++;
}

if(turning_sampling_time_flag >= 25) {
p->todo_type = on_the_move;
car_moving(forward,200);
forward_sampling_time_flag = 0;
turning_sampling_time_flag = 0;
for(i = 0;i < 4;i++) {
p->encoder_pulse[i] = 0;
p->encoder_pulse_old[i] = 0;
}
}
break;
......
default:
break;
}

}

設置刀片位置和速度

刀片位置由兩個(gè)伺服系統控制。如果要在刀片上下移動(dòng)時(shí)保持刀片的水平位置不變,則兩個(gè)舵機必須在相反的方向上改變相同的角度。兩個(gè)舵機的相反方向的角度變化必須相同。封裝一個(gè)用于設置刀片位置的接口,以位置枚舉值作為輸入。

void blade_position_set(BLADE_POSITION value)
{
switch(value) {

case low:

timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,3100);
timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,3000);
break;

case medium:

timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,2800);
timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,2700);
break;

case high:

timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,2600);
timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,2500);
break;

default:
break;
}
}

葉片速度由 ESC 控制并封裝在blade_speed_set();.

void blade_speed_set(BLADE_SPEED speed)
{
switch(speed) {

case init:

timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,1500);
break;

case off:

timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,0);
break;

case low_speed:

timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,1800);
break;

case medium_speed:

timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,1900);
break;

case high_speed:

timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,2000);
break;

default:
break;
}
}

5.接收GNSS數據

涂鴉 GNSS 模塊 GUC300 模塊通過(guò)串口通信向 MCU 發(fā)送 GNSS 數據。我們使用USART1MCU的來(lái)接收數據,因為USART0已經(jīng)用于與Wi-Fi模塊的串行通信。

  • 初始化串口:
void uart_init(void)
{
/* USART interrupt configuration */
nvic_irq_enable(USART0_IRQn, 0, 0);
nvic_irq_enable(USART1_IRQn, 1, 1);
/* enable USART clock */
rcu_periph_clock_enable(RCU_USART0);

/* connect port to USART0_Tx */
gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);
/* connect port to USART0_Rx */
gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);

/* configure USART Tx as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);
/* configure USART Rx as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);
/* USART configure */
usart_deinit(USART0);
usart_baudrate_set(USART0,115200U);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);

/* enable USART clock */
rcu_periph_clock_enable(RCU_USART1);

/* connect port to USART0_Tx */
gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_5);
/* connect port to USART0_Rx */
gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_6);

/* configure USART Tx as alternate function push-pull */
gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_5);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_5);
/* configure USART Rx as alternate function push-pull */
gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_6);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6);
/* USART configure */
usart_deinit(USART1);
usart_baudrate_set(USART1,9600U);
usart_receive_config(USART1, USART_RECEIVE_ENABLE);
usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
usart_enable(USART1);

/* enable USART0 receive interrupt */
usart_interrupt_enable(USART0, USART_INT_RBNE);

/* enable USART1 receive interrupt */
usart_interrupt_enable(USART1, USART_INT_RBNE);
}
  • 初始化 USART 中斷處理函數。GUC300 默認每秒輸出$GNRMC, $GNGGA, $GPGSV, 和$GPGGA句子。我們可以解析$GPGGA句子。
  • $GPGGA句子包含17個(gè)字段:標題,位置的UTC時(shí)間狀態(tài),緯度,緯度方向,經(jīng)度,經(jīng)度方向,定位質(zhì)量,正在使用的衛星數量,精度水平稀釋?zhuān)?a target='_blank' class='arckwlink_none'>天線(xiàn)高度高于/低于平均海平面,天線(xiàn)高度單位、起伏(大地水準面和WGS84橢球的關(guān)系)、起伏的單位、校正數據的年齡、差分基站ID、校驗和、句子終止符。
  • 例子:$GPGGA,014434.70,3817.13334637,N,12139.72994196,E,4,07,1.5,6.571,M,8.942,M,0.7,0016*79
  • 按照上述格式處理串行數據。
#define USART_FH_len 6  // The length of the header.
char USART_FH[USART_FH_len]={'$','G','N','G','G','A'}; // Header
#define USART_FT_len 2  // The length of the trailer.
uint8_t USART_FT[USART_FT_len]={0X0D,0X0A}; // Frame trailer
uint8_t data_buf[128] = {0};
uint8_t rx_buf[128] = {0};
uint8_t buff_len = 0;
void USART1_IRQHandler(void)
{
if((RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_RBNE)) &&
(RESET != usart_flag_get(USART1, USART_FLAG_RBNE))){

rx_buf[buff_len++] = (uint8_t)usart_data_receive(USART1);
if(rx_buf[0] != USART_FH[0]) {
rx_buf[0] = 0;
buff_len = 0;
}
if(buff_len >= USART_FH_len) {
if(strncmp((char*)rx_buf,USART_FH,USART_FH_len) == 0) {
if(strncmp(&rx_buf[buff_len-2],(char*)USART_FT,USART_FT_len) == 0) {
memcpy(data_buf,rx_buf,buff_len);
memset(rx_buf,0,buff_len);
buff_len = 0;
}
}else {
memset(rx_buf,0,USART_FH_len);
buff_len = 0;
}
}
}
}
void gps_data_task(void *pvParameters)
{
MAP_POINT_t *p;
p = &map_point[point_1];
uint8_t data_len = 0;
while(1) {
vTaskDelay(100);

data_len = strlen((char*)data_buf);
if(data_len != 0){
gps_data_pick(point_1, data_buf, data_len);
memset(data_buf,0,data_len);
}
}
}

概括

恭喜!您已經(jīng)成功地制作了機器人割草機的原型。您可以添加更多酷炫和有用的功能來(lái)制作功能齊全的割草機。涂鴉物聯(lián)網(wǎng)平臺提供便捷的物聯(lián)網(wǎng)開(kāi)發(fā)工具和服務(wù),旨在讓您的物聯(lián)網(wǎng)項目更輕松、更高效。查看并發(fā)現更多很棒的想法

?


下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評論

查看更多

下載排行

本周

  1. 1山景DSP芯片AP8248A2數據手冊
  2. 1.06 MB  |  532次下載  |  免費
  3. 2RK3399完整板原理圖(支持平板,盒子VR)
  4. 3.28 MB  |  339次下載  |  免費
  5. 3TC358743XBG評估板參考手冊
  6. 1.36 MB  |  330次下載  |  免費
  7. 4DFM軟件使用教程
  8. 0.84 MB  |  295次下載  |  免費
  9. 5元宇宙深度解析—未來(lái)的未來(lái)-風(fēng)口還是泡沫
  10. 6.40 MB  |  227次下載  |  免費
  11. 6迪文DGUS開(kāi)發(fā)指南
  12. 31.67 MB  |  194次下載  |  免費
  13. 7元宇宙底層硬件系列報告
  14. 13.42 MB  |  182次下載  |  免費
  15. 8FP5207XR-G1中文應用手冊
  16. 1.09 MB  |  178次下載  |  免費

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費
  3. 2555集成電路應用800例(新編版)
  4. 0.00 MB  |  33566次下載  |  免費
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費
  7. 4開(kāi)關(guān)電源設計實(shí)例指南
  8. 未知  |  21549次下載  |  免費
  9. 5電氣工程師手冊免費下載(新編第二版pdf電子書(shū))
  10. 0.00 MB  |  15349次下載  |  免費
  11. 6數字電路基礎pdf(下載)
  12. 未知  |  13750次下載  |  免費
  13. 7電子制作實(shí)例集錦 下載
  14. 未知  |  8113次下載  |  免費
  15. 8《LED驅動(dòng)電路設計》 溫德?tīng)栔?zhù)
  16. 0.00 MB  |  6656次下載  |  免費

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費
  3. 2protel99se軟件下載(可英文版轉中文版)
  4. 78.1 MB  |  537798次下載  |  免費
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420027次下載  |  免費
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費
  11. 6電路仿真軟件multisim 10.0免費下載
  12. 340992  |  191187次下載  |  免費
  13. 7十天學(xué)會(huì )AVR單片機與C語(yǔ)言視頻教程 下載
  14. 158M  |  183279次下載  |  免費
  15. 8proe5.0野火版下載(中文版免費下載)
  16. 未知  |  138040次下載  |  免費
亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看