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.
    • 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