ghost_95
Posts: 8
Joined: Sat Feb 13, 2021 2:29 pm

Re: I created a DHT11 driver using PIO in MicroPython

Wed Feb 17, 2021 7:07 am

@danjperron

Now it works for my board too! Thank you very much :D

techiebouncer
Posts: 6
Joined: Tue Jun 25, 2019 7:57 am

Re: I created a DHT11 driver using PIO in MicroPython

Tue Feb 23, 2021 4:11 pm

everything goes well but not with floating-point value. just increments with round off

danjperron
Posts: 3871
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: I created a DHT11 driver using PIO in MicroPython

Tue Feb 23, 2021 7:49 pm

everything goes well but not with floating-point value. just increments with round off
DHT11 or DHT22 ?

DHT11 has no floating point.! It is +/- 2°C

techiebouncer
Posts: 6
Joined: Tue Jun 25, 2019 7:57 am

Re: I created a DHT11 driver using PIO in MicroPython

Wed Feb 24, 2021 5:28 am

definitely not mate, its DHT11 with C or C++ the value is clean with respect to decimals but not with micropython. same sensor with accurate values in C and also in arduino

techiebouncer
Posts: 6
Joined: Tue Jun 25, 2019 7:57 am

Re: I created a DHT11 driver using PIO in MicroPython

Wed Feb 24, 2021 6:16 am

https://github.com/ikornaselur/pico-dht11

This looks promising, with more accurate results.but you got to use all three files inside pico

danjperron
Posts: 3871
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: I created a DHT11 driver using PIO in MicroPython

Wed Feb 24, 2021 2:30 pm

definitely not mate, its DHT11 with C or C++ the value is clean with respect to decimals but not with micropython. same sensor with accurate values in C and also in arduino
One of my boss will complain right away!

He will tell you that your sensor has an error of +/- 2 degree. There is no point to display more precision .

I.M.O. The DHT11 shouldn't report mantissa (fractional-part) at all!

Why using a float when an integer will do the trick?

gregwa
Posts: 31
Joined: Tue Feb 02, 2021 10:15 am

Re: I created a DHT11 driver using PIO in MicroPython

Wed Mar 03, 2021 9:23 am

This works well for me. I also turned another person onto the library which worked well for him as well.
THANK YOU! :D

danjperron
Posts: 3871
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: I created a DHT11 driver using PIO in MicroPython

Wed Mar 03, 2021 2:55 pm

OK difference using StateMachine versus interrupts.

StateMachine code runs on itself. No interrupts and at constant selected clock. The cpu could do is own stuff,
This mean that no interrupts will perturbate the timing of the StateMachine.

Interrupts are not exactly constant. When an interrupt occurs you have some delays. Other interrupts could have priority over and will cause delay. It won't show normally but if your system use a lot of interrupts this is problematic.

Ex:
https://forum.micropython.org/viewtopi ... 895#p55331
This is about using the timer with callback to calculate pulse time. On this example the clock generated by tgit's not constant if you compare to the version using StateMachine.


I.M.O. Using StateMachine is more precise in timing and free the cpu usage to do other task.
But to free other task the StateMachine modules needs the FIFO status.
I'm able to add this in my code using mem32 but is not build-in yet!

Presently I'm working on an interrupt version. I know is contradictory but is to get fifo data from StateMachine. It will interrupt only on each byte. So 5 interrupts to read the DHT sensor. Also this will provide a way to the cpu to do something else and not waiting for the results.

ctrob
Posts: 9
Joined: Sat Mar 27, 2021 4:13 pm

Re: I created a DHT11 driver using PIO in MicroPython

Sun Mar 28, 2021 9:59 am

Hi,

I thought it would be nice to try out a PIO driver for the DHT11 too but you beat me to it! I only got my Pico recently as an addon to another order and, while this protocol is a little quirky, it is clearly way too popular to be ignored for very long. Anyway, I downloaded your code and it worked right away but I can still contribute.

You shouldn't need to power the DHT11 on each time and I am not sure about the general wisdom of powering it via an IO line from the microcontroller! I just connect mine to the 3v3 and I also follow the datasheet to poll the DHT11 only once per second.

I wrote a VHDL driver for the FPGA on the Arduino Vidor and issues with debouncing the signal edges, but that was running at a much higher clock. Also concerned with timeouts - particular if the device isn't connected and not using up the cpu as the transaction conservatively takes up to around 25ms to complete. I was also concerned that the 'common' method I have seen and used before of timing the pulses is little complicated compared with similar protocols.

