Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Neopixels/ws2812 support #166

Open
eadmaster opened this issue Jun 17, 2024 · 5 comments
Open

Feature Request: Neopixels/ws2812 support #166

eadmaster opened this issue Jun 17, 2024 · 5 comments

Comments

@eadmaster
Copy link

eadmaster commented Jun 17, 2024

an implementation for standard firmata is here based on Adafruit_NeoPixel lib.

As alternative, FastLED also supports ws2812 leds.

Related: firmata/arduino#167

@eadmaster eadmaster changed the title Feature Request: Neopixels support Feature Request: Neopixels/ws2812 support Jun 17, 2024
@pgrawehr
Copy link
Contributor

It shouldn't be too hard to include the linked code as module in ConfigurableFirmata. That would first need an API proposal at https://github.com/firmata/protocol, as the link above seems to make an unofficial protocol extension.

Also, I don't think it's needed at all. WS2812 uses SPI to communicate with the strip, so you can just use the current version of ConfigurableFirmata (which does support SPI) and use some WS2812 driver on top of it (such as this one).

@eadmaster
Copy link
Author

eadmaster commented Jun 19, 2024

WS2812 uses SPI to communicate with the strip, so you can just use the current version of ConfigurableFirmata (which does support SPI)

It seems a good alternative, but i still cannot get it to work this way:

import pyfirmata
import time

board = pyfirmata.Arduino('/dev/ttyUSB0')

# Initialize SPI on the Arduino
board.send_sysex(pyfirmata.START_SYSEX, [0x42, 0x00])  # SPI_BEGIN
board.send_sysex(pyfirmata.START_SYSEX, [0x42, 0x02, 0x00])  # SPI_SET_CLOCK, Clock Divider: 0 (4MHz)
board.send_sysex(pyfirmata.START_SYSEX, [0x42, 0x04, 0x00])  # SPI_SET_BIT_ORDER, MSBFIRST
board.send_sysex(pyfirmata.START_SYSEX, [0x42, 0x06, 0x00])  # SPI_SET_DATA_MODE, SPI_MODE0

def spi_write(data):
    message = [0x42, 0x08] + data  # SPI_TRANSFER command
    board.send_sysex(pyfirmata.START_SYSEX, message + [pyfirmata.END_SYSEX])

def set_pixel_color(red, green, blue):
    prefix = [0x00]  # NeoPixel start frame marker
    pixel_data = [red, green, blue]
    suffix = [0x00]  # NeoPixel end frame marker
    data = prefix + pixel_data + suffix
    spi_write(data)

# Example usage: setting the first pixel to red
print("red")
set_pixel_color(255, 0, 0) 
time.sleep(10)
board.exit()

EDIT: for context: a single WS2812 led is connected to pin "IO23" (SPI MOSI) on the Wemos D1 R32 board. ConfigurableFirmata v3.2.0 was flashed on the board with SPI enabled.

@pgrawehr
Copy link
Contributor

board.send_sysex(pyfirmata.START_SYSEX, [0x42, 0x00])  # SPI_BEGIN
board.send_sysex(pyfirmata.START_SYSEX, [0x42, 0x02, 0x00])  # SPI_SET_CLOCK, Clock Divider: 0 (4MHz)
board.send_sysex(pyfirmata.START_SYSEX, [0x42, 0x04, 0x00])  # SPI_SET_BIT_ORDER, MSBFIRST
board.send_sysex(pyfirmata.START_SYSEX, [0x42, 0x06, 0x00])  # SPI_SET_DATA_MODE, SPI_MODE0

Where did you find these command sequences? According to https://github.com/firmata/protocol/blob/master/spi.md SPI_DATA is 0x68, not 0x42. Thus your command sequence should begin like

START_SYSEX, 0x68, 0x0, 0x0, END_SYSEX
START_SYSEX, 0x68, 0x01, 0x0 (depending on CS line to use), 0x8, ....

And also the pixel_data you send can't work that way, because you need use 7-bit data mode (the firmata protocol considers the MSB of every byte sent as start of a command character. For SPI transfer, that means that you have to convert every byte sent either into two bytes (with the first byte containing the top bit of the data byte) or, when the encoding bit is set (bit 3 of byte 4 of the DATA_MODE command) use packed encoding (pack 7 bytes into 8 transfer bytes).

@eadmaster
Copy link
Author

eadmaster commented Jun 23, 2024

sorry, still not working, here it is my updated code.
The bitwise manipulation needed seems pretty tricky. So i've switched to this StandardFirmata fork which is much easier to use.

@pgrawehr
Copy link
Contributor

sorry, still not working, here it is my updated code. The bitwise manipulation needed seems pretty tricky.
I would expect that pyfirmata does that for you, but unfortunately, that doesn't seem to be maintained any more. I don't have control over that. You probably have to do some debugging (on both the server and the board side) to make sure the commands are properly understood.
So i've switched to this StandardFirmata fork which is much easier to use.
The commands for your particular case seem easier, but I doubt you'll get it to work nicely without debugging the commands either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants