Test program for my Multi_WS2811 library that started out as a fork of heroic/WS2811. My library uses hardware DMA on the FRDM-KL25Z to drive up to 16 strings of WS2811 or WS2812 LEDs in parallel.
Dependencies: Multi_WS2811 mbed MMA8451Q
Fork of WS2811 by
NOTE: I have accidentally pushed changes for another fork of this program that I used in the recent Georgetown Carnival Power Tool Races. When I get some time, I will restore the test program to its original glory.
You can see my power tool racer (Nevermore's Revenge) here
This tests my FRDM-KL25Z multi-string WS2811/WS2812 library. It uses the accelerometer to change the rainbow phase on two strings of LEDs as well as the touch sense to change brightness.
A video of this program in operation is here.
Here is the library that I developed to run the LEDs:
Import libraryMulti_WS2811
Library allowing up to 16 strings of 60 WS2811 or WS2812 LEDs to be driven from a single FRDM-KL25Z board. Uses hardware DMA to do a full 800 KHz rate without much CPU burden.
Diff: main.cpp
- Revision:
- 34:cd56c00ed910
- Parent:
- 33:43b504e417e3
- Child:
- 36:9ee1ec2135d5
--- a/main.cpp Thu Jun 11 15:33:47 2015 +0000 +++ b/main.cpp Fri Jun 12 11:44:26 2015 -0700 @@ -1,140 +1,138 @@ -#include "mbed.h" -#include "Colors.h" -#include "TSISensor.h" -#include "MMA8451Q.h" - -#define MMA8451_I2C_ADDRESS (0x1d<<1) - -#define INSTANTIATE_TEMPLATES 1 -#include "WS2811.h" - -// I/O pin usage -// PTD0 TPM0 CH0 monitor -// PTD1 TPM0 CH1 monitor -// PTD2 data output for strip# 1 -// PTD3 data output for strip# 2 -// PTD4 blinking eyes output (HI = ON) - -unsigned const DATA_OUT_PIN1 = 2; // PTD2 -unsigned const DATA_OUT_PIN2 = 3; // PTD3 - -const unsigned MAX_LEDS_PER_STRIP = 32; - -// per LED: 3 * 20 mA = 60mA max -// 60 LEDs: 60 * 60mA = 3600 mA max -// 120 LEDs: 7200 mA max -unsigned const nLEDs = MAX_LEDS_PER_STRIP; - -template class WS2811<MAX_LEDS_PER_STRIP>; - -typedef WS2811<MAX_LEDS_PER_STRIP> MyWS2811; - -MyWS2811 lightStrip1(nLEDs, DATA_OUT_PIN1); -MyWS2811 lightStrip2(nLEDs, DATA_OUT_PIN2); - -Serial pc(USBTX, USBRX); -Timer timeRunning; - -TSISensor touchSensor; -MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS); -PwmOut rled(LED_RED); -PwmOut gled(LED_GREEN); -// LED_BLUE is on PTD1 - -float touchPercentage; -unsigned frames; - -float const minBrite = 0.2; -float const maxBrite = 0.5; -float brite; - -void readTouchSensor() -{ - touchPercentage *= 0.9; - touchPercentage += touchSensor.readPercentage() * 0.1; - brite = minBrite + (maxBrite - minBrite) * touchPercentage; -} - -// @brief sets different colors in each of the LEDs of a strip -// @param strip the light strip -// @param sat saturation, 0.0 - 1.0 -// @param brite brightness, 0.0 - 1.0 -// @param hueShift shift, 0.0 - 1.0 is equivalent to 0 - 360 degrees -static void showRainbow(MyWS2811 &strip, float sat, float brite, float hueShift) -{ - unsigned nLEDs = strip.numPixels(); - for (unsigned i = 0; i < nLEDs; i++) { - uint8_t r, g, b; - float hue = ((float)i / (float)nLEDs) + hueShift; - HSBtoRGB(hue, sat, brite, &r, &g, &b); - strip.setPixelColor(i, r, g, b); - } - strip.show(); -} - -static void showSolidColor(MyWS2811 &strip, uint8_t r, uint8_t g, uint8_t b) -{ - unsigned nLEDs = strip.numPixels(); - for (unsigned i = 0; i < nLEDs; i++) { - strip.setPixelColor(i, r, g, b); - } - strip.show(); -} - -int main(void) -{ - pc.baud(115200); - - - lightStrip1.begin(); - lightStrip2.begin(); - rled = 1.0; - gled = 1.0; - - float sat = 1.0; - - timeRunning.start(); - - uint8_t r =0; - uint8_t g =0; - uint8_t b =0; - for (;;) { - if (r < 40) - r++; - else if (g < 40) - g++; - else if (b < 40) - b++; - else { - unsigned running = timeRunning.read_us(); - pc.printf("%u frames in %u usec = %u frames / sec\r\n", frames, running, frames * 1000000 / running); - break; - } - - showSolidColor(lightStrip1, r, g, b); - showSolidColor(lightStrip2, r, g, b); - MyWS2811::startDMA(); - - frames++; - } - - timeRunning.reset(); - frames = 0; - - float xyz[3]; - acc.getAccAllAxis(xyz); - pc.printf("x: %f y: %f z: %f\r\n", xyz[0], xyz[1], xyz[2]); - - for (;;) { - acc.getAccAllAxis(xyz); - rled = 1.0 - fabs(xyz[0]); - gled = 1.0 - fabs(xyz[1]); - readTouchSensor(); - showRainbow(lightStrip1, sat, brite, fabs(xyz[0])); - showRainbow(lightStrip2, sat, brite, fabs(xyz[1])); - MyWS2811::startDMA(); - - frames ++; - } -} - +#include "mbed.h" +#include "Colors.h" +#include "MMA8451Q.h" + +#define MMA8451_I2C_ADDRESS (0x1d<<1) + +#define INSTANTIATE_TEMPLATES 1 +#include "WS2811.h" + +// I/O pin usage +// PTD0 TPM0 CH0 monitor +// PTD1 TPM0 CH1 monitor +// PTD2 (D11) data output for strip# 1 +// PTD3 (D12) data output for strip# 2 +// PTA2 (D3) blinking eyes output (HI = ON) + +unsigned const DATA_OUT_PIN1 = 2; // PTD2 +unsigned const DATA_OUT_PIN2 = 3; // PTD3 + +const unsigned MAX_LEDS_PER_STRIP = 32; + +// per LED: 3 * 20 mA = 60mA max +// 60 LEDs: 60 * 60mA = 3600 mA max +// 120 LEDs: 7200 mA max +unsigned const nLEDs = MAX_LEDS_PER_STRIP; + +template class WS2811<MAX_LEDS_PER_STRIP>; + +typedef WS2811<MAX_LEDS_PER_STRIP> MyWS2811; + +MyWS2811 lightStrip1(nLEDs, DATA_OUT_PIN1); +MyWS2811 lightStrip2(nLEDs, DATA_OUT_PIN2); + +Serial pc(USBTX, USBRX); + +MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS); +PwmOut rled(LED_RED); // max = 0.0 +PwmOut gled(LED_GREEN); // max = 0.0 +// LED_BLUE is on PTD1 +PwmOut eyes(D3); // max = 1.0 + +float touchPercentage; + +float const minBrite = 0.2; +float const maxBrite = 0.5; +float brite; + +// @brief sets different colors in each of the LEDs of a strip +// @param strip the light strip +// @param sat saturation, 0.0 - 1.0 +// @param brite brightness, 0.0 - 1.0 +// @param hueShift shift, 0.0 - 1.0 is equivalent to 0 - 360 degrees +static void showRainbow(MyWS2811 &strip, float sat, float brite, float hueShift) +{ + unsigned nLEDs = strip.numPixels(); + for (unsigned i = 0; i < nLEDs; i++) { + uint8_t r, g, b; + float hue = ((float)i / (float)nLEDs) + hueShift; + HSBtoRGB(hue, sat, brite, &r, &g, &b); + strip.setPixelColor(i, r, g, b); + } + strip.show(); +} + +static void showSolidColor(MyWS2811 &strip, uint8_t r, uint8_t g, uint8_t b) +{ + unsigned nLEDs = strip.numPixels(); + for (unsigned i = 0; i < nLEDs; i++) { + strip.setPixelColor(i, r, g, b); + } + strip.show(); +} + +static void selfTest() +{ + pc.printf("self test: "); + + pc.printf("LEDs ."); + rled = 0.0; // red LED on + wait(1.0); + pc.printf("."); + rled = 1.0; // red LED off, green LED on + gled = 0.0; + wait(1.0); + pc.printf("."); + gled = 1.0; // green LED off, eyes on + eyes = 1.0; + wait(1.0); + pc.printf("."); + eyes = 0.0; + pc.printf(", "); + + pc.printf("light strips"); + float rgb[4] = { 1.0, 0.0, 0.0, 0.0 }; + for (int i = 0; i < 3; i++) { + showSolidColor(lightStrip1, rgb[0], rgb[1], rgb[2]); + showSolidColor(lightStrip2, rgb[1], rgb[2], rgb[0]); + MyWS2811::startDMA(); + if (i == 2) break; + wait(1.0); + rgb[3] = rgb[2]; + rgb[2] = rgb[1]; + rgb[1] = rgb[0]; + rgb[0] = rgb[3]; + pc.printf("."); + } + + pc.printf("\r\n"); +} + +int main(void) +{ + pc.baud(115200); + pc.printf("\r\nNevermore's Revenge!\r\ncompiled " __DATE__ ", " __TIME__ "\r\n"); + + lightStrip1.begin(); + lightStrip2.begin(); + + rled = 1.0; + gled = 1.0; + eyes = 0.0; + + selfTest(); + + float xyz[3]; + + for (;;) { + acc.getAccAllAxis(xyz); + pc.printf("x: %f y: %f z: %f\r\n", xyz[0], xyz[1], xyz[2]); + rled = 1.0 - fabs(xyz[0]); + gled = 1.0 - fabs(xyz[1]); + eyes = fabs(xyz[2]); + showRainbow(lightStrip1, 1.0, maxBrite, fabs(xyz[0])); + showRainbow(lightStrip2, 1.0, maxBrite, fabs(xyz[1])); + MyWS2811::startDMA(); + } +} +