利用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 所示:

 程序代码:


#include <aos/aos.h>
#include "aos/cli.h"
#include "dht11.h"

#ifndef TAG
#define TAG "app"
#endif


uint8_t H_inte = 0;
uint8_t H_frac = 0;
uint8_t T_inte = 0;
uint8_t T_frac = 0;

static csi_gpio_pin_t pin_dht11;

void delay_ms(unsigned char n)
{
    udelay(n * 1000);
}

void delay_us(unsigned char n)
{
    udelay(n);
}

/*DHT11复位和检测响应函数,返回值:1-检测到响应信号;0-未检测到响应信号*/
u8 DHT11RstAndCheck(void)
{
    u8 timer = 0;

	csi_gpio_pin_dir(&pin_dht11, GPIO_DIRECTION_OUTPUT);
    csi_gpio_pin_write(&pin_dht11, GPIO_PIN_LOW); //输出低电平
    delay_ms(20);    	                          //拉低至少18ms
    csi_gpio_pin_write(&pin_dht11, GPIO_PIN_HIGH); //输出高电平
    delay_us(30);     	                           //拉高20~40us
	
	csi_gpio_pin_dir(&pin_dht11, GPIO_DIRECTION_INPUT);
    while (!csi_gpio_pin_read(&pin_dht11)) //等待总线拉低,DHT11会拉低40~80us作为响应信号
    {
        timer++;               //总线拉低时计数
        delay_us(10);
    }
    if (timer>10 || timer<2) //判断响应时间
    {
        return 0;
    }
	
    timer = 0;
    while (csi_gpio_pin_read(&pin_dht11))           //等待DHT11释放总线,持续时间40~80us
    {
        timer++;               //总线拉高时计数
        delay_us(10);
    }
    if (timer>10 || timer<2) //检测响应信号之后的高电平
    {
        return 0;
	}
    
    return 1;
}

/*读取一字节数据,返回值-读到的数据*/
u8 DHT11ReadByte(void)
{
    u8 i;
    u8 byt = 0;

	csi_gpio_pin_dir(&pin_dht11, GPIO_DIRECTION_INPUT);
    for (i=0; i<8; i++)
    {
        while (csi_gpio_pin_read(&pin_dht11));  //等待低电平,数据位前都有50us低电平时隙
        while (!csi_gpio_pin_read(&pin_dht11)); //等待高电平,开始传输数据位
        delay_us(40);
        byt <<= 1;         //因高位在前,所以左移byt,最低位补0
        if (csi_gpio_pin_read(&pin_dht11))      //将总线电平值读取到byt最低位中
        {
            byt |= 0x01;
        }
    }

    return byt;
}

/*读取一次数据,返回参数:Humi-湿度,Temp-温度;返回值: 0-成功,1-失败*/
u8 DHT11ReadData(u8 *H_inte, u8 *H_frac, u8 *T_inte, u8 *T_frac)
{
    s8 sta = 0;
    u8 i;
    u8 buf[5];
//	u8 H_inte = 0;
//	u8 H_frac = 0;
//	u8 T_inte = 0;
//	u8 T_frac = 0;

    if (DHT11RstAndCheck())         //检测响应信号
    {
        for(i=0;i<5;i++)            //读取40位数据
        {
            buf[i]=DHT11ReadByte(); //读取1字节数据
        }
        if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4]) //校验成功
        {
            *H_inte = buf[0]; //湿度整数部分数据
			*H_frac = buf[1]; //湿度小数部分数据
            *T_inte = buf[2]; //温度整数部分数据
			*T_frac = buf[3]; //温度小数部分数据
		//	LOGD("zyd", "temp:%d.%d",*T_inte,*T_frac);
		//	LOGD("zyd", "humi:%d.%d",*H_inte,*H_frac);
//			char tmp1[8], tmp2[8];
//			sprintf(tmp1, "%d.%d",H_inte,H_frac);
//			sscanf(tmp1, "%f", Humi);
//			sprintf(tmp2, "%d.%d",T_inte,T_frac);
//			sscanf(tmp2, "%f", Temp);
        }
        sta = 0;
    }
    else //响应失败返回-1
    {
        *H_inte = 0; //湿度整数部分数据
		*H_frac = 0; //湿度小数部分数据
		*T_inte = 0; //温度整数部分数据
		*T_frac = 0; //温度小数部分数据
        sta = 1;
    }
    
    return sta;    
}

