6. ws2812
(image from
green
5mm
‣ SMD5050 Package
‣ ws2811 controller
‣ three separate LEDs
red
blue
HARDWARE
controller
7. ws2811
one-wire serial data-signal
0 1.25μs 2.5μs 3.75μs
5μs
1 0 1 1
+5V
0V
t
wavelength λ pulsewidth
frequency 800kHz
wavelength 1.25μs
8. ws2811
one-wire serial data-signal
+5V
0V
350ns (±150ns) 800ns (±150ns)
λ = 1.25μs (±600ns)
(f = 800kHz)
0
t
9. ws2811
one-wire serial data-signal
+5V
0V
750ns (±150ns) 600ns (±150ns)
λ = 1.25μs (±600ns)
(f = 800kHz)
1
t
10. ws2811
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
b 2 8 0 f 4
#80b2f4
in HTML-Notation
11. ws2811
one-wire serial data-signal
LED 01
Register
#000000
DIN DOUT
LED 02
Register
#000000
DIN DOUT
LED 03
Register
#000000
DIN DOUT
+5V
GND
+5V
GND
+5V
GND
+5V
GND
12. ws2811
one-wire serial data-signal
LED 01
Register
#ff8800
DIN DOUT
1
#ff8800
LED 02
Register
#000000
DIN DOUT
LED 03
Register
#000000
DIN DOUT
— —
+5V
GND
+5V
GND
+5V
GND
+5V
GND
13. ws2811
one-wire serial data-signal
LED 01
Register
#ff8800
DIN DOUT
2
#00ffff
LED 02
Register
#00ffff
DIN DOUT
LED 03
Register
#000000
DIN DOUT
#00ffff —
+5V
GND
+5V
GND
+5V
GND
+5V
GND
14. ws2811
one-wire serial data-signal
LED 01
Register
#ff8800
DIN DOUT
3
#0000ff
LED 02
Register
#ffff00
DIN DOUT
LED 03
Register
#0000ff
DIN DOUT
#0000ff #0000ff
+5V
GND
+5V
GND
+5V
GND
+5V
GND
15. ws2811
one-wire serial data-signal
LED 01
Register
#000000
DIN DOUT
4
reset
LED 02
Register
#000000
DIN DOUT
LED 03
Register
#000000
DIN DOUT
reset reset
+5V
GND
+5V
GND
+5V
GND
+5V
GND
16. neopixel etc.
where to get your ws2812
USA http://www.adafruit.com/category/168
https://www.sparkfun.com/search/results?term=ws2812
http://www.watterott.com/index.php?page=search&keywords=ws2812
GERMANY
OTHER
INTERNATIONAL
ebay, amazon (search "ws2812")
direct from china: banggood.com, www.dx.com, alibaba.com
22. problem
the signal-level needs to be changed
1.6 Million times per second.
(image from http://www.electrobob.com/ws2812-level-translator/)
23. Arduino: no problem*
‣ CPU running at 16MHz
‣ 62 nanoseconds per instruction
‣ lots of time™ in between level changes…
* assembler-programming required :(
24. solution awesomeness
awesomeness
solutions
programming it
with arduino
#hhjs
sleep
(based on a totally representative study with 1 participant)
25. Raspbian: problem
‣ because multitasking.
‣ when the process runs depends on lots
of factors we can’t control
26. 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
27. Raspberry Pi PWM
+5V
0V
1 0 0 bits written to
(frequency: 2.4 MHz)
0
t
PWM cycle: 416ns
PWM-Registers
28. Raspberry Pi PWM
+5V
0V
1 1 0 bits written to
(frequency: 2.4 MHz)
1
t
PWM cycle: 416ns
PWM-Registers
29. Raspbian: problem
‣ store prepared pixel-data in memory
‣ let the DMA-Controller transfer data
to PWM-Module
‣ CPU or OS are not involved!
30.
31. solution awesomeness
awesomeness
solutions
arduino
#hhjs
sleep
program it in C
on raspberry
build a server
in C and control
with node
write a
node-addon.
36. writing node-addons
accepting arguments/ throwing exceptions
// rpi_ws281x.cc
Handle<Value> Init(const Arguments& args) {
HandleScope scope;
if(args.Length() < 1 || !args[0]->IsNumber()) {
ThrowException(Exception::TypeError(
String::New("init(): argument 0 is not a number")));
return scope.Close(Undefined());
}
int numLEDs = args[0]->Int32Value();
// ... the actual binding-code ...
return scope.Close(Undefined());
}
37. writing node-addons
lessons learned…
‣ writing a simple node addon is not as
complicated as it seems
‣ i should write more C++
‣ most of the code to deal with arguments and
type-checking
‣ better understanding how V8 works
39. hello ws281x-native
the javascript-side
var ws281x = require('../lib/binding/ws281x-native');
var NUM_LEDS = 100,
data = new Uint32Array(NUM_LEDS);
ws281x.init(NUM_LEDS);
data[42] = 0xff0000;
ws281x.render(data);
setTimeout(function() { ws281x.reset(); }, 2000);
40. hello ws281x-native
of course it didn't end there
‣ API feels a bit too low-level
‣ numbers as colors are complicated
‣ need to manually manage the data-array
41. matrix-API
the javascript-side
var ws281x = require('../lib/ws281x'),
m = ws281x.createMatrix(10,10)
Color = ws281x.Color;
var offset = 0,
c1 = new Color('red'), c2 = new Color('blue');
setInterval(function() {
m.clear();
for(var i=0; i<10; i++) {
var color = Color.mix(c1, c2, ((i % 10) / 10));
m.set(i%10, (i+offset)%10, color);
}
offset++;
m.render();
}, 1000 / 30);
42. solution awesomeness
awesomeness
solutions
arduino
#hhjs
sleep
program it in C
on raspberry
build a server
in C and control
with node
✔
write a
node-addon.
43. solution awesomeness
awesomeness
solutions
#hhjs
sleep
program it in C
on raspberry
build a server
in C and control
with node
write a
node-addon.
use
<canvas>
44. canvas-API
‣ web-technology FTW!
‣ has more stuff than we need.
‣ can be rendered server-side with node-canvas
‣ also works in the browser
45. canvas-API
the javascript-side
var ws281x = require('../lib/ws281x'),
canvas = ws281x.createCanvas(10,10),
ctx = canvas.ctx,
Color = ws281x.Color;
var c1 = new Color('red'), c2 = new Color('blue');
function rnd(max) { return (max || 1) * Math.random(); }
function rndi(max) { return Math.round(rnd(max)); }
setInterval(function() {
var c = 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);
46. more to come…
‣ open-source everything [really soon]
‣ browser-based IDE on the raspberry [in progress]
‣ integrate with other hardware [planning]
‣ improved 3d-printed casing [some day…]
47. final thoughts
why would you want to do that?
‣ do something you love. just for the fun.
‣ understand how stuff works.
‣ learn something new.
‣ no deadlines (well, except you do a talk about it)
48. <3
thank you!
come to me if you have any questions…
Martin Schuhfuss – @usefulthink