A uLisp extension for driving NeoPixels


#1

This is an extension for uLisp to drive NeoPixel LED displays from a variety of different platforms.

Introduction

NeoPixel is Adafruit’s name for individually-addressable RGB color pixels and strips based on the WS2812, WS2811, and SK6812 LED/drivers, using a single control wire. This uLisp extension is a Lisp interface to the Adafruit NeoPixel Library on GitHub for controlling one or more NeoPixels.

It supports the following platforms that uLisp supports:

  • AVR ATmega and ATtiny (any 8-bit) - 8 MHz, 12 MHz, and 16 MHz
  • ATSAMD21 (Arduino Zero/M0 and other SAMD21 boards) @ 48 MHz
  • ATSAMD51 @ 120 MHz
  • ESP8266 any speed
  • ESP32 any speed
  • Nordic Semiconductor nRF51 and nRF52 boards

Installing the NeoPixel extension

You first need to install the Adafruit NeoPixel Library, either via the Arduino IDE Library Manager , or by adding the ZIP file from GitHub to your libraries folder.

Then:

  • Uncomment #define extensions at the start of the main uLisp source file.
  • Compile and upload uLisp with the file NeoPixels.ino included in the same folder as the uLisp source file for your platform.

The NeoPixel functions will then be added to the built-in functions in uLisp, together with their documentation.

Here is the NeoPixels Extension: NeoPixels.ino.

Or get it from GitHub at: https://github.com/technoblogy/ulisp-neopixels.

Functions

This NeoPixel extension provides the following Lisp functions, that are directly equivalent to the functions in the Adafruit NeoPixel Library:

Function Description
(pixels-begin) Configures the NeoPixel pin for output.
(pixels-clear) Sets all pixel colors to off.
(pixels-fill rgbw first count) Fills all or part of the NeoPixel strip with a fixed colour.
(pixels-set-pixel-color index rgbw ) Set a pixel’s color using a packed RGB or RGBW value.
(pixels-set-pixel-color index red green blue [white]) Set a pixel’s color using separate red, green, blue, and optionally white components.
(pixels-color red green blue [white]) Converts separate red, green, blue, and optionally white values into a single packed 32-bit RGB or RGBW color.
(pixels-color-hsv hue sat val) Converts separate hue (0 to 65535), saturation (0 to 255), and value (0 to 255) values into a single packed 32-bit RGB or RGBW color.
(pixels-show) Transmits the pixel data to the NeoPixels.
(pixels-rainbow [first-hue] [cycles] [sat] [val] [gammify]) Fills the NeoPixel strip with one or more cycles of hues.

The rgbw parameter is a packed colour value returned by calling pixels-color or pixels-color-hsv.

Note that:

(pixels-set-pixel-colour index red green blue)

is equivalent to:

(pixels-set-pixel-colour index (pixels-colour red green blue))

Apart from pixels-color and pixels-color-hsv all the functions return nil.

Configuration

To use the NeoPixel extension you need to specify the number of NeoPixels in your strip, and the digital pin number they’re connected to, with lines similar to the following at the start of the extension:

#define NEOPIXEL_NUM 5 
#define PIN_NEOPIXEL 8

These are automatically set to the correct values for the NeoPixels on the following boards, which I’ve tested:

  • Adafruit PyBadge
  • Adafruit PyGamer
  • Adafruit Circuit Playground Bluefruit
  • Adafruit QT Py M0
  • Adafruit QT Py ESP32-S2
  • Adafruit NeoPixel Trinkey (using the Adafruit Gemma M0 board definition)

Examples

Because this is Lisp, you can interactively configure your NeoPixel strip from the Serial Monitor by entering individual commands. Here’s an example, assuming a 10-NeoPixel strip:

Configure the output pin correctly by calling:

(pixels-begin)

Clear all the NeoPixels:

(pixels-clear)

Set the first NeoPixel to faint red:

(pixels-set-pixel-color 0 32 0 0 0)

Make the change take effect:

(pixels-show)

Make the red colour move progressively along the strip:

(dotimes (x 10) (pixels-set-pixel-color x 32 0 0 0) (pixels-show) (delay 200))

Turn off all the NeoPixels:

(pixels-clear)
(pixels-show) 

Rotating rainbow

For more complicated animated effects you can write a program, and run it with a single command.

The following program displays a rotating rainbow:

(defun rotate ()
  (pixels-begin)
  (loop
   (dotimes (n 1000)
    (pixels-rainbow (* n 65) 1 255 50)
    (pixels-show))))

To run it give the command:

(rotate)

The photograph at the start of the post shows this running on an Adafruit Circuit Playground Bluefruit.

Not implemented

The NeoPixel extension doesn’t currently implement the following functions. This may change if there’s enough demand:

  • updateLength() or updateType(), as these are deprecated.
  • setBrightness(), as it has shortcomings (described in the ReadMe on GitHub).
  • delay_ns(), setPin(), getPixelColor(), getBrightness(), or gamma32().