【技术分享】浅谈基于Apollo2 mcu的智慧农业系统

日期:2019-07-08 作者:AG贵宾厅赌场创研社 返回列表

导语


智慧农业系统是未来农业发展的趋势所在,它能够通过传感器,实时检测作物的各种生长状况,和各类环境数据。通过联网与大数据的比对获取,并通过智能硬件提供适合作物生长的最佳温度,湿度,酸碱盐等。


在在智能农业发展的道路上,一直存在一个难关。那就是关于智能硬件供电问题。数据采集接口由智能硬件提供,面对超大范围的组网,电缆不可能布置到每一个点上。那么对于智能硬件功耗的要求就非常高。


Ambiq 拥有的亚阀值功率优化技术专利,使得其能耗比性能相当的mcu 低个5至10倍,这个技术重新定义了“低功耗”。正因为这个技术,Apollo2 mcu 也是最适合智慧农业智能硬件的主mcu 。 14位的ADC,6组 I²C接口,2组UART,等丰富的外设接口,能够保证各类传感器的需求。


智能硬件低功耗设计及各类驱动接口


1、低功耗设计


Apollo2 mcu 可以直接使用官方移植好的FreeRTOS。系统中通过以下设定,选择需要保留的FLASH,SRAM大小。同时也能够选择各类外设接口的开断电。


1562305491553038.png



Am_hal_pwrctrl_memory_enable 主要是针对flash 和 SRAM。可选大小如下;

         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主要是对外设接口的使能,可选范围:

AM_HAL_PWRCTRL_PWRONSTATUS_ioses_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    

     

如果客户没有连续采集或者传输要求,在低功耗模式下,都按最小flash和SRAM保留,接口使用完之后进行断电关闭。


2、使用spi接口点亮OLED屏


首先是开启IOM_0_2的POWER(根据个人选择那组IO决定)紧接着进行初始化SPI,初始化OLED,执行显示代码,关闭OLED,关闭SPI POWER。粗略流程如下:


1562305513538066.png

Apollo2 MCU 的SPI和I²C 是共用IOM接口,所以在配置上面没有太大的区别。需要修改的是Mode 选择(AM_HAL_IOM_SPIMODE/ AM_HAL_IOM_I2CMODE),和对应的GPIO口配置。而速率,时钟极性和相位,读写的字符长度都是在config里面进行修改。


1562305537611084.png


3、UART是常用的异步串口通信协议,传输数据是以字节形式,一位位串行输出。


(1)几个重要的位置


1) 起始位:先发出一个逻辑“0”的信号,表示传输字符开始。


2) 数据位:紧接着起始位之后。数据靠时钟进行定位,数据位的个数可以由用户决定。


3) 奇偶校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以次来校验数据传送的正确性。


4)停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。停止位不仅仅是表示传输的结束,并且提供设备之间时钟的校准。


4.png

图1


各个位的配置,在am_hal_uart_config_t中完成:

 

5.png


(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) 在使用串口需要注意两点:


第一:串口数据传输,有可能会被各类更高优先级的中断打断,所以为了保证数据的完整性,应该设置中断保护机制。


第二:因为串口输出需要一定的打印时间,如果时间不足,同样会导致数据不完整或者丢失。可以调用以下方法解决:


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转换


通常是指一个将模拟信号转变为数字信号。这是一个,把经过与标准量比较处理后的模拟量转换成以二进制数值表示的一个过程。故任何一个ADC转换都需要一个参考模拟量作为转换的标准,比较常见的参考标准为最大的可转换信号大小。


(1)Apollo mcu 的最大可转换信号为3.3V,但他的参考电压分提供四种参考类型:

 

-内部参考电压1.5V     AM_HAL_ADC_REF_INT_1P5

-内部参考电压2V       AM_HAL_ADC_REF_INT_2P0

-外部参考电压1.5V     AM_HAL_ADC_REF_EXT_1P5

-外部参考电压2V       AM_HAL_ADC_REF_EXT_2P0


这4部分,可以在代码配置当中选择:

sADCConfig.ui32Reference = AM_HAL_ADC_REF_INT_2P0;


(2)Apollo2 mcu提供的三种工作模式:


1)模式0,ADC进行料需采集,延时基本为0


2)模式1,ADC在样本采集之间是关闭的,但是不需要重新校准,延时<50us


