Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    DHT 11 sensor always return same value

    Scheduled Pinned Locked Moved LoPy
    dht11lopypycom
    16 Posts 4 Posters 5.9k Views 5 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • robert-hhR Offline
      robert-hh @bihut
      last edited by

      @bihut Is a pull-up resistor in the data line? 4k7 Ohm is reccomended. And does the raw data reading look reasonable?

      1 Reply Last reply Reply Quote 0
      • robert-hhR Offline
        robert-hh @jmarcelino
        last edited by robert-hh

        @jmarcelino The code tries to perform a kind of digital sampling and then deduce the value from the samples time data. That assumes that during the loop the sampling is to some extend continuous. That's why IRQ's are disables. The whole DHT11 data takes about 40 ms. I'm not sure whther 500 samples are sufficient. That has to be determined. And the decoding looks wrong, if the ratio between sample timing and DHT11 timing is not known. The decoding here seems to assume a samping period of about 50 µs.

        J 1 Reply Last reply Reply Quote 0
        • J Offline
          jmarcelino @robert-hh
          last edited by jmarcelino

          @robert-hh
          Correct, 300 (not even 500) samples seems way too small for something like that.

          We saw in the pin interrupts experiments that toggling a Pin between (0) and (1) takes about 2-6 μS, so I'd expect reading should be similar maybe 1-2 μS.

          Total time for a reading from the DHT11 is 23.4 ms or 23400 μS so you really want to take and store at least the same (23400) samples to have a chance. (corrected in later reply, a buffer of 300 samples should suffice)

          Since we're only discerning between 28 μS (0) and 70 μS (1) pulses with 50 μS between them to me the more reasonable option is to simple add a small delay to the loop. But then you want to make sure it's properly calibrated/tested to the needs.

          0_1490782747130_CombinedTiming.jpg

          But again I'd strongly suggest moving on from the DHT11. It's a really cheap and nasty device. Anything that needs disabling IRQs especially in a LoRa device like the LoPy is a "bad idea"

          robert-hhR 1 Reply Last reply Reply Quote 0
          • robert-hhR Offline
            robert-hh @jmarcelino
            last edited by

            @jmarcelino The loop is a little bit slower than 1-2µs, because the loop management needs time too. But that has to be determined. So without real timing testing cou cannot get any results. There were people who managed to get this type of code working on ESP8266.
            Nevertheless, knowing about the irreular timing of the esp devices, it's better to use sensors with a stanard communication method.

            1 Reply Last reply Reply Quote 1
            • J Offline
              jmarcelino
              last edited by

              Just noticed the original poster is also using G4 (P14) which is an input-only pin, so trying to set it high dht_pin(1) does nothing. This means the DHT11 is not initialising.

              robert-hhR 1 Reply Last reply Reply Quote 1
              • robert-hhR Offline
                robert-hh @jmarcelino
                last edited by

                @jmarcelino Right, that's whatI wanted to check too. But at that point the docs at machine.pin should spend a few words about it. Normal users would not look into the esp32 data sheet.

                J 1 Reply Last reply Reply Quote 0
                • J Offline
                  jmarcelino @robert-hh
                  last edited by jmarcelino

                  @robert-hh
                  You don't need to look into the esp32 data sheet, it's on the LoPy pinout map with a red warning sign: https://docs.pycom.io/pycom_esp32/_downloads/lopy_pinout.pdf

                  "Only Input pins!"

                  The pinout map should really be required reading for everyone. Maybe the text could be made larger.

                  By the way I tested the loop - you are absolutely right I was overlooking the loop and memory access involved - each cycle takes about 20 μS. So perhaps 1200 samples could be enough.

                  robert-hhR 1 Reply Last reply Reply Quote 0
                  • robert-hhR Offline
                    robert-hh @jmarcelino
                    last edited by

                    @jmarcelino If a cycle takes 20 µs, and the actual reading time is less than 5 ms (160 µs lead in and 40 bits at 120µs worst case), then 250 samples are sufficient. So with 300 takes the buffer is large enough. So taking the wrong Input is the first thing to change.

                    J 1 Reply Last reply Reply Quote 1
                    • J Offline
                      jmarcelino @robert-hh
                      last edited by jmarcelino

                      @robert-hh
                      Good catch, I was going by the datasheet which states 23ms for a read, but that includes the initial delay already accounted for in the code.

                      So in summary @bihut :

                      -Change power supplt to 3.3v
                      -Use another Pin that isn't input only (so don't use G5, G4, G0, G3, G31, G30)

                      1 Reply Last reply Reply Quote 0
                      • robert-hhR Offline
                        robert-hh @bihut
                        last edited by robert-hh

                        @bihut I gave your code a try, and as @jmarcelino saidm

                        • the port was wrong, and
                        • the first trailing 0/1 change was not detected because python was busy with changing functions.
                          The attached code works with my AM2302, which is identical to DHT22.
                        from machine import enable_irq, disable_irq,  Pin
                        import time
                        _LIMIT = const(8)
                        _BUFFERSIZE = const(1000)
                        
                        def getval(pin) :
                            ms = [1] * _BUFFERSIZE
                            pin(0)
                            time.sleep_us(20000)
                            pin(1)
                            irqf = disable_irq()
                            mslen = len(ms)
                            for _ in range(mslen):
                                ms[_] = pin()      ## sample input and store value
                            enable_irq(irqf)
                            return ms
                        
                        def decode(inp):
                            res= [0]*5
                            bits=[]
                            ix = 0
                            try:
                                if inp[0] == 1 : ix = inp.index(0, ix) ## skip to first 0
                        #        ix = inp.index(1,ix) ## skip first 0's to next 1
                        #        ix = inp.index(0,ix) ## skip first 1's to next 0
                                while len(bits) < len(res)*8 : ##need 5 * 8 bits :
                                    ix = inp.index(1,ix) ## index of next 1
                                    ie = inp.index(0,ix) ## nr of 1's = ie-ix
                                    bits.append(ie-ix)
                                    ix = ie
                            except Exception as err:
                                print (err, ix, len(bits))
                                return([0xff,0xff,0xff,0xff])
                        
                            for i in range(len(res)):
                                for v in bits[i*8:(i+1)*8]:   #process next 8 bit
                                    res[i] = res[i]<<1  ##shift byte one place to left
                                    if v > _LIMIT:
                                        res[i] = res[i]+1  ##and add 1 if lsb is 1
                        
                            if (res[0]+res[1]+res[2]+res[3])&0xff != res[4] :   ##parity error!
                                print("Checksum Error")
                                res= [0xff,0xff,0xff,0xff]
                        
                            return(res[0:4])
                        
                        def DHT11(pin):
                            res = decode(getval(pin))
                            temp = 10*res[0] + res[1]
                            hum = 10 * res[2] + res[3]
                            return temp, hum
                        
                        def DHT22(pin) :
                            res = decode(getval(pin))
                            hum = res[0]*256+res[1]
                            temp = res[2]*256 + res[3]
                            if (temp > 0x7fff):
                                temp = 0x8000 - temp
                            return temp, hum
                        
                        dht_pin=Pin('G7', mode=Pin.OPEN_DRAIN)
                        dht_pin(1)
                        
                        temp, hum = DHT11(dht_pin)
                        
                        temp_str = '{}.{}'.format(temp//10,temp%10)
                        hum_str = '{}.{}'.format(hum//10,hum%10)
                        
                        # Print or upload it
                        print(temp_str, hum_str)
                        

                        It matches with a 10% difference with two cheap commercial temp/humidity devices I have, but I cannot tell which is right or wrong
                        Update: After an hour of settling, the two sensors show almost identical readings.

                        robert-hhR 1 Reply Last reply Reply Quote 1
                        • robert-hhR Offline
                          robert-hh @robert-hh
                          last edited by robert-hh

                          @robert-hh A slight re-arrangement of lines in getval() made the capture get the leading '0' bit. That also tells how critical the timing is. Still, even with IRQ disabled, sometimes transitions are missing.

                          from machine import enable_irq, disable_irq,  Pin
                          import time
                          _LIMIT = const(8)
                          _BUFFERSIZE = const(1000)
                          
                          def getval(pin) :
                              ms = [1] * _BUFFERSIZE
                              mslen = len(ms)
                              pin(0)
                              time.sleep_us(20000)
                              pin(1)
                              irqf = disable_irq()
                              for _ in range(mslen):
                                  ms[_] = pin()      ## sample input and store value
                              enable_irq(irqf)
                              return ms
                          
                          def decode(inp):
                              res= [0]*5
                              bits=[]
                              ix = 0
                              try:
                                  if inp[0] == 1 : 
                                      ix = inp.index(0, ix) ## skip to first 0
                                  ix = inp.index(1,ix) ## skip first 0's to next 1
                                  ix = inp.index(0,ix) ## skip first 1's to next 0
                                  while len(bits) < len(res)*8 : ##need 5 * 8 bits :
                                      ix = inp.index(1,ix) ## index of next 1
                                      ie = inp.index(0,ix) ## nr of 1's = ie-ix
                                      bits.append(ie-ix)
                                      ix = ie
                              except Exception as err:
                                  print (err, ix, len(bits))
                                  return([0xff,0xff,0xff,0xff])
                          
                              for i in range(len(res)):
                                  for v in bits[i*8:(i+1)*8]:   #process next 8 bit
                                      res[i] = res[i]<<1  ##shift byte one place to left
                                      if v > _LIMIT:
                                          res[i] = res[i]+1  ##and add 1 if lsb is 1
                          
                              if (res[0]+res[1]+res[2]+res[3])&0xff != res[4] :   ##parity error!
                                  print("Checksum Error")
                                  res= [0xff,0xff,0xff,0xff]
                          
                              return(res[0:4])
                          
                          def DHT11(pin):
                              res = decode(getval(pin))
                              temp = 10 * res[0] + res[1]
                              hum = 10 * res[2] + res[3]
                              return temp, hum
                          
                          def DHT22(pin) :
                              res = decode(getval(pin))
                              hum = res[0]*256+res[1]
                              temp = res[2]*256 + res[3]
                              if (temp > 0x7fff):
                                  temp = 0x8000 - temp
                              return temp, hum
                          
                          def run():
                              dht_pin=Pin('G7', mode=Pin.OPEN_DRAIN)
                              dht_pin(1)
                          
                              temp, hum = DHT11(dht_pin)
                          
                              temp_str = '{}.{}'.format(temp//10,temp%10)
                              hum_str = '{}.{}'.format(hum//10,hum%10)
                          
                              # Print or upload it
                              print(temp_str, hum_str)
                          
                          run()
                          
                          1 Reply Last reply Reply Quote 0
                          • Jurassic PorkJ Offline
                            Jurassic Pork
                            last edited by

                            This post is deleted!
                            1 Reply Last reply Reply Quote 0
                            • Jurassic PorkJ Offline
                              Jurassic Pork @jmarcelino
                              last edited by

                              hello,
                              if someone can try my dht11 class and say me if it works for him.
                              It seems to be OK with a SiPy powered with USB .
                              DHT11_PyCom

                              Friendly, J.P

                              1 Reply Last reply Reply Quote 0

                              Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                              Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                              With your input, this post could be even better 💗

                              Register Login
                              • 1 / 1
                              • First post
                                Last post

                              Pycom on Twitter

                              Pycom