adafruit / Adafruit_CircuitPython_DotStar

Dotstarrin' away in CircuitPython land
MIT License
46 stars 38 forks source link

fill() function has undesired delay #37

Closed HHH-01 closed 4 years ago

HHH-01 commented 4 years ago

The fill() function doesn't switch fast enough. It seems to have a big delay somewhere, which I couldn't spot. My expectation will have a color-switching very fast ~1ms or even slower, but apparently, it would take 100ms or more and can be detected the color change by eyes.

See the code below:

import adafruit_dotstar import digitalio import board import math import time import random

num_pixels = 40 brightness = 0.005

pixels = adafruit_dotstar.DotStar(board.SCK, board.MOSI, num_pixels, brightness=brightness, auto_write=False)

BLACK = (0, 0, 0) WHITE = (255, 255, 255)

while True:

pixels.fill(WHITE) pixels.show() time.sleep(0.001)

pixels.fill(BLACK) pixels.show() time.sleep(0.001)

kevinjwalters commented 4 years ago

It copies data around if brightness is not 1. There are lots of forum discussions about this including: Adafruit Forums: Slow Dotstars--help!

What hardware are you describing/using?

Depending on your cable length/quality you can also play with the data transmission rate which becomes a factor for large numbers of pixesl: Adafruit Forums: adafruit_dotstar, spi speed/frequency and long cables

zissou1 commented 4 years ago

Im experience the exact same issue as huynh213 at Brightness 1. I also written almost the exact same code for testing and timed about 100ms per fill(). I never used Neopixels or anything so i wasn't sure what I expected in terms of speed. Using SPI on Trinket M0 with external power supply for 120 dotstars strip warm white 3000K.

zissou1 commented 4 years ago

Using very short cables (same as was attached to end of strip).

kevinjwalters commented 4 years ago

An easy change for a bit of extra speed would be for fill() to be implemented implemented with direct calls to _set_item(). It could also replicate some of the logic for faster buffer writes.

Looks llike brightness=1 might be a fraction faster than brightness=1.0 too.

kevinjwalters commented 4 years ago

I was after some better update rates a while back and resorted to breaking the object encapsulation and writing directly to the buffer, see https://github.com/kevinjwalters/circuitpython-examples/blob/master/gemma-m0/dotstar-racer.py for an example of this.

It looks like .buf is now ._buf which is a useful example of how this misuse can lead to application problems.

kevinjwalters commented 4 years ago

This is for neopixels but there is a disappointing performance penalty for using fill(), from a CPB board running 5.0.0-alpha.5

Adafruit CircuitPython 5.0.0-alpha.5 on 2019-11-04; Adafruit Circuit Playground Bluefruit with nRF52840
>>> import time
>>> import board
>>> import neopixel
>>> pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=1)
>>> for i in range(10):
...     t1 = time.monotonic() ; pixels.fill((0,0,3)) ; t2 = time.monotonic() ; print(t2-t1)
...
...
...
0.0100098
0.0100098
0.0100098
0.0100098
0.0100098
0.0100098
0.0100098
0.0100098
0.0100098
0.0100098
>>> tenblue = [(0,0,3)] * 10
>>> for i in range(10):
...     t1 = time.monotonic() ; pixels[0:10] = tenblue ; t2 = time.monotonic() ; print(t2-t1)
...
...
...
0.00390625
0.00415039
0.00488281
0.00415039
0.00488281
0.00390625
0.00390625
0.00390625
0.00415039
0.00488281
rhooper commented 4 years ago

@kevinjwalters Have a peek at the master branch of circuitpython (likely coming to a beta near you soon) and https://github.com/rhooper/Adafruit_CircuitPython_DotStar/blob/pixelbuf/adafruit_dotstar.py