PDA

View Full Version : DHT22, AM2302 and pic18F2320



bitmaniac
- 3rd April 2013, 13:16
Hi! my friends!

I am starting a project for my father's home-made incubator egg machine.

Αs I had an DHT22 (ΑΜ2302) humidity sensor in-hand I tried to make a quick code to see if I can use it....

I studied carefully this datasheet http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Weather/RHT03.pdf
BUT I also found another datasheet elsewhere (I will upload the link as soon as I find the link) with slightly different timming values for starting pulse etc

Here is a rough description of connected circuit + the code I tried out

DHT-22 connected to PORTB.4 of 18F2320
I use NO external pull-up on pin2 (DATA) but pic PORTB PULL-UPS ,instead.

my code:


'***************************************
'* Name : 18f2320_DHT22_AM2302.BAS *
'* Author : BITmaniac *
'* Notice : Copyright (c) 2013 *
'* Date : 1/3/2013 *
'***************************************

;include "ALLDIGITAL.pbp"
;@ __CONFIG _CONFIG1H, _INTIO2_OSC_1H & _IESO_OFF_1H ' use internal osc
@ __CONFIG _CONFIG1H, _XT_OSC_1H & _IESO_OFF_1H ' use internal osc
@ __CONFIG _CONFIG2L, _PWRT_OFF_2L & _BOR_OFF_2L
@ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_512_2H
@ __CONFIG _CONFIG3H, _MCLRE_OFF_3H & _PBAD_DIG_3H ;& _CCP2MX_OFF_3H
@ __CONFIG _CONFIG4L, _LVP_OFF_4L

define osc 4

DEFINE LCD_DREG PORTC ' LCD Data Port
DEFINE LCD_DBIT 4 ' Starting Data Bit
DEFINE LCD_RSREG PORTC ' Register Select Port
DEFINE LCD_RSBIT 2 ' Register Select Bit
DEFINE LCD_RWREG PORTC ' LCD read/write port
DEFINE LCD_RWBIT 1 ' LCD read/write bit
DEFINE LCD_EREG PORTC ' Enable Port
DEFINE LCD_EBIT 0 ' Enable Bit
DEFINE LCD_BITS 4 ' Data Bus Size
DEFINE LCD_LINES 2 ' Number of Lines on LCD
DEFINE LCD_COMMANDUS 2000
DEFINE LCD_DATAUS 50
pause 1000

ADCON0=0
ADCON1=00001111 'All digital
CMCON=7 'Comparators OFF
INTCON2.7=0 'RBPU =0 , TURN ON PORTB PULL-UPS

TRISA=%00000000
TRISB=%00001111


PORTA=0
PORTB=0

humread var word '16-bit var to store humidity
tmpread var word '16-bit var to store temperature
checksum var BYTE '8-bit var to store checksum
x var byte 'general var
p var byte [40] 'store pulse var

led var LATA.0

clear
high LATA.1:high LATA.2:high LATA.3:high LATA.4
high PORTB.4
;---------- main program -------------
high led
pause 500
LCDout $FE,$1,"DHT-22 sensor"
LCDout $FE,$c0,"reading..."

start:
;---- check_DHT22 ----
;-== send StartSignal ==-
TRISB.4 = 0 'Data port is output
high PORTB.4
low PORTB.4
pause 20
high PORTB.4
pauseus 20
;-== wait response from Sensor ==-
TRISB.4 = 1 'Data port is input
while PORTB.4=1:wend 'wait for low
pauseus 80
while PORTB.4=0:wend 'wait for high
pauseus 20
low led
;-== read 40bits data from DHT22 ==-
for x=1 to 40
pulsin PORTB.4,1,p(x) 'measure 40 high pulses only & store (resoloution is 10us)
next x
;-== convert to '0' & '1' ==-
for x=1 to 40
if p(x)>=2 and p(x)<=4 then p(x)=0 'if pulsewidth between 20 and 40uS then read as '0'
if p(x)>=6 and p(x)<=8 then p(x)=1 'if pulsewidth between 60 and 80uS then read as '1'
next x
;-== convert bin to dec ==-
humread=32768*p(1)+16384*p(2)+8192*p(3)+4096*p(4)+ 2048*p(5)+1024*p(6)+512*p(7)+256*p(8)+128*p(9)+64* p(10)+32*p(11)+16*p(12)+8*p(13)+4*p(14)+2*p(15)+1* p(16)
tmpread=16384*p(18)+8192*p(19)+4096*p(20)+2048*p(2 1)+1024*p(22)+512*p(23)+256*p(24)+128*p(25)+64*p(2 6)+32*p(27)+16*p(28)+8*p(29)+4*p(30)+2*p(31)+1*p(3 2)
checksum=128*p(33)+64*p(34)+32*p(35)+16*p(36)+8*p( 37)+4*p(38)+2*p(39)+1*p(40)
;-== show real values ==-
;-== show real values ==-
lcdout $fe,$01,"Hum:",dec humread,"% >",dec checksum
lcdout $fe,$C0,"Temp:",dec tmpread,"o"
goto start



(see remarks inside the code)

The problem I have is -as far as I can see- I get response from the sensor BUT with strange results ...see attached foto

Any ideas are welcome...

maybe the problem is with pulsin command trying to catch-up with the sensor pulses.... or timming problems....

Also noticed that I get no CRC checksum data ! (following > charackter in the foto)

6953

Any advice is welcome.

Demon
- 3rd April 2013, 20:52
P is defined as byte, but referred as bit?

Edit: what if you display the data you receive, pause a few seconds, then continue. Confirm you're getting data as you expect it.

