600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > dht11 java_树莓派从DHT11读取温湿度

dht11 java_树莓派从DHT11读取温湿度

时间:2020-04-10 14:57:33

相关推荐

dht11 java_树莓派从DHT11读取温湿度

树莓派之DHT11传感器

硬件DHT11

主要看其原理,具体的详细原理大家就搜索引擎都能搜到。

也是为了好奇心,入手一台便宜的示波器,看看具体波形,下面是我所测:

这张显示首次触发,主机至少下拉18ms。图中可以看到主机下拉快近30ms,其实代码实现中我也是用的是18ms。具体原因为什么会测出是快30ms下面谈到代码实现再解释。

这张图显示的是主机拉高20~40us,但实际代码中并不需要主动拉高。

这张图显示的是DHT11开始响应的信号80us低电平80us高电平,表示下面即将开始40位的数据输出。

这张图显示的是一位数据0的表示即:50us的低电平26~28us的高电平。

这张图显示的是一位数据1的表示:50us低电平70us高电平。

代码实现

之前有看到一个博客说是要修改/boot/config.txt,于是查看/boot/overlays/README的确有这么一段:

Name: dht11

Info: Overlay for the DHT11/DHT21/DHT22 humidity/temperature sensors

Also sometimes found with the part number(s) AM230x.

Load: dtoverlay=dht11,=

Params: gpiopin GPIO connected to the sensor's DATA output.

(default 4)

**但我实际测试时,开启和不开启都能测出同样的温湿度。**我不知道这是什么原因,我的树莓派装的是64位的。如果有对这个了解的请给我科普一下。我觉得官方既然有这段话,肯定是有原因的。

现在补充下,开启dtoverlay=dht11就可以直接读取温湿度,不需要自己实现了:

$ sudo cat /sys/devices/platform/dht11@0/iio\:device0/in_temp_input #读取温度

$ sudo cat /sys/devices/platform/dht11@0/iio\:device0/in_humidityrelative_input #读取湿度

但我实际使用过程中发现很多时候是读不出来,读出来的也都是0。网上查询了下,说是比较不稳定,遇到系统采样就读取错误。

下面是我读出的各种错误:

这是湿度读取,有读取错误,也有读到0,反正大多数情况是读取错误,很少读取到0,没有一次读取到正确湿度。

这是温度读取,有读到0,有读到错误,更有连接超时,也是大多数情况读取错误,很少情况读出0和连接超时,也是没有一次读到正确温度。

也在网上找了很多博客以及github上面对读DHT11数据的实现,发现很多都是使用计数器加死循环来读取数据的。感觉这样读是很不准确的,因为对树莓派我使用的都是远程连接库,这涉及到网络的延迟,毕竟你使用的计数器在本机并不在树莓派机器上。所以我采用了pigpio库的示例稍做修改,但也并不能完全排除网络延迟(触发时)。下面可以创建dht.py文件,将下面的代码复制进去:

import time

import pigpio

# 有效状态

DHT_GOOD = 0

# 校验不一致

DHT_BAD_CHECKSUM = 1

# 超出量程

DHT_BAD_DATA = 2

# 超时

DHT_TIMEOUT = 3

class sensor:

"""

A class to read the DHT11 temperature/humidity sensors.

"""

def __init__(self, pi, gpio, callback=None):

"""

Instantiate with the Pi and the GPIO connected to the

DHT temperature and humidity sensor.

Optionally a callback may be specified. If specified the

callback will be called whenever a new reading is available.

The callback receives a dictionary of GPIO, status,

temperature, and humidity.

The status will be one of:

0 DHT_GOOD (a good reading)

1 DHT_BAD_CHECKSUM (receieved data failed checksum check)

2 DHT_BAD_DATA (data receieved had one or more invalid values)

3 DHT_TIMEOUT (no response from sensor)

"""

self._pi = pi

self._gpio = gpio

self._callback = callback

# 标记数据是否解码完成

self._new_data = False

