🦔

温度センサー DHT11、DHT22のサンプルコード

2022/12/18に公開

DHT11

回路、配線図

micropython @ESP32

ドライブのDHTをインポートして使える

import dht
import machine

d = dht.DHT11(machine.Pin(4))
d.measure()
d.temperature() # 例: 23 (°C)
d.humidity()    # 例: 41 (% RH)

d = dht.DHT22(machine.Pin(4))
d.measure()
d.temperature() # 例: 23.6 (°C)
d.humidity()    # 例: 41.3 (% RH)

micropython @RP2

上記のdhtはRP2では使えません!!
(温度を取得しても0となります)

こちらの記事を参考にします
https://jhalfmoon.com/dbc/2021/05/28/micropython的午睡27-ラズパイpico、dht11接続、ソフト現物合わせ/

以下、引用

class Dht11
class Dht11:
    """DHT11 temperature/humidity sensor IF class"""
    def __init__(self, pinN):
        self.dht11 = Pin(pinN, Pin.OPEN_DRAIN, Pin.PULL_UP)
        self.dht11.value(1)
        self.buf = []
        self.temperature = None
        self.humidity = None
        self.crc = False
        self.crcC = None
        self.crcR = None
        self.ERROR = 0
    def startSignal(self):
        self.dht11.value(0)
        time.sleep_ms(19)
        self.dht11.value(1)
        time.sleep_us(20)
    
    def waitSIG(self, sig, timeOut):
        count = 0
        while self.dht11.value() == sig:
            count += 1
            if count > timeOut:
                return False
        return True
    
    def bitRead(self):
        while self.dht11.value() == 0:
            pass
        if self.dht11.value() == 0:
            return 0
        if self.dht11.value() == 0:
            return 0
        if self.dht11.value() == 0:
            return 0
        if self.dht11.value() == 0:
            return 0
        if self.dht11.value() == 0:
            return 0
        if self.dht11.value() == 0: #6
            return 1
        if self.dht11.value() == 0:
            return 1
        return 1
    
    def b2B(self, lis):
        work = 0
        for i in lis:
            work <<=1
            work += i
        return work
    
    def convertData(self):
        rhI = self.b2B(self.buf[0:7])
        rhD = self.b2B(self.buf[7:15])
        tmI = self.b2B(self.buf[15:23])
        tmD = self.b2B(self.buf[23:31])
        self.crcR = self.b2B(self.buf[31:39])
        self.crcC = (rhI + rhD + tmI + tmD) & 0xFF
        if self.crcR == self.crcC:
            self.crc = True
        else:
            self.crc = False
        self.temperature = (tmI & 0x7F) + (tmD / 10)
        if tmI & 0x80:
            self.temperature *= -1
        self.humidity = rhI + (rhD / 10 )
        self.buf.clear()
    def read(self):
        self.ERROR = 0
        self.startSignal()
        if not self.waitSIG(0, 100):
            self.ERROR = 1
            return False
        if not self.waitSIG(1, 1000):
            self.ERROR = 2
            return False
        if not self.waitSIG(0, 1000):
            self.ERROR = 3
            return False
        for idx in range(40):
            b1 = self.bitRead()
            self.buf.append(b1)
        self.convertData()
        return True
main.py
dht11 = Dht11(17)

DHT22 micropython @RP2

こちらのライブラリを使います
https://github.com/danjperron/PicoDHT22

DHT22.py
DHT22.py
'''
 *
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2021 Daniel Perron
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
'''

import utime
import rp2
from rp2 import PIO, asm_pio
from machine import Pin

