Slow bytearray?

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
MFornander
Posts: 3
Joined: Thu Mar 03, 2016 7:42 am

Slow bytearray?

Post by MFornander » Fri Apr 14, 2017 4:06 pm

Hello from an excited and concerned backer!

We got a WeMos D1 Mini board (ESP8266-12F) driving a 240 LED strand using MicroPython 1.8.7 last night but we are a little concerned. Actually we are really happy that it works at all but we could use some advice.

First of all we got a speed of about 1 fps using the neopixel library. We got up to 2 fps by upping the clock rate to 160MHz. Then we found the low level esp.neopixel_write and thought it was the neopixel library taking time converting internal data structures before writing to LEDs. It was not. Instead, most of the time was taken in the main Python for loop simply accessing the 240*3 bytearray!

We've always done C++ on Teensy/ARM but would love Python's interpreted aspect to realize the Burning Man project idea. We also need wireless access and a cheap board so the $4 WeMos is perfect. In the end we got about 150fps by only changing six byte on the bytearray to move a single LED down the strand. We would like to procedually generate all 240 LEDs so that's not a solution.

Is anyone else using MicroPython on ESP8266 to drive 200+ WS8212 LEDs per strand at a decent rate? Any tricks?

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: Slow bytearray?

Post by deshipu » Fri Apr 14, 2017 9:16 pm

You can always write the relevant function in C or assembly, and have the rest in Python.

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

Re: Slow bytearray?

Post by stijn » Sat Apr 15, 2017 6:51 am

simply accessing the 240*3 bytearray
What exactly do you mean with 'accessing', can you show some code?

MFornander
Posts: 3
Joined: Thu Mar 03, 2016 7:42 am

Re: Slow bytearray?

Post by MFornander » Mon Apr 17, 2017 10:31 pm

Thanks for the reply!

This is the cleaned up code. All "mode" setting use the esp.neopixel_write to remove that possibility. The other modes are:
0: noop - just write the zero bytearray to the LEDs
1: set six bytes, aka two LEDs to move a single LED across all pixels
2: set all 240*3 values, fading up all LEDs to pink and then starting over.

noop = 142 fps
6 bytes = 125 fps
720 bytes = 27 fps

Why is accessing all bytearray values so slow? Is there is faster way?

Code: Select all

import utime
import machine
import esp


if __name__ == '__main__':
    i = 0
    offset = 0
    on = False
    led = machine.Pin(2, machine.Pin.OUT)
    gpio4 = machine.Pin(4, machine.Pin.OUT)

    machine.freq(160000000)

    rgb = bytearray(240*3)
    oldTime = utime.ticks_ms()
    mode = 1

    while True:

        # mode 0: 142 fps

        # mode 1: 125 fps
        if mode == 1:
            rgb[offset*3 + 0] = 0
            rgb[offset*3 + 1] = 0
            rgb[offset*3 + 2] = 0

            offset = offset + 1
            offset = offset % 239

            rgb[offset*3 + 0] = 0
            rgb[offset*3 + 1] = 255
            rgb[offset*3 + 2] = 255

        # mode 2: 27 fps
        elif mode == 2:
            for j in range(0, 240*3, 3):
                rgb[j + 0] = 0
                rgb[j + 1] = offset
                rgb[j + 2] = offset

            offset = offset + 1
            offset = offset % 239

        esp.neopixel_write(gpio4, rgb, True)

        if on:
            led.low()
            on = False
        else:
            led.high()
            on = True

        newTime = utime.ticks_ms()
        print("FPS:", int(1000.0 / utime.ticks_diff(newTime, oldTime)))
        oldTime = newTime

Post Reply