SPI controlling LED Strip UCS1903
-
I am trying to control a strip of lights that I have using a UCS1903.
I am not understanding things correctly. I understand that a square wave can be used to indicate a 1 or a 0 and that pauses in sending a signal can indicate other functions.
How does this translate to sending infomation over spi.
Im not sure. If I could watch was is happening on the MOSI as it is attached to the flash storage...if I connect the DIN of my light strip to MOSI and install software or boot up the machine, the lights start going about changing colours and lighting up...
But plugged into CS1 and trying to send data..
The lights take a 24bit piece of data r(8bits) g(8bits) and b(8bits)
Here is code showing how my brain is comprehending this.
import onionSpi import time busnum = 1 deviceid = 32766 spi = onionSpi.OnionSpi(busnum, deviceid) spi.speed = 400000 spi.delay = 1 spi.mosi = 18 spi.mode = 0 #spi.bitsPerWord = 1000 # spi.bitsPerWord = 24 # spi.modeBits = ['lsbfirst'] spi.modeBits = 0x8 spi.setupDevice() spi.registerDevice() #spi.bitsPerWord = 3 device_check = spi.checkDevice() print device_check print 'SPI MOSI GPIO: %d'%(spi.mosi) print 'SPI Speed: %d Hz (%d kHz)'%(spi.speed, spi.speed/1000) print 'Mode Bits: 0x%x'%(spi.modeBits) # R7 R6 R5 R4 R3 R2 R1 R0 G7 G6 G5 G4 G3 G2 G1 G0 B7 B6 B5 B4 B3 B2 B1 B0 led_rgb = [] led_full = [ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ] led_red = [ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ] led_green = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] led_blue = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] # ret1 = spi.writeBytes(0x00, led_red) # ret2 = spi.writeBytes(0x00, led_green) # ret3 = spi.writeBytes(0x00, led_blue) # print ret1 # print ret2 # print ret3 vals = [0x00, 0x1C, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2D] ret = spi.write(vals) # spi.write(led_red) # time.sleep(1) # spi.write(led_green) # time.sleep(1) # spi.write(led_blue) # time.sleep(1)
-
@Paul-Chabot: From the datasheet you linked, these UCS1903 chips are close relatives to the WS281x family of LED chain chips.
To generate the required signal with SPI, you'd need to have a SPI interface available exclusively for the purpose (which you don't on Omega2), and you need to have tight control of the SPI to send a long uninterrupted stream of data (which usually works on Arduino&Co, but is difficult on a Linux system).
But luckily, there's hardware better suited for the task than the SPI in Omega2's MT7688 chip: the PWM unit. It's still a bit tricky to meet all timing constraints, but definitely possible. I know because I wrote a kernel driver named p44-ledchain exactly for the purpose I needed it for Omega2 based projects like this (with 200 WS2813 LEDs).
Now, the UCS1903 has slightly different timings specs than the chips already supported in
p44-ledchain
(WS2811, WS2812, WS2813, P9823, SK6812). Still, I think it should work with the P9823 setting. If not, just let me know and I can add another option for the UCS1903 chip to the driver.If you want to give it a try:
Install the driver (needs
--force-depends
because there's no 100% kernel version match):cd /tmp wget http://plan44.ch/downloads/experimental/kmod-p44 ledchain_4.4.61%2B0.9-2_mipsel_24kc.ipk opkg install --force-depends kmod-p44-ledchain*
Then load the driver and configure it for a chain of 100 P9823 (see here for detailed description of the module parameters):
insmod /lib/modules/4.4.61/p44-ledchain.ko ledchain0=0,100,3
Now you need to configure one of the GPIO pins to provide PWM0 output (GPIO 18 or 46 have that option):
omega2-ctrl gpiomux set pwm0 pwm; # for GPIO 18 omega2-ctrl gpiomux set uart1 pwm01; # for GPIO 46
Finally you need to connect your DIN of the first UCS1903 in the chain to the PWM0 output pin of the Omega2 (GPIO 18 or 46). As the Omega2 is 3.3V and the UCS1903 is 5V powered, the high level coming from the Omega2 might not be sufficient for the UCS1903. In my experience with WS281x chips, it can work sometimes, but not reliably. So the right way to do it is adding a level shifter such as a 74AHCT1G125.
Now you can just write a string of RGB values into /dev/ledchain0 to control the LEDs, for example:
echo -en '\xFF\x00\x00\x00\xFF\x00\x00\x00\xFF' >/dev/ledchain0
to make the first LED red, second green, third blue.
There's more info and details in this forum thread