Fading LEDs with PWM on all pins with Pi Zero & Node.js

ezgif.com-optimize

I’ve been converting my ST4i workshop from Arduino to Node.js/Raspberry Pi and one of limitations is a lack of built-in PWM pins. PWM or Pulse Width Modulation can be used to fade LEDs up and down rather than just turn them on and off. If you’re new to PWM, here’s a full explanation at Sparkfun.

On the Pi Zero, you can only enable 2 hardware PWM pins at one time, and the library I’m using to control the GPIO pins doesn’t support PWM at all! (The ubiquitous onoff node module).

After a bit of searching, I found the pigpio Node.js module, and this, in turn is a wrapper for the Pigpio C library.

As far as I can tell, it manages the PWM duty cycle in software, so it’s not as performant as the built-in hardware PWM pins, but as it’s written in C I’m sure it’s fast and certainly my experience so far suggests it’s super smooth.

If you want to try it for yourself, follow the instructions on the github page. I had a slight amount of weirdness, it didn’t seem to install straight away, but I deleted everything and started again and it seemed better.

I also had another problem – somehow I had started the pigpiod daemon and this clashed with the Node.js module code. Either the installer for pigpio did it or else I ran in manually while trying to get things running. sudo killall pigpiod should sort it out.

And a final thing to look out for – if you have node 0.10.29 on your Raspberry Pi (the version that comes with Raspbian Jesse) you’ll have a problem running any Node.js module that uses Nan, the native addon library. I first encountered this when I updated the LED matrix library to work with newer versions of Node.js, but it’s simple enough to fix. See this thread on github for solutions.

Once you have it installed you can do PWM output on any GPIO pin, here’s a set up for 9 LEDs like in the image above.

9 Leds on a Raspberry Pi

You can then use this code to get the nice pulsing effect in the animation.

 
var Gpio = require('pigpio').Gpio; 
 
// change these to match your LED GPIO pins : 
var ledPins = [21,20,16,12,26,19,13,6,5]; 
 
var leds = [];
 
// initialise all the pins
for (var i = 0; i<ledPins.length; i++) { 
	var led = new Gpio(ledPins[i], {mode: Gpio.OUTPUT});    
	leds.push(led);
}
 
// get a loop running 60 times a second (1000/60 = 16.6)
setInterval(loop, 16); 
 
function loop() { 
 
	for(var i = 0; i<leds.length; i++) { 
 
		var led = leds[i]; 
		// calculate a sin wave for brightness dependent on time and 
		// position in the row of LEDs
		var brightness = Math.sin(((Date.now()/16)+(i*5))*0.2)*0.5 + 0.5; 
		// a quick way to do a cubic ease in - it means the LEDs get brighter
		// slower. It compensates for the fact that LEDs get bright quick. 
		brightness*=brightness*brightness; 
		// the pigpio library complains if you send it a floating point number
		// so we have to round it down.
		brightness = Math.floor(brightness*255);
		led.pwmWrite(brightness);
	}	
 
}

Note the issue with sending floating point numbers – I’m surprised that this isn’t handled at the other end but it’s easy enough to fix with a Math.floor.

And also notice how I’m using cubic easing to smooth out the brightness curve on the LEDs.

You can also use the pigpio library to control hobby servo motors. That’s what I’ll be doing next!

More about my ST4i workshops.

Controlling 7 segment LED displays on Raspberry Pi with Node.js

As part of the preparation for my upcoming workshops (last two tickets left!) , I’ve been working on writing Node.js code to drive various bits of hardware that are included in the free kit that comes with the course. So I’ve made my first ever npm package! And it drives cute LED displays running on the MAX7219 chip.

In particular, there are two little LED displays that I really love. One is an 8 x 8 LED matrix, and the other is an 8 character 7 segment display. (The ‘7 segment’ refers to the arrangement of LEDs that makes up the number shape – think of the displays on the Delorean time-machine dashboard).

They’re both driven by the same chip, the MAX7219, which can drive 64 LEDs, so perfect for both of these displays, and you can actually daisy chain up to 8 of them together and run them from the same pins. There is already a Node.js library that can run these, and it works fine (MAX7219) – it’s geared towards the 7 segment display and it works with the native SPI device on the Raspberry Pi.

But it is possible to run a MAX7219 chip without using the SPI device. You can ‘bit-bang’ the GPIOs – this is a way of sending digital data out of pins manually by setting them to high or low for each bit. It’s probably more performant to use the native SPI device but this method is perfectly fast enough for most applications, can be connected to any pins, can have multiple outputs, and is simpler to set up (as you don’t have to enable the SPI device on the Raspberry Pi).

[UPDATE – I just found this post with more about how bit-banging the MAX7219 works]

I’ve also implemented a few other fun features :

  • Display a number on the 7 segment display, with a fixed number of decimal places and leading zeros
  • A full alphabet – send it any alpha-numeric character and the library will do its best to represent it (obviously m’s and w’s are a bit crap 🙂 )
  • Set a specific led at x and y coordinate of the 8 x 8 matrix – for fun graphics output

It’s based on the Arduino LedControl library so much of the API is similar, but it’s currently in a very early state so expect the API to change.

See the github page for more details.

Upgrading a node module that wraps C code

Today I wanted to get this ultra-thin LED matrix working with Raspberry Pi in NodeJS as part of my work on my new ST4i workshop.

Ultrathin RGB Matrix_02

The SeeedStudio Ultrathin Red LED matrix.

It’s such a nice bright matrix, I really love it, but they’re a little weird to work with. They use the HUB75 protocol which scans across the screen doing a few pixels at a time, so they tend to look super flickery on a standard slow Arduino. But there’s this C++ library for Raspberry Pi that is way faster and some nice person has wrapped it in a Node.js module.

Although I got the C++ code working, I couldn’t install the Node module – the compilation process failed. After some exploration, I realised that the module was designed for older versions of Node (I think a maximum of 0.12.0) and I’m running 5.4.1.

I tried to revert my Node version with n but that seemed temperamental on the Raspberry Pi ARM versions of node. I couldn’t get it working, and it didn’t feel right to switch Node versions if I didn’t have to.

So plan B – I set to work updating the node module. There’s lots of documentation on how to wrap C++ code into Node addons and I have to admit, it’s pretty intense! At least for me, as I haven’t really got much experience of the V8 engine.

But I figured it out – the main issues were how objects are passed back and forth between the JavaScript and C++. It works! But sadly I think it’s probably broken in older versions.

I really should use the Native Abstractions which is a way to wrap C++ code that will remain compatible with past and future versions of Node.js, but one thing at a time. I’ll take a look at that next.

[UPDATE here’s a link to my fork of the repo]

[UPDATE 2 Now rewritten to work with Nan! So is hopefully good for Node.js versions 0.8, 0.10, 0.12, 4 and 5. here’s a link to my fork of the repo, pull request pending.]

[UPDATE 3 My pull request has been accepted and the main repo is now updated.]

In the meantime, enjoy the particles!