Reading temperature and humidity

Hi

I try to play with viper on ST nucleo, and I would like to read temperature and humidity on a dth22 sensors. Is it possible and can you give me some tip, I can not find any valuable information on the forum.

Thanks

Hi @mike 
the DTH22 is a digital sensor that streams on the data pin a series of pulses of different width.
long pulses are data 1 and short pulses are 0.
you can use the Viper ICU for capturing the pulses streaming from the sensor and then analyze them in order to convert the packet in data bits

here you can find the adafruit python library for raspberry that can be use as reference https://github.com/adafruit/Adafruit_Python_DHT

i suggest you to check ho the Viper infrared library works. at the end of the day what you need is a pulse time to data bit decoding algorithm that is what is already available in the infrared lib. you can find the lib here:
[viper install folder]\compiler\libs\infrared.py

moreover, @AndiB did a great job implementing a soft serial receiver for Viper that can be easily adapted to become a DTH22 reading lib. see here https://community.viperize.it/discussion/comment/406/#Comment_406


i also noted on the datsheet that the DHT22 need a trigger on the data wire for triggering the data sending.

this can be done by setting the pin connected to the DHT22 as pullup.Then the following cycle can be done for triggering the data sending:

  1. dht22 pin set to LOW
  2. wait at least 1000 us
  3. dht pin set to HIGH
  4. start ICU capture for 41 events (starting edge + 8bits * 5 packets) or timeout in 2.8 ms (roughly calculated as 40bits * 70us )
  5. decode the received time as 5 byte 
  6. convert received bytes as: DATA=8 bit integral RH data+8 bit decimal RH data+8 bit integral T data+8 bit decimal T data+8 bit check-sum
    If the data transmission is right
  7. calculate and verify the checksum: check-sum should be the last 8 bit of "8 bit integral RH data+8 bit decimal RH
    data+8 bit integral T data+8 bit decimal T data
info in very bad chinese/english here https://www.sparkfun.com/datasheets/Sensors/Temperature/DHT22.pdf

Points 4 and 5 are are the most tricky but the are already implemented and described in the infrared lib.

Hi Floyd,

Thanks for these valuable informations. I may not have time to implement this now, but I’ll give it a try and report my success or failure when I’ll investigate it.

Hi Mike, hi Floyd,

thanks to your discussion on reading a DHT22 I’ve finally read through the datasheet plus the adafruit DHT code, and started working on a Viper port for it.

It’s now all up and running, using timers to avoid threading problems.
Code can be found here:
https://hackaday.io/project/8242-viperphoton-weather-station/log/28666-dht22-temperaturehumidity-sensor

Let me know if there’s any bugs still,
Andi

Cool!
I am gonna download and test as soon as I’ll find a dht22
 :D 

Oh great ! I did not see the message earlier. I’ll have a look and give feedback very soon.

Mike

I would like to test this code on a DHT11. From what I read on adafruit:

sensor protocol and timing is similar to the DHT22 so check out the DHT22 datasheet for more information

I did a copy and past of AndiB’ s code. I connected the signal to D3, gnd and the power to 3.3v and even to VIN (5V) since those D pins are 5V tolerant on the Photon. But the code stops on “starting”.

Am I doing something wrong or there is some difference that I didn’t take into account?

On Adafruit they state “Comes with a 4.7K or 10K resistor, which you will want to use as a pullup from the data pin to VCC”. Maybe this is the part that I am missing?

It’s outputting 512 as temp and 1356 as humidity. Maybe some math needs to be changed.

Ok I did a very little mod to the code and I think it’s working even on DHT11, I’m getting 20° for temperature and 56% for humidity. The temperature is the same of a cheap IKEA alarm clock  :smiley: .

Changes:
1)renamed DHT22 to DHT11
2) from 0:16 to 0:8 and from 16:32 to 16:24 since the last 8 bits are 0 because dht11 only returns integer values from the temperature and humidity reading.

# extract hum, temp parts (8bits each)
    tmp_hum = BinListDHT11[0:8]    #1st 8 bits are humidity, 2nd 8 bits are temperature
    tmp_temp = BinListDHT11[16:24]
3)<br>The for goes up to 8 not 16 for the reason explained before.<br><pre class="CodeBlock"><pre class="CodeBlock">for i in range(8):<br>&nbsp; &nbsp; &nbsp; &nbsp; DHT11_temp += tmp_temp[i]*(2**i)<br>&nbsp; &nbsp; &nbsp; &nbsp; DHT11_hum += tmp_hum[i]*(2**i)<br>&nbsp; &nbsp; DHT11_temp = DHT11_temp<br>&nbsp; &nbsp; DHT11_hum = DHT11_hum<br>&nbsp; &nbsp;&nbsp;<br>&nbsp; &nbsp; digitalWrite(_receivepinShort, HIGH)
4) removed the /10 divison for the same reason of 2) and 3) mod since since there isn't the decimal for DHT11.<br><br><pre class="CodeBlock">&nbsp; &nbsp; DHT11_temp = DHT11_temp<br>&nbsp; &nbsp; DHT11_hum = DHT11_hum
A big thanks to "andreas.betz" of course, the author of the DHT22 code who did the big job.
Here the code with my mods :