I have spent a while trying to use interrupts with this driver and all attempts (uasyncio, _thread etc) have failed. I can signal an IRQ from the PIO code to run some python call-back but all attempts to block the main thread on any sort of concurrency primitive and to unblock it from the call back failed, often with a crashed Pico.

Given this device is limited to one access/second, the python driver could just set the PIO code off to run and sleep for 25ms and then check whether it has completed. This solves the CPU issue and the timeout issue but... the micropython PIO interface doesn't seem to give enough access to the state machines to check whether they have finished - it may be needed to write a C driver to do this properly. That said, I have just extended the code to signal the IRQ after 40 bits have been set, set a (global) completion flag that can be checked by the python code when it wakes up from the sleep - and this works, the driver has an indication of success (fails <24ms passes >= 24ms with my ambient humidity / temperature!)..

Another issue is that the receive FIFO is 4 bytes and we need 5 bytes or the PIO stalls. The PIO can be configured to join the FIFOs so we can have 8 bytes on the receive and no transmit FIFO. This works but is not in the API (yet). Rather than hack the library, it turns out the configuration is stored in the array generated by asm_pio and this can be modified to give an 8 byte receive FIFO:

Code: Select all

DHT11[4] = DHT11[4] | (1 << 31)
With an 8 byte input FIFO the driver can wait until all the data has been received before continuing, so only one interrupt is required (or none if the SM could be inspected directly).

I don't think input debouncing is an issue at the clock speeds we are using, and I have dropped the clock to 500KHz, but I added a few delay cycles in after checking edges for extra security.

It's bothered me that the standard approach involves timing the signal. This is no problem for regular software or VHDL and helps with terminating an abnormal transaction but I looked at this again and found an alternative simpler way: sample the data pulse after (say) 50us of the rising edge and the line indicates what the bit value is: zero pulse are short (<23us) so the line will be zero, one pulses are longer (70us) so the line is still high. This means we just need a 50us delay after the rising edge is detected before shifting the next data bit in directly from the pin.

I have implemented this in the code below (without the completion IRQ) and it comes in at just 13 instructions. After 40 bits have been transferred the pin stays high and the SM blocks waiting for another bit.

It would be nice to reset the state machine to avoid reinitialising the whole PIO by using jmp/set the pc to 0 again but there isn't a way to do this from micropython. My guess is that if I rewrote all this in C then I would have access to all the PIO registers I would need to get this running the way I'd like but I would prefer to keep this pure python.

Anyway, thanks for getting this working and hopefully I've moved things on a bit.

Code: Select all

    # Requires 500Khz clock
    # Drive output low for at least 20ms to activate the device
    set(pindirs,1)
    set(pins,0)

    set(y, 9) [7]                # 20ms delay
    label ('outer_20ms')         # 10 * 31 * (31 + 1) / 500kHz = 20ms
    set(x, 30)                   # (plus fine tuning for the sake of it)
    label ('inner_20ms')
    jmp(x_dec,'inner_20ms') [31]
    jmp(y_dec,'outer_20ms') [5]
     
    # Look for the device response (~90us low pulse)
    # Add some delay to 'debounce' edges
    set(pindirs,0)
    wait(1,pin,0) [1]            # Wait for input to release (high pulse ~12us)
    wait(0,pin,0) [1]            # Wait for device to drive low (low pulse ~83us)
    wait(1,pin,0) [1]            # Wait for device to release line (high pulse ~86us)

    wrap_target()                # Read data bits from device

    # (once 40 bits have been read code will block here with input permanently high)
    wait(0,pin,0) [1]            # Wait for start of data + debounce (low pulse ~54us)
    wait(1,pin,0) [24]           # Wait for high signal and then 50us

    # After 50us input will indicate bit value (high pulse zero ~23us, one ~70us)
    in_(pins, 1)                 # Shift the data bit into the isr
    wrap()                       # Loop to read the remaining bits from device

danjperron
Posts: 3871
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: I created a DHT11 driver using PIO in MicroPython

Sun Mar 28, 2021 1:59 pm

@ctrob

Yes I know! asm_pio is a little bit restrictive!

This is why I didn't use the wait command! If the sensor is stuck you are stuck unless you put a timer to wait for a response after so many ms.

The way I decide was to use jmp instead! if the sensor failed I will get a checksum error.

And yes power on/off the dht22 is optional.

ctrob
Posts: 9
Joined: Sat Mar 27, 2021 4:13 pm

Re: I created a DHT11 driver using PIO in MicroPython

Sun Mar 28, 2021 6:14 pm

danjperron wrote:
Sun Mar 28, 2021 1:59 pm
This is why I didn't use the wait command! If the sensor is stuck you are stuck unless you put a timer to wait for a response after so many ms.

