Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 09:23 23 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : DHT11 Humidity Sensor on an F4 (or any MMBasic)

     Page 3 of 3    
Author Message
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 5074
Posted: 09:06am 27 Aug 2021
Copy link to clipboard 
Print this post

humid ?

"bitbang humid" on picomite

Volhout
PicomiteVGA PETSCII ROBOTS
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 2630
Posted: 01:05pm 27 Aug 2021
Copy link to clipboard 
Print this post

@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 Kingdom
Posts: 10287
Posted: 01:18pm 27 Aug 2021
Copy link to clipboard 
Print this post

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

  Quote  Data formats:
8bit humidity integer data + 8bit decimal data +8 bit temperature and humidity data + 8bit
temperature decimal integer data +8 bit parity bit.
Note: The fractional portion wherein the temperature and humidity of 0.

Parity bit data definition
"8bit humidity decimal integer data + 8bit humidity temperature data +8 bit decimal integer
data + 8bit temperature data" 8bit parity bit is equal to the result of the end of eight.
Example One 40 receives the data to:
00110101 00000000 00011000 00000000 01001101
High humidity 8 Low humidity 8
High temperature 8 Low temperature 8 Parity bit


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: Australia
Posts: 2630
Posted: 12:42am 28 Aug 2021
Copy link to clipboard 
Print this post

"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
�Print
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
�Print
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

 Print
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
 
     Page 3 of 3    
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025