**This is an old revision of the document!**
Table of Contents
Pseudocode
Function: Pio ( -- ) \ set port I/O function. SDA --> P1.0
Function: wakeup ( -- ) \ notify sensor to prepare the data
Function: @data ( -- sun moon hum tmp chk chksum ) \ get sensor data
get response time of sensor, store in register 'sun' (just for testing)
get startpulse duration, store in register 'moon'
40 loop
read bit using 'moon' based delay
lshift bit into array xx yy zz
08 loop
lshift array \ adjust xx yy zz --> hum tmp chk
calculate chksum
Function: (dht22) ( -- sun moon hum tmp chk chksum ) \ wake up and read sensor
Function: dht22 ( -- ) \ print temperatur and humidity
Function: test ( n -- ) \ multiple readings
n loop dht22
Sorce Code
\ Read DHT22 data. (bit bang)
\ TI MSP430G2553 Launchpad with noForth mv 2553 240101
(*
To do: monitor timeout
History
v0066 - Display negative temperatures correctly.
V0065 - Represent tenths of degrees of temperatures.
V0064 - Loops named with ( A ) ... ( D ). Variants of loops B and D studied. These loop variations of B and D work well. Comments revised. mk 20250423 05:25
V0063 - Cleaned up the code. Data output reduced to the essentials. mk 20250421 02:04
V0062 - Works well, output rounded to whole digits. mk 20250419 21:51
Previous versions: Successive approximation to the solution.
Patch millisecond to 100 microseconds.
See: config2553.f
00c7 10B2 rom!
hex 10B2 DMP
After COLD this value is active.
addr acronym registername
020 P1IN Input
021 P1OUT Output
022 P1DIR Direction
023 P1IFG Interupt Flag
024 P1IES Interrupt Edge Select
025 P1IE Interrupt Enable
026 P1SEL Port Select
041 P1SEL2 Port Select2
027 P1REN Resistor Enable
*)
asm\
hex
\ tools
code cls ( -- ) s0 # sp mov next end-code \ clear stack
code p1H #1 021 & .b bis next end-code \ set lines
code p1L #1 021 & .b bic next end-code
code p6H 40 # 021 & .b bis next end-code
code p6L 40 # 021 & .b bic next end-code
\ Assign DHT22 data line to pin p1.0, controll pin to p1.6
: Pio ( -- ) \ set I/O function
41 027 *bic \ p1ren off
41 025 *bic \ p1ie disable interrupt
41 026 *bic \ P1SEL I/0
41 041 *bic \ P1SEL2 I/0
41 022 *bis \ set out for P1.0, P1.6
;
: wakeup ( -- ) \ notify sensor to prepare the data
pio p1H p6H 1 ms p1L 10 ms ( p6L ) p1H ; \ 1 ms == 100┬Ás !
Code @data ( -- sun moon xx yy zz chksum ) \ read sensor data
\ i.e ( -- sun moon hum tmp chk chksum )
\ get response time
#1 022 & .b bic \ p1,0 IN
#0 sun mov
#1 024 & .b bis \ FALLING EDGE\__
#1 023 & .b bic \ clear P1IFG
40 # 021 & .b bic \ p6L\___ (for logic analyser)
begin, ( A ) \ wait for edge
#1 023 & .b bit \ test bit
\ Z: Set if result is zero, reset otherwise
\ C: Set if result is not zero, reset otherwise (.NOT. Zero)
cc? while,
#1 sun add
repeat,
40 # 021 & .b bis \ ___/p6H (for logic analyser)
tos sp -) mov
sun tos mov ( -- sun )
\ get startpulse time
#0 moon mov
#1 024 & .b bic \ ___/ RISING EDGE
#1 023 & .b bic \ clear P1IFG
40 # 021 & .b bic \ p6L\___ (for logic analyser)
begin, ( B ) \ wait for edge
#1 023 & .b bit \ test bit
\ Z: Set if result is zero, reset otherwise
\ C: Set if result is not zero, reset otherwise (.NOT. Zero)
cc? while,
#1 moon add
repeat,
40 # 021 & .b bis \ ___/p6H (for logic analyser)
tos sp -) mov
moon tos mov ( -- moon )
\ read 40 bits to array
#0 xx mov \ init array
#0 yy mov
#0 zz mov
dm 40 # day mov
begin, ( C )
#1 023 & .b bic \ clear P1IFG
begin, \ wait for edge
#1 023 & .b bit \ test IFG
\ Z: Set if result is zero, reset otherwise
\ C: Set if result is not zero, reset otherwise (.NOT. Zero)
cs? until,
\ wait to read bit
moon w mov
w w add \ 2*moon, Loop D is about twice as fast as loop B.
40 # 021 & .b bic \ p6L\___ (for logic analyser)
begin, ( D )
#1 w sub
0=? until,
\ read bit
40 # 021 & .b bis \ __/p6H (for logic analyser)
020 & w .b mov \ read data line: bit H or L
#1 w bia \ get bit
\ tos sp -) mov
\ w tos mov ( ... -- ... bit ) \ test
\ #1 sr bic \ clear carry bit
\ shift left all bits
zz zz add
yy yy addc
xx xx addc
w zz bix \ = xor : write data bit
#1 day sub
0=? until, \ 40 bits are read
\ adjust bits
8 # day mov \ lshift 40 bits up 8x -> xx=hum yy=tmp
begin,
zz zz add
yy yy addc
xx xx addc
#1 day sub
0=? until,
\ push data to stack
tos sp -) mov xx tos mov ( -- xx )
tos sp -) mov yy tos mov ( -- yy )
zz swpb \ get upper byte
tos sp -) mov zz tos mov ( -- zz.b )
\ calculate checksumme
#0 w mov
xx w .b add xx swpb xx w .b add
yy w .b add yy swpb yy w .b add
tos sp -) mov
w tos mov
next end-code
\ display
decimal
: (dht22) ( -- sun moon hum tmp chk chksum )
cls wakeup @data
;
: decemit ( c -- ) \ print c from DEC special character set
hx 1B emit [char] ( emit [char] 0 emit emit
hx 1B emit [char] ( emit [char] B emit \ back to normal output
;
: .tmp ( tmp -- ) \ Print temperature with sign, one decimal place and degree symbol
dup hx 8000 and hx 8000 =
if [char] - else [char] + then emit
hx 7fff and ( tmp -- +tmp )
10 /mod 3 .r [char] . emit .
[char] f decemit
[char] C emit space
;
: .hum ( hum -- ) \ Print the relative humidity rounded to whole digits
10 / . ." %rel" space
;
: dht22 ( -- ) \ get temperatur and humidity
cr (dht22) ( 2 + ) \ add 2 for 'else' part
= if ." chk " else ." chksum error" cls exit then
.tmp space space .hum space space
\ ( sun moon -- ) drop drop
( sun moon -- ) . . \ testing
;
(*
The DHT22 starts its next measurement AFTER the query and saves the values.
These are output with the next query, so they are old.
For up-to-date values, query twice.
There must be more than 2 seconds between each query, otherwise the DHT22 will not respond again.
*)
: test ( n -- )
>r
cr ." discard old values..." (dht22) cls
cr ." reading current data:"
r> 0 do
dm 40000 ms \ wait until the sensor is ready again.
dht22
loop
;
shield nn\
freeze
( finis)
Numerical representation of the measured values
- This is already included in the source code.
Humidity
The first 16 bits coming from the DHT22 are the relative humidity in tenths of a percent. They can be processed directly with the 16-bit noForth and correspond to a positive integer. Rounded to whole digits for display purposes. Here is an excerpt from the noforth source code:
: .hum ( hum -- ) 10 / . ." %rel" space ;
Temperature
The next 16 bits are the temperature in tenths of a degree Celsius. Temperatures from zero degrees and higher can be processed directly using the 16-bit noForth; they correspond to a positive integer.
Temperatures below zero degrees are represented by the DHT22 as follows: The MSB of the 16-bits is set, but otherwise the temperature is specified as a positive integer. This number format does not correspond to the two's complement of noForth. Here, the MSB must first be evaluated to determine the sign. The sign is prepended for output. The measured value can then be further processed as a positive integer. Whole degrees are displayed to the left of the decimal point, tenths to the right. The unit °C is specified.
: .tmp ( tmp -- )
dup hx 8000 and hx 8000 = \ check MSB
if [char] -
else [char] +
then emit
hx 7fff and ( tmp -- +tmp ) \ reset MSB
10 /mod 3 .r [char] . emit . \ --> TTT.T
[char] f decemit [char] C emit \ print °C
space
;