DHT22 / AM2302 library for Wipy

Discuss development of drivers for external hardware and components, such as LCD screens, sensors, motor drivers, etc.
Target audience: Users and developers of drivers.
Miguel
Posts: 20
Joined: Fri Sep 09, 2016 7:53 am

DHT22 / AM2302 library for Wipy

Post by Miguel » Fri Sep 09, 2016 8:10 am

Hello!

Does anybody has a working driver for DHT22 and Wipy? I tried to use a code from this thread viewtopic.php?t=1392 but with no success (I always get the exception in decode function).

Michal

User avatar
platforma
Posts: 258
Joined: Thu May 28, 2015 5:08 pm
Location: Japan

Re: DHT22 / AM2302 library for Wipy

Post by platforma » Fri Sep 09, 2016 1:49 pm

Take a loot at http://wiki.micropython.org/Home#Other-Devices

I believe there is a DHT22 library somewhere there. I'm not sure if there has been any other work by somebody else in the meantime.

Miguel
Posts: 20
Joined: Fri Sep 09, 2016 7:53 am

Re: DHT22 / AM2302 library for Wipy

Post by Miguel » Fri Sep 09, 2016 3:58 pm

I know that library from Honza Kurik but it's written for pyboard and I don't know how to replace that ExtInt class. Wipy doesn's have such class in its machine module. Any help would be appreciated.

SpotlightKid
Posts: 463
Joined: Wed Apr 08, 2015 5:19 am

Re: DHT22 / AM2302 library for Wipy

Post by SpotlightKid » Fri Sep 09, 2016 8:08 pm

Miguel wrote:I don't know how to replace that ExtInt class. Wipy doesn's have such class in its machine module.
http://docs.micropython.org/en/latest/w ... ne.Pin.irq

quantalume
Posts: 15
Joined: Thu Aug 04, 2016 3:04 pm

Re: DHT22 / AM2302 library for Wipy

Post by quantalume » Mon Sep 12, 2016 6:57 pm

It should be pretty straightforward to modify the pyb driver for the WiPy as both external interrupts and the Timer class are implemented. I'll take a crack at this in the next few days if nobody beats me to it.

Miguel
Posts: 20
Joined: Fri Sep 09, 2016 7:53 am

Re: DHT22 / AM2302 library for Wipy

Post by Miguel » Mon Sep 12, 2016 7:28 pm

I have already checked the driver and realized that the Timer class on Wipy doesn't have the counter method. I thought it could be replaced with timerchannel.irq and a simple handler (counter function) but it's difficult to experiment without REPL (viewtopic.php?f=11&t=2127).

I am a total beginner so I will appreciate your help a lot.

Michal

quantalume
Posts: 15
Joined: Thu Aug 04, 2016 3:04 pm

Re: DHT22 / AM2302 library for Wipy

Post by quantalume » Mon Sep 12, 2016 10:34 pm

Miguel wrote:I have already checked the driver and realized that the Timer class on Wipy doesn't have the counter method.
True; however, his code sets the timer period to 1 uS and counts the number of uS between falling edges. We could do the same with something like this (inside the interrupt handler):

Code: Select all

times[index] = time.ticks_diff(start, time.ticks_us())
The value of start would be initialized in do_measurement() where he sets micros.counter(0).

Miguel
Posts: 20
Joined: Fri Sep 09, 2016 7:53 am

Re: DHT22 / AM2302 library for Wipy

Post by Miguel » Wed Sep 14, 2016 8:19 pm

I am still not able to make it work.

I modified the driver from Honza Kurik (https://github.com/kurik/uPython-DHT22) and polygontwist (https://github.com/polygontwist/uPython-DHT22) this way:

Code: Select all

from machine import Pin
import utime

# We need to use global properties here as any allocation of a memory (aka declaration of a variable)
# during the read cycle causes non-acceptable delay and we are loosing data than
data = None
dhttype = 0 #0=DHT11 1=DHT21/DHT22

FALL_EDGES = 42 # we have 42 falling edges during data receive

comm_start = 0
times = list(range(FALL_EDGES))
index = 0

# The interrupt handler
def edge(line):
   global index
   global comm_start
   global times
   times[index] = utime.ticks_diff(comm_start, time.ticks_us())
   if index < (FALL_EDGES - 1): # Avoid overflow of the buffer in case of any noise on the line
      index += 1

def init(data_pin = 'GP4', the_dhttype = 'DHT11'):
   global data
   global dhttype
   if(the_dhttype=='DHT11'):
      dhttype = 0
   else:
      dhttype = 1
   # Configure the pin for data communication
   data = Pin(data_pin)
   # Prepare interrupt handler
   data.irq(trigger=Pin.IRQ_FALLING, handler=None)
   data.irq(trigger=Pin.IRQ_FALLING, handler=edge)

# Start signal
def do_measurement():
   global comm_start
   global data
   global index
   # Send the START signal
   comm_start = utime.ticks_us
   data.init(mode = Pin.OUT)
   data.value(0)       # Host pulls low for 1 ms minimum
   utime.sleep_ms(2)   
   data.value(1)       # Host pulls high for 20 - 40 us
   utime.sleep_us(30)
   index = 0
   # Activate reading on the data pin
   data.init(mode = Pin.IN, pull = Pin.PULL_UP)
   # Till 5mS the measurement must be over
   utime.sleep_ms(5)

# Parse the data read from the sensor
def process_data():
   global dhttype
   global times
   i = 2 # We ignore the first two falling edges as it is a response on the start signal
   result_i = 0
   result = list([0, 0, 0, 0, 0])
   while i < FALL_EDGES:
      result[result_i] <<= 1
      if times[i] - times[i - 1] > 100:
         result[result_i] += 1
      if (i % 8) == 1:
         result_i += 1
      i += 1
   [int_rh, dec_rh, int_t, dec_t, csum] = result
	
   if dhttype==0:		#dht11
      humidity = int_rh 		#dht11 20% ~ 90%
      temperature = int_t 	#dht11 0..50°C
   else:			#dht21,dht22
      humidity = ((int_rh * 256) + dec_rh)/10 
      temperature = (((int_t & 0x7F) * 256) + dec_t)/10
      if (int_t & 0x80) > 0:
         temperature *= -1
	
   comp_sum = int_rh + dec_rh + int_t + dec_t
   if (comp_sum & 0xFF) != csum:
      raise ValueError('Checksum does not match')
   return (humidity, temperature)#,int_rh,dec_rh,int_t,dec_t)

def measure():
   do_measurement()
   if index != (FALL_EDGES -1):
      raise ValueError('Data transfer failed: %s falling edges only' % str(index))
   return process_data()

def hum():
   return measure()[0]

def temp():
   return measure()[1]


#using:
#import dht
#dht.init(the_dhttype='DHT22')
#dht.measure()
But there has to be a problem in init function, because sensor doesn't send any data. Any ideas?

Michal

Miguel
Posts: 20
Joined: Fri Sep 09, 2016 7:53 am

Re: DHT22 / AM2302 library for Wipy

Post by Miguel » Sun Sep 18, 2016 12:27 pm

I have installed MicroPyhton with disabled multithreading (many thanks to Robert: viewtopic.php?f=11&t=2127&start=40#p13927), fixed few typos and now I am finally getting some data from sensor. But nothing meaningful so far. Any help wuld be appreciated.

Michal

Code: Select all

from machine import Pin
import utime

# We need to use global properties here as any allocation of a memory (aka declaration of a variable)
# during the read cycle causes non-acceptable delay and we are loosing data than
data = None
dhttype = 0 #0=DHT11 1=DHT21/DHT22
FALL_EDGES = 42 # we have 42 falling edges during data receive
comm_start = 0
times = list(range(FALL_EDGES))
index = 0


# The interrupt handler
def edge(line):
   global index
   global comm_start
   global times
   times[index] = utime.ticks_diff(comm_start, utime.ticks_us())
   if index < (FALL_EDGES - 1): # Avoid overflow of the buffer in case of any noise on the line
      index += 1
   return   


def init(data_pin = 'GP4', the_dhttype = 'DHT11'):
   global data
   global dhttype
   if(the_dhttype=='DHT11'):
      dhttype = 0
   else:
      dhttype = 1
   # Configure the pin for data communication
   data = Pin(data_pin)
   # Prepare interrupt handler
   data.irq(trigger=Pin.IRQ_FALLING, handler=edge)


# Start signal
def do_measurement():
   global comm_start
   global data
   global index
   comm_start = utime.ticks_us()   
   data.init(mode = Pin.OUT)
   # Send the START signal   
   data.value(0)          # Host pulls low for 1 ms minimum
   utime.sleep_ms(2)   
   data.value(1)          # Host pulls high for 20 - 40 us
   utime.sleep_us(30)
   # Activate reading on the data pin
   index = 0
   data.init(mode = Pin.IN, pull = Pin.PULL_UP)
   # Till 5mS the measurement must be over
   utime.sleep_ms(5)


# Parse the data read from the sensor
def process_data():
   global dhttype
   global times
   i = 2 # We ignore the first two falling edges as it is a response on the start signal
   result_i = 0
   result = list([0, 0, 0, 0, 0])
   while i < FALL_EDGES:
      result[result_i] <<= 1
      if times[i] - times[i - 1] > 100:
         result[result_i] += 1
      if (i % 8) == 1:
         result_i += 1
      i += 1
   [int_rh, dec_rh, int_t, dec_t, csum] = result
	
   if dhttype==0:   #dht11
      humidity = int_rh 		#dht11 20% ~ 90%
      temperature = int_t 	#dht11 0..50°C
   else:            #dht21,dht22
      humidity = ((int_rh * 256) + dec_rh)//10 
      temperature = (((int_t & 0x7F) * 256) + dec_t)//10
      if (int_t & 0x80) > 0:
         temperature *= -1
	
   comp_sum = int_rh + dec_rh + int_t + dec_t
   if (comp_sum & 0xFF) != csum:
      raise ValueError('Checksum does not match')
   return (humidity, temperature)


def measure():
   global index
   do_measurement()
   if index != (FALL_EDGES -1):
      raise ValueError('Data transfer failed: {} falling edges only'.format(str(index)))
   return process_data()


def hum():
   return measure()[0]


def temp():
   return measure()[1]


#using:
#import dht
#dht.init(the_dhttype='DHT22')
#dht.measure()


jgmdavies
Posts: 57
Joined: Tue Aug 09, 2016 2:39 pm

Re: DHT22 / AM2302 library for Wipy

Post by jgmdavies » Tue Sep 20, 2016 8:47 am

Hi Michal,

Did you get this working by any chance?

I'm going to have a look soon - just waiting for DHT22s to arrive.

Are you sure your 'data' pin is always high for long enough at the start, before you make it low for "1 ms minimum"?

Also, shouldn't you make it active low again for a while after the "20 - 40 us" high? As it's then switched to an input, with PULL_UP, presumably it may not go low at that stage.

Thanks,
Jim

Post Reply