導(dǎo)語
智慧農(nóng)業(yè)系統(tǒng)是未來農(nóng)業(yè)發(fā)展的趨勢(shì)所在,它能夠通過傳感器,實(shí)時(shí)檢測(cè)作物的各種生長狀況,和各類環(huán)境數(shù)據(jù)。通過聯(lián)網(wǎng)與大數(shù)據(jù)的比對(duì)獲取,并通過智能硬件提供適合作物生長的最佳溫度,濕度,酸堿鹽等。
在在智能農(nóng)業(yè)發(fā)展的道路上,一直存在一個(gè)難關(guān)。那就是關(guān)于智能硬件供電問題。數(shù)據(jù)采集接口由智能硬件提供,面對(duì)超大范圍的組網(wǎng),電纜不可能布置到每一個(gè)點(diǎn)上。那么對(duì)于智能硬件功耗的要求就非常高。
Ambiq 擁有的亞閥值功率優(yōu)化技術(shù)專利,使得其能耗比性能相當(dāng)?shù)?a target="_blank">mcu 低個(gè)5至10倍,這個(gè)技術(shù)重新定義了“低功耗”。正因?yàn)檫@個(gè)技術(shù),Apollo2 mcu 也是最適合智慧農(nóng)業(yè)智能硬件的主mcu 。 14位的ADC,6組 I2C接口,2組UART,等豐富的外設(shè)接口,能夠保證各類傳感器的需求。
智能硬件低功耗設(shè)計(jì)及各類驅(qū)動(dòng)接口
1、低功耗設(shè)計(jì)
Apollo2 mcu 可以直接使用官方移植好的FreeRTOS。系統(tǒng)中通過以下設(shè)定,選擇需要保留的FLASH,SRAM大小。同時(shí)也能夠選擇各類外設(shè)接口的開斷電。
Am_hal_pwrctrl_memory_enable 主要是針對(duì)flash 和 SRAM??蛇x大小如下;
AM_HAL_PWRCTRL_MEMEN_CACHE
AM_HAL_PWRCTRL_MEMEN_CACHE_DIS
AM_HAL_PWRCTRL_MEMEN_FLASH512K
AM_HAL_PWRCTRL_MEMEN_FLASH1M
AM_HAL_PWRCTRL_MEMEN_SRAM8K
AM_HAL_PWRCTRL_MEMEN_SRAM16K
AM_HAL_PWRCTRL_MEMEN_SRAM24K
AM_HAL_PWRCTRL_MEMEN_SRAM32K
AM_HAL_PWRCTRL_MEMEN_SRAM64K
AM_HAL_PWRCTRL_MEMEN_SRAM96K
AM_HAL_PWRCTRL_MEMEN_SRAM128K
AM_HAL_PWRCTRL_MEMEN_SRAM160K
AM_HAL_PWRCTRL_MEMEN_SRAM192K
AM_HAL_PWRCTRL_MEMEN_SRAM224K
AM_HAL_PWRCTRL_MEMEN_SRAM256K
AM_HAL_PWRCTRL_MEMEN_ALL (the default, power-up state)
而am_hal_pwrctrl_periph_enable主要是對(duì)外設(shè)接口的使能,可選范圍:
AM_HAL_PWRCTRL_PWRONSTATUS_IOS_UARTS
AM_HAL_PWRCTRL_PWRONSTATUS_IOM_3_5
AM_HAL_PWRCTRL_PWRONSTATUS_IOM_0_2
AM_HAL_PWRCTRL_PWRONSTATUS_ADC
AM_HAL_PWRCTRL_PWRONSTATUS_PDM
如果客戶沒有連續(xù)采集或者傳輸要求,在低功耗模式下,都按最小flash和SRAM保留,接口使用完之后進(jìn)行斷電關(guān)閉。
2、使用spi接口點(diǎn)亮OLED屏
首先是開啟IOM_0_2的POWER(根據(jù)個(gè)人選擇那組IO決定)緊接著進(jìn)行初始化SPI,初始化OLED,執(zhí)行顯示代碼,關(guān)閉OLED,關(guān)閉SPI POWER。粗略流程如下:
Apollo2 MCU 的SPI和I2C 是共用IOM接口,所以在配置上面沒有太大的區(qū)別。需要修改的是Mode 選擇(AM_HAL_IOM_SPIMODE/ AM_HAL_IOM_I2CMODE),和對(duì)應(yīng)的GPIO口配置。而速率,時(shí)鐘極性和相位,讀寫的字符長度都是在config里面進(jìn)行修改。
3、UART是常用的異步串口通信協(xié)議,傳輸數(shù)據(jù)是以字節(jié)形式,一位位串行輸出。
(1)幾個(gè)重要的位置
1) 起始位:先發(fā)出一個(gè)邏輯“0”的信號(hào),表示傳輸字符開始。
2) 數(shù)據(jù)位:緊接著起始位之后。數(shù)據(jù)靠時(shí)鐘進(jìn)行定位,數(shù)據(jù)位的個(gè)數(shù)可以由用戶決定。
3) 奇偶校驗(yàn)位:數(shù)據(jù)位加上這一位后,使得“1”的位數(shù)應(yīng)為偶數(shù)(偶校驗(yàn))或奇數(shù)(奇校驗(yàn)),以次來校驗(yàn)數(shù)據(jù)傳送的正確性。
4)停止位:它是一個(gè)字符數(shù)據(jù)的結(jié)束標(biāo)志??梢允?位、1.5位、2位的高電平。停止位不僅僅是表示傳輸?shù)慕Y(jié)束,并且提供設(shè)備之間時(shí)鐘的校準(zhǔn)。
圖1
各個(gè)位的配置,在am_hal_uart_config_t中完成:
(2)Apollo2 mcu ,UART的初始化程序如下:
uart_init(uint32_t ui32Module)
{
// Make sure the UART RX and TX pins are enabled
am_bsp_pin_enable(COM_UART_TX);
am_bsp_pin_enable(COM_UART_RX);
//
// Power on the selected UART
//
am_hal_uart_pwrctrl_enable(ui32Module);
am_hal_uart_clock_enable(ui32Module);
//
// Disable the UART before configuring it.
//
am_hal_uart_disable(ui32Module);
//
// Configure the UART.
//
am_hal_uart_config(ui32Module, &g_sUartConfig);
//
// Enable the UART FIFO.
//
am_hal_uart_fifo_config(ui32Module, AM_HAL_UART_TX_FIFO_1_2 | AM_HAL_UART_RX_FIFO_1_2);
am_hal_uart_enable(ui32Module);
}
(3) 在使用串口需要注意兩點(diǎn):
第一:串口數(shù)據(jù)傳輸,有可能會(huì)被各類更高優(yōu)先級(jí)的中斷打斷,所以為了保證數(shù)據(jù)的完整性,應(yīng)該設(shè)置中斷保護(hù)機(jī)制。
第二:因?yàn)榇谳敵鲂枰欢ǖ拇蛴r(shí)間,如果時(shí)間不足,同樣會(huì)導(dǎo)致數(shù)據(jù)不完整或者丟失。可以調(diào)用以下方法解決:
Void uart_transmit_delay(uint32_t ui32Module)
{
//
// Wait until busy bit clears to make sure UART fully transmitted last byte
//
while ( am_hal_uart_flags_get(ui32Module) & AM_HAL_UART_FR_BUSY );
}
使用例子如下列代碼:
am_util_stdio_printf("Hello World!\t\n\n");
uart_transmit_delay(ui32Module);
4、ADC轉(zhuǎn)換
通常是指一個(gè)將模擬信號(hào)轉(zhuǎn)變?yōu)?a target="_blank">數(shù)字信號(hào)。這是一個(gè),把經(jīng)過與標(biāo)準(zhǔn)量比較處理后的模擬量轉(zhuǎn)換成以二進(jìn)制數(shù)值表示的一個(gè)過程。故任何一個(gè)ADC轉(zhuǎn)換都需要一個(gè)參考模擬量作為轉(zhuǎn)換的標(biāo)準(zhǔn),比較常見的參考標(biāo)準(zhǔn)為最大的可轉(zhuǎn)換信號(hào)大小。
(1)Apollo mcu 的最大可轉(zhuǎn)換信號(hào)為3.3V,但他的參考電壓分提供四種參考類型:
-內(nèi)部參考電壓1.5V AM_HAL_ADC_REF_INT_1P5
-內(nèi)部參考電壓2V AM_HAL_ADC_REF_INT_2P0
-外部參考電壓1.5V AM_HAL_ADC_REF_EXT_1P5
-外部參考電壓2V AM_HAL_ADC_REF_EXT_2P0
這4部分,可以在代碼配置當(dāng)中選擇:
sADCConfig.ui32Reference = AM_HAL_ADC_REF_INT_2P0;
(2)Apollo2 mcu提供的三種工作模式:
1)模式0,ADC進(jìn)行料需采集,延時(shí)基本為0
2)模式1,ADC在樣本采集之間是關(guān)閉的,但是不需要重新校準(zhǔn),延時(shí)<50us
3)模式2,ADC在樣本采集之間完全斷電,需要重新校準(zhǔn)(初始化ADC),延時(shí)<600us
三種模式的主要差異,是轉(zhuǎn)換間隔,模式一適用于長時(shí)間,不間斷的進(jìn)行轉(zhuǎn)換,模式二是短間隔,中間從新啟動(dòng)ADC轉(zhuǎn)換快速。模式三轉(zhuǎn)換中間可以完全關(guān)閉ADC,但是重新啟動(dòng)時(shí)也需要重新配置校準(zhǔn)ADC。
圖2
(3)代碼配置
考慮到環(huán)境數(shù)據(jù)不會(huì)快速改變,所以這里選用模式2 。通過軟件定時(shí)器喚醒ADC進(jìn)行檢測(cè),從而達(dá)到最低功耗的效果。配置ADC代碼如下:(參考電壓 內(nèi)部2.0V 、14位精度、LPOWER2模式、掃描一次)
Void adc_config(void)
{
am_hal_adc_config_t sADCConfig;
//
// Enable the ADC power domain.
//
am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_ADC);
//
// Set up the ADC configuration parameters. These settings are reasonable
// for accurate measurements at a low sample rate.
//
sADCConfig.ui32Clock = AM_HAL_ADC_CLOCK_HFRC;
sADCConfig.ui32TriggerConfig = AM_HAL_ADC_TRIGGER_SOFT;
sADCConfig.ui32Reference = AM_HAL_ADC_REF_INT_2P0;
sADCConfig.ui32ClockMode = AM_HAL_ADC_CK_LOW_POWER;
sADCConfig.ui32PowerMode = AM_HAL_ADC_LPMODE_0;
sADCConfig.ui32Repeat = AM_HAL_ADC_NO_REPEAT;
am_hal_adc_config(&sADCConfig);
am_hal_adc_int_enable(AM_HAL_ADC_INT_CNVCMP);
// Set up an ADC slot
am_hal_adc_slot_config(0, AM_HAL_ADC_SLOT_AVG_1 |
AM_HAL_ADC_SLOT_14BIT |
AM_HAL_ADC_SLOT_CHSEL_SE0 |
AM_HAL_ADC_SLOT_ENABLE);
am_hal_adc_enable();
}
使用LPOWER2 模式的時(shí)候,需要注意,當(dāng)定時(shí)器觸發(fā)中斷的時(shí)候,time_ISR里面需要重新配置ADC,adc_config完成之后,才能進(jìn)行定時(shí)器觸發(fā),執(zhí)行順序不能顛倒:
(4)電壓十六進(jìn)制轉(zhuǎn)換成10進(jìn)制數(shù)值并顯示
由datasheet的資料顯示(圖3),ADC檢測(cè)MAX電壓為VDDH,而VDDH為3.3V。所以ADC的檢測(cè)范圍應(yīng)該為 0~3.3V ,超過3.3V只會(huì)顯示最大值3.3V。長時(shí)間檢測(cè)超過標(biāo)準(zhǔn)范圍的電壓值,可能對(duì)引腳甚至芯片造成破壞。
圖3
14位精度下,采集次數(shù)為1 的轉(zhuǎn)換代碼可以通過以下實(shí)現(xiàn):
if (ui32Status & AM_HAL_ADC_INT_CNVCMP)
{
g_ui16ADCVDD_code = am_hal_adc_fifo_pop();
//g_ui16ADCVDD_code = AM_HAL_ADC_FIFO_SAMPLE(g_ui16ADCVDD_code);
am_util_stdio_printf("g_ui16ADCVDD_code= 0x%05X\t\n",g_ui16ADCVDD_code);
fVBATT = ((float)g_ui16ADCVDD_code) * 3.3f / 1024.0f / 64.0f ; // 2^16
am_util_stdio_printf("VDD= %.3f\t\n",fVBATT);
}
但如果只是單次檢測(cè),最大值為3.298,并不能達(dá)到3.3的最大值。小數(shù)點(diǎn)后面的精度,是根據(jù)檢測(cè)的次數(shù)所決定的。(如圖4)選擇為14.6模式,采集次數(shù)選擇(圖5),次數(shù)越多,小數(shù)點(diǎn)精度越高。在使用128次采集的時(shí)候要特別注意,得到的累加值是大于FIFO通道容量的,需要進(jìn)行移位操作。
? ? ??
圖4
圖5
組網(wǎng)通信與云服務(wù)器
1、設(shè)備間組網(wǎng)與添加節(jié)點(diǎn)
針對(duì)于使用場(chǎng)景的不同,大范圍農(nóng)田可以選擇使用SX1260/ SX1278 LORA進(jìn)行組網(wǎng)。小范圍類似大棚,可以選用ZigBee或者藍(lán)牙mesh。ZigBee和藍(lán)牙m(xù)esh都有自組網(wǎng)功能,數(shù)據(jù)交換和節(jié)點(diǎn)添加相對(duì)簡單。
如果選用的LORA模塊,筆者個(gè)人建議使用應(yīng)答模式的星型網(wǎng)組網(wǎng)(圖6)。每個(gè)節(jié)點(diǎn)的地址使用Apollo2 mcu 自帶的chip ID作為參照。數(shù)據(jù)交替通過主節(jié)點(diǎn)對(duì)單個(gè)節(jié)點(diǎn)發(fā)出心跳指令,子節(jié)點(diǎn)喚醒后獲取各類數(shù)據(jù)并上傳,然后等待應(yīng)答,如果應(yīng)答超時(shí),既丟包,重復(fù)發(fā)送如果仍無法收到,將會(huì)發(fā)給備用主節(jié)點(diǎn)報(bào)錯(cuò)。
同理,如果主節(jié)點(diǎn)發(fā)送心跳指令沒有數(shù)據(jù)應(yīng)答,會(huì)進(jìn)行等待、重發(fā),長時(shí)間無應(yīng)答會(huì)將該地址節(jié)點(diǎn)踢出循環(huán)列表同時(shí)給服務(wù)器發(fā)出報(bào)錯(cuò)。
圖6
LORA通信暫不支持自組網(wǎng)功能。該功能相對(duì)簡單,主節(jié)點(diǎn)廣播發(fā)出添加節(jié)點(diǎn)模式,子節(jié)點(diǎn)待命等待主節(jié)點(diǎn)單個(gè)檢索地址。每個(gè)檢索完畢的地址,都會(huì)退出添加節(jié)點(diǎn)模式。當(dāng)主節(jié)點(diǎn)檢索完所有已知節(jié)點(diǎn)后,會(huì)二次發(fā)出新節(jié)點(diǎn)廣播。二次收到的新節(jié)點(diǎn)就主動(dòng)循環(huán)給主節(jié)點(diǎn)發(fā)送自己的地址。直到主節(jié)點(diǎn)發(fā)送應(yīng)答才結(jié)束。
2、設(shè)備與服務(wù)器通信
TCP(Transmission Control Protocol) 傳輸控制協(xié)議。TCP是主機(jī)對(duì)主機(jī)層的傳輸控制協(xié)議,提供可靠的連接服務(wù),采用三次握確認(rèn)建立一個(gè)連接。TCP標(biāo)志位有6種 標(biāo)示:
SYN(synchronous建立連接)
ACK(acknowledgement 確認(rèn))
PSH(push傳送)
FIN(finish結(jié)束)
RST(reset重置)
URG(urgent緊急)
Sequence number(順序號(hào)碼)
Acknowledge number(確認(rèn)號(hào)碼)。
流程如圖7所示:
第一次握手:客戶端發(fā)送syn包(syn=j)到服務(wù)器,并進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器確認(rèn);
第二次握手:服務(wù)器收到syn包,必須確認(rèn)客戶的SYN(ack=j+1),同時(shí)自己也發(fā)送一個(gè)SYN包(syn=k),即SYN+ACK包,此時(shí)服務(wù)器進(jìn)入SYN_RECV狀態(tài);
第三次握手:客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1),此包發(fā)送完畢,客戶端和服務(wù)器進(jìn)入ESTABLISHED狀態(tài),完成三次握手。握手完成后,兩臺(tái)主機(jī)開始傳輸數(shù)據(jù)了。
圖7
主節(jié)點(diǎn),通過轉(zhuǎn)接口模塊接入互聯(lián)網(wǎng),同時(shí)模塊設(shè)置好TCP/IP 協(xié)議進(jìn)行傳輸。對(duì)于服務(wù)端的TCP/IP 協(xié)議,筆者使用的是SocketAsyncEventArgs類進(jìn)行編寫。SocketAsyncEventArgs是.net提供的關(guān)于異步socket類。也就是高性能復(fù)用IO。對(duì)比與傳統(tǒng)socket,使用該類編寫的Server性能和吞吐量都有很大的提升。初始化代碼如下:
啟動(dòng),socket監(jiān)聽代碼:
圖9
在使用socket通信時(shí),如果長時(shí)間沒有數(shù)據(jù)交互。服務(wù)器是會(huì)直接斷連。筆者這里使用雙應(yīng)答模式。服務(wù)器向智能硬件發(fā)送心跳包,智能硬件應(yīng)答并上傳數(shù)據(jù)。如果中間因?yàn)?a href="http://www.wenjunhu.com/v/tag/1722/" target="_blank">網(wǎng)絡(luò)或者各方面原因失去連接。智能硬件會(huì)根據(jù)定時(shí)器設(shè)置主動(dòng)向服務(wù)器發(fā)送確認(rèn)連接信號(hào),如果無應(yīng)答,既斷連。智能硬件將會(huì)重新啟動(dòng)TCP協(xié)議。多次連接失敗將會(huì)發(fā)出鏈接異常警報(bào),提醒人工進(jìn)行排查。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論