Picbasic code for DHT11 ?
Picbasic code for DHT11 ?
Last edited by Thanasis; - 8th March 2014 at 08:28.
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
Last edited by Thanasis; - 8th March 2014 at 08:44.
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/showthr...ighlight=DHT11
This link explains how these sensors work
http://ruijc.webnode.com/products/le...sensor-reader/
Show us your code and doubts so we can help you.
Regards
Rui
a look here ???
http://www.picbasic.co.uk/forum/show...684#post119684
Alain
************************************************** ***********************
Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
************************************************** ***********************
IF there is the word "Problem" in your question ...
certainly the answer is " RTFM " or " RTFDataSheet " !!!
*****************************************
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.
http://www.picbasic.co.uk/forum/showthread.php?t=16196
Last edited by Thanasis; - 13th March 2014 at 18:35.
Steve Earl www.datageo.co.uk
Hi, thank you for the response, code that tests are:
Code:@ 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
Last edited by Archangel; - 29th March 2015 at 00:20.
Ηι! Τ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!
web: bitmaniac.blogspot.gr , youtube: mychannelRobotics , aeromodelling r/c , picprogramming , Retro Computer Collector
@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![]()
web: bitmaniac.blogspot.gr , youtube: mychannelRobotics , aeromodelling r/c , picprogramming , Retro Computer Collector
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.
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.Code: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
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.
Code:'**************************************************************** '* 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
Last edited by Archangel; - 29th March 2015 at 00:22. Reason: code tags
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.
Code: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
Last edited by Art; - 31st March 2015 at 15:58.
Bookmarks