实验需要读取温湿度使用正点原子开发板,发现偶尔会出现读取湿度值与温度值相同的错误,概率比较低。但是还是会出错,因此使用下列方法进行避免。
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