Slide 1

Slide 1 text

Martin Schuhfuss – @usefulthink something with raspberry-pi, hardware-hacking and hardware-hacking & web-technology

Slide 2

Slide 2 text

rpi-ws281x Martin Schuhfuss – @usefulthink

Slide 3

Slide 3 text

ws2812 LED-Controller ws2811 rpi- full-color LED with integrated controller

Slide 4

Slide 4 text

(image from http://www.adafruit.com/products/1138)

Slide 5

Slide 5 text

how it works

Slide 6

Slide 6 text

ws2812 how LEDs are connected LED 01 DIN DOUT LED 02 DIN DOUT LED 03 DIN DOUT +5V GND +5V GND +5V GND +5V GND DATA

Slide 7

Slide 7 text

ws2812 how colors are sent to the LEDs LED 01 DIN DOUT Register #000000 LED 02 DIN DOUT Register #000000 LED 03 DIN DOUT Register #000000 +5V GND +5V GND +5V GND DATA +5V GND

Slide 8

Slide 8 text

ws2812 how colors are sent to the LEDs LED 01 DIN DOUT Register #ff8800 #ff8800 1 LED 02 DIN DOUT Register #000000 LED 03 DIN DOUT Register #000000 — — +5V GND +5V GND +5V GND DATA +5V GND

Slide 9

Slide 9 text

ws2812 how colors are sent to the LEDs LED 01 DIN DOUT Register #ff8800 LED 02 DIN DOUT Register #000000 LED 03 DIN DOUT Register #000000 — +5V GND +5V GND +5V GND DATA +5V GND

Slide 10

Slide 10 text

ws2812 how colors are sent to the LEDs LED 01 DIN DOUT Register #ff8800 #00ffff 2 LED 02 DIN DOUT Register #00ffff LED 03 DIN DOUT Register #000000 #00ffff — +5V GND +5V GND +5V GND DATA +5V GND

Slide 11

Slide 11 text

ws2812 how colors are sent to the LEDs LED 01 DIN DOUT Register #ff8800 LED 02 DIN DOUT Register #00ffff LED 03 DIN DOUT Register #000000 +5V GND +5V GND +5V GND DATA +5V GND

Slide 12

Slide 12 text

ws2812 how colors are sent to the LEDs LED 01 DIN DOUT Register #ff8800 #0000ff 3 LED 02 DIN DOUT Register #00ffff LED 03 DIN DOUT Register #0000ff #0000ff #0000ff +5V GND +5V GND +5V GND DATA +5V GND

Slide 13

Slide 13 text

ws2812 how colors are sent to the LEDs LED 01 DIN DOUT Register #000000 reset 4 LED 02 DIN DOUT Register #000000 LED 03 DIN DOUT Register #000000 reset reset +5V GND +5V GND +5V GND DATA +5V GND

Slide 14

Slide 14 text

more detail… (image from http://sklep.atnel.pl/pl/p/WS2812B-TASMA-RGB-W-0,5m/98)

Slide 15

Slide 15 text

ws2812 HARDWARE ‣ SMD5050 Package ‣ ws2811 controller ‣ three LEDs

Slide 16

Slide 16 text

colors on the wire one-wire serial data-signal 1 0 1 1 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 1 0 1 0 0 8 0 2 b f 4 #80b2f4 in HTML-Notation duration: 30µs (33k color-values per second)

Slide 17

Slide 17 text

(image from http://www.electrobob.com/ws2812-level-translator/) this is what bits really look like. (scale: t = 0.5µs, U = 1V)

Slide 18

Slide 18 text

3.75µ s 1.25µ s 0V +5V t wavelength λ pulsewidth frequency 800kHz wavelength 1.25µs 0 2.5µ s 5µ s 1 0 1 1 PWM-Signals transport binary data with just one wire

Slide 19

Slide 19 text

PWM-Signals transport binary data with just one wire 0V +5V λ = 1.25µs (±600ns) (f = 800kHz) 350ns (±150ns) 800ns (±150ns) 0 t

Slide 20

Slide 20 text

0V +5V λ = 1.25µs (±600ns) (f = 800kHz) 750ns (±150ns) 600ns (±150ns) 1 t PWM-Signals transport binary data with just one wire

Slide 21

Slide 21 text

drivers

Slide 22

Slide 22 text

(image from http://www.electrobob.com/ws2812-level-translator/) the signal-level needs to be changed 1.6 Million times per second. problem

Slide 23

Slide 23 text

Arduino: no problem* ‣ CPU running at 16MHz ‣ 62 nanoseconds per instruction ‣ quite some time in between level changes (20 instructions per bit)… ‣ nothing else running on the CPU * requires assembler-programming to get this right :/

Slide 24

Slide 24 text

Arduino: but… ‣ no higher-level languages 
 (actually, just C and ASM) ‣ integration with stuff™ hardly possible ‣ booooring!

Slide 25

Slide 25 text

Raspberry Pi ‣ Broadcom BCM2xxx SoC ‣ 700MHz ARM CPU / 512MB RAM ‣ SD-Card as Harddrive ‣ 100MBit LAN / HDMI / USB / Audio ‣ runs raspbian OS ‣ …and is really cheap Ethernet HDMI micro-USB (power supply) SD-Card GPIO Status-LEDs USB Digital-Audio Analog-Audio

Slide 26

Slide 26 text

Raspberry Pi ‣ interface to external hardware ‣ controllable logic-pins ‣ sensors, motors, anything ‣ SPI / UART / I2C GPIO

Slide 27

Slide 27 text

Raspbian: problem ‣ because multitasking ‣ nearly impossible to get the timing right ‣ when processes run depends on lots of factors we can’t really control

Slide 28

Slide 28 text

Raspberry Pi PWM ‣ „serializer“-mode ‣ bits in data-registers represent signal-level per PWM-cycle ‣ only a few bytes in registers ‣ needs DMA to transport data

Slide 29

Slide 29 text

Raspberry Pi PWM 0V +5V PWM cycle: 416ns (frequency: 2.4 MHz) 0 t 1 0 0 bits written to PWM-Registers

Slide 30

Slide 30 text

Raspberry Pi PWM 0V +5V PWM cycle: 416ns (frequency: 2.4 MHz) 1 t 1 1 0 bits written to PWM-Registers

Slide 31

Slide 31 text

Raspbian: problem ‣ store prepared pixel-data in memory ‣ let the DMA-Controller transfer data to PWM-Module ‣ CPU or OS are not involved!

Slide 32

Slide 32 text

how it works…

Slide 33

Slide 33 text

lets just say it's complicated.

Slide 34

Slide 34 text

‣ awesome C-Library by Jeremy Garff ‣ base for everything that follows rpi_ws281x // configuration and central data-structure ws2811_t ledstring = { .freq = TARGET_FREQ, .dmanum = DMA, .channel = { [0] = { .gpionum = GPIO_PIN, .count = NUM_LEDS, .invert = 0, .brightness = 255 }, [1] = { … } }, }; // setup all that complicated hardware-stuff ws2811_init(&ledstring); // write some RGB-values to the LED-array ws2811_led_t* leds = ledstring.channel[0].leds; leds[42] = 0xff0000; leds[23] = 0x0000ff; // send it away ws2811_render(&ledstring); // …sometime later: tear-down complicated stuff ws2811_fini(&ledstring);

Slide 35

Slide 35 text

let's do this in Javascript

Slide 36

Slide 36 text

‣ native node.js-bindings for rpi_ws281x ‣ JS-interface mirrors the C-API ‣ wrapper handles only type-checking and conversions between V8-types and C rpi-ws281x-native var ws281x = { init: function(numLeds, options) { … }, /** @param {Uint32Array} ledData */ render: function(ledData) { … }, reset: function() { … } }; npm install

Slide 37

Slide 37 text

hello rainbow var ws281x = require('rpi-ws281x-native'),
 pixelData = new Uint32Array(100);
 
 ws281x.init(100);
 
 // ---- animation-loop
 var offset = 0;
 setInterval(function () {
 for (var i = 0; i < 100; i++) {
 pixelData[i] = rainbowColor((offset + i) % 256);
 }
 
 offset = (offset + 1) % 256;
 ws281x.render(pixelData);
 }, 30);


Slide 38

Slide 38 text

‣ API is a bit too low-level ‣ need to manually manage the data-array ‣ numbers as colors are complicated ‣ no shapes, nothing useful. problems hello rainbow

Slide 39

Slide 39 text

hello web-technology ‣ want to draw lines, shapes, text, … ‣ need fast primitive draw-commands ‣ maybe even support for images?

Slide 40

Slide 40 text

hello -API ‣ stable and fast ‣ even more features than we need ‣ works in every browser ‣ complete implementation for node.js available
 (via node-canvas npm module)

Slide 41

Slide 41 text

hello -API var ws281x = require('rpi-ws281x'),
 canvas = ws281x.createCanvas(10,10),
 ctx = canvas.ctx;
 
 var c1 = new ws281x.Color('red'),
 c2 = new ws281x.Color('blue');
 
 function rnd(max) { return (max || 1) * Math.random(); }
 function rndi(max) { return Math.round(rnd(max)); }
 
 setInterval(function() {
 var c = ws281x.Color.mix(c1,c2, rnd());
 
 ctx.clearRect(0,0,10,10);
 ctx.fillStyle = 'rgb(' + c.rgb.join(',') + ')';
 ctx.fillRect(rndi(10)-2, rndi(10)-2, rndi(10), rndi(10));
 
 canvas.render();
 }, 1000/5);

Slide 42

Slide 42 text

-API ‣ did I say this works in the browser? ‣ let's add a WebSocket and do this…

Slide 43

Slide 43 text

thank you! come to me if you have any questions… <3 Martin Schuhfuss – @usefulthink