PDA

View Full Version : Dht11 - 16f877a



Thanasis
- 8th March 2014, 08:16
Picbasic code for DHT11 ?

Thanasis
- 8th March 2014, 08:25
Hello, I want to measure the humidity in an incubator.
I have the PIc 16F877A. Osc:20MHz.
Does anyone know the code to DTH11 in pic basic pro.
thank you

cyberroth
- 8th March 2014, 13:06
I have not done it with PBP, but in another life I did it with PICAXE BASIC.

After being queried, the DHT11 returns 41 Bits of Data. The first bit is an ACK and can be ignored. The next 16 bits are Humidity bits. ONly the first 8 of these bits are used wth the DHT-11. The next 16 bits are Temperature bits and again only the first 8 are used. The next 8 bits are the checksum.

First Bit - Ignore or use for interrupt

Bit 1 - 8 Humidity MSByte
Bit 9 - 16 Hymidity LSByte (Only used with DHT22 - Ignore - All zeros
Bit 17 - 24 Temperature MSByte
Bit 25 - 32 Temperature LSByte (Only used with DHT22 - Ignore - All zeros
Bit 33 = 40 Checksum - use if desired

The protocol is such that each bit starts with a 50us low, followed by either a 27us high Pulse or a 70us high pulse,where 27us = "0" nd 70us = "1"

These pulses can be read with pulsin and then tested with an IF statement to determine if a pulse is a 1 or a 0.


There is only 50us between bits so the PIC only has 50us to read the bit & determine if a 1 or 0 before the next bit arrives.

I am not going to write & debug the code for you if that is what you are looking for. However, below is a link to the Picaxe Basic code that may be helpful. You should not need the 555 timer or 74HC221 since PBP it is compiled code and runs much, much faster than Picaxe Basic interpreted code.

http://www.picaxeforum.co.uk/showthread.php?19459-DHT11-Humidity-Sensor&highlight=DHT11

Thanasis
- 8th March 2014, 14:50
I have not done it with PBP, but in another life I did it with PICAXE BASIC.

After being queried, the DHT11 returns 41 Bits of Data. The first bit is an ACK and can be ignored. The next 16 bits are Humidity bits. ONly the first 8 of these bits are used wth the DHT-11. The next 16 bits are Temperature bits and again only the first 8 are used. The next 8 bits are the checksum.

First Bit - Ignore or use for interrupt

Bit 1 - 8 Humidity MSByte
Bit 9 - 16 Hymidity LSByte (Only used with DHT22 - Ignore - All zeros
Bit 17 - 24 Temperature MSByte
Bit 25 - 32 Temperature LSByte (Only used with DHT22 - Ignore - All zeros
Bit 33 = 40 Checksum - use if desired

The protocol is such that each bit starts with a 50us low, followed by either a 27us high Pulse or a 70us high pulse,where 27us = "0" nd 70us = "1"

These pulses can be read with pulsin and then tested with an IF statement to determine if a pulse is a 1 or a 0.


There is only 50us between bits so the PIC only has 50us to read the bit & determine if a 1 or 0 before the next bit arrives.

I am not going to write & debug the code for you if that is what you are looking for. However, below is a link to the Picaxe Basic code that may be helpful. You should not need the 555 timer or 74HC221 since PBP it is compiled code and runs much, much faster than Picaxe Basic interpreted code.

http://www.picaxeforum.co.uk/showthread.php?19459-DHT11-Humidity-Sensor&highlight=DHT11


Thank you very much, but I have not dealt with picaxe.

ruijc
- 8th March 2014, 16:11
This link explains how these sensors work

http://ruijc.webnode.com/products/leitor-de-medi%C3%A7%C3%B5es-para-sensores-dht11-e-dht22-dht11-and-dht22-sensor-reader/

Show us your code and doubts so we can help you.

Regards
Rui

Acetronics2
- 8th March 2014, 17:44
a look here ???
http://www.picbasic.co.uk/forum/showthread.php?t=17867&p=119684#post119684

Alain

Thanasis
- 8th March 2014, 20:03
Informative article, thank you very much.

Thanasis
- 13th March 2014, 18:24
After reading related articles ... I did test the code below forum member

Making use with: PIC16F877A, OSC: 20Mhz ...... I could not get it to work ..... if anyone has a solution to Picbasic Pro let's publish.:rolleyes:


http://www.picbasic.co.uk/forum/showthread.php?t=16196

EarlyBird2
- 13th March 2014, 21:22
After reading related articles ... I did test the code below forum member

Making use with: PIC16F877A, OSC: 20Mhz ...... I could not get it to work ..... if anyone has a solution to Picbasic Pro let's publish.:rolleyes:


http://www.picbasic.co.uk/forum/showthread.php?t=16196

Publish the code you tested please.

Thanasis
- 13th March 2014, 22:54
Publish the code you tested please.

Hi, thank you for the response, code that tests are:


@ errorlevel-306
INCLUDE "modedefs.bas"
Define OSC 20 ' 20MHz
Define ADC_BITS 10 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

dht var byte[32]
humidite var byte
haut var byte
bas var byte
temp var byte
x var byte
dht11 var portb.0

start:
TRISB.0 = 0 '
high dht11
pause 2000 ' wait 2 sec
low dht11 : pause 18' send 20ms low
high dht11 : pauseus 30 ' send 40us hi
TRISB.0 = 0
PulsIn PORTB.0, 1, haut
if haut < 15 then goto start
for x = 31 to 0 step-1
PulsIn PORTB.0, 1, dht[x] ' 1
next x
For x = 31 to 0 step-1
if dht[x] > 9 then
dht[x]=1
else
dht[x]=0
endif
next x
humidite=dht[31]*128+dht[30]*64+dht[29]*32+dht[28]*16+dht[27]*8+dht[26]*4+dht[25]*2+dht[24]*1
temp=dht[15]*128+ dht[14]*64+dht[13]*32+dht[12]*16+dht[11]*8+dht[10]*4+dht[9]*2+dht[8]*1
SEROUT2 PORTC.5,16468,["Humidite = ",#humidite,"% ",10 ,13]
SEROUT2 PORTC.5,16468,["Temperature = ",#temp,"C ",10 ,13]
goto start

bitmaniac
- 16th March 2014, 08:11
Ηι! Τhanasis

My friend if you want to use my program -as is- you have to use 4Mhz crystal. Ιf you use 20Mhz you have to change pulse measurements values as the resolution from 10us goes down to 2us with crystal at 20Mhz!

bitmaniac
- 17th March 2014, 06:12
@Thanasis ...if you want to keep 20Mhz try to change

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'

to this one

if pulse(x)>=9 and pulse(x)<=21 then p(x)=0 'if pulsewidth between 20 and 40uS then read as '0'
if pulse(x)>=29 and pulse(x)<=41 then p(x)=1 'if pulsewidth between 60 and 80uS then read as '1'

and let me know :smile:

Scampy
- 4th February 2015, 16:41
@

and let me know :smile:

OK an old post I know, but I received a DHT11 today and had a play. This works fine on an 18F2520 running with a 20mhz crystal.



ASM
__CONFIG _CONFIG1H, _OSC_HS_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM


'************************************************* ******************************
' LCD (20 x 4) set up
'************************************************* ******************************

DEFINE LCD_DREG PORTB ' LCD Data port
DEFINE LCD_DBIT 0 ' starting Data bit (0 or 4)
DEFINE LCD_EREG PORTB ' LCD Enable port
DEFINE LCD_EBIT 5 ' Enable bit (on EasyPIC 5 LCD)
DEFINE LCD_RSREG PORTB ' LCD Register Select port
DEFINE LCD_RSBIT 4 ' Register Select bit (on EasyPIC 5 LCD)
DEFINE LCD_BITS 4 ' LCD bus size (4 or 8 bits)
DEFINE LCD_LINES 4 ' number of lines on LCD
DEFINE LCD_COMMANDUS 2000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us

'************************************************* ******************************
' Defines Statements
'************************************************* ******************************

DEFINE OSC 20 ' 18F4520 / 18F2520, 20mhz crystal
ADCON1 = $0F
clear

'************************************************* ******************************
'Analog and Comparator settings
'************************************************* ******************************

ADCON0 = %00000000 'AD converter module disabled
ADCON1 = %00001111 'All Digital
ADCON2 = %00000000
CMCON = 7 'Disable Comparators

'************************************************* ******************************
'Port and Register settings (interrupts)
'************************************************* ******************************

TRISA = %00010111
TRISB = %00000011
T0CON = %11000111

T1CON = %00000001 ; free-running, 1:1 prescaler
TMR1H = %11111111
TMR1L = %11111011


'************************************************* ******************************

LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD

'************************************************* ******************************

dht var byte[32]
humidite var byte
haut var byte
bas var byte
temp var byte
x var byte
dht11 var portA.5

'************************************************* ******************************
start:
TRISA.5 = 0 '
high dht11
pause 2000 ' wait 2 sec
low dht11 : pause 18' send 20ms low
high dht11 : pauseus 30 ' send 40us hi
TRISA.5 = 0
PulsIn PORTA.5, 1, haut
if haut < 15 then goto start
for x = 31 to 0 step-1
PulsIn PORTA.5, 1, dht[x] ' 1
next x
For x = 31 to 0 step-1
if dht(x)>=9 and dht(x)<=21 then dht(x)=0 'if pulsewidth between 20 and 40uS then read as '0'
if dht(x)>=29 and dht(x)<=41 then dht(x)=1 'if pulsewidth between 60 and 80uS then read as '1'
next x
humidite=dht[31]*128+dht[30]*64+dht[29]*32+dht[28]*16+dht[27]*8+dht[26]*4+dht[25]*2+dht[24]*1
temp=dht[15]*128+ dht[14]*64+dht[13]*32+dht[12]*16+dht[11]*8+dht[10]*4+dht[9]*2+dht[8]*1
lcdout $FE,1
lcdout $FE,$C0,"Humidite = ",#humidite,"% "
lcdout $FE,$80,"Temperature = ",#temp,$DF,"C"
goto start


I've used Port A, pin 5 as the data line as I used an EasyPIC5 development board, and has the readings displayed on an 4 x 20 LCD rather than serial out.

tbarania
- 28th March 2015, 20:17
Below is code that will work to communicate with a DHT11 humidity sensor. The code is only for the humidity integer value. I don't measure the temperature or checksum, but this can easily be done by expanding the number of bits read.

I found that certain routines, like the for/next that some people have used, probably don't run fast enough with a 4MHz clock. 20MHz works well. Using a different scheme I can read the DHT1 with a 4MHz clock.

Also remember that pulsin doesn't measure in usec but rather in increments of microseconds depending on the clock speed. For example, at 4MHz each count on pulsin represents 10usec. So a count of 7 is actually 7 x 10 = 70usec. Likewise for 8MHz it is 8usec/count (7 x 8usec = 56usec) and at 20MHz is is 2usec/count (7 x 2usec = 14usec). Similarly, at 20MHz to read 70usec you need 70/2 = 35 counts, tho I'd look for >=30 counts to give some leeway.





'************************************************* ***************
'* Name : DHT11_test.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2015 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 3/28/2015 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************

'
' PIC16F688
'
' Running at 20MHz but code also shown for 4MHz
'
' The configuration bits for the 16F688 I set in MPLAB manually. Depedning on your processor you will have to
' determine and set your own bits.
'



DEFINE OSC 20 '20 MHz clock frequency, need a fast clock for this to work best
define HSER_RCSTA 90h 'enable the serial port receiver
define HSER_TXSTA 24h 'set up the serial port, enable transmit for fast clock
define HSER_BAUD 9600 'select the baud rate, run slow for the RF xmitter
define HSER_CLROERR 1 'automatically clear the buffer overrun error


i var byte
rhdata var byte
hum var byte[8]
humidity var byte 'humidity data byte
humid var byte

dbit0 var byte
dbit1 var byte
dbit2 var byte
dbit3 var byte
dbit4 var byte
dbit5 var byte
dbit6 var byte
dbit7 var byte

togl var portc.0 'not used except to add delay
rhpin var portc.2 'relativity sensor data bit
TxD var portc.4 'transmitted data
RxD var portc.5 'received data

CMCON0 = %00000111 'comparator off
OSCCON = %01110110 ' external 20 runs at 4 MHz internal clock
ADCON0 = %10000000 'ADC is disabled
ANSEL = %00000000 'all digital
TRISA = %11111111 'set up port A where 1 = input, 0 = output
TRISC = %11101011 'set up port C where 1 = input, 0 = output



'================================================= ================================================== =======================================
'
' This routine below works but needs a clock faster than 4MHz or the For/Next loop isn't fast enough. This might be what is causing
' people consternation if they run at the common 4MHz clock.
'
'
'================================================= ================================================== =======================================

rhpin = 1 'initial condition
pause 2000 'wait for the DHT to start up

mainloop:

trisc.2 = 0 'now set portc.2 (the DHT11 I/O pin) to output mode
rhpin = 0 'set rhpin = portc.2 low
pause 30 'wait 30 msec, must wait at least 18 msec for DHT11 to detect the signal
trisc.2 = 1 'now make portb.2 an input. Since this line is pulled high with an R rhpin becomes high
'rhpin stays high 20-40usec until DHT pulls it low (actually ~13usec measured on scope)

pulsin rhpin, 0, rhdata 'execute an active low pulse measurement
'When the pulse goes back high it stays for 80 usec and goes low followed by data

if rhdata > 50 then goto subloop 'if this takes way over 100 usec then error (50 x 2usec/pulsin count = 100usec)
rhdata = 0 'clear rhdata. Since < 130 usec then get ready for data which will be next low to high

pauseus 30 'delay makes sure the next pulse is a high going data pulse. Probably isn't needed.

For i = 7 To 0 Step -1 '8 bits (1..8)

Pulsin rhpin, 1, rhdata ' receive pulses from sensor. 8 bits of integer part of data come first, ignore rest
If rhdata >= 30 Then ' A "1" is defined for a bit width of 70usec, a "0" for bit width <30 usec.
'Remember, Pulsin counts increments depending on the clock frequency. At 20MHz clock
' frequency 30 rhdata counts => 30 x 2usec = 60usec. Rhdata >= 30 counts == data = 1
hum[i] = 1 ' if >50 usec then logic 1
Else
hum[i] = 0 ' if not >=50 usec then is a 0
endif

next i

pause 500 'not needed, was added during testing for readability of printout

humidity = hum[7]*128+hum[6]*64+ hum[5]*32+hum[4]*16+ hum[3]*8+hum[2]*4+ hum[1]*2+hum[0]*1

hserout ["A", 9, dec3 humidity, 13] 'serial output

pause 2000 ' wait for the rest of the DHT timing



'************************************************* ************************************************** ***************************************
'
'
' The scheme below will work with a 4MHz clock, but the timing number to check dbit is shown for 20MHz. For 4MHz compare dbit
' to 6 not 30.
'
'
'
'************************************************* ************************************************** ***************************************

humid = 0
trisc.2 = 0 'now set portc.2 to output
rhpin = 0 'set rhpin = portc.2 low
pause 30 'wait 30 msec, must wait at least 18 msec for DHT11 to detect the signal
trisc.2 = 1 'make portb.2 an input. Since this line is pulled high with an R rhpin becomes high

toggle togl 'use to add some delay here. Pauseus can't be < 24 usec at 4MHz clock

luupy:
if rhpin = 1 then goto luupy 'wait for the DHT pin to go low then delay until the DHT is ready

pauseus 130 'this delay ignores the first high going DHT pulse for initializaion and instead
' moves ahead to wait for first dat abit high transition.

pulsin rhpin, 1, dbit7 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit6 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit5 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit4 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit3 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit2 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit1 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec

pulsin rhpin, 1, dbit0 'measure the pulsewidth of the DHT transmitted bit. Low ~ 26-28usec, high ~70usec



hserout [13] 'the dbits can be printed if desired. This is used to check the data. Not needed.
hserout ["C", 9, dec2 dbit6, 9, dec2 dbit5, 9, dec2 dbit4, 9, dec2 dbit3, 9, dec2 dbit2, 9, dec2 dbit1, 9, dec2 dbit0, 13] 'optional


'100% humidity = 0110 0100. Don't need to add bit 7
if dbit6 >= 30 then 'check each bit to see if greater than 60 usec (30 x 2usec). If so the bit is a 1 so
humid = 64 ' add its decimal equivalent to the humidity byte to get he rh value
endif
if dbit5 >= 30 then
humid = humid + 32 'NOTE: if using 4MHz clock then test dbit for >=6 (6 x 10usec/pulsin count = 60 usec)
endif
if dbit4 >= 30 then
humid = humid + 16
endif
if dbit3 >= 30 then
humid = humid + 8
endif
if dbit2 >= 30 then
humid = humid + 4
endif
if dbit1 >= 30 then
humid = humid + 2
endif
if dbit0 >= 30 then
humid = humid + 1 'at this point the humid value is the humidity value
endif


hserout ["D", 9, dec3 humid, 13] 'serial output
hserout [13] 'linefeed for better output readability. This isn't needed.

pause 2000 'need to wait at least a second before repeating this data read sequence


GoTo mainloop



subloop:
hserout ["Sensor not ready", 13]
GoTo mainloop

end

Art
- 31st March 2015, 15:42
That’s about how I would have gone about it i.e. reading it with timing, and looking at the buffer later,
It looks like a job for portb.0 interrupt so the code doesn’t have to spend most time waiting.

It’s a shame there isn’t an option in PBP to carry the bit after rotating a byte like humid to wrap it in a loop.
For the last part the timing doesn’t matter anymore. There’s more than one way to skin a cat.



bb var byte ‘ bit index
ii var byte ‘ counter
dbit var byte[7] ‘ declare the array of bytes representing received bit times

humid = 0 ‘ reset humid!
bb = 1 ‘ set intial index value
for ii = 0 to 6 ‘ address each bit
if dbit[ii] > 29 then
humid = humid + bb ‘ set the bit
endif
bb = bb + bb ‘ multiply index by 2 each step
next ii