Great suggestions!
I’ve written a few more examples, and have adopted the following conventions:
- The first parameter is always len, the number of NeoPixels on the strip.
- All the other parameters should be optional, with defaults that give a good display.
- The brightness parameter, if supplied, should go from 0 to 1 as you suggested.
- The speed parameter, if supplied, should also go from 0 to 1 where 0.2 will be a recommended speed.
- Finally, the examples should use unwind-protect to turn off the LEDs when you escape from the function, to save you having to do that manually.
Here are the examples:
Wave
This is an updated version of the original example:
(defun wave (len &optional (speed 0.2) (bri 0.25))
(let ((strip nil)
(scroll 0)
(step (/ len)))
(dotimes (n len) (push 0 strip))
(unwind-protect
(loop
(let ((i scroll))
(mapl #'(lambda (c) (setf (car c) (wheel i bri)) (incf i step))
strip))
(neopixel *pin-bit* strip)
(incf scroll (/ speed len)))
(neopixel *pin-bit* (mapcar #'(lambda (c) 0) strip)))))
It uses wheel, which is a colour wheel that returns a colour value for values of i from 0 to 1, wrapping round to the start, and at brightness bri, also 0 to 1. It uses a subfunction tri that gives a triangle function:
(defun wheel (i &optional bri)
(let ((x (* i 768)))
(+ (ash (tri (+ x 256) bri) 16) (ash (tri x bri) 8) (tri (+ x 512) bri))))
(defun tri (x bri)
(let ((y (mod x 768)))
(truncate (* bri (max (if (< y 256) y (- 511 y)) 0)))))
Chase
This provides a pattern of lights that travels along the string.
(defun chase (leds &optional (speed 0.2) (col #x404040))
(let ((strip nil))
(dotimes (n leds) (if (zerop (mod n 3)) (push col strip) (push 0 strip)))
(unwind-protect
(loop
(neopixel *pin-bit* strip)
(delay (truncate 20 speed))
(setq strip (append (cdr strip) (list (first strip)))))
(neopixel *pin-bit* (mapcar #'(lambda (c) 0) strip)))))
It takes an optional colour value for all the lights, default 25% white.
It works as follows: First it sets up a list with every third element set to the colour col. Then the strip is repeatedly shifted to the left by removing the first element and appending it to the end.
Twinkle
This simulates flashing coloured fairy lights. Each NeoPixel flashes with a regular period, and with a consistent colour, but the periods of all the lights are slightly different, so the sequence of flashes is continuously varying and unpredictable.
(defun twinkle (len &optional (bri 0.25))
(let ((strip nil)
(scroll 0)
(step (/ len))
(offset 120)
(n 0))
(dotimes (n len) (push 0 strip))
(unwind-protect
(loop
(dotimes (i len)
(let* ((j (mod (+ 7 (* i 13)) len))
(k (mod n (+ offset j))))
(setf (nth i strip) (if (zerop k) (wheel (* j step) bri) 0))))
(neopixel *pin-bit* strip)
(delay 5)
(incf n))
(neopixel *pin-bit* (mapcar #'(lambda (c) 0) strip)))))
It needs the functions wheel and tri defined above to give the colours of the lights.
It works as follows: Each NeoPixel is assigned an integer such that NeoPixel i is given the integer j defined as:
(mod (+ 7 (* i 13)) len)
The value n counts up from zero. When n is divisible by (+ offset j) for any NeoPixel, that NeoPixel is turned on with the colour j; otherwise it is turned off.
Look forward to any comments! I’ll also update the original ARM NeoPixel page with these examples in due course.