/*DHT11初始化函数*/
u8 DHT11Init(void)
{
	csi_pin_set_mux(PA7, PIN_FUNC_GPIO);
	csi_gpio_pin_init(&pin_dht11, PA7);
    csi_gpio_pin_dir(&pin_dht11, GPIO_DIRECTION_OUTPUT);

    return DHT11RstAndCheck(); //返回DHT11状态
}

2,LVGL显示。

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

显示程序代码:

#include <aos/aos.h>
#include "aos/cli.h"
#include <stdlib.h>
#include <string.h>
#include "display.h"
#include "dht11.h"

#ifndef TAG
#define TAG "app"
#endif

lv_obj_t *temp;
lv_obj_t *humi;

//float Humi;
//float Temp;

void gui_main_menu_create(void)
{
    lv_obj_t *p0 = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_long_mode(p0, LV_LABEL_ALIGN_CENTER);
    lv_label_set_align(p0, LV_LABEL_ALIGN_CENTER);
    lv_obj_set_pos(p0, 0, 4);
    lv_obj_set_size(p0, 60, 10);
    lv_label_set_text(p0, "TEMP:");//\nGUI\nDEMO
	
	
	temp = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_long_mode(temp, LV_LABEL_ALIGN_CENTER);
    lv_label_set_align(temp, LV_LABEL_ALIGN_CENTER);
    lv_obj_set_pos(temp, 64, 4);
    lv_obj_set_size(temp, 60, 10);
    lv_label_set_text(temp, "22");//\nGUI\nDEMO
	
	lv_obj_t *p2 = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_long_mode(p2, LV_LABEL_ALIGN_CENTER);
    lv_label_set_align(p2, LV_LABEL_ALIGN_CENTER);
    lv_obj_set_pos(p2, 0, 32);
    lv_obj_set_size(p2, 60, 10);
    lv_label_set_text(p2, "HUMI:");//\nGUI\nDEMO
	
	humi = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_long_mode(humi, LV_LABEL_ALIGN_CENTER);
    lv_label_set_align(humi, LV_LABEL_ALIGN_CENTER);
    lv_obj_set_pos(humi, 64, 32);
    lv_obj_set_size(humi, 60, 10);
    lv_label_set_text(humi, "42%");//\nGUI\nDEMO
}


void set_label_temp_value(uint16_t value)
{
       lv_label_set_text_fmt(temp, "%d.%d C",value,value%10); 

}

void set_label_humi_value(uint16_t value)
{
       lv_label_set_text_fmt(humi, "%d.%d %%",value/10,value%10);
}



void set_label_temp_float_value(uint8_t inte , uint8_t frac)
{
       lv_label_set_text_fmt(temp, "%d.%d C",inte,frac); 

}

void set_label_humi_float_value(uint8_t inte , uint8_t frac)
{
       lv_label_set_text_fmt(humi, "%d.%d %%",inte,frac); 
}



void gui_lvgl_task(void *arg)
{	
	uint16_t i=0;	
	
    lv_init();
    /*Initialize for LittlevGL*/
    oled_init();
	DHT11Init();
    /*Select display 1*/
    // demo_create();
   // gui_label_create();
   gui_main_menu_create();

    while (1) {
        /* Periodically call the lv_task handler.
         * It could be done in a timer interrupt or an OS task too.*/
        lv_task_handler();
		i++;
		if(i>100)
		{
			i=0;
			//num =  DHT11ReadData(&dht11_temp, &dht11_humi);	
			DHT11ReadData(&H_inte,&H_frac,&T_inte, &T_frac);
			set_label_temp_float_value(T_inte,T_frac);
			set_label_humi_float_value(H_inte,H_frac);
			//LOGD(TAG, "Hello world! YoC");
		}		
        aos_msleep(5);  //zyd; long time will make error 
        lv_tick_inc(1);
    }
}

3,WIFI连接。

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

代码程序:

/*
 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
 */
#include <stdlib.h>
#include <string.h>
#include <aos/list.h>
#include <aos/debug.h>

#include <drv/gpio.h>
#include <drv/gpio_pin.h>
#include <drv/pin.h>

#include <uservice/uservice.h>
#include <uservice/eventid.h>

#include <yoc/sysinfo.h>
#include <board.h>

#include <yoc/at_port.h>
#include <yoc/netmgr.h>
#include <devices/w800.h>
//#include "player_demo.h"
#include "cJSON.h"
#include "w800_api.h"
//#include "thp_get.h"
#include "wifi.h"
#include "dht11.h"

#define TAG "APP"
//extern Result_S res_data; 

int iot_con_flag = 0;

netmgr_hdl_t app_netmgr_hdl;

//extern int w800_living_wjap(const char *myssid,const char *mypassword);
//extern int w800_living_idmau(const char *mykey,const char *myname,const char *mysecret,const char *mypsecretconst);
//extern int w800_living_idmcon(void);
//extern int w800_living_idmpp(const char *dev_id, const char *msg, int *packet_id);

static csi_gpio_pin_t g;

void led_pin_init()
{
    csi_pin_set_mux(PA25, PIN_FUNC_GPIO);
    csi_gpio_pin_init(&g, PA25);
    csi_gpio_pin_dir(&g, GPIO_DIRECTION_OUTPUT);

	csi_gpio_pin_write(&g, GPIO_PIN_HIGH);
}

void led_refreshed(int sw_led)
{
    if (sw_led == 1)
    {
        csi_gpio_pin_write(&g, GPIO_PIN_LOW);
    }
    else
    {
        csi_gpio_pin_write(&g, GPIO_PIN_HIGH);
    }
}

unsigned char buff_accept[68];
cJSON *str_json, *str_value;  //初始化json结构体指针

static int net_reset_err_times = 0;

void app_exception_event(uint32_t event_id)
{
    switch(event_id) {
    case EVENT_NETMGR_NET_DISCON:
        LOGD(TAG, "EVENT_NETMGR_NET_DISCON");
        net_reset_err_times++;
        if (net_reset_err_times >= MAX_NET_RESET_ERR_TIMES) {
            LOGD(TAG, "Net Reset times %d, reboot", net_reset_err_times);
            //do reboot
            aos_reboot();
        } else {
            LOGD(TAG, "Net Reset after %d second", NET_RESET_DELAY_TIME);
            netmgr_reset(app_netmgr_hdl, NET_RESET_DELAY_TIME);
        }
        break;
    case EVENT_NETMGR_GOT_IP:
        net_reset_err_times = 0;
        break;
    }
}

void connect_tcp_server(char *server_ip, uint16_t port)
{
	char ssid[32];
	int bssid[6];
	int channel;
	int rssi;
	
	
	w800_ap_info( ssid, bssid , &channel,  &rssi);
	printf("ssid: %s\r\n", ssid);
	printf("channel: %d\r\n", channel);
	printf("rssi: %d\r\n", rssi);
	
	w800_connect_remote(0, NET_TYPE_TCP_CLIENT, server_ip, port);

	
}

static void network_event(uint32_t event_id, const void *param, void *context)
{
    switch(event_id) {
    case EVENT_NETMGR_GOT_IP:
        LOGD(TAG, "net got ip");
//		connect_tcp_server("192.168.2.226",1111);
        break;
    case EVENT_NETMGR_NET_DISCON:
        LOGD(TAG, "net disconnect");
		break;
    }

    /*do exception process */
    app_exception_event(event_id);
}


//
int iot_apply(char *strbuff)
{
	strcpy((char *)buff_accept,strbuff);	
	str_json = cJSON_Parse((char *)buff_accept);   //创建JSON解析对象,返回JSON格式是否正确
    if(str_json == NULL)
	{
		LOGI(TAG"error:%s;\r\n",cJSON_GetErrorPtr());
		cJSON_Delete(str_json);//释放内存 	
		return -1;
	}
	else
	{
		cJSON *str_value = cJSON_GetObjectItem(str_json, "led");
		LOGI(TAG,"led powerstate:%d;\r\n",str_value->valueint);
		//led_refreshed(str_value->valueint);
		//res_data.led = str_value->valueint;
		cJSON_Delete(str_json);//释放内存 	
		return 1;
	}
	
}

int iot_connect_dome(void)
{
	 //char *my_ssid = "TP-LINK_AF26";//2.4GHZ WiFi ssidTP-LINK_678C14	 
	 //char *my_password = "20190213";//2.4GHZ WiFi password  
//	 char *my_ssid = "dong123";//2.4GHZ WiFi ssid
//	 char *my_password = "donghae12";//2.4GHZ WiFi password    
	 char *my_ssid = "zyd";//2.4GHZ WiFi ssid
	 char *my_password = "12345678";//2.4GHZ WiFi password
  
	 char *my_key = "a1QNjTo9nGU";//ProductKey
	 char *my_name = "RVB2601";//DeviceName
	 char *my_secret = "ec7d6db43764c9a480e332bf269db138";//DeviceSecret
	 char *my_p_secret = "o9EvLXL7szMFH95H";//Product Secret
 
     
	 int ret1 = -1;
	 int ret2 = -1;
	 int ret3 = -1;

	 ret1 = w800_living_wjap(my_ssid,my_password);
	 if (ret1 == 0){
		printf("AT+WJAP:OK!\n");
	 }
	 else{
		printf("AT+WJAP:ERROR!\n");
	 }
	 ret2 = w800_living_idmau(my_key,my_name,my_secret,my_p_secret);
	 if (ret2 == 0){
		printf("AT+IDMAU:OK!\n");
	 }
	 else{
		printf("AT+IDMAU:ERROR!\n");
	 }
	 ret3 = w800_living_idmcon();
	 if (ret3 == 0){
		printf("AT+IDMCON:OK!\n");
	 }
	 else{
		printf("AT+IDMCON:ERROR!\n");
	 }
	 if(ret1 == 0 && ret2 == 0 && ret3 == 0){
		return 0;
	 }else{
		return -1;
	 }
}


static void network_init()
{
    w800_wifi_param_t w800_param;
    /* init wifi driver and network */
    w800_param.reset_pin      = PA21;
    w800_param.baud           = 1*1000000;
    w800_param.cs_pin         = PA15;
    w800_param.wakeup_pin     = PA25;
    w800_param.int_pin        = PA22;
    w800_param.channel_id     = 0;
    w800_param.buffer_size    = 4*1024;

    wifi_w800_register(NULL, &w800_param);
    app_netmgr_hdl = netmgr_dev_wifi_init();

    if (app_netmgr_hdl) {
        utask_t *task = utask_new("netmgr", 2 * 1024, QUEUE_MSG_COUNT, AOS_DEFAULT_APP_PRI);
        netmgr_service_init(task);
//        netmgr_config_wifi(app_netmgr_hdl, "@PHICOMM_20", 11, "12345678", 8);
//		w800_packet_input_cb_register(&w800_data_receive_callback);
        netmgr_start(app_netmgr_hdl);
		
		//   /* Subscribe */
		event_subscribe(EVENT_NETMGR_GOT_IP, network_event, NULL);
		event_subscribe(EVENT_NETMGR_NET_DISCON, network_event, NULL);
    }
}

