adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.02k stars 1.19k forks source link

STM32F411CE Blackpill - stalls when using time.sleep() #4452

Open jerryneedell opened 3 years ago

jerryneedell commented 3 years ago

I've been running thestandard "color_wheel" demo on an STM32F411CE Blackpill with a 16 RGB neopixel ring. I noticed that when it is running, the pattern occasionally "stalls" for varying amounts of time - sometimes over a full second. I added a print out the time between cycles of the the color wheel and you can see in the sample below how it sometime takes a lot longer between cycles. I have no idea why... I tried just running a counter that does not use neopixels and I did not see this behavior. I also tried running it on a feather_STM32F405_espress and could not reproduce the behavior. I also tried with both 3.3 and 5V on the Neopixels. Same behavior.

I will try to find a more minimal example, but I wanted to get this out ion case anyone has any suggestions.

This was run with CP from the tip of main and the latest neopixel.mpy

Firmware Adafruit CircuitPython 6.2.0-beta.4-286-ge084a9267 on 2021-03-21; stm32f411ce-blackpill-with-flash with STM32F411CE

>>>
>>> import ring
71.631  -- ignore this on
1.02402
1.01999
1.02301
1.01999
1.02301
1.01999
1.02301
1.01999
2.59    <<<<< long delay
1.021
1.022
1.021
1.022
1.02002
1.02298
1.02002
1.02298
1.02002
1.02298
1.022
1.021
1.022
1.021
1.022
1.021
1.022
1.021
1.022
1.021
1.022
1.021
1.36603   <<< shorter delay
1.021
1.02298
1.02002
1.02298
1.02002

code run - note Print in the while True loop after each rainbow cycle


from digitalio import *
from board import *
import neopixel
import time

pixpin = A1
numpix = 16

#led = DigitalInOut(D13)
#led.direction = Direction.OUTPUT

strip = neopixel.NeoPixel(pixpin, numpix, brightness=0.2,auto_write=False)

def wheel(pos):
    # Input a value 0 to 255 to get a color value.
    # The colours are a transition r - g - b - back to r.
    if (pos < 0):
        return (0, 0, 0)
    if (pos > 255):
        return (0, 0, 0)
    if (pos < 85):
        return (int(pos * 3), int(255 - (pos*3)), 0)
    elif (pos < 170):
        pos -= 85
        return (int(255 - pos*3), 0, int(pos*3))
    else:
        pos -= 170
        return (0, int(pos*3), int(255 - pos*3))

def rainbow_cycle(wait):
    for j in range(255):
        for i in range(len(strip)):
            idx = int ((i * 256 / len(strip)) + j)
            strip[i] = wheel(idx & 255)
        strip.show()
        time.sleep(wait)
last_time = 0 
try:
    while True:
        rainbow_cycle(0.001)
        now = time.monotonic()
        print(now - last_time)
        last_time = now

except:
    pass

finally:
    for i in range(len(strip)):
        strip[i] = (0,0,0)
    strip.show()
jerryneedell commented 3 years ago

The frequency of the "stalls" is highly variable. They appear to occur more reliably after a RESET or power cycle and are less frequent after a soft reboot. Sometimes it will run for minutes with out a stall and the length of the stall is also highly variable.

My apologies for the vagueness of this issue.... it is odd.

hierophect commented 3 years ago

STM32 uses the DWT for the neopixel writes, which I don't think should be messed up by anything else in the port, but maybe there's something going on with port_get_raw_ticks?

jerryneedell commented 2 years ago

FYI -- I just updated my BlackPill to 7.3.0-beta.1 and this issue is still present. Also updated to current neopixel.py from bundle. Same code.py as above.

Adafruit CircuitPython 7.3.0-beta.1 on 2022-04-07; stm32f411ce-blackpill-with-flash with STM32F411CE
>>> 
soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
213.004   <<<initial delay -- ignore
1.021
1.01904
1.16095
1.02002
1.25403
2.35095  <<< long pause
1.01904
1.021
1.01996
1.56799  <<< long pause
1.02002
1.021
1.01904
DavePutz commented 2 years ago

This issue looks to be with time.sleep() and not related at all to neopixels. Reducing the test script to:

import time

def wait_cycle(wait):
    for j in range(255):
        time.sleep(wait)
last_time = 0 
try:
    while True:
        wait_cycle(0.01)
        now = time.monotonic()
        print(now - last_time)
        last_time = now
except:
    pass

Gets the following results:

1371.69
3.78174
3.39111
3.5542
3.21875
3.66504
3.15234
3.11377
3.09277
3.07617
3.03516
2.97705
2.92871
2.88623
2.83789
2.77295
2.67529
2.71484
2.68994
2.62305
2.66699
2.63477
2.56201
13.1763
18.9448
11.9951
8.98975
7.11914
6.80225
5.94873
5.1001
4.9668
4.82324
4.3252
4.69678
4.13281
4.06641
3.979
3.91895
3.79004
3.40674
3.61279
3.23047
3.17676
3.34814
3.0459
2.99316
2.91162
2.7251
2.78809
2.73096
2.68701
2.61182
2.5874
22.519
11.8936
8.90332
7.14404

Note the pattern of slowing dropping towards the expected time of 2.55 seconds and then jumping way up again.

jerryneedell commented 2 years ago

Odd -- I get very different timing on mine. @DavePutz What board are you using?


Adafruit CircuitPython 7.3.0-beta.1 on 2022-04-07; stm32f411ce-blackpill-with-flash with STM32F411CE
>>> import hang
35.892
10.832
10.109
12.774
12.267
9.03198
16.355
6.34702
jerryneedell commented 2 years ago

with a minor change -- the timing is better -- but still has the odd slowdowns

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
673.351
2.48999
2.49097
2.49023
2.48999
2.48999
4.2168
2.48999
2.49121
3.61401
2.48999
4.39185
9.47217
2.48999
2.49097
2.48999
2.48999

using


def wait_cycle(wait):
    for j in range(25):
        time.sleep(wait)
last_time = 0 
try:
    while True:
        wait_cycle(0.1)
        now = time.monotonic()
        print(now - last_time)
        last_time = now
except:
    pass
DavePutz commented 2 years ago

@jerryneedell - I have a stm32f411ce-blackpill with STM32F411CE (i.e. not the flash version). I'm running a local build from the current main branch.

jerryneedell commented 2 years ago

@jerryneedell - I have a stm32f411ce-blackpill with STM32F411CE (i.e. not the flash version). I'm running a local build from the current main branch.

odd -- I wonder why mine (with flash) is running the .01 sleep loop so much more slowly....

jerryneedell commented 2 years ago

Regardless, clearly something is broken in time.sleep(). Thanks for narrowing this down -- I will modify the issue title to remove the neopixel slander ;-)

DavePutz commented 2 years ago

Another interesting result from testing: if the sleep time is 1 second then there are no stalls - the expected sleep is correct every time.

dhalbert commented 10 months ago

Let's close this based on probably being fixed by #6303.