![]() |
Forum Index : Microcontroller and PC projects : DHT11 Humidity Sensor on an F4 (or any MMBasic)
![]() ![]() |
|||||
Author | Message | ||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5074 |
humid ? "bitbang humid" on picomite Volhout PicomiteVGA PETSCII ROBOTS |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2630 |
@toml_12953 "In the 05.07.01 manual it gives the syntax HUMID pinnum, temp, humidity [, DHT11] Where DHT11 is 1 if you're using the DHT11. It adjusts the timing to work with the 11." As noted in a previous post the purpose of using the DHT22 option for the DHT11 is to get the tenths of degrees. HUMID pinnum, temp, humidity, 1 gives whole degrees only. Also in a previous post. "The DHT11 accuracy isn't very good so to make use of this you will need to measure the error with an accurate thermometer and make corrections in your code. A single point measurement would be ok in an airconditioned space, but if the temp. range is large two or more calibration points can be used to make a correction curve." My DHT11 needs +1.1 degree correction. Still wasting time Because the DHT11 and DHT22 require different "Wakeup Pulse" lengths, if you have one of each they can share the same pin. I don't have a DHT22 so to test this so wrote a program for the F4 to emulate a DHT22 and both can be read when the two are accessed by a MM2 running the posted program. |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10287 |
The DHT11 has an accuracy of +/- 5% RH and +/- 2degC at 25 degrees. The datasheet is in difficult English but the examples show the fraction bytes as always being zero and the datasheet states So IMHO it is completely pointless getting fractions of a degree or RH with the DHT11 Edited 2021-08-27 23:20 by matherp |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2630 |
"So IMHO it is completely pointless getting fractions of a degree or RH with the DHT11" Searching the net I have found several different descriptions of the DHT11 data, one showing the decimals. Perhaps there are two versions of DHT11. My unit does have the decimal for temperature but not for humidity. The 40 bit word is as follows:- Byte 1 �Humidity, left of point - Negative not allowed Byte 2 �Humidity, right of point = 0 always Byte 3 �Temperature, left of point - Negative not allowed Byte 4 �Temperature, right of point - 0 to 9 Byte 5 �Checksum So: T = Byte3 + Byte4 / 10 Due to the low accuracy of the DHT11 not using the decimal in the HUMID function is reasonable. It is only of use if calibrated against an accurate thermometer. The DHT22 function uses two 16 bit words for H*10 & T*10. It just take a little arithmetic to extract the DHT11 data from it. It just requires a longer "wake up" pulse provided by another pin. Still more time wasting:- A single pin can be used to read a DHT11 via the DHT22 function �with a hardware pulse extender to bridge the gap between the end of the "wake up" pulse and the start of the HUMID function - measured at about 250uS. It has to be triggered by a long pulse but ignore the short data pulses. will post when the RC values are sorted out. EDIT Feb 2022 Had forgotten about this. A simple timer worked sometimes but not good enough. Two NE555's worked well but just too complicated to save a single pin. Here is a 1 pin version for the PicoMite using Peter's CSub LOG. 'Pico_Humid-7.bas 'The DHT11 isn't very accurate so record it's reading at two accurate temperatures for calibration. T1ref = 9.3 : T1dht = 7.9 : T2ref = 26.6 : T2dht = 25.9 �'Insert your DHT11 calibration points here. GCal = (T2ref - T1ref) / (T2dht - T1dht) 'Calibration gradient TCal = T2ref-(GCal*T2dht) � �'Temp offset for Tdht=0 Print " Temperature Calibration Points", "T1ref="T1ref ,"T1dht="T1dht, , "T2ref="T2ref , "T2dht="T2dht Print " Correction factors - TCal="TCal,"GCal="GCal Dim a%(84) 'array to receive the timestamps Dim b%=84 'maximum number of transitions to receive Dim c%=20000 'timeout of the CSUB in microseconds Dim d%(42) 'array for positive timestamp differences, (42) for last neg. diff. Dim e%(42) 'array for data bits, (42) for data word Dim integer byte(5), i : Dim float t, h SetTick 2000,DHT : DHT Do : Loop Sub DHT �toggle = Not toggle � 'alternate LOG and BITBANG HUMID readouts �If toggle Then �i=1 : a%(81)=0 : e%(42)=0 �SetPin gp6,dout,oc 'send a wake up pulse to the DHT11 �Pin(gp6) = 1 �Pulse gp6,22 : Print "20mS Pulse" �Pause 19 : Timer = 0 �SetPin gp6, off �SetPin gp6,cin,3 'set pin 9 (GP6) to cause a H/W interrupt on both edges �LOG a%(),b%,c% 'initialise the logging �Print "waiting for LOG to fill a%()" �Do While (a%(81)=0) And (Timer<5) :Loop �'loop until enough transitions recorded �If Timer >= 5 Then Print " LOG timeout" �Do While a%(i) 'read all valid data from a%() ��If (a%(i)+a%(i+1)) >= 0 Then �'synchronise with falling edge �� Inc i ��Else �� d%(i/2)=a%(i+2)-a%(i) � �'measure cycles- falling edge to falling edge �� Select Case d%(i/2) �� �Case 101 To 150 � � � �'pulse high longer than nominal low = 1 �� � e%(i/2)=1 �� �Case �50 To 100 � � � �'pulse high shorter than nominal low = 0 �� � e%(i/2)=0 �� �Case Else 'if pulse too long or too short leave old bit in place. Record it and adjacent. � �� Print "Pulse Error" � �� If i>2 Then �Print a%(i-2),a%(i-1),,a%(i-3)+a%(i-2),a%(i-2)+a%(i-1),,a%(i-3)-a%(i-1) � � �If i>1 Then �Print a%(i),a%(i+1),,a%(i-1)+a%(i),a%(i)+a%(i+1),,a%(i-1)-a%(i+1) � � �Print a%(i+2),a%(i+3),,a%(i+1)+a%(i+2),a%(i+2)+a%(i+3),,a%(i+1)-a%(i+3) � � �Print a%(i+4),a%(i+5),,a%(i+3)+a%(i+4),a%(i+4)+a%(i+5),,a%(i+3)-a%(i+5) �� End Select �� Print e%(i/2); 'print the bits �� If e%(i/2)<>-1 Then e%(42)=(e%(42)<<1)+e%(i/2) 'assemble pulses into 40 bit word ��EndIf ��Inc i,2 'increment the loop counter �Loop �Print " �Bits" �Print Bin$(e%(42),40),"Assembled word" �SetPin gp6, off �byte(5)=0 �For n=0 To 4 �'seperate the bytes ��byte(n)= (e%(42)>>(n*8)) And 255 ��If n > 0 Then byte(5)=byte(5)+byte(n) 'add the bytes for cheksum ��Print byte(n); �Next �Print " Bytes (reverse order) - Cheksum, T decimal, Temp. H decimal, Humidity" �byte(5)=byte(5) And 255 �'finish cheksum calculation �Tu = byte(1)*.1 + byte(2) �'add decimal to temp �T11 = Cint(10*(GCal*Tu+TCal))/10 �'calculate corrected temp. �Print �"cheksum"byte(5), " Temp"T11"`C","Humidity"byte(4)"%",,"uncorrected temp"Tu �If byte(5)<>byte(0) Then Print "checksum error" � �Print �"Bits/sec."Int(500000*79/(Abs(a%(80))-Abs(a%(1)))) � Else � �Bitbang humid gp6,Tu,h,1 � �T11 = Cint(Cint(10*(GCal*Tu+TCal))/10) �'calculate corrected temp. then round it � �Print "BitBang Humid"," �Temp"T11,"Humidity"h,,"uncorrected temp"Tu �EndIf End Sub ' This CSUB logs activity on GP6, each transition of the pin is ' logged to the nearest microsecond. The timestamp is positive for positive ' going transitions and negated for negative going ones CSub LOG 0000002F 'timout 4B0CB570 4B0C681D 4798681B 428B6A6B D10DD303 42836A2B 4B08D20A 2300681A 4A076013 60136812 681B4B06 601A2201 46C0BD70 10000388 100003A8 10000384 100003C4 100003CC 'intprog 4B16B570 6825681C 3B016923 2B006123 4B13DD0E 2009681B 28004798 4B11D014 4798681B 60696028 33086823 BD706023 681A4B0D 60132300 68124A0C 4B0C6013 2201681B E7E4601A 681B4B06 23004798 418B4242 606B602A 46C0E7E6 10000388 10000328 100003A8 10000384 100003C4 100003CC 'main 0015B570 681B4B0C 447A4A0C 4B0C601A 4A0C681B 601A447A 681C4B0B 680B6020 4B0A6123 4798681B 686B682A 414B1812 62636222 46C0BD70 100003C4 FFFFFF7F 10000384 FFFFFF2D 10000388 100003A8 End CSub Update - replace Csub LOG with this, the old one will mess the Pico up, requiring it to be 'Nuked' and reflashed if used on recent firmware.. "The LOG CSUB compiled with the new header file as required from V5.07.05 Beta13 onwards." CSUB LOG 00000041 'check_timer B082B580 4B10AF00 3320681B 4B0F607B 4798681B 681A687B 4299685B D10ED803 D8004290 4B0AE00B 2200681B 4B09601A 2200681B 4B08601A 2201681B 46C0601A B00246BD 46C0BD80 1000038C 100003AC 10000388 100003C8 100003D0 'intprog B085B590 4B22AF00 60FB681B 681B4B20 60BB3310 681B68FB 68BB607B 1E5A681B 601A68BB 681B68BB DC0B2B00 681B4B19 601A2200 681B4B18 601A2200 681B4B17 601A2201 681B4B16 47982009 D0081E03 681B4B14 00024798 6879000B 604B600A 4B10E00C 4798681B 000B0002 42502100 687C4199 000B0002 60636022 681B68FB 001A3308 601A68FB 46BD46C0 BD90B005 1000038C 10000388 100003C8 100003D0 1000032C 100003AC 'main B088B580 60F8AF00 607A60B9 681B4B16 447A4A16 4B16601A 4A16681B 601A447A 681B4B15 4B1461FB 3310681B 4B1261BB 3320681B 68FA617B 601A69FB 681A68BB 69BB685B 4B0D601A 4798681B 000B0002 68086879 18126849 6979414B 604B600A 46BD46C0 BD80B008 100003C8 FFFFFF43 10000388 FFFFFEDD 1000038C 100003AC End CSUB EDIT 2 Sep 2022 At maximum speed the PicoMite can catch the data with a compact For / Next loop. No CSUB needed. 'DHT11 reader using just a For - Next loop to sample the data. Uses GP0 - pin 1 'Use OPTION CPUSPEED 378000 for best resultts, barely functions at 252 MHz. 'The DHT11 isn't very accurate so record it's reading at two accurate temperatures for calibration. T1ref = 9.3 : T1dht = 7.9 : T2ref = 26.6 : T2dht = 25.9 �'Insert your DHT11 calibration points here. GCal = (T2ref - T1ref) / (T2dht - T1dht) 'Calibration gradient TCal = T2ref-(GCal*T2dht) � �'Temp offset for Tdht=0 'Print " Temperature Calibration Points", "T1ref="T1ref ,"T1dht="T1dht, , "T2ref="T2ref , "T2dht="T2dht 'Print " Correction factors - TCal="TCal,"GCal="GCal CLS 111 Do �DHT11 'Sub DHT11 output variables are T & RH, 1000 = check sum error �On Error skip 3 : RTC GetReg 17,Tdeg : RTC GetReg 18,Tdec : TempRTC=Tdeg+Tdec/256 'read DS3231 temp, if installed �Tc = Cint(10*(GCal*T+TCal))/10 �'calculate corrected temp. rounded to tenths �If RH < 101 Then Print "Temp ";Tc,"Humidity ";RH,"TempRTC";TempRTC,Tdeg,Tdec �If RH < 101 Then � Text 19,40, "Temp "+Str$(T,2,1)+" � Tc "+Str$(Tc,2,1),,,3 � Text 19,80, "Humidity "+Str$(RH,2),,,3 � Text 19,120, "TempRTC "+Str$(TempRTC,2,2),,,3 � Text 19,160, "Time " + Time$,,,3 � Text 19,200, "Date " + Date$,,,3 �EndIf �Pause 1937 �'total loop time about 2 seconds Loop Sub DHT11 'output variables are T & RH �Local integer a(330), bit(45), byte(4), m=0, n=0, i=3, low, high, CSum ' �' deliver 18mS low pulse to wake up DHT11 (it has a pullup resistor) �SetPin 1,dout :Pause 18 �SetPin 1,din 'Get the samples For n=0 To 329:a(n)=Pin(1):Next �SetPin 1,off 'Got the samples 'for max. speed the above 'for-next' must be on one line with fewest characters. ' ' �For n=0 To 329 : Print a(n); : Next : Print 'un-comment to show the samples 'Data format - 80uS high start pulse, 50uS low + 25uS high = 0, 50uS low + 70uS high = 1 'start processing samples �'Find the end of the start pulse �Do : Inc i : Loop Until ((a(i-3)=1) And (a(i-2)=1) And (a(i-1)=1) And (a(i)=0)) �low=0 � 'uS.90 = average number of samples / 90uS for decoding. (0 < 90uS < 1) � For j=i To 329 � �If a(j) = 0 Then Inc low � Next � uS.90 = low / (2000/90) 'there are 40 x 50uS lows = 2000uS per reading � low=0 : Print uS.90;" Samples / 90uS" �Do While i<329 ' Count samples in each Low / High pair. Save in bit() � high=0 : low=0 � Do While (a(i)=0) And (i<329) : Inc i : Inc low : Loop � Do While (a(i)=1) And (i<329) : Inc i : Inc high : Loop � If a(i) = 0 Then bit(m) = low + high �'save bit length � �If m > 44 Then i=329 ' Done - got sample numbers for all the bits � Inc m �Loop �For i=0 To 44 'turn sample numbers into logic levels - adjusted for sampling rate. � If bit(i)=0 Then i=44 � If bit(i) > uS.90 Then � � bit(i)=1 � �Else � � bit(i)=0 � EndIf �Next �For n=0 To 4 :byte(n)=0:Next �fe=0 : CSum=0 �For n=0 To 4 � For i=bit(0) To 7+bit(0) � �byte(n) = (byte(n)<<1)+bit(i+8*n) � Next � If n<4 Then:CSum=CSum+byte(n):EndIf �' calculate check-sum ' �Print Bin$(byte(n),8),byte(n) 'Show bytes �Next �CSum=CSum Mod 256 �' calculate check-sum �If CSum = byte(4) Then � RH=byte(0):T=byte(2)+byte(3)/10 �' calculate Temp. �Else � RH = 1000 : T = 1000 �EndIf End Sub EDIT 3 January 2024 CSub LOG has been recompiled again for PicoMite Version 5.08.00 by @disco4now. Here is the program again with minor changes to suit the new firmware. 'Pico_Humid-7.bas 'The DHT11 isn't very accurate so record it's reading at two accurate temperatures for calibration. T1ref = 9.3 : T1dht = 7.9 : T2ref = 26.6 : T2dht = 25.9 'Insert your DHT11 calibration points here. GCal = (T2ref - T1ref) / (T2dht - T1dht) 'Calibration gradient TCal = T2ref-(GCal*T2dht) 'Temp offset for Tdht=0 Print " Temperature Calibration Points", "T1ref="T1ref ,"T1dht="T1dht, , "T2ref="T2ref , "T2dht="T2dht Print " Correction factors - TCal="TCal,"GCal="GCal Dim a%(86) 'array to receive the timestamps Dim b%=84 'maximum number of transitions to receive Dim c%=20000 'timeout of the CSUB in microseconds Dim d%(43) 'array for high/low cycle periods, (42) for data bits Dim e%(43) 'array for data bits Dim integer byte(5), i : Dim float t, h SetTick 2000,DHT : DHT Do : Loop Sub DHT toggle = Not toggle 'alternate LOG and DEVICE HUMID readouts If toggle Then i=1 : a%(81)=0 : e%(42)=0 SetPin gp6,dout 'send a wake up pulse to the DHT11 Pin(gp6) = 1 Pulse gp6,22 : Print "20mS Pulse" Pause 19 : Timer = 0 SetPin gp6, off SetPin gp6,cin,3 'set pin 9 (GP6) to cause a H/W interrupt on both edges LOG a%(),b%,c% 'initialise the logging Print "waiting for LOG to fill a%()" Do While (a%(81)=0) And (Timer<5) :Loop 'loop until enough transitions recorded If Timer >= 5 Then Print " LOG timeout" Do While a%(i) 'read all valid data from a%() If (a%(i)+a%(i+1)) >= 0 Then 'synchronise with falling edge Inc i Else d%(i/2)=a%(i+2)-a%(i) 'measure cycles- falling edge to falling edge Select Case d%(i/2) Case 101 To 150 'pulse high longer than nominal low = 1 e%(i/2)=1 Case 50 To 100 'pulse high shorter than nominal low = 0 e%(i/2)=0 Case Else 'if pulse too long or too short leave old bit in place. Record it and adjacent. Print "Pulse Error" If i>2 Then Print a%(i-2),a%(i-1),,a%(i-3)+a%(i-2),a%(i-2)+a%(i-1),,a%(i-3)-a%(i-1) If i>1 Then Print a%(i),a%(i+1),,a%(i-1)+a%(i),a%(i)+a%(i+1),,a%(i-1)-a%(i+1) Print a%(i+2),a%(i+3),,a%(i+1)+a%(i+2),a%(i+2)+a%(i+3),,a%(i+1)-a%(i+3) Print a%(i+4),a%(i+5),,a%(i+3)+a%(i+4),a%(i+4)+a%(i+5),,a%(i+3)-a%(i+5) End Select Print e%(i/2); 'print the bits If e%(i/2)<>-1 Then e%(42)=(e%(42)<<1)+e%(i/2) 'assemble pulses into 40 bit word EndIf Inc i,2 'increment the loop counter Loop Print " Bits" Print Bin$(e%(42),40),"Assembled word" SetPin gp6, off byte(5)=0 For n=0 To 4 'seperate the bytes byte(n)= (e%(42)>>(n*8)) And 255 If n > 0 Then byte(5)=byte(5)+byte(n) 'add the bytes for cheksum Print byte(n); Next Print " Bytes (reverse order) - Cheksum, T decimal, Temp. H decimal, Humidity" byte(5)=byte(5) And 255 'finish cheksum calculation Tu = byte(1)*.1 + byte(2) 'add decimal to temp T11 = Cint(10*(GCal*Tu+TCal))/10 'calculate corrected temp. Print "cheksum"byte(5), " Temp"T11"`C","Humidity"byte(4)"%",,"uncorrected temp"Tu If byte(5)<>byte(0) Then Print "checksum error" Print "Bits/sec."Int(500000*79/(Abs(a%(80))-Abs(a%(1)))) Else Device humid gp6,Tu,h,1 T11 = Cint(Cint(10*(GCal*Tu+TCal))/10) 'calculate corrected temp. then round it Print "Device Humid"," Temp"T11,"Humidity"h,,"uncorrected temp"Tu EndIf End Sub ' This CSUB logs activity on GP6, each transition of the pin is ' logged to the nearest microsecond. The timestamp is positive for positive ' going transitions and negated for negative going ones 'File LOG.bas written 23-01-2024 08:10:57 v1.44 CSUB LOG 00000042 'check_timer B082B580 4B10AF00 3320681B 4B0F607B 4798681B 681A687B 4299685B D10ED803 D8004290 4B0AE00B 2200681B 4B09601A 2200681B 4B08601A 2201681B 46C0701A B00246BD 46C0BD80 10000384 100003A4 10000380 100003C0 100003C8 'intprog B084B580 4B23AF00 60FB681B 681B4B21 60BB3310 681B68FB 68BB607B 1E5A681B 601A68BB 681B68BB DC0B2B00 681B4B1A 601A2200 681B4B19 601A2200 681B4B18 701A2201 681B4B17 47982009 D0081E03 681B4B15 00024798 6879000B 604B600A 4B11E00D 4798681B 000B0002 21002000 41991A80 000B0002 600A6879 68FB604B 3308681B 68FB001A 46C0601A B00446BD 46C0BD80 10000384 10000380 100003C0 100003C8 10000324 100003A4 'main B088B580 60F8AF00 607A60B9 681B4B16 447A4A16 4B16601A 4A16681B 601A447A 681B4B15 4B1461FB 3310681B 4B1261BB 3320681B 68FA617B 601A69FB 681A68BB 69BB685B 4B0D601A 4798681B 000B0002 68086879 18126849 6979414B 604B600A 46BD46C0 BD80B008 100003C0 FFFFFF3F 10000380 FFFFFED9 10000384 100003A4 End CSUB Edit June 2024 Yet more messing about with the DHT11. A significant contributor to the size of T and H errors appears to be internal heating when using the minimum 2S read interval. As it sleeps between reads increasing the interval to 30S allows it to cool to ambient. Comparing the readings with the more accurate AHT10 and DS18B20 the typical difference is less than 0.5C, usually about 0.2C so a correction factor is no longer needed. For humidith the improvement is even greater. Below 15% the difference is about 2%, at 30% the DHT11 is 6 to 8% high. At 65% it reads 74% so is within its specified +/-10%. AHT10 humid AHT10 temp DS3231 temp DHT11 temp DHT11 humid DS18B20 1 DS18B20 2 66 % 11.7 C 11.75 C 11.8 C 74 % 11.8 C 12.5 C 66 % 11.7 C 11.75 C 12.1 C 75 % 11.9 C 12.6 C 66 % 11.6 C 11.75 C 12.3 C 75 % 11.9 C 12.7 C Edited 2024-06-17 11:48 by phil99 |
||||
![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |