返回列表 发新帖我要提问本帖赏金: 80.00元(功能说明)

[资料干货] 超声波传感器&烟雾传感器接入机智云平台实现远程监控

[复制链接]
1482|4
 楼主| dql2015 发表于 2023-1-9 19:31 | 显示全部楼层 |阅读模式
#申请原创#
@21小跑堂
1、目的
最近在学习各个厂家的物联网云平台,体验各个厂家的物联网云平台接入方案和设备端开发过程。本帖以超声波传感器和烟雾传感器数据接入机智云平台为例进行分析,实现在手机APP上监测超声波传感器测距数据和烟雾传感器数据2个参数。

2、开发过程
通过官方文档学习了机智云平台功能和设备接入原理后,只需要3步即可将设备接入云平台:MCU端开发,云端配置,设备调试。
硬件模块:机智云gokit开发板(扩展板带有esp8266无线WIFI模块、底板为STM32F103C8T6)。

stm32端开发
stm32端工作是编写ADC采集程序读取烟雾传感器数据,编写超声波传感器驱动程序读取超声波传感器测距数据,与云端交互的逻辑代码。
stm32cubemx配置如下:



云端配置

在机智云开发者中心创建一个产品,然后编辑数据点。数据点是设备产品的功能的抽象,用于描述产品功能及其参数。创建数据点后,设备与云端通讯的数据格式即可确定,设备、机智云可以相互识别设备与机智云互联互通的数据。


本次项目需要把stm32获取的烟雾数据、测距数据2个参数上传到服务器,这2个参数为数值类型,对于云端来讲只读,数据点可从excel导入或者导入机智云提供的范例后再修改。

自动生成MCU SDK
自动生成的MCUSDK代码实现了机智云通信协议的解析与封包、传感器数据与通信数据的转换逻辑,并封装成了简单的 API。自动生成的代码包基于keil软件,在自动生成的代码包里面添加自己需要的传感器驱动后目录结构如下:

当设备收到云端或 APP 端的数据后,程序会将数据转换成对应的事件并通知到应用层,开发者只需要在对应的事件处理逻辑中添加传感器的控制函数,便可完成产品的开发。

MCU通过烧录好GAgent固件的WIFI/GPRS模组与服务器交互的逻辑,可以看出整个过程全部被封装,留给用户的接口很简单,对于资源足够的MCU,用户只需要在MCU实现3个接口函数即串口发送、串口中断接收、定时器1ms中断即可通过无线通信模组联网。而数据点相关、云端交互相关全部由MCU代码自动生成工具生成,只需在Gizwits_product.c文件填充业务逻辑。前面提到的三个接口是串口收发、定时器1ms中断,本次stm32配置了串口2(根据机智云的协议,串口参数为:波特率9600、无校验、停止位1)作为与WIFI模组通信的接口;定时器10为1ms中断,作为MCU与WIFI模组的“心跳”信号;下面就是如何在具体位置填充这3个接口:

串口接收数据回调写入环形缓存:
  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle)  
  2. {  
  3.     if(UartHandle->Instance == USART2)  
  4.     {  
  5.                                 gizPutData((uint8_t *)&aRxBuffer, 1);

  6.         HAL_UART_Receive_IT(&huart2, (uint8_t *)&aRxBuffer, 1);//开启下一次接收中断  
  7.     }  
  8. }  

串口发送数据写入环形缓存接口接口:
  1. int32_t uartWrite(uint8_t *buf, uint32_t len)
  2. {
  3.                 uint8_t crc[1] = {0x55};
  4.     uint32_t i = 0;
  5.        
  6.     if(NULL == buf)
  7.     {
  8.         return -1;
  9.     }

  10.     for(i=0; i<len; i++)
  11.     {
  12.         HAL_UART_Transmit_IT(&huart2, (uint8_t *)&buf[i], 1);
  13.                                 while (huart2.gState != HAL_UART_STATE_READY);//Loop until the end of transmission

  14.         if(i >=2 && buf[i] == 0xFF)
  15.         {
  16.                                                 HAL_UART_Transmit_IT(&huart2, (uint8_t *)&crc, 1);
  17.                                                 while (huart2.gState != HAL_UART_STATE_READY);//Loop until the end of transmission
  18.         }
  19.     }

  20. #ifdef PROTOCOL_DEBUG
  21.     GIZWITS_LOG("MCU2WiFi[%4d:%4d]: ", gizGetTimerCount(), len);
  22.     for(i=0; i<len; i++)
  23.     {
  24.         GIZWITS_LOG("%02x ", buf[i]);

  25.         if(i >=2 && buf[i] == 0xFF)
  26.         {
  27.             GIZWITS_LOG("%02x ", 0x55);
  28.         }
  29.     }
  30.     GIZWITS_LOG("\n");
  31. #endif
  32.                
  33.                 return len;
  34. }  
用户驱动初始化接口:
  1. void userInit(void)
  2. {
  3.     memset((uint8_t*)¤tDataPoint, 0, sizeof(dataPoint_t));
  4.     delay_init(); // 延时 初始化
  5.                 rgbLedInit(); // RGB LED 初始化
  6.                 dht11Init(); // 温湿度初始化
  7.                 irInit(); // 红外初始化
  8.     /** Warning !!! DataPoint Variables Init , Must Within The Data Range **/
  9.     /*
  10.       currentDataPoint.valueLED_OnOff = ;
  11.       currentDataPoint.valueLED_Color = ;
  12.       currentDataPoint.valueLED_R = ;
  13.       currentDataPoint.valueLED_G = ;
  14.       currentDataPoint.valueLED_B = ;
  15.       currentDataPoint.valueInfrared = ;
  16.       currentDataPoint.valueTemperature = ;
  17.       currentDataPoint.valueHumidity = ;
  18.       currentDataPoint.valueDistance = ;
  19.       currentDataPoint.valueAirQuality = ;
  20.       currentDataPoint.valueAlert_1 = ;
  21.       currentDataPoint.valueAlert_2 = ;
  22.       currentDataPoint.valueFault_LED = ;
  23.       currentDataPoint.valueFault_TemHum = ;
  24.       currentDataPoint.valueFault_IR = ;
  25.     */

  26. }
数据上报到云平台逻辑代码:
  1. void userHandle(void)
  2. {
  3.         uint8_t ret = 0;
  4.         static uint32_t thLastTimer = 0;
  5.         static uint32_t thLastTimer2 = 0;
  6.        
  7.         if((gizGetTimerCount() - thLastTimer) > 2000)
  8.         {
  9.                 ret = dht11Read((uint8_t *)¤tDataPoint.valueTemperature,(uint8_t *)¤tDataPoint.valueHumidity);
  10.                 if(ret != 0)
  11.                 {
  12.                         GIZWITS_LOG("Failed to read DHT11 [%d] \n", ret);
  13.                 }
  14.                 //printf("Temp=%d Hum=%d\r\n",currentDataPoint.valueTemperature,currentDataPoint.valueHumidity);
  15.                 thLastTimer = gizGetTimerCount();
  16.         }
  17.        
  18.         if((gizGetTimerCount() - thLastTimer2) > 200)
  19.         {
  20.                 currentDataPoint.valueInfrared = irHandle();
  21.                
  22.                 if(HAL_TIM_Base_Start(&htim4)!=HAL_OK)
  23.                 {
  24.                         printf("HAL_TIM_Base_Start Error!\r\n");
  25.                 }
  26.                 HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,GPIO_PIN_SET);
  27.                 delay_us(10);
  28.                 HAL_GPIO_WritePin(Trig_GPIO_Port,Trig_Pin,GPIO_PIN_RESET);
  29.                        
  30.                 while(!HAL_GPIO_ReadPin(Echo_GPIO_Port, Echo_Pin));
  31.                 v1=htim4.Instance->CNT;
  32.                 while(HAL_GPIO_ReadPin(Echo_GPIO_Port, Echo_Pin));
  33.                 v2=htim4.Instance->CNT;
  34.                 htim4.Instance->CNT=0;
  35.                 if(HAL_TIM_Base_Stop(&htim4)!=HAL_OK)
  36.                 {
  37.                         printf("HAL_TIM_Base_Stop Error!\r\n");
  38.                 }
  39.                 printf("v2=%d v1=%d\r\n",v2,v1);
  40.                 Distance=(v2-v1)*17/(float)1000;       
  41.                
  42.                 AirQuality = ((float)((float)ConvertedValue * VREF)/MAX_CONVERTED_VALUE);
  43.                 printf("distance=%0.1fcm AirQuality=%d\r\n",Distance,AirQuality);

  44.                 thLastTimer2 = gizGetTimerCount();
  45.                
  46.                 currentDataPoint.valueDistance = Distance;
  47.                 currentDataPoint.valueAirQuality = AirQuality;
  48.         }
  49. /*
  50.     currentDataPoint.valueInfrared = ;//Add Sensor Data Collection
  51.     currentDataPoint.valueTemperature = ;//Add Sensor Data Collection
  52.     currentDataPoint.valueHumidity = ;//Add Sensor Data Collection
  53.     currentDataPoint.valueDistance = ;//Add Sensor Data Collection
  54.     currentDataPoint.valueAirQuality = ;//Add Sensor Data Collection
  55.     currentDataPoint.valueAlert_1 = ;//Add Sensor Data Collection
  56.     currentDataPoint.valueAlert_2 = ;//Add Sensor Data Collection
  57.     currentDataPoint.valueFault_LED = ;//Add Sensor Data Collection
  58.     currentDataPoint.valueFault_TemHum = ;//Add Sensor Data Collection
  59.     currentDataPoint.valueFault_IR = ;//Add Sensor Data Collection

  60.     */
  61.    
  62. }
