最近因为嵌入式的课程设计,买了一些硬件,显示屏跟着官方文档可以基本上没有问题完成所有的设置并正常使用;可是到了 DHT11 这儿就出现了问题,我在网上找了好几个版本的代码,都没有办法能够直接正常从传感器那儿获取数据。
比如下面这个,原地址在这儿:
#!/usr/bin/python
#-*- coding:utf-8 -*-
import RPi.GPIO as GPIO
import time
channel = 7 #引脚号Pin7
data = [] #温湿度值
j = 0 #计数器
GPIO.setmode(GPIO.BOARD) #以BOARD编码格式
time.sleep(1) #时延一秒
GPIO.setup(channel, GPIO.OUT)
GPIO.output(channel, GPIO.LOW)
time.sleep(0.02) #给信号提示传感器开始工作
GPIO.output(channel, GPIO.HIGH)
GPIO.setup(channel, GPIO.IN)
while GPIO.input(channel) == GPIO.LOW:
continue
while GPIO.input(channel) == GPIO.HIGH:
continue
while j < 40:
k = 0
while GPIO.input(channel) == GPIO.LOW:
continue
while GPIO.input(channel) == GPIO.HIGH:
k += 1
if k > 100:
break
if k < 8: #通过计数的方式判断是数据位高电平长短,以置0或1。(此方式有待商榷)
data.append(0)
else:
data.append(1)
j += 1
print ("sensor is working.")
print (data) #输出初始数据高低电平
humidity_bit = data[0:8] #分组
humidity_point_bit = data[8:16]
temperature_bit = data[16:24]
temperature_point_bit = data[24:32]
check_bit = data[32:40]
humidity = 0
humidity_point = 0
temperature = 0
temperature_point = 0
check = 0
for i in range(8):
humidity += humidity_bit[i] * 2 ** (7 - i) #转换成十进制数据
humidity_point += humidity_point_bit[i] * 2 ** (7 - i)
temperature += temperature_bit[i] * 2 ** (7 - i)
temperature_point += temperature_point_bit[i] * 2 ** (7 - i)
check += check_bit[i] * 2 ** (7 - i)
tmp = humidity + humidity_point + temperature + temperature_point #十进制的数据相加
if check == tmp: #数据校验,相等则输出
print ("temperature : ", temperature, ", humidity : " , humidity)
else: #错误输出错误信息,和校验数据
print ("wrong")
print ("temperature : ", temperature, ", humidity : " , humidity, " check : ", check, " tmp : ", tmp)
GPIO.cleanup() #重置针脚
其他的代码都与这个大同小异,但是出来的结果永远是一串的高电平。
于是乎我继续在网上搜索解决问题的方法,无论是 StackOverflow、CSDN、SegmentFault 全都是只有提问题的,而没有回答问题的,底下还有很多的评论在问是否解决了问题。
后来我继续在论坛里面逛瞎逛结果让我碰到了这样的一句话:Python 的运行太慢,而且 DHT11 对实验的要求高,可能就获取不到正确的时序序列了。
这个说法点醒了我,因为网上大部分的 DHT11 通信 Python 代码都是由 Python2 改来的,而且很多人反映代码用不了,全是高电平(跟我这儿的症状一样),所以这也是有可能的。
如何解决的?
所以接下来就不能够使用 Python 去写了,好在我的 C 基础还行,所以网上抄抄,自己进行了魔改,编译出了一个小程序去与传感器通信,并且获取到了正确的温度和湿度,最后用 Python 去调用就行了。
果然 Python 还是不能够解决一切问题的(笑)。
源码如下,来自这儿:
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
#define HIGH_TIME 32
int pinNumber =1; //use gpio1 to read data
uint32 databuf;
uint8 readSensorData(void)
{
uint8 crc;
uint8 i;
pinMode(pinNumber,OUTPUT); // set mode to output
digitalWrite(pinNumber, 0); // output a high level
delay(25);
digitalWrite(pinNumber, 1); // output a low level
pinMode(pinNumber, INPUT); // set mode to input
pullUpDnControl(pinNumber,PUD_UP);
delayMicroseconds(27);
if(digitalRead(pinNumber)==0) //SENSOR ANS
{
while(!digitalRead(pinNumber)); //wait to high
for(i=0;i<32;i++)
{
while(digitalRead(pinNumber)); //data clock start
while(!digitalRead(pinNumber)); //data start
delayMicroseconds(HIGH_TIME);
databuf*=2;
if(digitalRead(pinNumber)==1) //1
{
databuf++;
}
}
for(i=0;i<8;i++)
{
while(digitalRead(pinNumber)); //data clock start
while(!digitalRead(pinNumber)); //data start
delayMicroseconds(HIGH_TIME);
crc*=2;
if(digitalRead(pinNumber)==1) //1
{
crc++;
}
}
return 1;
}
else
{
return 0;
}
}
int main (void)
{
printf("Use GPIO1 to read data!\n");
if (-1 == wiringPiSetup()) {
printf("Setup wiringPi failed!");
return 1;
}
pinMode(pinNumber, OUTPUT); // set mode to output
digitalWrite(pinNumber, 1); // output a high level
printf("Enter OS-------\n");
while(1) {
pinMode(pinNumber,OUTPUT); // set mode to output
digitalWrite(pinNumber, 1); // output a high level
delay(3000);
if(readSensorData())
{
printf("Congratulations ! Sensor data read ok!\n");
printf("RH:%d.%d\n",(databuf>>24)&0xff,(databuf>>16)&0xff);
printf("TMP:%d.%d\n",(databuf>>8)&0xff,databuf&0xff);
databuf=0;
}
else
{
printf("Sorry! Sensor dosent ans!\n");
databuf=0;
}
}
return 0;
}