#
#     A     B   C   D   E   F
#          ___     ___     ...
#     ____/   \___/   \___/   \
#
#     A = start pulse (> 1ms )
#     B = 2-40 us 
#     C = 80 us
#     D = 80 us
#
#     E and F are  data clock
#
#     E = 50 us
#     F =  26-28 us => 0    70 us => 1
#

    
@asm_pio(set_init=(PIO.OUT_HIGH),autopush=True, push_thresh=8)
def DHT22_PIO():
    # clock set at 500Khz  Cycle is 2us
    # drive output low for at least 20ms
    set(y,1)                    # 0
    pull()                      # 1
    mov(x,osr)                  # 2
    set(pindirs,1)              # 3 set pin to output
    set(pins,0)                 # 4 set pin low
    label ('waitx')
    jmp(x_dec,'waitx')          # 5 decrement x reg every 32 cycles
    set(pindirs,0)              # 6 set pin to input 
    # STATE A. Wait for high at least 80us. max should be  very short
    set(x,31)                   # 7 
    label('loopA')
    jmp(pin,'got_B')            # 8
    jmp(x_dec,'loopA')          # 9
    label('Error')
    in_(y,1)                    # 10
    jmp('Error')                # 11  Infinity loop error

    # STATE B. Get HIGH pulse. max should be 40us
    label('got_B')
    set(x,31)                   # 12
    label('loop_B')
    jmp(x_dec,'check_B')        # 13
    jmp('Error')                # 14
    label('check_B') 
    jmp(pin,'loop_B')           # 15
 
    # STATE C. Get LOW pulse. max should be 80us
    set(x,31)                   # 16
    label('loop_C')
    jmp(pin,'got_D')            # 17     
    jmp(x_dec,'loop_C')         # 18
    jmp('Error')                # 19
    
    # STATE D. Get HIGH pulse. max should be 80us
    label('got_D')
    set(x,31)                   # 20
    label('loop_D')
    jmp(x_dec,'check_D')        # 21
    jmp('Error')                # 22
    label('check_D')
    jmp(pin,'loop_D')           # 23
    
    # STATE E. Get Low pulse delay. should be around 50us
    set(x,31)                   # 24
    label('loop_E')
    jmp(pin,'got_F')            # 25
    jmp(x_dec,'loop_E')         # 26
    jmp('Error')                # 27
   
    # STATE F.
    # wait 40 us
    label('got_F')              
    nop() [20]                  # 28
    in_(pins,1)                 # 29
    # now wait for low pulse
    set(x,31)                   # 30
    jmp('loop_D')               # 31    




class PicoDHT22:
    
    def __init__(self,dataPin, powerPin=None,dht11=False,smID=1):
        self.dataPin = dataPin
        self.powerPin = powerPin
        self.dht11 = dht11
        self.smID = smID
        self.dataPin.init(Pin.IN, Pin.PULL_UP)
        if self.powerPin is not None:
            self.powerPin.init(Pin.OUT)
            self.powerPin.value(0)
        self.sm= rp2.StateMachine(self.smID)
        




    def read_array(self):
        if self.powerPin is not None:
            self.powerPin.value(1)
            utime.sleep_ms(800)
        utime.sleep_ms(200)
        #start state machine
        self.sm.init(DHT22_PIO,freq=500000,
                     set_base=self.dataPin,
                     in_base=self.dataPin,
                     jmp_pin=self.dataPin)
        if self.dht11:
            self.sm.put(10000)
        else:
            self.sm.put(1000)
        self.sm.active(1)
        value = []
        for i in range(5):
            value.append(self.sm.get())
        self.sm.active(0)
        if self.powerPin is not None:
            self.powerPin.value(0)
        return value
 
    def read(self):
        value = self.read_array()
        sumV = 0
        for i in range(4):
            sumV += value[i]
        if (sumV & 0xff) == value[4]:
            if self.dht11:
                humidity=value[0] & 0x7f
                temperature=value[2] 
            else:                
                humidity=((value[0]<<8)  + value[1])/10.0
                temperature=(((value[2] &0x7f) << 8)  + value[3]) /10.0 
            if (value[2] & 0x80) == 0x80:
                temperature = -temperature            
            return temperature, humidity
        else:
            return None, None
        
if __name__ == "__main__":
    from machine import Pin
    from PicoDHT22 import PicoDHT22
    import utime
    dht_data = Pin(15,Pin.IN,Pin.PULL_UP)
    dht_sensor=PicoDHT22(dht_data,Pin(14,Pin.OUT),dht11=False)
    while True:
        T,H = dht_sensor.read()
        if T is None:
            print(" sensor error")
        else:
            print("{:3.1f}'C  {:3.1f}%".format(T,H))
        #DHT22 not responsive if delay to short
        utime.sleep_ms(500)

C/C++ @Arduino UNO

実行前にライブラリを追加する必要があります

サンプルコード
#include <dht11.h>
dht11 DHT11;
#define DHT11PIN 8
void setup()
{
	Serial.begin(9600);
}
void loop()
{
	DHT11.read(DHT11PIN);
	Serial.print("Temperature=");
	Serial.print(DHT11.temperature);
	Serial.print(" C");
	Serial.print('\t');
	Serial.print("Humidity=%");
	Serial.println(DHT11.humidity);
	delay(500);
}

Discussion