Skip to content

Display instability during NeoPixel show() on Fruit Jam #10564

@relic-se

Description

@relic-se

CircuitPython version and board name

Adafruit CircuitPython 10.0.0-beta.2-3-gf86bf4c085 on 2025-08-04; Adafruit Fruit Jam with rp2350b

Code/REPL

import asyncio
import board
from displayio import Group, Bitmap, Palette, TileGrid
import supervisor
from vectorio import Rectangle

from adafruit_fruitjam.peripherals import request_display_config
from neopixel import NeoPixel

SIZE = 100
VELOCITY = 1

request_display_config(640, 480)
display = supervisor.runtime.display
main_group = Group()
display.root_group = main_group

bg_palette = Palette(1)
bg_palette[0] = 0xff0000
tile_grid = TileGrid(Bitmap(display.width, display.height, 1), pixel_shader=bg_palette)
main_group.append(tile_grid)

class Bouncer(Group):

    def __init__(self, color:int, velocity:int=VELOCITY, size:int=SIZE, **kwargs):
        super().__init__(**kwargs)
        palette = Palette(1)
        palette[0] = color
        self._velocity = [velocity] * 2
        self._size = size
        self.append(Rectangle(pixel_shader=palette, width=size, height=size))
    
    def update(self) -> None:
        global display

        if self._edge(self.x, self._velocity[0], display.width):
            self._velocity[0] *= -1
        self.x += self._velocity[0]

        if self._edge(self.y, self._velocity[1], display.height):
            self._velocity[1] *= -1
        self.y += self._velocity[1]

    def _edge(self, position:int, velocity:int, limit:int) -> bool:
        return (velocity > 0 and position + self._size + velocity > limit) or (velocity < 0 and position + velocity < 0)

bouncers = (
    Bouncer(0x00ff00),
    Bouncer(0x0000ff, x=display.width - SIZE),
    Bouncer(0xffff00, x=display.width - SIZE, y=display.height - SIZE),
    Bouncer(0x00ffff, y=display.height - SIZE),
)
for bouncer in bouncers:
    main_group.append(bouncer)

neopixels = NeoPixel(board.NEOPIXEL, 5)
async def neopixels_handler() -> None:
    global neopixels
    while True:
        neopixels.fill(0xff0000)
        await asyncio.sleep(2)
        neopixels.fill(0x00ff00)
        await asyncio.sleep(2)
        neopixels.fill(0x0000ff)
        await asyncio.sleep(2)

async def bouncer_handler() -> None:
    global display, rect
    while True:
        for bouncer in bouncers:
            bouncer.update()
        await asyncio.sleep(1/30)

async def main():
    await asyncio.gather(
        asyncio.create_task(neopixels_handler()),
        asyncio.create_task(bouncer_handler()),
    )

# initial display refresh
display.refresh(target_frames_per_second=30)

asyncio.run(main())

Behavior

Display will temporarily black out occasionally when neopixels are updated and will resume operation after about a second. No errors are reported.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions