收藏官网首页
查看: 1020|回复: 0

【机友分享】基于机智云平台+STM32的温湿度和光照强度获取

593

主题

632

帖子

3万

积分

版主

Rank: 7Rank: 7Rank: 7

积分
32126
 楼主| 发表于 2023-8-29 16:00:33 | 显示全部楼层 |阅读模式
免费使用STM32、APP自动代码生成工具
本帖最后由 Kara 于 2023-8-29 16:03 编辑

基于机智云物联网云平台+STM32的温湿度和光照强度获取

本文的开发项目由开发者发布在CSDN博客(F l e)分享,该设计采用esp8266烧写机智云固件。并且esp8266STM32进行通信,则stm32可以通过esp8266与机智云服务器进行数据交互,而机智云服务器可以和机智云app进行数据交互。为此,实现stm32通过esp8266可以与机智云app进行数据交互。
stm32作为MCU与传感器进行数据交互,得到传感器采集的数值,所以完成的是传感器和app的数据交互。由于本次实验增加了对光照强度的采集,所以又增加了一个三色RGB灯外设。通过机智云app可以调节RGB灯的光强,以此来模拟光照强度的变化。整个设计的传感器数据流向如下图所示:
1.png

另外,对于用机智云app调节RGB灯的光强的数据流向如下图:
2.png


一、传感器的测试
本次设计利用STM32CubeMX进行开发,代码设计过程分模块进行,分别编写测试用例验证各模块的功能,包括oled模块、按键模块、dht11模块、光敏电阻模块、rgb模块。
1oled模块
①接线:
3.png

②代码编写:
本次设计中oled采用硬件SPI2驱动,STM32CubeMX的设计如下图:
4.png

5.png

6.png

利用STM32CubeMX生成的SPI主要代码如上所示。在生成的SPI代码上进一步编写oled.coled.h文件。
oled.c封装了以下的函数:
7.png

测试函数:
  1. int main(void)
  2. {
  3.     HAL_Init();
  4.     SystemClock_Config();
  5.     MX_GPIO_Init();
  6.     MX_SPI2_Init();
  7.     OLED_Init();
  8.     OLED_ShowString(0, 0, "wait for set esp8266,press key1 to set esp8266 with AIRLINK_MODE");
  9. }
复制代码

③测试用例实验结果:
8.png

由上图可知,oled模块的显示函数能够正确显示。
2、按键模块
①接线:
9.png

KEY_R0接地,KEY_L0KEY_L1可以用于检测按键状态。
对应的引脚为:
10.png

②代码编写:
STM32CubeMX设计如下:
11.png

PC11设置为输出模式,PC10PB5设置为输入模式。
Key.c封装了以下函数:
  1. void key_init(void)
  2. {
  3.    HAL_GPIO_WritePin(KEY_COM_GND_GPIO_Port,KEY_COM_GND_Pin,GPIO_PIN_RESET);
  4. }

  5. void Test_key(void)
  6. {
  7.    if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)==GPIO_PIN_SET)
  8.    {
  9.       OLED_ShowString(0,0,"key1_up");
  10.    }
  11.    else
  12.    {
  13.       OLED_ShowString(0,0,"key1_down");
  14.    }
  15.    if(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin)==GPIO_PIN_SET)
  16.    {
  17.       OLED_ShowString(0,10,"key2_up");
  18.    }
  19.    else
  20.    {
  21.       OLED_ShowString(0,10,"key2_down");
  22.    }
  23.    OLED_Refresh_Gram();
  24. }

  25. 测试用例:

  26. int main(void)
  27. {
  28.    MX_GPIO_Init();
  29.    key_init();
  30.    while(1)
  31.    {
  32.       Test_key();
  33.    }
  34. }
复制代码

③测试用例实验结果:
12.png

由图中可以看出,按键一被按下时显示key1_downkey2_up与理论相符。

3dht11模块
①接线:
13.png

②代码编写:
由于dht11的数据引脚有时需要作为输入,有时需要作为输出,所以不在STM32CubeMX设置。
Dht11.c主要封装了以下函数:
14.png

这里的us延时并没有使用定时器来产生,而是用系统时钟来实现:
  1. void delay_us(uint32_t us)
  2. {
  3.     uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
  4.     while (delay--)
  5.    {
  6.       ;
  7.    }
  8. }
复制代码

测试用例:
  1. int main(void)
  2. {
  3.   HAL_Init();
  4.   SystemClock_Config();
  5.   MX_GPIO_Init();
  6.   MX_SPI2_Init();
  7.   OLED_Init();
  8.   while(1)
  9.   {
  10.       Test_dht11();
  11.    }

  12. void Test_dht11(void)
  13. {
  14.    char txt[16];
  15.    while(1)
  16.    {
  17.       DHT11_Read_Data(&humidity_integer,&humidity_decimal,&temperature_integer,&temperature_decimal);
  18.       sprintf(txt, "temp:%d.%d", temperature_integer,temperature_decimal);
  19.       OLED_ShowString(0,0,txt);
  20.       sprintf(txt, "humi:%d.%d", humidity_integer,humidity_decimal);
  21.       OLED_ShowString(0,10,txt);
  22.       OLED_Refresh_Gram();
  23.    }
  24. }
复制代码

③测试用例实验结果:
15.png

由上图可以看出,温度为23.3℃,湿度为53.0%,湿度的小数为0,与理论相符。

4、光敏电阻模块
①接线:
16.png

②代码编写:
STM32CubeMX设置ADC1IN0如下:
17.png

Stm32Rct6ADC12位的,这里没有更改的选项,则ADC读取的最大值是2^12=4096
这里采样时间Sampling Time选择1.5个周期。ADC采样时间 = (采样周期+12.5周期)* 1/ADC时钟频率,这里ADC采样时间=1.5+12.5*1/12 = 1.167us
light_check5506.c主要封装以下函数:
  1. void light_check5506_init(void)
  2. {
  3.    HAL_ADCEx_Calibration_Start(&hadc1);
  4.    HAL_Delay(200);
  5. }

  6. uint32_t light_check5506_getinitvalue(void)
  7. {
  8.    HAL_ADC_Start(&hadc1);
  9.   HAL_ADC_PollForConversion(&hadc1,50);//ÏÞʱ50ms
  10.    return HAL_ADC_GetValue(&hadc1);
  11. }

  12. uint32_t light_check5506_get0to100value(void)
  13. {
  14.    //°µ-->ÁÁ£º0~100
  15.    uint32_t value;
  16.    value=light_check5506_getinitvalue();
  17.    value=4096-value;//ÔʼÊý¾ÝÊÇÔ½°µÊý¾ÝÔ½´ó
  18.    value=(value*100/4096);//»¯Îª0~100µÄÊý,±ØÐëÏȳËÒÔ100ÔÙ³ý£¬ÒòΪȫ²¿ÊÇÕûÊý
  19.    return value;
  20. }

  21. void Test_5506(void)
  22. {
  23.    uint32_t value;
  24.    char txt[16];
  25.    while(1)
  26.    {
  27.       value=light_check5506_get0to100value();
  28.       sprintf(txt, "light(0-100):%d", value);  
  29.       OLED_ShowString(0,0,txt);
  30.       OLED_Refresh_Gram();
  31.    }
  32. }
复制代码

测试用例:
  1. main(void)
  2. {
  3.     HAL_Init();
  4.     SystemClock_Config();
  5.     MX_GPIO_Init();
  6.     MX_SPI2_Init();
  7.     MX_ADC1_Init();
  8.     OLED_Init();
  9.     light_check5506_init();
  10.     while(1)`
  11.     {
  12.         Test_5506();
  13.     }
  14. }
复制代码

③测试用例实验结果:
18.png

ADC读取的值归一化到0~100后光照强度的数值为18
5rgb模块
①接线:
19.png

②代码编写:
STM32CubeMX设置TIM8的三个通道如下:
20.png

计数周期Counter Period设置为255,这是为了便于查找RGB颜色表进行颜色设置,占空比Pulse设置为50%
Rgb.c封装了以下函数:
  1. void rgb_init(void)
  2. {
  3.    HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_1);
  4.    HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_2);
  5.    HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_3);
  6. }
  7. void Test_rgb(void)
  8. {
  9.     rgb_setpwm(10.0,100.0,200.0);
  10. }
  11. void rgb_setpwm(uint8_t pwm_r,uint8_t pwm_g,uint8_t pwm_b)
  12. {
  13.    __HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_1,pwm_r);
  14.    __HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_2,pwm_g);
  15.    __HAL_TIM_SET_COMPARE(&htim8, TIM_CHANNEL_3,pwm_b);

  16. }
复制代码
测试用例:
  1. main(void)
  2. {
  3.     HAL_Init();
  4.     SystemClock_Config();
  5.     MX_GPIO_Init();
  6.     MX_SPI2_Init();
  7.     MX_TIM8_Init();
  8.     rgb_init();
  9.     OLED_Init();
  10.     while(1)`
  11.     {
  12.        Test_rgb();   
  13. }
  14. }
复制代码

③测试
用例实验结果:
21.png

由上图可知RGB灯被点亮。

二、通过esp8266实现数据上传和数据回传
在进行数据上传与数据回传之前,首先进行用于打印数据的串口1的设置和用于stm32esp8266通信的串口2
串口1
22.png

22-1.png

串口1设置PA9PA10分别作为TXRX,波特率为115200,不使能中断。
串口2
23.png

24.png

25.png

串口2设置PA2PA3分别作为TXRX,波特率为9600,使能中断。


1、数据上传------温湿度数据、关照强度数据
①主要代码
  1. void userHandle(void)
  2. {
  3.     DHT11_Read_Data( & humidity_integer, & humidity_decimal, & temperature_integer, & temperature_decimal);
  4.     currentDataPoint.valuehumidity = humidity_integer;
  5.     currentDataPoint.valueLight_intensity = light_check5506_get0to100value();
  6.     currentDataPoint.valueDHT11 = temperature_integer + 0.1 * temperature_decimal;
  7. }
复制代码

userHandle(void)中添加温湿度数据的采集以及光照强度的读取。userHandle()main函数中while循环的内容。
26.png

由上图可以看出,userHandle对于用户来说是最顶层的,数据在userHandle中采集,依次经过gizCheckReport判断是否上报当前状态的数据、gizDataPoints2ReportData完成用户区数据到上报型数据的转换、gizReportData将转换后的上报数据通过串口发送给 WiFi 模块。
②设计结果:
首先确保esp8266和手机都已经连接到同一个网络,这里用电脑作为这个网络。
27.png

由上图可知手机和esp8266已经连接上了电脑。机智云app连接上esp8266后得到上传来的数据:
28.png

29.png

Oled上的数据是stm32收集的,右边图的数据是机智云app通过esp8266收到的,两者一致,说明数据交互是正确的。

2、数据回传------RGB三数值
①主要代码
  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.     # if MODULE_TYPE
  8.     gprsInfo_t * gprsInfoData = (gprsInfo_t *)gizdata;
  9.     # else
  10.     moduleInfo_t * ptModuleInfo = (moduleInfo_t *) gizdata;
  11.     # endif
  12.     if ((NULL == info) || (NULL == gizdata))
  13.     {
  14.         return -1;
  15.     }
  16.     for (i=0; i < info->num; i++)
  17.     {
  18.         switch(info->event[i])
  19.         {
  20.             case EVENT_LED_R:
  21.                 currentDataPoint.valueLED_R = dataPointPtr->valueLED_R;
  22.                 GIZWITS_LOG("Evt:EVENT_LED_R %d\n", currentDataPoint.valueLED_R);
  23.                 rgb_setpwm(currentDataPoint.valueLED_R, currentDataPoint.valueLED_G, currentDataPoint.valueLED_B);
  24.                 break;
  25.             case EVENT_LED_G:
  26.                 currentDataPoint.valueLED_G = dataPointPtr->valueLED_G;
  27.                 GIZWITS_LOG("Evt:EVENT_LED_G %d\n", currentDataPoint.valueLED_G);
  28.                 rgb_setpwm(currentDataPoint.valueLED_R, currentDataPoint.valueLED_G, currentDataPoint.valueLED_B);
  29.                 break;
  30.             case EVENT_LED_B:
  31.                 currentDataPoint.valueLED_B = dataPointPtr->valueLED_B;
  32.                 GIZWITS_LOG("Evt:EVENT_LED_B %d\n", currentDataPoint.valueLED_B);
  33.                 rgb_setpwm(currentDataPoint.valueLED_R, currentDataPoint.valueLED_G, currentDataPoint.valueLED_B);
  34.                 break;
  35.         }
  36.     }
  37. }
复制代码

gizwitsEventProcess中的EVENT_LED_REVENT_LED_GEVENT_LED_B分别添加对对RGB三个PWM的赋值,赋值之后使其立即生效。
30.png

protocolIssuedProcessgizwitsHandle 调用,接收来自云端或 app端下发的相关协议数据。ACTION_CONTROL_DEVICE进行“控制型协议”的相关处理,gizDataPoint2Event根据协议生成“控制型事件”,并进行相应数据类型的转化转换,gizwitsEventProcess是位于数据回传过程中的最底层,根据已生成的“控制型事件”进行相应处理。
②设计结果:
首先确保esp8266和手机都已经连接到同一个网络,这里用电脑作为这个网络。
31.png

由上图可知手机和esp8266已经连接上了电脑。机智云app设置RGB三个PWM数值,得到oled上的数据为:
32.png

33.png

由上图可知,图中为机智云app设置的三个PWM数值,左图再oled上为同样的数值,说明数据交互正确。

三、总结与体会
①通过这次设计接触了STM32CubeMX这个软件,相比与之前的标准库,STM32CubeMX生成的Hal库不仅封装度更高,而且更有利于开发者进行快速开发,而且在本次实验中机智云生成的代码也是基于Hal库的,这说明以后对于stm32来说,会越来越趋向于Hal开发。
②官网永远是对解决问题的最好地方,机智云的官方文档给了我极大帮助。
esp8266的烧录对于供电要求十分苛刻,导致多次烧录都失败了,所以在制pcb的时候加上了esp8266的烧录接口,以及GPIO的接地开关,还有复位电路。PCB扩展板图如下
34.png

stmRct6板的供电十分差,由于刚开始只是接了ST-LINK进行供电,导致dht11oled一起使用时dht11VCC口只有2.6V,进而使得dht11通信一直不成功,这也说明了一切先从电源管理开始,确保供电没问题再查找软件问题。

PCB工程、代码获取:https://gitee.com/guoxianda/intelligent-cloud-platform




您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

加入Q群 返回顶部

版权与免责声明 © 2006-2023 Gizwits IoT Technology Co., Ltd. ( 粤ICP备11090211号 )

快速回复 返回顶部 返回列表