self._in_code = False

# DHT11计数读取的bit位

self._bits = 0

# DHT11读取的数据

self._code = 0

# 标记数据的状态

self._status = DHT_TIMEOUT

self._temperature = 0.0

self._humidity = 0.0

pi.set_mode(gpio, pigpio.INPUT)

self._last_edge_tick = pi.get_current_tick() - 10000

# 上升沿触发,这是读取DHT11数据的方法,也是这段代码的核心

self._cb_id = pi.callback(gpio, pigpio.RISING_EDGE, self._rising_edge)

def _datum(self):

return {'gpio': self._gpio, 'status': self._status,

'temperature': self._temperature, 'humidity': self._humidity}

def _validate_DHT11(self, b1, b2, b3, b4):

t = b2

h = b4

# 判断读取的温湿度是否超过DHT11的量程

# 只要有一项在量程范围内即认为数据有效

if ((t >= 0) and (t <= 50)) or ((h >= 20) and (h <= 90)):

valid = True

else:

valid = False

return (valid, t + b1 / 100, h + b3 / 100)

def _decode_dht11(self):

"""

+-------+

| DHT11 |

+-------+

Temp C| 0-50 |

+-------+

RH% | 20-80 |

+-------+

0 1 2 3 4

+------+------+------+------+------+

DHT11 |check-| temp | temp | RH% | RH% |

|sum | | | | |

+------+------+------+------+------+

"""

b0 = self._code & 0xff

b1 = (self._code >> 8) & 0xff

b2 = (self._code >> 16) & 0xff

b3 = (self._code >> 24) & 0xff

b4 = (self._code >> 32) & 0xff

chksum = (b1 + b2 + b3 + b4) & 0xFF

if chksum == b0:

valid, t, h = self._validate_DHT11(b1, b2, b3, b4)

if valid:

self._temperature = t

self._humidity = h

self._status = DHT_GOOD

else:

self._status = DHT_BAD_DATA

else:

self._status = DHT_BAD_CHECKSUM

self._new_data = True

def _rising_edge(self, gpio, level, tick):

edge_len = pigpio.tickDiff(self._last_edge_tick, tick)

self._last_edge_tick = tick

if edge_len > 10000:

self._in_code = True

self._bits = -2

self._code = 0

elif self._in_code:

self._bits += 1

if self._bits >= 1:

self._code <<= 1

if (edge_len >= 60) and (edge_len <= 150):

if edge_len > 100:

# 1 bit

self._code += 1

else:

# invalid bit

self._in_code = False

if self._in_code:

if self._bits == 40:

self._decode_dht11()

self._in_code = False

def _trigger(self, ajust):

self._new_data = False

self._status = DHT_TIMEOUT

self._pi.write(self._gpio, 0)

time.sleep((18 + ajust) / 1000)

self._pi.set_mode(self._gpio, pigpio.INPUT)

def cancel(self):

"""

"""

if self._cb_id is not None:

self._cb_id.cancel()

self._cb_id = None

# 参数ajust用于远程连接时的微调可以为负数

def read(self, ajust=0):

"""

This triggers a read of the sensor.

The returned data is a dictionary of GPIO, status,

temperature, and humidity.

The status will be one of:

0 DHT_GOOD (a good reading)

1 DHT_BAD_CHECKSUM (receieved data failed checksum check)

2 DHT_BAD_DATA (data receieved had one or more invalid values)

3 DHT_TIMEOUT (no response from sensor)

"""

self._trigger(ajust)

for i in range(5): # timeout after 0.25 seconds.

time.sleep(0.05)

if self._new_data:

break

datum = self._datum()

if self._callback is not None:

self._callback(datum)

return datum

这里使用的是上升沿触发,并且调用树莓派的tick这样避免了在本机使用计数器来读取数据的不准确性。但其中触发DHT11时使用的是本机的time.sleep,还记得上面图片主机下拉接近30ms吗?这就是因为调用的是本机线程的sleep。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。