WS281x, SK6812 driver for the Omega2? [Solved]



  • Short update for those waiting - my kernel driver for driving WS2812 using the Omega2 hardware PWM already works with a test LED chain of 24 WS2812 :-)
    It's not yet 100% reliable, and the code is a mess, caused by all the experiments I needed to find out how that sparsely documented PWM engine actually works. I need to clean up before publishing it, but I expect to get that done in the next few weeks.



  • Finally - the driver is ready!

    See p44-ledchain in my feed for LEDE on github.

    People testing it with various LED chains welcome, my current test object is the "pixelboard" (of which you find some parts in the same feed already) with 200 WS2813 LEDs.

    0_1489058389340_Pixelboard.jpg



  • Very cool! So I'm planning to order some SK6812 for a small project. But it would be first time for me building and installing a kernel driver on Omega2. Could you make a small howto guide?



  • @Anders-Öster
    If you want to build it yourself, you need to install a LEDE buildroot (see onion docs and maybe my post here).
    Once you have setup that, you can:

    • add the plan44 feed to feeds.conf.default by adding a line
      src-git plan44 ssh://plan44@plan44.ch/home/plan44/sharedgit/plan44-public-feed.git;master
    • have LEDE fetch the latest stuff from all feeds with
      ./scripts/feeds update -a
    • "install" (meaning: make ready for being included in compilation) the p44ledchain package with
      ./scripts/feeds install kmod-p44-ledchain
    • enable the package for actually being built in the configuration
      (make menuconfig, then select it under kernel modules -> other modules -> kmod-p44-ledchain)
    • build the package with
      make package/p44-ledchain/compile

    Now you'll have the compiled package in bin/targets/ramips/mt7688/packages/kmod-p44-ledchain_....ipk

    For those that don't want to invest the time (1-2h build time for the initial LEDE make run) and disk space (~15GB), here's a built package for p44-ledchain.

    Sadly, because Onion still hasn't published their complete LEDE build environment (yes, @administrators, my ceterum censeo once again) it is not possible to build a kernel module that actually installs cleanly on the omega firmware.

    So, either way (self-built or downloaded from the link above), you need to override kernel version dependency checks when installing

    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*
    

    And because of the kernel version mismatch, insmod does not find the module automatically, so you need to specify the full path:

    insmod /lib/modules/4.4.61/p44-ledchain.ko ledchain0=0,200,2
    

    (this is for 200 WS2813 connected to PWM0)

    good luck!



  • @luz

    Thanks for the howto!



  • Hi
    I'm wondering if (and how) it is possible to dim the LED with the p44-ledchain module? (keyword: change of duty cycle)
    Regards
    Laurent



  • @Laurent-Nittler yes, you can dim (and color) every LED separately!

    In fact, the bytes you write to the /dev/ledchainX device correspond to the brightness (duty cycle) of the red, green and blue part of the LEDs (and a separate white LED for SK6812). With this, you can set any color and any brightness.

    Let's assume you have WS2813 connected to PWM0, then

    echo -en '\xFF\xFF\xFF' >/dev/ledchain0
    

    switches the first LED to full white brightness (255=0xFF = full on for all three R,G,B channels. Whereas:

    echo -en '\x7F\x7F\x7F' >/dev/ledchain0
    

    sets all three LEDs to half duty cycle (127=0x7F)

    A somewhat dimmed green (red=off, green=160=0xA0, blue=off) would be:

    echo -en '\x00\xA0\x00' >/dev/ledchain0
    

    and so forth.

    To control more LEDs, just write a longer string to /dev/ledchain0, 3 bytes for every LED in the chain (4 for RGBW LEDs like SK6812).

    Of course, you wouldn't do that with echo except for the first manual tests, but using some script/program that calculates the string to be sent to /dev/ledchain0.



  • Thanks Luz for this explanation.
    I forgot that HSL values could be transformed into the RGB values.

    I used python to control the 8 LED ring (WS2812b) using code like

    with open('/dev/ledchain0','w') as export:
    			export.write(col_string)
    

    where 'col_string' is a a text string containing all the RGB values for the hole ring.
    However sometimes (especially when I have to calculate the RGB values and then compose the string), I get an error 'ValueError: invalid \x escape'

    Maybe this isn't the best way to control the LED with python and you can advise a better one.

    Regards



  • @LaurentN Although I'm not fluent at all in Python, I'd say there's no reason why Python should not work fine controlling LED chains with p44-ledchain.

    @LaurentN said in WS281x, SK6812 driver for the Omega2? [Solved]:

    However sometimes (especially when I have to calculate the RGB values and then compose the string), I get an error 'ValueError: invalid \x escape'

    That sounds like you are trying to use the literal string syntax (the backslash escapes in \xhh form, with hh being a two-digit hex number) to construct your string, but maybe in a way that sometimes outputs only one digit instead of two, which could be the cause of the ValueError?

    Probably there's a more direct way to get numeric byte values into a string or byte array in Python.



  • Re: [WS281x](SK6812 driver for the Omega2? [Solved])

    Hi.
    In the last days I played a bit with Python to get the WS281x working wirth Luz' module.
    As I want to use HLS color schema (it allows to change the luminosity of the color by only one number), I programmed a function HLS to RGB color string:

    def hls2rgb(h,l,s):
    	r, g, b = colorsys.hls_to_rgb(h,l,s)
    	shr = str(hex(int(r * 255.0)))
    	shg = str(hex(int(g * 255.0)))
    	shb = str(hex(int(b * 255.0)))
    	# print ([int(255.0*r), int(255.0*g), int(255.0*b)])
    	if len(shr) == 3:
    		shr = shr[0:2] + str(0) + shr[2]
    	if len(shg) == 3:
    		shg = shg[0:2] + str(0) + shg[2]
    	if len(shb) == 3:
    		shb = shb[0:2] + str(0) + shb[2]
    	col_led_string = shr[2:4].decode('hex') +shg[2:4].decode('hex') + shb[2:4].decode('hex')
    

    By using the following additional function, it allows using a 2 dimensional color matrix which is converted in the corresponding hex color string needed for the module. (It might be useful and easier to use a matrix to handle LED chains instead of a string of hexadigitals)

    def hls2rgb_hexstring(hls_matrix):
    	dim1 = len(hls_matrix)
    	try:
    		dim2t = len(hls_matrix[0])
    	except:
    		dim2t = 0
    	if dim2t == 0:
    		dim2 = dim1
    		dim1 = 1
    	else: 
    		dim2 = dim2t
    	
    	if dim1 == 1:
    		h = hls_matrix[0]/360.0
    		l = hls_matrix[1]/100.0
    		s = hls_matrix[2]/100.0
    		col_led_string = hls2rgb(h,l,s)
    		return col_led_string
    	else:
    		col_led_string=""
    		for i in range(0,dim1):
    			h = hls_matrix[i][0]/360.0
    			l = hls_matrix[i][1]/100.0
    			s = hls_matrix[i][2]/100.0
    			col_led_string = col_led_string + hls2rgb(h,l,s)
    		return col_led_string
    

    To display a color gradient among several LED's (here 40) one has to run this code, which is using both function above:

    color_start = 0
    color_end = 359
    nr_led = 40
    lum = 2
    sat = 100
    colorMatrix = []
    for i in range(color_start,color_end, abs(color_end-color_start)/nr_led):
    	colorMatrix.append([i,lum,sat])
    	#print [i,lum, sat]
    print colorMatrix
    with open('/dev/ledchain0','w') as export:
    	export.write(hls2rgb_hexstring(colorMatrix))
    

Log in to reply
 

Looks like your connection to Onion Community was lost, please wait while we try to reconnect.