void wifi_task(void *arg) 
{
	int ret = -1;
	char report_buf[80];
	
	const char *dev_id = "0";
	int pkt_id = 0;
	
	char tmp1[8];
	char tmp2[8];
	float CurrentTemperature=0;
	float CurrentHumidity=0;
//	int len = sizeof(report_buf);
//	int timeout=120;
	
	
	event_service_init(NULL);
	//ulog_init();
	aos_set_log_level(AOS_LL_DEBUG);
	network_init();

//	event_subscribe(EVENT_NETMGR_GOT_IP, network_event, NULL);
//	event_subscribe(EVENT_NETMGR_NET_DISCON, network_event, NULL);
//	

	
	ret = iot_connect_dome();
	//   /* Subscribe */
	
	if (ret == 0){
		printf("connect iot success\n");
	}else{
		printf("connect iot error\n");
	}
	
	while (1) {
		
//		snprintf(report_buf,len,pdata,sht20Info.humidity,sht20Info.tempreture);
//		w800_send_data(report_buf,  len, timeout);
		
		
		sprintf(tmp1, "%d.%d",H_inte,H_frac);
		sscanf(tmp1, "%f", &CurrentHumidity);
		sprintf(tmp2, "%d.%d",T_inte,T_frac);
		sscanf(tmp2, "%f", &CurrentTemperature);

		snprintf(report_buf,80,"{\\\"CurrentTemperature\\\":%.1f,\\\"CurrentHumidity\\\":%.1f}",CurrentTemperature,CurrentHumidity);
		
		LOGD("zyd", "temp:%.1f",CurrentTemperature);
		LOGD("zyd", "humi:%.1f",CurrentHumidity);
		//snprintf(report_buf,80,"{\\\"CurrentTemperature\\\":%.1f,\\\"CurrentHumidity\\\":%.1f}",sht20Info.tempreture,sht20Info.humidity);
		//printf( "==> start attribute upload\n");
		w800_living_idmpp(dev_id, report_buf, &pkt_id);

	    aos_msleep(2000);
	}
	
}

五、作品源码

六、视频演示

七、项目总结

八、其他

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
【RT-Thread作品秀】温湿度监测设计作者:Star.Water 概述产生背景:当前温湿度监控设备大多只能显示当前环境参数,不能查看历史记录和历史曲线图,不能直观的显示温度湿度的变化情况。所以本次设计预计做出一款可以显示当前和历史曲线的产品。 实现功能:仪表盘显示当期的温度,湿度;历史曲线显示历史数据。 开发环境硬件:ART-Pi RT-Thread版本:rt-thread-v4.0.2 开发工具及版本:MDK5.21 RT-Thread使用情况概述移植RT-Thread到STM32H50,设置系统滴答时钟产生1ms中断,驱动RT-Thread. #define RT_HEAP_SIZE (1024*40) //1024 #define RT_MAIN_THREAD_STACK_SIZE 1024 #define RT_USING_HEAP 其他为默认 硬件框架以ART-Pi为主,驱动1024*600 7寸电容触摸屏,阿里云stm32L4开发负责传感器参数采集,数据记录写入SD卡。ART-Pi和stm32L4都是用RT-Thread RTOS,通过串口通讯。 屏幕: 屏幕转接参考正点原子和野火的屏幕,自己画,嘉立创打样,10*10以内5元,由于屏幕大小位180mm*100,所以用3块子拼接而成。 软件框架说明RTT通过系统滴答定时器产生1ms中断驱动;LVGL通过定时器3产生1ms中断驱动。 各个线程资源分配如下: 机智云WIFI远程遥控和传感器参数采集在STM32L496子上。 软件模块说明APT-Pi与STM32L496通讯采用自定义的协议,协议内容如下: 协议包头包尾均采用双字节验证,减小内容中出现包头包尾的概率,每一帧数据的结尾添加16bit的校验值,避免通讯受到干扰时发送参数错误。 在使用过程中发现RT-Thread的printf和sprintf函数功能不完善,不能使类似%0.2来确定小数的位数和格式。 演示效果LVGL调试使用VS2017,在电脑断调试完成后快速移植到单片机。以下图片为仿真截图。 视频见附件。 代码地址代码见附件。 比赛感悟一直想要自己写一个LVGL,但是白天需要上班,晚上带孩子,没有时间搞,借助这次比赛给自己压力,每天晚上加班总算把LVGL入门了。 RT-Thread是一款很方便移植的RTOS,仅需要一个中断来驱动就好,方便移植。之前一直没有使用RTT的软件包,这次发现RTT的软件包很方便,以后一定要学习一下,这次因为时间紧迫,所以还是使用MDK开发,自己手动移植RTT,其他驱动自己添加。在功能上还有很多预想没有实现,后期会组不添加完善功能。 非常感谢RT-Thread提供的参赛机会,让我学到了知识,也了解了更多关于RT-Thread,比赛虽然快要结束了,但是在学习的道路上永不止步!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值