Threads

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
Post Reply
lbayo
Posts: 15
Joined: Tue Mar 16, 2021 2:10 pm

Threads

Post by lbayo » Sun Apr 04, 2021 10:34 pm

Hi,

After a lot of testing, I have come to the conclusion that micropython threads (at least on ESP32) interfere with other functions of the chip.
In particular:
My DHT11 (one-wire) temperature sensor, does not work or does very badly when there are active threads.
The i2c OLED display that I use takes a few seconds to display the text, while without threads is almost immediate
Perhaps the use of threads seems to produce alterations in the timing of the system, used by one-wire and I2C. Perhaps it disable interrupts for longer than is convenient and both, the I2C bus and the one-wire, which are highly timing dependent, malfunction.
Has anyone else observed the phenomenon?
Is there any solution?
Should I give up the use of threads?

stijn
Posts: 615
Joined: Thu Apr 24, 2014 9:13 am

Re: Threads

Post by stijn » Mon Apr 05, 2021 6:47 am

Is the problem you're describing just having active threads in general, or rather the code which runs in the threads? Can you show the minimal code to reproduce this? For example: if you have a normal single-threaded application which works fine, then when that same application starts one thread which does nothing but just sleeps, do you observe any effects already? If not, the problem isn't merely active threads but what gets done in them. E.g. suppose you start a thread with an infinite loop, it is going to take as much CPU time as possible so there will be adverse effects on everything. But such loop makes no sense in reality.

User avatar
pythoncoder
Posts: 5140
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Threads

Post by pythoncoder » Mon Apr 05, 2021 9:16 am

As a general point, it is eminently possible that timing is affected because threading uses pre-emptive multi tasking. I would use uasyncio for timing critical applications because it uses cooperative multi tasking.
Peter Hinch

lbayo
Posts: 15
Joined: Tue Mar 16, 2021 2:10 pm

Re: Threads

Post by lbayo » Mon Apr 05, 2021 4:55 pm

Hi,

Thanks to pythoncoder and stijn.
The actual program is over 600 lines of python code, but I have simplified it into an easy example of this malfunction.
The system (ESP32) consists of a DHT11 temperature sensor (@pin 33) and a led (@pin 32) to blink.
In the sample program, two threads are created: one to read the sensor and print values and the other to blink the led.
Each time a temperature sensor reading is taken, the read values ​​or an error message, if applicable, are printed.

Code: Select all

from machine import Pin 
from utime import sleep
import dht
import _thread


def blink():
    pin = Pin(32, Pin.OUT)
    while Run:
        pin.value(1)
        sleep(0.1)
        pin.value(0)
        sleep(0.2)

def read_sensor():
    s11=dht.DHT11(Pin(33))
    while Run:
        try:
            s11.measure()
            temp=s11.temperature()
            hum=s11.humidity()
            print ("T:",temp, "ºC   Hum:",hum,"%")
        except:
            print ("----DHT fail")
        sleep(3)

#-----------------
#  MAIN LOOP
#-----------------
Run=True
_thread.start_new_thread(read_sensor, ())
_thread.start_new_thread(blink, ())

n=0
while n<20:
    n+=1
    print (n)
    sleep(10)
Run=False



As can be seen, when executing the program (under Thonny), numerous cases of sensor reading error appear. A output example is :

Code: Select all

1
T: 24 ºC   Hum: 46 %
T: 24 ºC   Hum: 46 %
----DHT fail
2
T: 24 ºC   Hum: 46 %
T: 24 ºC   Hum: 46 %
T: 24 ºC   Hum: 46 %
3
----DHT fail
----DHT fail
----DHT fail
----DHT fail
4
----DHT fail
T: 24 ºC   Hum: 46 %
----DHT fail
5
T: 24 ºC   Hum: 46 %
----DHT fail
As you can see, sometimes it reads good and sometimes not.
Program is stopped by STOP button.

I can try to put code in main loop, without any thread, read sensor never fails. The code is

Code: Select all

from machine import Pin 
from utime import sleep
import dht

def read_sensor():
    s11=dht.DHT11(Pin(33))
    try:
        s11.measure()
        temp=s11.temperature()
        hum=s11.humidity()
        print ("T:",temp, "ºC   Hum:",hum,"%")
    except:
        print ("----DHT fail")

#-----------------
#  MAIN LOOP
#-----------------

n=0
while n<20:
    n+=1
    print (n)
    read_sensor()
    sleep(3)
and the output is

Code: Select all

>>> %Run -c $EDITOR_CONTENT
1
T: 24 ºC   Hum: 46 %
2
T: 24 ºC   Hum: 46 %
3
T: 24 ºC   Hum: 46 %
4
T: 24 ºC   Hum: 46 %
5
T: 24 ºC   Hum: 46 %

─────────────────────────
MicroPython v1.14 on 2021-02-02; ESP32 module with ESP32
Type "help()" for more information.
>>> 
This problem also appears using the I2C interfaces.
My conclusion is, as pythoncoder points out, that when using interfaces whose operation depends on timings, the use of threads is not a good idea and only causes problems

Thanks

User avatar
pythoncoder
Posts: 5140
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Threads

Post by pythoncoder » Tue Apr 06, 2021 6:29 am

The point being that when a uasyncio Task is running it gets guaranteed execution until it yields to the scheduler, and so provides precise, deterministic timing. This is definitely true on bare metal ports, and I believe it is true on ESP32 because the RTOS runs on a separate core.
Peter Hinch

lbayo
Posts: 15
Joined: Tue Mar 16, 2021 2:10 pm

Re: Threads

Post by lbayo » Tue Apr 06, 2021 11:31 am

Thank you Peter.

Can you tell me where I can find a complete documentation about uasincio? (in order to avoid having to spend longtime searching on unhelpful websites)

kevinkk525
Posts: 925
Joined: Sat Feb 03, 2018 7:02 pm

Re: Threads

Post by kevinkk525 » Tue Apr 06, 2021 12:21 pm

Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

Post Reply