A NodeJS driver for the Unicorn HAT Mini from Pimoroni. This software is based on Pimoroni's official driver and examples written in Python.
The device is a 17x7 RGB LED matrix with 4 buttons.
npm i unicorn-hat-mini
Cloning this repository will bring with demos that are not part of the npm package. Sudo must be used to access the GPIO when calling the demo. Ctrl-C can be used to exit the demos.
# random colors on each pixel every 0.5 seconds
sudo node ./demo/index.js
# moving rainbow across the display, direct port from Python example
sudo node ./demo/rainbow.js
This driver makes use of node-rpio in the gpiomem: false
mode which requires you to run this as root (sudo
). Additional troubleshooting and rationale can be found in the node-rpio README.
const UHM = require('unicorn-hat-mini');
const uhm = new UHM();
uhm.brightness = 0.1;
uhm.setAll(255, 255, 255);
uhm.show();
To allow control of the IO not used by the HAT, UHM.rpio
is available to set up additional IO and other functionality that the node-rpio library provides.
UHM() is a class and must be called with new
. It returns an instance of the driver uhm
.
const uhm = UHM({brightness: 0.5});
Option | Default | Description |
---|---|---|
options.brightness | 0.2 | Global Brightness of display 0.0-1.0 |
options.enableButtons | true | Use the internal button handler and event emitter. Set to false if you prefer to set up your own access to the HAT's buttons |
options.exitProcess | true | The driver cleans up the open IO ports when SIGINT , SIGTERM , SIGUSR2 (for compatability with nodemon) |
Constant number of rows on HAT device.
Constant number of columns on HAT device.
Instance of node-rpio provided for allowing configuration of additional IO not used by the HAT.
Set the color of the pixel at (row, col). Must call uhm.show()
for changes to be displayed on the HAT.
// set pixel at row 3 column 5 to purple
uhm.setPixel(3,5,255,0,255);
// Optional variant:
uhm.setPixel(3,5,[255,0,255]);
Parameter | Range | Description |
---|---|---|
row | 0-3 | Vertical position of selected pixel |
col | 0-16 | Horizontal position of selected pixel |
r | 0-255 | Red value of pixel. Automatically converted to the HAT limits of 0-63. Optional variant: r can be an array of color values [r, g, b] . |
g | 0-255 | Green value of pixel. Automatically converted to the HAT limits of 0-63. |
b | 0-255 | Blue value of pixel. Automatically converted to the HAT limits of 0-63. |
Get the color of the pixel at (row, col).
// set pixel at row 3 column 5 to purple
uhm.setPixel(3,5,255,0,255);
const pixel = uhm.getPixel(3,5,255,0,255);
// pixel = [255, 0, 255]
Parameter | Range | Description |
---|---|---|
row | 0-3 | Vertical position of selected pixel |
col | 0-16 | Horizontal position of selected pixel |
Set the color of all pixels. Must call uhm.show()
for changes to be displayed on the HAT.
// set all pixels to yellow
uhm.setAll(255,255,0);
// Optional variant:
uhm.setPixel([255,255,0]);
Parameter | Range | Description |
---|---|---|
r | 0-255 | Red value of pixel. Automatically converted to the HAT limits of 0-63. Optional variant: r can be an array of color values [r, g, b] . |
g | 0-255 | Green value of pixel. Automatically converted to the HAT limits of 0-63. |
b | 0-255 | Blue value of pixel. Automatically converted to the HAT limits of 0-63. |
Return all pixels as an array in the format: [row][col] = [r, g, b] format
const all = uhm.getAll();
// all = [[[r, g, b], [r, g, b], ...], [[r, g, b], ...], ...]
Update the display with the latest display buffer as modified by uhm.setPixel()
and uhm.setAll()
.
uhm.show();
Set all pixels to black/off.
uhm.clear();
Set or read the current global brightness of the display 0.0 - 1.0.
// set brightness to 50%
uhm.brightness = 0.5;
// read current brightness
console.log(uhm.brightness)
// displays 0.5
// read state of button A
const buttonState = uhm.buttonA;
Returns the state of any of the 4 buttons. The value is not read by accessing this property, instead the driver polls the 4 buttons and produces events (see uhm.on
) for change of button states. The most recent state of each button is recorded internally during each event and this most-recent value is returned by these properties. If options.enableButtons
is false
returns undefined.
A set of events triggered by pressing and releasing buttons. Events can be triggered in the pressed state:
event =
'button-a-pressed'
'button-b-pressed'
'button-x-pressed'
'button-y-pressed'
In the released state:
event =
'button-a-released'
'button-b-released'
'button-x-released'
'button-y-released'
On both state changes:
event =
'button-a'
'button-b'
'button-x'
'button-y'
Or for any button state change:
event =
'button'
The handler takes the same callback signature for all button states
handler = (button, state) => {
// button = 'a', 'b', 'x', 'y'
// state = true for pressed, false for released
}
A simple example
// displays "button b is true" or "button b is false"
// as the button is pressed and released
uhm.on('button-b', (button, state) => {
console.log(`Button ${button} is ${state}`);
});
Debugging presents some challenges because the node application must be run as sudo. The solution that I have come up with uses VSCode and a separately launched nodemon process. Saving a file will trigger nodemon to restart the process and the debugger will need to be connected again.
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach",
"port": 9229,
"request": "attach",
"skipFiles": [
"<node_internals>/**",
"**/node_modules/**"
],
"type": "node",
"address": "127.0.0.1",
"continueOnAttach": true, // This causes the paused process to continue upon attaching the debugger. It saves a step of having to press F5 (continue) when starting the debugger. It creates the "feel" of launching the process directly inside VSCode
"localRoot": "${workspaceFolder}",
"remoteRoot": "/home/ubuntu/projects/unicorn-hat-mini"
}
]
}
# run nodemon
# inspect-brk causes the debugger to pause immediately upon entering the program
sudo ./node_modules/nodemon/bin/nodemon.js --inspect-brk demo/rainbow.js