云平台下发控制接口代码:
  1. int8_t gizwitsEventProcess(eventInfo_t *info, uint8_t *gizdata, uint32_t len)
  2. {
  3.   uint8_t i = 0;
  4.   dataPoint_t *dataPointPtr = (dataPoint_t *)gizdata;
  5.   moduleStatusInfo_t *wifiData = (moduleStatusInfo_t *)gizdata;
  6.   protocolTime_t *ptime = (protocolTime_t *)gizdata;
  7.   
  8. #if MODULE_TYPE
  9.   gprsInfo_t *gprsInfoData = (gprsInfo_t *)gizdata;
  10. #else
  11.   moduleInfo_t *ptModuleInfo = (moduleInfo_t *)gizdata;
  12. #endif

  13.   if((NULL == info) || (NULL == gizdata))
  14.   {
  15.     return -1;
  16.   }

  17.   for(i=0; i<info->num; i++)
  18.   {
  19.     switch(info->event[i])
  20.     {
  21.       case EVENT_LED_OnOff:
  22.         currentDataPoint.valueLED_OnOff = dataPointPtr->valueLED_OnOff;
  23.         GIZWITS_LOG("Evt: EVENT_LED_OnOff %d \n", currentDataPoint.valueLED_OnOff);
  24.         if(0x01 == currentDataPoint.valueLED_OnOff)
  25.         {
  26.           //user handle
  27.                                         ledRgbControl(254, 0, 0);
  28.         }
  29.         else
  30.         {
  31.           //user handle
  32.                                         ledRgbControl(0, 0, 0);                                       
  33.         }
  34.         break;

  35.       case EVENT_LED_Color:
  36.         currentDataPoint.valueLED_Color = dataPointPtr->valueLED_Color;
  37.         GIZWITS_LOG("Evt: EVENT_LED_Color %d\n", currentDataPoint.valueLED_Color);
  38.         switch(currentDataPoint.valueLED_Color)
  39.         {
  40.           case LED_Color_VALUE0:
  41.             //user handle
  42.                                          ledRgbControl(currentDataPoint.valueLED_R, currentDataPoint.valueLED_G,currentDataPoint.valueLED_B);
  43.             break;
  44.           case LED_Color_VALUE1:
  45.             ledRgbControl(254, 254, 0);
  46.             break;
  47.           case LED_Color_VALUE2:
  48.             ledRgbControl(254, 0, 70);
  49.             break;
  50.           case LED_Color_VALUE3:
  51.            ledRgbControl(238, 30, 30);
  52.             break;
  53.           default:
  54.             break;
  55.         }
  56.         break;

  57.       case EVENT_LED_R:
  58.         currentDataPoint.valueLED_R = dataPointPtr->valueLED_R;
  59.         GIZWITS_LOG("Evt:EVENT_LED_R %d\n",currentDataPoint.valueLED_R);
  60.         //user handle
  61.                         ledRgbControl(currentDataPoint.valueLED_R, currentDataPoint.valueLED_G,currentDataPoint.valueLED_B);
  62.         break;
  63.       case EVENT_LED_G:
  64.         currentDataPoint.valueLED_G = dataPointPtr->valueLED_G;
  65.         GIZWITS_LOG("Evt:EVENT_LED_G %d\n",currentDataPoint.valueLED_G);
  66.         //user handle
  67.                         ledRgbControl(currentDataPoint.valueLED_R, currentDataPoint.valueLED_G,currentDataPoint.valueLED_B);
  68.         break;
  69.       case EVENT_LED_B:
  70.         currentDataPoint.valueLED_B = dataPointPtr->valueLED_B;
  71.         GIZWITS_LOG("Evt:EVENT_LED_B %d\n",currentDataPoint.valueLED_B);
  72.         //user handle
  73.                         ledRgbControl(currentDataPoint.valueLED_R, currentDataPoint.valueLED_G,currentDataPoint.valueLED_B);
  74.         break;


  75.       case WIFI_SOFTAP:
  76.         break;
  77.       case WIFI_AIRLINK:
  78.         break;
  79.       case WIFI_STATION:
  80.         break;
  81.       case WIFI_CON_ROUTER:
  82.                                 ledRgbControl(0, 0, 0);
  83.         break;
  84.       case WIFI_DISCON_ROUTER:
  85.                                 ledRgbControl(250, 0, 0);
  86.         break;
  87.       case WIFI_CON_M2M:
  88.                                 ledRgbControl(0, 0, 0);
  89.         break;
  90.       case WIFI_DISCON_M2M:
  91.                                 ledRgbControl(0, 0, 250);
  92.         break;
  93.       case WIFI_RSSI:
  94.         GIZWITS_LOG("RSSI %d\n", wifiData->rssi);
  95.         break;
  96.       case TRANSPARENT_DATA:
  97.         GIZWITS_LOG("TRANSPARENT_DATA \n");
  98.         //user handle , Fetch data from [data] , size is [len]
  99.         break;
  100.       case WIFI_NTP:
  101.         GIZWITS_LOG("WIFI_NTP : [%d-%d-%d %02d:%02d:%02d][%d] \n",ptime->year,ptime->month,ptime->day,ptime->hour,ptime->minute,ptime->second,ptime->ntp);
  102.         break;
  103.       case MODULE_INFO:
  104.             GIZWITS_LOG("MODULE INFO ...\n");
  105.       #if MODULE_TYPE
  106.             GIZWITS_LOG("GPRS MODULE ...\n");
  107.             //Format By gprsInfo_t
  108.       #else
  109.             GIZWITS_LOG("WIF MODULE ...\n");
  110.             //Format By moduleInfo_t
  111.             GIZWITS_LOG("moduleType : [%d] \n",ptModuleInfo->moduleType);
  112.       #endif
  113.     break;
  114.       default:
  115.         break;
  116.     }
  117.   }

  118.   return 0;
  119. }
实现效果:
控制LED显示蓝色


控制LED显示红色


控制LED显示绿色


超声波和烟雾传感器数据采集上报效果:



总结:
机智云平台的接入还是十分简单的,基本上可以通过图形化简单的进行配置一下参数,然后生成代码包,基于代码包二次开发十分简单方便,只需要看懂从哪个入口填充上行或者下行处理代码就行;对于个人用户,目前只体验了传感器类数据接入开发,通过官网资料来看,目前还没看到音视频类设备接入方法,如果能够体验音视频类产品接入开发,可玩性增加不少。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

打赏榜单

21小跑堂 打赏了 80.00 元 2023-01-12
理由:恭喜通过原创审!期待您更多的原创作品~

评论

通过机智云,轻松部署建议的云平台,并可将单片机采集的传感器数据进行上传,同时手机APP进行显示。比较不错的主题,但是作者写作方向偏重于效果展示,对于实现过程和代码解释篇幅较短,希望后续可以稍加改进,获得更高的打赏。  发表于 2023-1-12 10:38
王栋春 发表于 2023-1-9 22:17 | 显示全部楼层
会者不难难者不会呀,没看懂呀。           
binoo7 发表于 2023-1-10 08:17 | 显示全部楼层
这个做学问可以,实际用,没有谁会这么搞,赔的裤衩都没有了
 楼主| dql2015 发表于 2023-1-10 11:15 | 显示全部楼层
binoo7 发表于 2023-1-10 08:17
这个做学问可以,实际用,没有谁会这么搞,赔的裤衩都没有了 ...

小微企业还是很多用的,自己部署服务器成本太高
您需要登录后才可以回帖 登录 | 注册

本版积分规则

104

主题

384

帖子

8

粉丝
快速回复 在线客服 返回列表 返回顶部