################################################################################
# Temperature
#
# Created: 2015-12-10 15:57:20.083102
#
################################################################################
################################################################################
# DHT11 on viperized Photon (V2)
#
# Created: 2015-12-04
#
# This software provides data readout from a DHT11 temperature+humidity sensor on any digital pin of an MCU running VIPER python.
# This code was developed and tested on a viperized Photon board (Particle Photon).
# It follows closely the Arduino code by Adafruit (https://github.com/adafruit/DHT-sensor-library).
#
# Copyright (c) 2015 A.C. Betz.  All right reserved. Developed using the VIPER IDE. 
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#
#############################################################################################################################

############
#########
# DO THESE THINGS IN THE MAIN PROGRAM
#########
############
# import the streams module for USB serial port.
import streams
# open the default serial port
streams.serial()
#import ICU library
import icu
import timers
############
#########
# end of things to do in main program
#########
############

#########
# functions
#########
def getDHT11data(_receivepin,_receivepinShort): #expects input like (D3.ICU,D3) [TODO: do some nifty string manipulation to get "D3" from D3.ICU]
    
    ### don't execute this more than once every 2s!
    
    timer1 = timers.timer()
    timer1.start()
    foo = 0
    
    DHT11_temp = 0
    DHT11_hum = 0
    BinListDHT11 = []
    timeListDHT11 = []
    
    #Go into high impedence state to let pull-up raise data line level andstart the reading process.
    pinMode(_receivepinShort,OUTPUT)
    digitalWrite(_receivepinShort, HIGH)
    timer1.reset()
    while timer1.get()<10:
        foo+=1
    #First set data line low for 10 milliseconds.
    digitalWrite(_receivepinShort, LOW)
    timer1.reset()
    while timer1.get()<10:
        foo+=1 # maybe change this while to one_shot?
    tmpICU = icu.capture(_receivepin,LOW,86,10000,time_unit=MICROS)#call to ICU seems to take some time, thus call *before* initiation is finished
    # End the start signal by setting data line high for [40 microseconds].
    digitalWrite(_receivepinShort, HIGH)
    pinMode(_receivepinShort,INPUT_PULLUP)
    
    # remove all even entries, they're just "start bits", discard 1st two entries
    for i in range(3,len(tmpICU),1):
        if i%2!=0: #these are the odd entries
            timeListDHT11.append(tmpICU[i])
    # convert to list of binaries
    for i in range(len(timeListDHT11)):
        if timeListDHT11[i] < 35:    # shouldn't be longer than 28us, but allow some wiggle room here
            BinListDHT11.append(0)
        else:
            BinListDHT11.append(1)    
    # extract hum, temp parts (8bits each)
    tmp_hum = BinListDHT11[0:8]    #1st 8 bits are humidity, 2nd 8 bits are temperature
    tmp_temp = BinListDHT11[16:24]
    tmp_tempSign = 1
    if tmp_temp[0] == 1:
        tmp_tempSign = -1 # neg temperatures are encoded most significant bit = 1
        tmp_temp[0] = 0
    tmp_temp = tmp_temp[::-1] #invert the list for conversion to decimal
    tmp_hum = tmp_hum[::-1]
    
    for i in range(8):
        DHT11_temp += tmp_temp[i]*(2**i)
        DHT11_hum += tmp_hum[i]*(2**i)
    DHT11_temp = DHT11_temp
    DHT11_hum = DHT11_hum
    
    digitalWrite(_receivepinShort, HIGH)
    
    timer1.clear()
    
    return (DHT11_hum, DHT11_temp)


############################################################################################
############################################################################################
#test the code
sleep(1000)
print("starting")
sleep(500)

global DHT11_temp
global DHT11_hum
timer2 = timers.timer()
timer2.start()
while True:
    if timer2.get()>2500:
        DHT11_hum, DHT11_temp = getDHT11data(D3.ICU,D3)
        print(DHT11_temp,DHT11_hum)
        timer2.reset()
     ```


Great job @Davide!
I’m really happy to see that my code was useful for you.

Also, it seems the DHT11 is the better sensor: my DHT22 is consistently a few degrees/percent too high… 

Great, thanks AndiB and Davide, I just tested both code with DHT11 and DHT22 and they work great on a nucleo F401. That’s awesome :slight_smile:

Mike

Great job guys!  <3

what could i do if ICU is not supported?