The way I decide was to use jmp instead! if the sensor failed I will get a checksum error.
Considering intended use of this senor, there should be a maximum of one transaction per second and a transaction takes a bounded time of around 25ms, especially in a multithreaded environment. I am quite happy to put the CPU to sleep for 25ms and then check up on the PIO state machine. There are two classes of faults with this transaction: noise (checksum error) and a harder fault or absence of the device so (protocol error) there is no response. If the state machine hasn't 'completed' within the time out then you have a protocol error (absence or serious inability to drive the line) otherwise you can verify the checksum. Whatever happens, the best you can do is retry in another second.

The advantage of the smaller program is that you might manage to fit two different protocols into one PIO unit, and run them concurrently on different state machines (if I understand this correctly), although not from micropython! I have no idea if this is useful!

Sebizarro
Posts: 1
Joined: Wed Jun 16, 2021 7:26 pm

Re: I created a DHT11 driver using PIO in MicroPython

Wed Jun 16, 2021 7:30 pm

Thank you! it works great!
after mixing some codes I've manage to display the values on a OLED display (:
does anyone know how to store the values and use it to create some graphics?

Stami
Posts: 4
Joined: Sun Aug 29, 2021 11:38 am

Re: I created a DHT11 driver using PIO in MicroPython

Sun Aug 29, 2021 11:44 am

hello to all

I think the code works very well.
but my output is always

about 50°C an hum of about 107%

i have 4x DHT, all of the return the same values.

maybe someone have an idea what's wrong?

danjperron
Posts: 3871
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: I created a DHT11 driver using PIO in MicroPython

Sun Aug 29, 2021 3:02 pm

Could you post a picture of your setup.

Some DHT22 are on a PCB and contain the pull-up resistor.

Stami
Posts: 4
Joined: Sun Aug 29, 2021 11:38 am

Re: I created a DHT11 driver using PIO in MicroPython

Tue Aug 31, 2021 7:29 pm

hello

yes I am using a DHT22 which is on a PCB (3Pin version)
Attachments
WhatsApp Image 2021-08-31 at 20.55.11.jpeg
WhatsApp Image 2021-08-31 at 20.55.11.jpeg (30.95 KiB) Viewed 613 times

danjperron
Posts: 3871
Joined: Thu Dec 27, 2012 4:05 am
Location: Québec, Canada

Re: I created a DHT11 driver using PIO in MicroPython

Thu Sep 02, 2021 2:59 am

HI Stami,

Thanks for the picture but it is too low quality and it is to far away.
I can't figure out where the wires are connected to and what type of DHT22.

If it is 3 pins it should be a DHT22 on PCB with resistors.

P.S. if you are not using GPIO 14 Pin to power up the DHT22 , just GPIO15 for data you could just remove the power pin declaration.
By default the power pin is Not used!

ex: on my DHT22.py class change the line 178 to

Code: Select all

dht_sensor=DHT22(dht_data,dht11=False)

Just in case did you try to add a 4k7 pull-up resistor?
Did you try to change the Pin in case this GPIO pin is broken.


Do you have Raspberry Pi? Try to connect the sensor to a raspberry Pi to see if it is working.
Use Joan's pigpio example https://abyz.me.uk/rpi/pigpio/code/DHT.py
ex: I put the data pin to the Raspberry PI GPIO21.(-) to GND and (+) to 3.3V

Code: Select all

wget https://abyz.me.uk/rpi/pigpio/code/DHT.py
sudo pigpiod
python DHT.py 21

Stami
Posts: 4
Joined: Sun Aug 29, 2021 11:38 am

Re: I created a DHT11 driver using PIO in MicroPython

Thu Sep 02, 2021 7:47 am

Hello!

thanks for your reply

Yes sorry, i had to resize/downsize the pic for upload (uploadsize is limited).
I also tried to add the resistor - the output was the same as without.
i tried to change the pin, i also tried with two other pico´s and i always get the same (wrong)output.


i will try today with a pi zero.
meanwhile i think there is something wrong with the DHT22´s not with the code.
maybe der are wrong calibrated. - i already order new DHT22 from another seller.

but anyway i will respond here as soon i have news.

Stami
Posts: 4
Joined: Sun Aug 29, 2021 11:38 am

Re: I created a DHT11 driver using PIO in MicroPython

Fri Sep 03, 2021 4:46 pm

hello danjperron!

the problem is solved! it was a hardware problem.
the sensor was wrong calibrated out of the factory (all 4 of them).
the new sensors are working with your code correctly!

thanks for your help!!!

greetings from austria
stami

Return to “MicroPython”