• 利用RVB2601开发板的温湿度采样


    一、项目背景

       通过农业物联网产品为6000万大棚种植户节省30%人工,提升20%收益。中国是世界上最大的大棚种植国家,但种植方式还停留在纯人工的传统模式上,尤其控温类操作,极其耗时。随着大棚种植规模的扩大,高频耗时的控温类操作,已经成为农户扩大生产的最大阻力。如果有智能云端温湿度监控系统,帮助农户节省人工,精准控温,让作物生长周期缩短,坐果率提升,作物品相提升,年收益提升

    二、作品简介

    本系统温湿度采集使用DHT11模块,实时读取温湿度数据。然后将数据先OLED屏幕上显示,并将数据上传到阿里云物联网平台。DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度±5%RH, 温度±2℃,量程湿度5~95%RH, 温度-20~+60℃。连接WIFI模块使用联盛德W800芯片,W800芯片采用40纳米工艺,芯片封装尺寸4mm*4mm,业界最小。芯片采用平头哥玄铁804(32位)CPU内核,最高主频达到240MHz;内置TEE安全引擎,为芯片提供了高性能的核心处理能力及安全可信的执行环境;内置DSP与浮点运算单元,支持2.4G IEEE802.11b/g/n Wi-Fi 标准协议,支持 BT/BLE4.2 蓝牙协议;支持丰富的MCU数字接口。

    三、系统框图

     四各部分功能说明和解析

    1,DHT11温度采集模块。

    DHT11 的技术参数如下:

    • 工作电压范围:3.3V-5.5V
    • 工作电流 :平均 0.5mA
    • 输出:单总线数字信号
    • 测量范围:湿度 20~90%RH,温度 0~50℃
    • 精度 :湿度±5%,温度±2℃
    • 分辨率 :湿度 1%,温度 1℃
      DHT11 的管脚排列如图 34.1.1 所示:

     程序代码:

    1. #include <aos/aos.h>
    2. #include "aos/cli.h"
    3. #include "dht11.h"
    4. #ifndef TAG
    5. #define TAG "app"
    6. #endif
    7. uint8_t H_inte = 0;
    8. uint8_t H_frac = 0;
    9. uint8_t T_inte = 0;
    10. uint8_t T_frac = 0;
    11. static csi_gpio_pin_t pin_dht11;
    12. void delay_ms(unsigned char n)
    13. {
    14. udelay(n * 1000);
    15. }
    16. void delay_us(unsigned char n)
    17. {
    18. udelay(n);
    19. }
    20. /*DHT11复位和检测响应函数,返回值:1-检测到响应信号;0-未检测到响应信号*/
    21. u8 DHT11RstAndCheck(void)
    22. {
    23. u8 timer = 0;
    24. csi_gpio_pin_dir(&pin_dht11, GPIO_DIRECTION_OUTPUT);
    25. csi_gpio_pin_write(&pin_dht11, GPIO_PIN_LOW); //输出低电平
    26. delay_ms(20); //拉低至少18ms
    27. csi_gpio_pin_write(&pin_dht11, GPIO_PIN_HIGH); //输出高电平
    28. delay_us(30); //拉高20~40us
    29. csi_gpio_pin_dir(&pin_dht11, GPIO_DIRECTION_INPUT);
    30. while (!csi_gpio_pin_read(&pin_dht11)) //等待总线拉低,DHT11会拉低40~80us作为响应信号
    31. {
    32. timer++; //总线拉低时计数
    33. delay_us(10);
    34. }
    35. if (timer>10 || timer<2) //判断响应时间
    36. {
    37. return 0;
    38. }
    39. timer = 0;
    40. while (csi_gpio_pin_read(&pin_dht11)) //等待DHT11释放总线,持续时间40~80us
    41. {
    42. timer++; //总线拉高时计数
    43. delay_us(10);
    44. }
    45. if (timer>10 || timer<2) //检测响应信号之后的高电平
    46. {
    47. return 0;
    48. }
    49. return 1;
    50. }
    51. /*读取一字节数据,返回值-读到的数据*/
    52. u8 DHT11ReadByte(void)
    53. {
    54. u8 i;
    55. u8 byt = 0;
    56. csi_gpio_pin_dir(&pin_dht11, GPIO_DIRECTION_INPUT);
    57. for (i=0; i<8; i++)
    58. {
    59. while (csi_gpio_pin_read(&pin_dht11)); //等待低电平,数据位前都有50us低电平时隙
    60. while (!csi_gpio_pin_read(&pin_dht11)); //等待高电平,开始传输数据位
    61. delay_us(40);
    62. byt <<= 1; //因高位在前,所以左移byt,最低位补0
    63. if (csi_gpio_pin_read(&pin_dht11)) //将总线电平值读取到byt最低位中
    64. {
    65. byt |= 0x01;
    66. }
    67. }
    68. return byt;
    69. }
    70. /*读取一次数据,返回参数:Humi-湿度,Temp-温度;返回值: 0-成功,1-失败*/
    71. u8 DHT11ReadData(u8 *H_inte, u8 *H_frac, u8 *T_inte, u8 *T_frac)
    72. {
    73. s8 sta = 0;
    74. u8 i;
    75. u8 buf[5];
    76. // u8 H_inte = 0;
    77. // u8 H_frac = 0;
    78. // u8 T_inte = 0;
    79. // u8 T_frac = 0;
    80. if (DHT11RstAndCheck()) //检测响应信号
    81. {
    82. for(i=0;i<5;i++) //读取40位数据
    83. {
    84. buf[i]=DHT11ReadByte(); //读取1字节数据
    85. }
    86. if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4]) //校验成功
    87. {
    88. *H_inte = buf[0]; //湿度整数部分数据
    89. *H_frac = buf[1]; //湿度小数部分数据
    90. *T_inte = buf[2]; //温度整数部分数据
    91. *T_frac = buf[3]; //温度小数部分数据
    92. // LOGD("zyd", "temp:%d.%d",*T_inte,*T_frac);
    93. // LOGD("zyd", "humi:%d.%d",*H_inte,*H_frac);
    94. // char tmp1[8], tmp2[8];
    95. // sprintf(tmp1, "%d.%d",H_inte,H_frac);
    96. // sscanf(tmp1, "%f", Humi);
    97. // sprintf(tmp2, "%d.%d",T_inte,T_frac);
    98. // sscanf(tmp2, "%f", Temp);
    99. }
    100. sta = 0;
    101. }
    102. else //响应失败返回-1
    103. {
    104. *H_inte = 0; //湿度整数部分数据
    105. *H_frac = 0; //湿度小数部分数据
    106. *T_inte = 0; //温度整数部分数据
    107. *T_frac = 0; //温度小数部分数据
    108. sta = 1;
    109. }
    110. return sta;
    111. }
    112. /*DHT11初始化函数*/
    113. u8 DHT11Init(void)
    114. {
    115. csi_pin_set_mux(PA7, PIN_FUNC_GPIO);
    116. csi_gpio_pin_init(&pin_dht11, PA7);
    117. csi_gpio_pin_dir(&pin_dht11, GPIO_DIRECTION_OUTPUT);
    118. return DHT11RstAndCheck(); //返回DHT11状态
    119. }

    2,LVGL显示。

    LVGL的作者是来自匈牙利的Gabor Kiss-Vamosikisvegabor,LVGL用C语言编写,以实现最大的兼容性(与C ++兼容),模拟器可在没有嵌入式硬件的PC上启动嵌入式GUI设计,同时LVGL作为一个图形库,它自带着接近三十多种小工具可以供开发者使用。这些强大的构建块按钮搭配上带有非常丝滑的动画以及可以做到平滑滚动的高级图形,同时兼具着不高的配置要求以及开源属性,显著的优势使得LVGL蔚然成风,成为广大开发者在选择GUI时的第一选择。

    显示程序代码:

    1. #include <aos/aos.h>
    2. #include "aos/cli.h"
    3. #include <stdlib.h>
    4. #include <string.h>
    5. #include "display.h"
    6. #include "dht11.h"
    7. #ifndef TAG
    8. #define TAG "app"
    9. #endif
    10. lv_obj_t *temp;
    11. lv_obj_t *humi;
    12. //float Humi;
    13. //float Temp;
    14. void gui_main_menu_create(void)
    15. {
    16. lv_obj_t *p0 = lv_label_create(lv_scr_act(), NULL);
    17. lv_label_set_long_mode(p0, LV_LABEL_ALIGN_CENTER);
    18. lv_label_set_align(p0, LV_LABEL_ALIGN_CENTER);
    19. lv_obj_set_pos(p0, 0, 4);
    20. lv_obj_set_size(p0, 60, 10);
    21. lv_label_set_text(p0, "TEMP:");//\nGUI\nDEMO
    22. temp = lv_label_create(lv_scr_act(), NULL);
    23. lv_label_set_long_mode(temp, LV_LABEL_ALIGN_CENTER);
    24. lv_label_set_align(temp, LV_LABEL_ALIGN_CENTER);
    25. lv_obj_set_pos(temp, 64, 4);
    26. lv_obj_set_size(temp, 60, 10);
    27. lv_label_set_text(temp, "22");//\nGUI\nDEMO
    28. lv_obj_t *p2 = lv_label_create(lv_scr_act(), NULL);
    29. lv_label_set_long_mode(p2, LV_LABEL_ALIGN_CENTER);
    30. lv_label_set_align(p2, LV_LABEL_ALIGN_CENTER);
    31. lv_obj_set_pos(p2, 0, 32);
    32. lv_obj_set_size(p2, 60, 10);
    33. lv_label_set_text(p2, "HUMI:");//\nGUI\nDEMO
    34. humi = lv_label_create(lv_scr_act(), NULL);
    35. lv_label_set_long_mode(humi, LV_LABEL_ALIGN_CENTER);
    36. lv_label_set_align(humi, LV_LABEL_ALIGN_CENTER);
    37. lv_obj_set_pos(humi, 64, 32);
    38. lv_obj_set_size(humi, 60, 10);
    39. lv_label_set_text(humi, "42%");//\nGUI\nDEMO
    40. }
    41. void set_label_temp_value(uint16_t value)
    42. {
    43. lv_label_set_text_fmt(temp, "%d.%d C",value,value%10);
    44. }
    45. void set_label_humi_value(uint16_t value)
    46. {
    47. lv_label_set_text_fmt(humi, "%d.%d %%",value/10,value%10);
    48. }
    49. void set_label_temp_float_value(uint8_t inte , uint8_t frac)
    50. {
    51. lv_label_set_text_fmt(temp, "%d.%d C",inte,frac);
    52. }
    53. void set_label_humi_float_value(uint8_t inte , uint8_t frac)
    54. {
    55. lv_label_set_text_fmt(humi, "%d.%d %%",inte,frac);
    56. }
    57. void gui_lvgl_task(void *arg)
    58. {
    59. uint16_t i=0;
    60. lv_init();
    61. /*Initialize for LittlevGL*/
    62. oled_init();
    63. DHT11Init();
    64. /*Select display 1*/
    65. // demo_create();
    66. // gui_label_create();
    67. gui_main_menu_create();
    68. while (1) {
    69. /* Periodically call the lv_task handler.
    70. * It could be done in a timer interrupt or an OS task too.*/
    71. lv_task_handler();
    72. i++;
    73. if(i>100)
    74. {
    75. i=0;
    76. //num = DHT11ReadData(&dht11_temp, &dht11_humi);
    77. DHT11ReadData(&H_inte,&H_frac,&T_inte, &T_frac);
    78. set_label_temp_float_value(T_inte,T_frac);
    79. set_label_humi_float_value(H_inte,H_frac);
    80. //LOGD(TAG, "Hello world! YoC");
    81. }
    82. aos_msleep(5); //zyd; long time will make error
    83. lv_tick_inc(1);
    84. }
    85. }

    3,WIFI连接。

    RVB2601 内置了联盛德公司高性能&安全的 WiFi4 芯片 W800,W800 通过 SPI 口与 CH2601 连接。W800 已经默认烧录基于 AT 的 WiFi 透传固件,开发者可基于 AT 网络指令,快速实现联网的应用场景。

    代码程序:

    1. /*
    2. * Copyright (C) 2019-2020 Alibaba Group Holding Limited
    3. */
    4. #include <stdlib.h>
    5. #include <string.h>
    6. #include <aos/list.h>
    7. #include <aos/debug.h>
    8. #include <drv/gpio.h>
    9. #include <drv/gpio_pin.h>
    10. #include <drv/pin.h>
    11. #include <uservice/uservice.h>
    12. #include <uservice/eventid.h>
    13. #include <yoc/sysinfo.h>
    14. #include <board.h>
    15. #include <yoc/at_port.h>
    16. #include <yoc/netmgr.h>
    17. #include <devices/w800.h>
    18. //#include "player_demo.h"
    19. #include "cJSON.h"
    20. #include "w800_api.h"
    21. //#include "thp_get.h"
    22. #include "wifi.h"
    23. #include "dht11.h"
    24. #define TAG "APP"
    25. //extern Result_S res_data;
    26. int iot_con_flag = 0;
    27. netmgr_hdl_t app_netmgr_hdl;
    28. //extern int w800_living_wjap(const char *myssid,const char *mypassword);
    29. //extern int w800_living_idmau(const char *mykey,const char *myname,const char *mysecret,const char *mypsecretconst);
    30. //extern int w800_living_idmcon(void);
    31. //extern int w800_living_idmpp(const char *dev_id, const char *msg, int *packet_id);
    32. static csi_gpio_pin_t g;
    33. void led_pin_init()
    34. {
    35. csi_pin_set_mux(PA25, PIN_FUNC_GPIO);
    36. csi_gpio_pin_init(&g, PA25);
    37. csi_gpio_pin_dir(&g, GPIO_DIRECTION_OUTPUT);
    38. csi_gpio_pin_write(&g, GPIO_PIN_HIGH);
    39. }
    40. void led_refreshed(int sw_led)
    41. {
    42. if (sw_led == 1)
    43. {
    44. csi_gpio_pin_write(&g, GPIO_PIN_LOW);
    45. }
    46. else
    47. {
    48. csi_gpio_pin_write(&g, GPIO_PIN_HIGH);
    49. }
    50. }
    51. unsigned char buff_accept[68];
    52. cJSON *str_json, *str_value; //初始化json结构体指针
    53. static int net_reset_err_times = 0;
    54. void app_exception_event(uint32_t event_id)
    55. {
    56. switch(event_id) {
    57. case EVENT_NETMGR_NET_DISCON:
    58. LOGD(TAG, "EVENT_NETMGR_NET_DISCON");
    59. net_reset_err_times++;
    60. if (net_reset_err_times >= MAX_NET_RESET_ERR_TIMES) {
    61. LOGD(TAG, "Net Reset times %d, reboot", net_reset_err_times);
    62. //do reboot
    63. aos_reboot();
    64. } else {
    65. LOGD(TAG, "Net Reset after %d second", NET_RESET_DELAY_TIME);
    66. netmgr_reset(app_netmgr_hdl, NET_RESET_DELAY_TIME);
    67. }
    68. break;
    69. case EVENT_NETMGR_GOT_IP:
    70. net_reset_err_times = 0;
    71. break;
    72. }
    73. }
    74. void connect_tcp_server(char *server_ip, uint16_t port)
    75. {
    76. char ssid[32];
    77. int bssid[6];
    78. int channel;
    79. int rssi;
    80. w800_ap_info( ssid, bssid , &channel, &rssi);
    81. printf("ssid: %s\r\n", ssid);
    82. printf("channel: %d\r\n", channel);
    83. printf("rssi: %d\r\n", rssi);
    84. w800_connect_remote(0, NET_TYPE_TCP_CLIENT, server_ip, port);
    85. }
    86. static void network_event(uint32_t event_id, const void *param, void *context)
    87. {
    88. switch(event_id) {
    89. case EVENT_NETMGR_GOT_IP:
    90. LOGD(TAG, "net got ip");
    91. // connect_tcp_server("192.168.2.226",1111);
    92. break;
    93. case EVENT_NETMGR_NET_DISCON:
    94. LOGD(TAG, "net disconnect");
    95. break;
    96. }
    97. /*do exception process */
    98. app_exception_event(event_id);
    99. }
    100. //
    101. int iot_apply(char *strbuff)
    102. {
    103. strcpy((char *)buff_accept,strbuff);
    104. str_json = cJSON_Parse((char *)buff_accept); //创建JSON解析对象,返回JSON格式是否正确
    105. if(str_json == NULL)
    106. {
    107. LOGI(TAG"error:%s;\r\n",cJSON_GetErrorPtr());
    108. cJSON_Delete(str_json);//释放内存
    109. return -1;
    110. }
    111. else
    112. {
    113. cJSON *str_value = cJSON_GetObjectItem(str_json, "led");
    114. LOGI(TAG,"led powerstate:%d;\r\n",str_value->valueint);
    115. //led_refreshed(str_value->valueint);
    116. //res_data.led = str_value->valueint;
    117. cJSON_Delete(str_json);//释放内存
    118. return 1;
    119. }
    120. }
    121. int iot_connect_dome(void)
    122. {
    123. //char *my_ssid = "TP-LINK_AF26";//2.4GHZ WiFi ssidTP-LINK_678C14
    124. //char *my_password = "20190213";//2.4GHZ WiFi password
    125. // char *my_ssid = "dong123";//2.4GHZ WiFi ssid
    126. // char *my_password = "donghae12";//2.4GHZ WiFi password
    127. char *my_ssid = "zyd";//2.4GHZ WiFi ssid
    128. char *my_password = "12345678";//2.4GHZ WiFi password
    129. char *my_key = "a1QNjTo9nGU";//ProductKey
    130. char *my_name = "RVB2601";//DeviceName
    131. char *my_secret = "ec7d6db43764c9a480e332bf269db138";//DeviceSecret
    132. char *my_p_secret = "o9EvLXL7szMFH95H";//Product Secret
    133. int ret1 = -1;
    134. int ret2 = -1;
    135. int ret3 = -1;
    136. ret1 = w800_living_wjap(my_ssid,my_password);
    137. if (ret1 == 0){
    138. printf("AT+WJAP:OK!\n");
    139. }
    140. else{
    141. printf("AT+WJAP:ERROR!\n");
    142. }
    143. ret2 = w800_living_idmau(my_key,my_name,my_secret,my_p_secret);
    144. if (ret2 == 0){
    145. printf("AT+IDMAU:OK!\n");
    146. }
    147. else{
    148. printf("AT+IDMAU:ERROR!\n");
    149. }
    150. ret3 = w800_living_idmcon();
    151. if (ret3 == 0){
    152. printf("AT+IDMCON:OK!\n");
    153. }
    154. else{
    155. printf("AT+IDMCON:ERROR!\n");
    156. }
    157. if(ret1 == 0 && ret2 == 0 && ret3 == 0){
    158. return 0;
    159. }else{
    160. return -1;
    161. }
    162. }
    163. static void network_init()
    164. {
    165. w800_wifi_param_t w800_param;
    166. /* init wifi driver and network */
    167. w800_param.reset_pin = PA21;
    168. w800_param.baud = 1*1000000;
    169. w800_param.cs_pin = PA15;
    170. w800_param.wakeup_pin = PA25;
    171. w800_param.int_pin = PA22;
    172. w800_param.channel_id = 0;
    173. w800_param.buffer_size = 4*1024;
    174. wifi_w800_register(NULL, &w800_param);
    175. app_netmgr_hdl = netmgr_dev_wifi_init();
    176. if (app_netmgr_hdl) {
    177. utask_t *task = utask_new("netmgr", 2 * 1024, QUEUE_MSG_COUNT, AOS_DEFAULT_APP_PRI);
    178. netmgr_service_init(task);
    179. // netmgr_config_wifi(app_netmgr_hdl, "@PHICOMM_20", 11, "12345678", 8);
    180. // w800_packet_input_cb_register(&w800_data_receive_callback);
    181. netmgr_start(app_netmgr_hdl);
    182. // /* Subscribe */
    183. event_subscribe(EVENT_NETMGR_GOT_IP, network_event, NULL);
    184. event_subscribe(EVENT_NETMGR_NET_DISCON, network_event, NULL);
    185. }
    186. }
    187. void wifi_task(void *arg)
    188. {
    189. int ret = -1;
    190. char report_buf[80];
    191. const char *dev_id = "0";
    192. int pkt_id = 0;
    193. char tmp1[8];
    194. char tmp2[8];
    195. float CurrentTemperature=0;
    196. float CurrentHumidity=0;
    197. // int len = sizeof(report_buf);
    198. // int timeout=120;
    199. event_service_init(NULL);
    200. //ulog_init();
    201. aos_set_log_level(AOS_LL_DEBUG);
    202. network_init();
    203. // event_subscribe(EVENT_NETMGR_GOT_IP, network_event, NULL);
    204. // event_subscribe(EVENT_NETMGR_NET_DISCON, network_event, NULL);
    205. //
    206. ret = iot_connect_dome();
    207. // /* Subscribe */
    208. if (ret == 0){
    209. printf("connect iot success\n");
    210. }else{
    211. printf("connect iot error\n");
    212. }
    213. while (1) {
    214. // snprintf(report_buf,len,pdata,sht20Info.humidity,sht20Info.tempreture);
    215. // w800_send_data(report_buf, len, timeout);
    216. sprintf(tmp1, "%d.%d",H_inte,H_frac);
    217. sscanf(tmp1, "%f", &CurrentHumidity);
    218. sprintf(tmp2, "%d.%d",T_inte,T_frac);
    219. sscanf(tmp2, "%f", &CurrentTemperature);
    220. snprintf(report_buf,80,"{\\\"CurrentTemperature\\\":%.1f,\\\"CurrentHumidity\\\":%.1f}",CurrentTemperature,CurrentHumidity);
    221. LOGD("zyd", "temp:%.1f",CurrentTemperature);
    222. LOGD("zyd", "humi:%.1f",CurrentHumidity);
    223. //snprintf(report_buf,80,"{\\\"CurrentTemperature\\\":%.1f,\\\"CurrentHumidity\\\":%.1f}",sht20Info.tempreture,sht20Info.humidity);
    224. //printf( "==> start attribute upload\n");
    225. w800_living_idmpp(dev_id, report_buf, &pkt_id);
    226. aos_msleep(2000);
    227. }
    228. }

    五、作品源码

    六、视频演示

    七、项目总结

    八、其他

  • 相关阅读:
    Easypoi map方式导入数据 ,List<Map<String, String>> 日期项数据为空(null)解决办法
    2022新版PMP考试有哪些变化?
    Java 并发编程解析 | 如何正确理解Java领域中的锁机制,我们一般需要掌握哪些理论知识?
    web端登录需要验证码
    使用c#将aj-report桌面化:3.C#操作java
    Springboot健康饮食推荐系统的设计与实现 毕业设计-附源码49517
    全网最详细的本地搭建GitLab代码仓库教学
    KubeSphere 社区双周报 | 功能亮点抢“鲜”看 | 2022-09-16
    SpringMVC的高频面试题
    elment以及elementPlus选中组件出现黑框问题解决!!
  • 原文地址:https://blog.csdn.net/m0_38012497/article/details/125120573