实验需要读取温湿度使用正点原子开发板,发现偶尔会出现读取湿度值与温度值相同的错误,概率比较低。但是还是会出错,因此使用下列方法进行避免。
int main(void) { uint16 t=0; //u8 temperature; //u8 humidity; //定义温湿度 int16 temperature; int16 humidity; uint32 index = 0; #define DEF_LvBSize 80 static int16 wendu[DEF_LvBSize]; static int16 shidu[DEF_LvBSize]; static int16 wendutmp[DEF_LvBSize]; static int16 shidutmp[DEF_LvBSize]; static int16 Tadd; static int16 Radd; static uint8 i; static uint8 j; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级 uart_init(9600); //串口初始化为115200 LED_Init(); //初始化与LED连接的硬件接口 LCD_Init(); //初始化LCD POINT_COLOR=RED; //设置字体为红色 LCD_ShowString(30,50,200,16,16,"WarShip STM32"); LCD_ShowString(30,70,200,16,16,"DHT11 TEST"); LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(30,110,200,16,16,"2015/1/16"); delay_ms(500); while(DHT11_Init()) //DHT11初始化 { LCD_ShowString(30,130,200,16,16,"DHT11 Error"); delay_ms(200); LCD_Fill(30,130,239,130+16,WHITE); delay_ms(200); printf("DHT11 Error"); } LCD_ShowString(30,130,200,16,16,"DHT11 OK"); POINT_COLOR=BLUE;//设置字体为蓝色 LCD_ShowString(30,150,200,16,16,"Temp: C"); LCD_ShowString(30,170,200,16,16,"Humi: %"); //初始化 // delay_ms(200); // DHT11_Read_Data_int16(&temperature,&humidity); // for(i=0;i<DEF_LvBSize;i++){ // wendu[i] = temperature; // shidu[i] = humidity; // } // while(1) { if(t%10==0) //每100ms读取一次 { //DHT11_Read_Data(&temperature,&humidity); //读取温湿度值 DHT11_Read_Data_int16(&temperature,&humidity); LCD_ShowNum(30+40,150,temperature,2,16); //显示温度 LCD_ShowNum(30+40,170,humidity,2,16); //显示湿度 for(i=0;i<DEF_LvBSize-1;i++){ wendu[i] = wendu[i+1]; shidu[i] = shidu[i+1]; } wendu[DEF_LvBSize-1] = temperature; shidu[DEF_LvBSize-1] = humidity; // Tadd = 0; // Radd = 0; // for(i=0;i<DEF_LvBSize;i++){ // Tadd += wendu[i]; // Radd += shidu[i]; // } // Tadd = Tadd / DEF_LvBSize; // Radd = Radd / DEF_LvBSize; // for(i=0;i<DEF_LvBSize;i++){ wendutmp[i] = wendu[i]; shidutmp[i] = shidu[i]; } for(i=0;i<DEF_LvBSize;i++){ for( j = i; j < DEF_LvBSize; j++ ){ if( wendutmp[i] < wendutmp[j] ){ Tadd = wendutmp[i]; wendutmp[i] = wendutmp[j]; wendutmp[j] = Tadd; } if( shidutmp[i] < shidutmp[j] ){ Radd = shidutmp[i]; shidutmp[i] = shidutmp[j]; shidutmp[j] = Tadd; } } } Tadd = wendutmp[DEF_LvBSize/2]; Radd = shidutmp[DEF_LvBSize/2]; LED1=!LED1; } delay_ms(10); t++; if(t==815) { static int16 oldShiD; if( Radd == Tadd ){ printf("\t\t\t\t\t\t\t湿度err\r\n"); if( oldShiD + 60 < Radd || oldShiD - 60 > Radd ){ Radd = oldShiD; printf("\t\t\t\t\t\told:\t%d\t%d\r\n",oldShiD,Tadd); } }else{ oldShiD = Radd; } printf("\t\tIndex:\t%d\t T: \t%d\t R: \t%d\r\n",index++,Tadd,Radd); t=0; LED0=!LED0; } } }其中函数 DHT11_Read_Data_int16(&temperature,&humidity); 原型如下:
//从DHT11读取一次数据 //temp:温度值(范围:0~50.0°) //humi:湿度值(范围:20%~90.0%) //返回值:0,正常;1,读取失败 uint8 DHT11_Read_Data_int16(int16 *temp,int16 *humi) { uint8 buf[5]; uint8 i; int16 wendu; int16 shidu; DHT11_Rst(); if(DHT11_Check()==0) { for(i=0;i<5;i++)//读取40位数据 { buf[i]=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { //*humi=buf[0]; //*temp=buf[2]; shidu = 10*buf[0] + buf[1]; //wendu = 10*buf[2] + buf[3]; //需要增加零下温度对buf[3]的高8位进行判断 if( buf[3]<128) //这样处理需要考虑返回值得数据类型 wendu = 10*buf[2] + buf[3]; else{ wendu = 0;//-(10*buf[2] + (buf[3]-128)); } *humi=shidu; *temp=wendu; } }else return 1; return 0; }这是在正点原子的试验基础上增加了,小数点后的数据,其他没有修改。 为10秒左右发送一条数据,经过一夜的测试获得如下数据
测试数据截图
温湿度曲线图 说明在长时间测试时可以有效避免当前的偶尔数据错误问题。 当然此种解决方法是回拨了问题的发生,在一些特殊场合不能使用,比如间隔时间更长的场合。就无法与上一次的数据进行正负6%的湿度范围极性对比。 而且如果湿度返回与温度十分接近的情况并没有测试。 至于是不是原有驱动程序的原因,暂时不是很清楚。 或者是不是个别传感器的个例也不是很清楚。 大家有什么更好的解决方案请留言。
再次说明一下我的解决思路, 首先对采集的数据进行冒泡排序,取中值, 再对要发送的数据进行记录,当湿度等于温度时,进行湿度检查如果与上一次发送出去的湿度差值在正负6%以上则认为此次湿度采集有问题,使用上一次的湿度代替当前湿度。 如果温湿度不相等,则记录这一次的湿度值。
特此记录以防防止忘记 anlog 2020年7月5日09:33:19