Edit 2: Does your array start at 0 or 1? (Haven't coded in a while).

Only 17 entries for temp, missing #17.

Robert

bitmaniac
- 4th April 2013, 05:40
P is defined as byte, but referred as bit?
It should be byte as it stores the width of the pulse (in uS) PULSIN receives.
Then it simply stores on itself the value of '1' or '0' according the width of this pulse.


Edit: what if you display the data you receive, pause a few seconds, then continue. Confirm you're getting data as you expect it.
Hmm! I will give it a try and let you knoiw ....Good thoughts my friend!


Edit 2: Does your array start at 0 or 1? (Haven't coded in a while).
I don't think is matter... Arrays start at 0.


Only 17 entries for temp, missing #17.
I just try to not capture the higher bit of temp (1 means temp is below 0 degrees Celsius) for the moment just testing....

Robert Thank you very much for replying

As I can see no example ANYWHERE in the net for DHT22 and picbasic , when completed it would be a good starting point for experiments with this low cost sensor!

bitmaniac
- 4th April 2013, 11:34
In order to find out what pulsin really grabs I used serout data to debug...
Here are the results so far -after reading the sensor 3 times.... :
NOTE I changed the code a little bit so I can capture all data (included the start transmit 1bit before each 'bit')

* * * START * * *
01=> 50uS bit_val= 1
02=> 20uS bit_val= 0
03=> 50uS bit_val= 1
04=> 30uS bit_val= 1
05=> 50uS bit_val= 1
06=> 70uS bit_val= 1
07=> 50uS bit_val= 1
08=> 70uS bit_val= 1
09=> 50uS bit_val= 1
10=> 20uS bit_val= 0
11=> 50uS bit_val= 1
12=> 30uS bit_val= 1
13=> 50uS bit_val= 1
14=> 20uS bit_val= 0
15=> 50uS bit_val= 1
16=> 30uS bit_val= 1
17=> 70uS bit_val= 1
18=> 20uS bit_val= 0
19=> 50uS bit_val= 1
20=> 60uS bit_val= 0
21=> 50uS bit_val= 1
22=> 70uS bit_val= 1
23=> 50uS bit_val= 1
24=> 30uS bit_val= 1
25=> 50uS bit_val= 1
26=> 20uS bit_val= 0
27=> 50uS bit_val= 1
28=> 0uS bit_val= 0
29=> 0uS bit_val= 0
30=> 0uS bit_val= 0
31=> 0uS bit_val= 0
32=> 0uS bit_val= 0
33=> 0uS bit_val= 0
34=> 0uS bit_val= 0
35=> 0uS bit_val= 0
36=> 0uS bit_val= 0
37=> 0uS bit_val= 0
38=> 0uS bit_val= 0
39=> 0uS bit_val= 0
40=> 0uS bit_val= 0
41=> 0uS bit_val= 0
42=> 0uS bit_val= 0
43=> 0uS bit_val= 0
44=> 0uS bit_val= 0
45=> 0uS bit_val= 0
46=> 0uS bit_val= 0
47=> 0uS bit_val= 0
48=> 0uS bit_val= 0
49=> 0uS bit_val= 0
50=> 0uS bit_val= 0
51=> 0uS bit_val= 0
52=> 0uS bit_val= 0
53=> 0uS bit_val= 0
54=> 0uS bit_val= 0
55=> 0uS bit_val= 0
56=> 0uS bit_val= 0
57=> 0uS bit_val= 0
58=> 0uS bit_val= 0
59=> 0uS bit_val= 0
60=> 0uS bit_val= 0
61=> 0uS bit_val= 0
62=> 0uS bit_val= 0
63=> 0uS bit_val= 0
64=> 0uS bit_val= 0
65=> 0uS bit_val= 0
66=> 0uS bit_val= 0
67=> 0uS bit_val= 0
68=> 0uS bit_val= 0
69=> 0uS bit_val= 0
70=> 0uS bit_val= 0
71=> 0uS bit_val= 0
72=> 0uS bit_val= 0
73=> 0uS bit_val= 0
74=> 0uS bit_val= 0
75=> 0uS bit_val= 0
76=> 0uS bit_val= 0
77=> 0uS bit_val= 0
78=> 0uS bit_val= 0
79=> 0uS bit_val= 0
80=> 0uS bit_val= 0
* * * END * * *

* * * START * * *
01=> 50uS bit_val= 1
02=> 20uS bit_val= 0
03=> 50uS bit_val= 1
04=> 30uS bit_val= 1
05=> 50uS bit_val= 1
06=> 70uS bit_val= 1
07=> 50uS bit_val= 1
08=> 70uS bit_val= 1
09=> 50uS bit_val= 1
10=> 20uS bit_val= 0
11=> 50uS bit_val= 1
12=> 30uS bit_val= 1
13=> 50uS bit_val= 1
14=> 20uS bit_val= 0
15=> 50uS bit_val= 1
16=> 20uS bit_val= 0
17=> 70uS bit_val= 1
18=> 20uS bit_val= 0
19=> 50uS bit_val= 1
20=> 70uS bit_val= 1
21=> 50uS bit_val= 1
22=> 60uS bit_val= 0
23=> 50uS bit_val= 1
24=> 30uS bit_val= 1
25=> 50uS bit_val= 1
26=> 20uS bit_val= 0
27=> 50uS bit_val= 1
28=> 0uS bit_val= 0
29=> 0uS bit_val= 0
30=> 0uS bit_val= 0
31=> 0uS bit_val= 0
32=> 0uS bit_val= 0
33=> 0uS bit_val= 0
34=> 0uS bit_val= 0
35=> 0uS bit_val= 0
36=> 0uS bit_val= 0
37=> 0uS bit_val= 0
38=> 0uS bit_val= 0
39=> 0uS bit_val= 0
40=> 0uS bit_val= 0
41=> 0uS bit_val= 0
42=> 0uS bit_val= 0
43=> 0uS bit_val= 0
44=> 0uS bit_val= 0
45=> 0uS bit_val= 0
46=> 0uS bit_val= 0
47=> 0uS bit_val= 0
48=> 0uS bit_val= 0
49=> 0uS bit_val= 0
50=> 0uS bit_val= 0
51=> 0uS bit_val= 0
52=> 0uS bit_val= 0
53=> 0uS bit_val= 0
54=> 0uS bit_val= 0
55=> 0uS bit_val= 0
56=> 0uS bit_val= 0
57=> 0uS bit_val= 0
58=> 0uS bit_val= 0
59=> 0uS bit_val= 0
60=> 0uS bit_val= 0
61=> 0uS bit_val= 0
62=> 0uS bit_val= 0
63=> 0uS bit_val= 0
64=> 0uS bit_val= 0
65=> 0uS bit_val= 0
66=> 0uS bit_val= 0
67=> 0uS bit_val= 0
68=> 0uS bit_val= 0
69=> 0uS bit_val= 0
70=> 0uS bit_val= 0
71=> 0uS bit_val= 0
72=> 0uS bit_val= 0
73=> 0uS bit_val= 0
74=> 0uS bit_val= 0
75=> 0uS bit_val= 0
76=> 0uS bit_val= 0
77=> 0uS bit_val= 0
78=> 0uS bit_val= 0
79=> 0uS bit_val= 0
80=> 0uS bit_val= 0
* * * END * * *

...remember that I use a 4Mhz crystal so the pulse width is returned in 10us increments.

Acoording to the above dubugging infos we can see a 50uS pulse wich according to datasheet is the pulse before each "0" or "1" pulse!

One weird thing is also tha after pulse number 27 I read no pulses!!

Demon
- 4th April 2013, 12:26
Did you use 100nF capacitor as mentionned in DHT22 datasheet?

Edit: there's a guy here that gets only 21 elements, sounds like a similar issue:
http://www.picaxeforum.co.uk/showthread.php?17733-Using-DHT22-Please-Help

Edit 2: this is in C, but read the blog at top. Has several interesting comments.
http://blog.ringerc.id.au/2012/01/using-rht03-aliases-rht-22.html?m=1

Can you run faster than 4mhz? Can you use internal osc instead? 18F generally can go quite fast.

Robert

bitmaniac
- 4th April 2013, 12:52
Thanks for trying to help my problem out my friend!

Yes, I tried with 100nf on power.

I am searching over the net for a week now and came across 2 different datasheet of the same sensor...DHT22 and sites with code in C e.t.c I have read most of them and trying to use picbasic instead!

I will examine carefully your links (VERY good infos!!!) and come back....

Demon
- 4th April 2013, 13:05
Well this guy got it working in C after playing with delays so it's most likely a timing issue.

18F2320 can run at 40MHz internally, I'd try that first. Others mention waiting at least 2 seconds between samples.

http://forum.43oh.com/topic/2239-solved-dht22-temp-rh-one-wire-sensor-on-energia/

Robert

bitmaniac
- 5th April 2013, 10:25
SUCCESS!!!

After trying to increase crystal to 25Mhz and also 40Mhz I had the same problem of grabing only the first 21 pulses.... (problems with PULSIN speed...hmm....)

Finally the solution was just to use PULSIN 40 times! in my code and not use the FOR NEXT LOOP !

So there was timming speed problems and had to improve my code for speed - a little...

Now I am getting correct results

Here is the final code (the only thing left is to check checksum for errors!) ENJOY.


'***************************************
'* Name : 18f2320_DHT22_AM2302.BAS *
'* Author : bitmaniac Alexandros Z.*
'* Notice : Copyright (c) 2013 *
'* Date : 5/4/2013 *
'***************************************

;include "ALLDIGITAL.pbp"
;@ __CONFIG _CONFIG1H, _INTIO2_OSC_1H & _IESO_OFF_1H ' use internal osc
@ __CONFIG _CONFIG1H, _HS_OSC_1H & _IESO_OFF_1H ' use internal osc
@ __CONFIG _CONFIG2L, _PWRT_OFF_2L & _BOR_OFF_2L
@ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_512_2H
@ __CONFIG _CONFIG3H, _MCLRE_OFF_3H & _PBAD_DIG_3H ;& _CCP2MX_OFF_3H
@ __CONFIG _CONFIG4L, _LVP_OFF_4L

DEFINE LCD_DREG PORTC ' LCD Data Port
DEFINE LCD_DBIT 4 ' Starting Data Bit
DEFINE LCD_RSREG PORTC ' Register Select Port
DEFINE LCD_RSBIT 2 ' Register Select Bit
DEFINE LCD_RWREG PORTC ' LCD read/write port
DEFINE LCD_RWBIT 1 ' LCD read/write bit
DEFINE LCD_EREG PORTC ' Enable Port
DEFINE LCD_EBIT 0 ' Enable Bit
DEFINE LCD_BITS 4 ' Data Bus Size
DEFINE LCD_LINES 2 ' Number of Lines on LCD
DEFINE LCD_COMMANDUS 2000
DEFINE LCD_DATAUS 50
pause 300

define osc 4

ADCON0=0
ADCON1=00001111 'All digital
CMCON=7 'Comparators OFF
INTCON2.7=0 'RBPU =0 , TURN ON PORTB PULL-UPS

TRISA=%00000000
TRISB=%00001111

PORTA=0
PORTB=0

humread var word '16-bit var to store humidity
tmpread var word '16-bit var to store temperature
checksum var BYTE '8-bit var to store checksum
x var byte 'general var
pulse var byte [81] 'store pulse var
p var bit [81] 'store pulse var

led var LATA.0
dht_port var PORTB.4

clear
high dht_port
high led

;---------- main program -------------
high led
LCDout $FE,$01,"DHT-22"
LCDout $FE,$C0,"testing..."
pause 2000

start:
;---- check_DHT22 ----
;-== send StartSignal ==-
TRISB.4 = 0 'Data port is output
high dht_port
pauseus 10 'send 10uS high pulse
low dht_port
pause 1 'send 1mS high pulse
high dht_port
;-== wait response from Sensor ==-
TRISB.4 = 1 'Data port is input
while dht_port=1:wend 'wait for low from DHT
while dht_port=0:wend 'wait for high FROM DHT
high led
;-== Grab 40bits data from DHT22 ==-
pulsin PORTB.4,1,pulse(1) 'Humidity HighBit data
pulsin PORTB.4,1,pulse(2)
pulsin PORTB.4,1,pulse(3)
pulsin PORTB.4,1,pulse(4)
pulsin DHT_port,1,pulse(5)
pulsin DHT_port,1,pulse(6)
pulsin DHT_port,1,pulse(7)
pulsin DHT_port,1,pulse(8)
pulsin DHT_port,1,pulse(9)
pulsin DHT_port,1,pulse(10)
pulsin DHT_port,1,pulse(11)
pulsin DHT_port,1,pulse(12)
pulsin DHT_port,1,pulse(13)
pulsin DHT_port,1,pulse(14)
pulsin DHT_port,1,pulse(15)
pulsin DHT_port,1,pulse(16) 'Humidity LowBit data
pulsin DHT_port,1,pulse(17) 'Temperature HighBit data (1 means below 0 degree!)
pulsin DHT_port,1,pulse(18)
pulsin DHT_port,1,pulse(19)
pulsin DHT_port,1,pulse(20)
pulsin DHT_port,1,pulse(21)
pulsin DHT_port,1,pulse(22)
pulsin DHT_port,1,pulse(23)
pulsin DHT_port,1,pulse(24)
pulsin DHT_port,1,pulse(25)
pulsin DHT_port,1,pulse(26)
pulsin DHT_port,1,pulse(27)
pulsin DHT_port,1,pulse(28)
pulsin DHT_port,1,pulse(29)
pulsin DHT_port,1,pulse(30)
pulsin DHT_port,1,pulse(31)
pulsin DHT_port,1,pulse(32) 'Temperature LowBit data
;pulsin DHT_port,1,pulse(33) 'Checksum HighBit
;pulsin DHT_port,1,pulse(34)
;pulsin DHT_port,1,pulse(35)
;pulsin DHT_port,1,pulse(36)
;pulsin DHT_port,1,pulse(37)
;pulsin DHT_port,1,pulse(38)
;pulsin DHT_port,1,pulse(39)
;pulsin DHT_port,1,pulse(40) 'Checksum LowBit
;-== convert to '0' & '1' ==-
for x=1 to 40
if pulse(x)>=2 and pulse(x)<=4 then p(x)=0 'if pulsewidth between 20 and 40uS then read as '0'
if pulse(x)>=6 and pulse(x)<=8 then p(x)=1 'if pulsewidth between 60 and 80uS then read as '1'
next x
;-== convert bin to dec ==-
humread=32768*p(1)+16384*p(2)+8192*p(3)+4096*p(4)+ 2048*p(5)+1024*p(6)+512*p(7)+256*p(8)+128*p(9)+64* p(10)+32*p(11)+16*p(12)+8*p(13)+4*p(14)+2*p(15)+1* p(16)
tmpread=16384*p(18)+8192*p(19)+4096*p(20)+2048*p(2 1)+1024*p(22)+512*p(23)+256*p(24)+128*p(25)+64*p(2 6)+32*p(27)+16*p(28)+8*p(29)+4*p(30)+2*p(31)+1*p(3 2)
;checksum=128*p(33)+64*p(34)+32*p(35)+16*p(36)+8*p (37)+4*p(38)+2*p(39)+1*p(40)
;-== show real values ==-
LCDout $FE,$01,"RHdata Tdata"
LCDout $FE,$C0,dec humread/10,".",dec humread//10,"% ",dec tmpread/10,".",dec tmpread//10,"oC" 'print integral part only
low led
pause 2000 'give some time to DHT to stabilize!....
goto start
END

6956

Finnally I would like to say A BIG THANK YOU to demon for sending me the correct infos to search about that helped me to pinpoint my problem!

Demon
- 5th April 2013, 12:00
Congrats! Did you comfirm the readings with another device? Looks a little hot and dry where you live. :)

Robert

Acetronics2
- 5th April 2013, 12:10
Hi, Alexandros

did you find this one?
http://embedded-lab.com/blog/?p=4333

interesting explanations there.

BTW ... How are you ???

Alain

bitmaniac
- 5th April 2013, 12:40
@ Demon I have not yet tested with another device... The photo wa taken before sensor given time to settle (as soon as I switched on!)

@Acetronics Hi! my good friend! There has been a looong time since my last visit here! (Actually for the last year I was working on my retro collection hobby with local retro-exchibitions etc!)
Yes I have seen this site infos....

rodrik
- 18th November 2014, 05:18
Hi,

I want to use those codes to read values each 15 minutes via serial port. I need two sensors to read. One on board , the second 10 meters of wire. To replace LCD codes to serial is very easy. I wonder the include "ALLDIGITAL.pbp" not shown here . Finally what's is oscillator frequency ?

The last version of PBP codes, seems from 5'th April 2013

Thanks

Archangel
- 18th November 2014, 08:43
Get it here: http://www.picbasic.co.uk/forum/content.php?r=154-All-Digital

First post OSC 4

blueocean
- 3rd November 2015, 15:07
what is lata.0? it's not named in the variables

mackrackit
- 4th November 2015, 01:56
what is lata.0? it's not named in the variables
Yes it is, it is an LED.

blueocean
- 11th November 2015, 16:21
Yes it is, it is an LED.

microcode syntax error on this line:

INTCON2.7=0

and a bad data type on this line:

led var LATA.0

blueocean
- 11th November 2015, 16:35
Yes it is, it is an LED.


but i used a pic16f876a, how can i change those two instructions?

mackrackit
- 15th November 2015, 00:42
Try
PORTA.0