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 Heroic Robotics

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "Colors.h"
00003 #include "MMA8451Q.h"
00004 
00005 #define MMA8451_I2C_ADDRESS (0x1d<<1)
00006 
00007 #define INSTANTIATE_TEMPLATES 1
00008 #include "WS2811.h"
00009 
00010 #include "audio.h"
00011 using namespace NKAudio;
00012 
00013 #include "1khz_1sec.h"
00014 
00015 AudioFile audioFiles[] = {
00016     { __1khz_1sec_s8, __1khz_1sec_s8_len },
00017     { 0, 0 } // mark end
00018 };
00019 
00020 // I/O pin usage
00021 // PTD2 (D11) data output for strip# 1
00022 // PTD3 (D12) data output for strip# 2
00023 // PTA12 (D3) servomotor (20 msec period; 1.0-2.0msec ON)
00024 // PTA5 (D5) blinking eyes output (HI = ON)
00025 // PTE30
00026 
00027 const unsigned DATA_OUT_PIN1 = 2; // PTD2
00028 const unsigned DATA_OUT_PIN2 = 3; // PTD3
00029 
00030 // actually, sides have 21 LEDs each, and ends have 10 LEDs each.
00031 const unsigned MAX_LEDS_PER_STRIP = 31;
00032 
00033 // per LED: 3 * 20 mA = 60mA max
00034 // 60 LEDs: 60 * 60mA = 3600 mA max
00035 // 120 LEDs: 7200 mA max
00036 const unsigned nLEDs = MAX_LEDS_PER_STRIP;
00037 
00038 template class WS2811<MAX_LEDS_PER_STRIP>;
00039 
00040 typedef WS2811<MAX_LEDS_PER_STRIP> MyWS2811;
00041 
00042 static MyWS2811 lightStrip1(nLEDs, DATA_OUT_PIN1);
00043 static MyWS2811 lightStrip2(nLEDs, DATA_OUT_PIN2);
00044 
00045 Serial pc(USBTX, USBRX);
00046 
00047 // accelerometer
00048 static MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS);
00049 
00050 // RGB LED on FRDM board
00051 static DigitalOut rled(LED_RED);       // PTB18 max = 0.0
00052 static DigitalOut gled(LED_GREEN);     // PTB19 max = 0.0
00053 // LED_BLUE is on PTD1
00054 
00055 static PwmOut servo(D3);    // PTA12
00056 static DigitalOut eyes(D5);     // PTA5
00057 
00058 // static DigitalOut greenLED2(D4);   // max = 1.0
00059 static DigitalIn button1(D6);      // low=ON, debounced
00060 // static DigitalIn button2(D7);      // low=ON, debounced
00061 
00062 // Limits
00063 const float maxBrite = 0.5;
00064 const float minServo = -0.7; // -1.0 = -60°
00065 const float maxServo = 0.6; // 1.0 = +60°
00066 
00067 // const float minFlapTime = (maxServo - minServo) * 0.17; // 0.17 seconds / 60° at 4.8V
00068 const float minFlapTime = 0.5;
00069 const float maxFlapTime = 1.0;
00070 float currentPosition = 1.0;
00071 float currentSpeed = 1.0;
00072 
00073 // @brief sets different colors in each of the LEDs of a strip
00074 // @param strip the light strip
00075 // @param sat saturation, 0.0 - 1.0
00076 // @param brite brightness, 0.0 - 1.0
00077 // @param hueShift shift, 0.0 - 1.0 is equivalent to 0 - 360 degrees
00078 static void showRainbow(MyWS2811 &strip, float sat, float brite, float hueShift, float hueRange = 1.0, int span = 1, int skip=0)
00079 {
00080     int nLEDs = strip.numPixels();
00081     int direction, first, last;
00082 
00083     if (span < 0) {
00084         direction = -1;
00085         first = nLEDs-1;
00086         last = -1;
00087         span = -span;
00088         skip = -skip;
00089     } else {
00090         direction = 1;
00091         first = 0;
00092         last = nLEDs;
00093     }
00094 
00095     for (int i = first; i != last; i += direction) {
00096         uint8_t r, g, b;
00097         float hue = (i * hueRange / nLEDs) + hueShift;
00098         HSBtoRGB(hue, sat, brite, &r, &g, &b);
00099         if ((i + skip) % span == 0)
00100             strip.setPixelColor((unsigned)i, r, g, b);
00101         else
00102             strip.setPixelColor((unsigned)i, 0, 0, 0);
00103     }
00104     strip.show();
00105 }
00106 
00107 static void showSolidColor(MyWS2811 &strip, uint8_t r, uint8_t g, uint8_t b)
00108 {
00109     unsigned nLEDs = strip.numPixels();
00110     for (unsigned i = 0; i < nLEDs; i++) {
00111         strip.setPixelColor(i, r, g, b);
00112     }
00113     strip.show();
00114 }
00115 
00116 // range is -1.0 (full CCW) to +1.0 (full CW)
00117 static void positionServo(float pos)
00118 {
00119     if (pos < minServo)
00120         pos = minServo;
00121     else if (pos > maxServo)
00122         pos = maxServo;
00123 
00124     if (pos < 0.0) {
00125         rled = 0;
00126         gled = 1;
00127     } else if (pos > 0.0) {
00128         rled = 1;
00129         gled = 0;
00130     } else {
00131         rled = gled = 1;
00132     }
00133 
00134     servo.pulsewidth_us((1.5 + (pos / 2.0)) * 1000.0);
00135 }
00136 
00137 void flap()
00138 {
00139     positionServo(currentPosition);
00140     currentPosition = -currentPosition;
00141 }
00142 
00143 static void selfTestServo()
00144 {
00145     pc.printf("Servo:\r\n");
00146     pc.printf("CCW, ");
00147     positionServo(-1.0);
00148     wait(1.0);
00149     pc.printf("CW, ");
00150     positionServo(+1.0);
00151     wait(1.0);
00152     pc.printf("center.\r\n");
00153     positionServo(0.0);
00154 }
00155 
00156 static void selfTestLEDs()
00157 {
00158     pc.printf("LEDs .");
00159     rled = 0; // red LED on
00160     wait(0.5);
00161     pc.printf(".");
00162     rled = 1; // red LED off, green LED on
00163     gled = 0;
00164     wait(0.5);
00165     pc.printf(".");
00166     gled = 1; // green LED off, eyes on
00167     eyes = 1;
00168     wait(0.5);
00169     pc.printf(".");
00170     eyes = 0;
00171     pc.printf("\r\n");
00172 }
00173 
00174 static void refreshLightStrips()
00175 {
00176     MyWS2811::startDMA();
00177     // 24 bits per LED, 800kHz (1.25usec/bit)
00178     // wait_us((MAX_LEDS_PER_STRIP * 24 * 10 / 8) + 100);
00179 }
00180 
00181 static void blankLightStrips()
00182 {
00183     showSolidColor(lightStrip1, 0, 0, 0);
00184     showSolidColor(lightStrip2, 0, 0, 0);
00185     refreshLightStrips();
00186 }
00187 
00188 static void selfTestLightStrips()
00189 {
00190     blankLightStrips();
00191     pc.printf("light strips");
00192     uint8_t rgb[4] = { (uint8_t)(255 * maxBrite), 0, 0, 0 };
00193     for (int i = 0; i < 3; i++) {
00194         showSolidColor(lightStrip1, rgb[0], rgb[1], rgb[2]);
00195         showSolidColor(lightStrip2, rgb[1], rgb[2], rgb[0]);
00196         refreshLightStrips();
00197         wait(1.0);
00198         rgb[3] = rgb[2];
00199         rgb[2] = rgb[1];
00200         rgb[1] = rgb[0];
00201         rgb[0] = rgb[3];
00202         pc.printf(".");
00203     }
00204     blankLightStrips();
00205     pc.printf("\r\n");
00206 }
00207 
00208 static void selfTest()
00209 {
00210     pc.printf("self test: ");
00211 
00212     selfTestLightStrips();
00213     selfTestServo();
00214     selfTestLEDs();
00215     
00216     pc.printf("done\n");
00217 }
00218 
00219 // rainbow that wraps around entire frame
00220 void updateStripsRainbow()
00221 {
00222     static int skip = 0;
00223 
00224     showRainbow(lightStrip1, 1.0, maxBrite, currentSpeed, 0.5, 3, skip);
00225     showRainbow(lightStrip2, 1.0, maxBrite, currentSpeed + 0.5, 0.5, -3, skip);
00226     refreshLightStrips();
00227     skip++;
00228     skip %= 3;
00229 }
00230 
00231 void updateEyes()
00232 {
00233     static bool eyesOn;
00234     eyes = eyesOn ? 1 : 0;
00235     eyesOn = !eyesOn;
00236 }
00237 
00238 int main(void)
00239 {
00240     pc.baud(115200);
00241     pc.printf("\r\n\r\nNevermore's Revenge!\r\ncompiled " __DATE__ ", " __TIME__ "\r\n");
00242 
00243     lightStrip1.begin();
00244     lightStrip2.begin();
00245 
00246     rled      = 1.0;
00247     gled      = 1.0;
00248     servo.period_ms(20);
00249 
00250     selfTest();
00251 
00252     Timer elapsedTime;
00253 
00254     Ticker flapper;
00255     flapper.attach(flap, maxFlapTime);
00256     
00257     Ticker stripUpdater;
00258     stripUpdater.attach(updateStripsRainbow, 0.3);
00259 
00260     Ticker eyeUpdater;
00261     eyeUpdater.attach(updateEyes, 0.2);
00262     
00263     elapsedTime.start();
00264 
00265     bool lastButton = button1.read();
00266 
00267     for (;; ) {
00268         bool buttonValue = button1.read();
00269         if (buttonValue != lastButton) {
00270             if (!buttonValue) {
00271                 flapper.detach();
00272                 flapper.attach(flap, maxFlapTime);
00273                 stripUpdater.detach();
00274                 stripUpdater.attach(updateStripsRainbow, 0.3);
00275             } else {
00276                 flapper.detach();
00277                 flapper.attach(flap, minFlapTime);
00278                 stripUpdater.detach();
00279                 stripUpdater.attach(updateStripsRainbow, 0.1);
00280             }
00281         }
00282 
00283         wait(0.1);
00284     }
00285 }