3)模式2,ADC在样本采集之间完全断电,需要重新校准(初始化ADC),延时<600us


三种模式的主要差异,是转换间隔,模式一适用于长时间,不间断的进行转换,模式二是短间隔,中间从新启动ADC转换快速。模式三转换中间可以完全关闭ADC,但是重新启动时也需要重新配置校准ADC。


6.png

图2

 

(3)代码配置


考虑到环境数据不会快速改变,所以这里选用模式2 。通过软件定时器唤醒ADC进行检测,从而达到最低功耗的效果。配置ADC代码如下:(参考电压 内部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 模式的时候,需要注意,当定时器触发中断的时候,time_ISR里面需要重新配置ADC,adc_config完成之后,才能进行定时器触发,执行顺序不能颠倒:


1562305610280850.png


(4)电压十六进制转换成10进制数值并显示


由datasheet的资料显示(图3),ADC检测MAX电压为VDDH,而VDDH为3.3V。所以ADC的检测范围应该为 0~3.3V ,超过3.3V只会显示最大值3.3V。长时间检测超过标准范围的电压值,可能对引脚甚至芯片造成破坏。



1562305643843366.png

图3


14位精度下,采集次数为1 的转换代码可以通过以下实现:


    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);            

    }

 

但如果只是单次检测,最大值为3.298,并不能达到3.3的最大值。小数点后面的精度,是根据检测的次数所决定的。(如图4)选择为14.6模式,采集次数选择(图5),次数越多,小数点精度越高。在使用128次采集的时候要特别注意,得到的累加值是大于FIFO通道容量的,需要进行移位操作。

9.png      

图4

 

10.png


图5


组网通信与云服务器

 

1、设备间组网与添加节点

 

针对于使用场景的不同,大范围农田可以选择使用SX1260/ SX1278 LORA进行组网。小范围类似大棚,可以选用ZigBee或者蓝牙mesh。ZigBee和蓝牙mesh都有自组网功能,数据交换和节点添加相对简单。

 

如果选用的LORA模块,笔者个人建议使用应答模式的星型网组网(图6)。每个节点的地址使用Apollo2 mcu 自带的chip ID作为参照。数据交替通过主节点对单个节点发出心跳指令,子节点唤醒后获取各类数据并上传,然后等待应答,如果应答超时,既丢包,重复发送如果仍无法收到,将会发给备用主节点报错。


同理,如果主节点发送心跳指令没有数据应答,会进行等待、重发,长时间无应答会将该地址节点踢出循环列表同时给服务器发出报错。


1562305694534497.png

图6

 

LORA通信暂不支持自组网功能。该功能相对简单,主节点广播发出添加节点模式,子节点待命等待主节点单个检索地址。每个检索完毕的地址,都会退出添加节点模式。当主节点检索完所有已知节点后,会二次发出新节点广播。二次收到的新节点就主动循环给主节点发送自己的地址。直到主节点发送应答才结束。


2、设备与服务器通信


TCP(Transmission Control Protocol) 传输控制协议。TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握确认建立一个连接。TCP标志位有6种 标示:


SYN(synchronous建立连接)

ACK(acknowledgement 确认)

PSH(push传送)

FIN(finish结束)

RST(reset重置)

URG(urgent紧急)

Sequence number(顺序号码)

Acknowledge number(确认号码)。

 

流程如图7所示:


第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;


第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;


第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。握手完成后,两台主机开始传输数据了。


12.png

图7

 

主节点,通过转接口模块接入互联网,同时模块设置好TCP/IP 协议进行传输。对于服务端的TCP/IP 协议,笔者使用的是SocketAsyncEventArgs类进行编写。SocketAsyncEventArgs是.net提供的关于异步socket类。也就是高性能复用IO。对比与传统socket,使用该类编写的Server性能和吞吐量都有很大的提升。初始化代码如下:


13.png


启动,socket监听代码:


14.png

 图9


在使用socket通信时,如果长时间没有数据交互。服务器是会直接断连。笔者这里使用双应答模式。服务器向智能硬件发送心跳包,智能硬件应答并上传数据。如果中间因为网络或者各方面原因失去连接。智能硬件会根据定时器设置主动向服务器发送确认连接信号,如果无应答,既断连。智能硬件将会重新启动TCP协议。多次连接失败将会发出链接异常警报,提醒人工进行排查。

返回列表