driver for WS2812B LED, modified for better compatibility with LPC812 and LPC1549

Dependencies:   BurstSPI

Dependents:   RGB-balls cylon

Fork of wsDrive by Andy A

Committer:
AndyA
Date:
Fri Nov 07 09:25:52 2014 +0000
Revision:
2:1f20efb81649
Parent:
1:741864ea11d4
Child:
3:3c48065d20ff
remove excess cut and paste;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AndyA 0:b3665f91bedc 1 #ifndef __wsDrive_h__
AndyA 0:b3665f91bedc 2 #define __wsDrive_h__
AndyA 0:b3665f91bedc 3
AndyA 0:b3665f91bedc 4 #include "BurstSPI.h"
AndyA 0:b3665f91bedc 5
AndyA 1:741864ea11d4 6 /****************************************************************
AndyA 1:741864ea11d4 7 * An alternative WS2811/2812 driver using the BusrtSPI library
AndyA 1:741864ea11d4 8 * Credit for the inspiration goes to Jacob for his pixelArray library
AndyA 1:741864ea11d4 9 * http://developer.mbed.org/users/JacobBramley/code/PixelArray/
AndyA 1:741864ea11d4 10 *
AndyA 1:741864ea11d4 11 * This version was written mainly to help me understand what was going on
AndyA 1:741864ea11d4 12 * While the end result is the same the code is completely from scratch.
AndyA 1:741864ea11d4 13 *
AndyA 1:741864ea11d4 14 *****************************************************************/
AndyA 0:b3665f91bedc 15
AndyA 1:741864ea11d4 16
AndyA 1:741864ea11d4 17 /** A structure used to hold a single pixel or a pixel colour
AndyA 1:741864ea11d4 18 *
AndyA 1:741864ea11d4 19 * Each colour can be set to any value between 0 and 255.
AndyA 1:741864ea11d4 20 * 0 = off, 255 = full brightness.
AndyA 1:741864ea11d4 21 *
AndyA 1:741864ea11d4 22 * Note, lots of LEDs on bright will use a lot of power, make sure your supply can cope.
AndyA 1:741864ea11d4 23 *
AndyA 1:741864ea11d4 24 * @param G The green component
AndyA 1:741864ea11d4 25 * @param R The red component
AndyA 1:741864ea11d4 26 * @param B The blue component
AndyA 1:741864ea11d4 27 */
AndyA 0:b3665f91bedc 28 typedef struct pixelInfo {
AndyA 0:b3665f91bedc 29 unsigned char G;
AndyA 0:b3665f91bedc 30 unsigned char R;
AndyA 0:b3665f91bedc 31 unsigned char B;
AndyA 0:b3665f91bedc 32 } pixelInfo;
AndyA 0:b3665f91bedc 33
AndyA 0:b3665f91bedc 34
AndyA 1:741864ea11d4 35 /** Drives a WS2812 LED chain
AndyA 1:741864ea11d4 36 *
AndyA 1:741864ea11d4 37 * An alternative WS2811/2812 driver using the BusrtSPI library
AndyA 1:741864ea11d4 38 *
AndyA 1:741864ea11d4 39 * Credit for the inspiration goes to Jacob for his pixelArray library
AndyA 1:741864ea11d4 40 * http://developer.mbed.org/users/JacobBramley/code/PixelArray/
AndyA 1:741864ea11d4 41 *
AndyA 1:741864ea11d4 42 * This version was written mainly to help me understand what was going on and is a little more basic.
AndyA 1:741864ea11d4 43 * While the end result is muc the same the code is completely from scratch.
AndyA 1:741864ea11d4 44 *
AndyA 1:741864ea11d4 45 * BurstSPI is used to generate the timing so support is limited to the parts supported by that library.
AndyA 1:741864ea11d4 46 *
AndyA 1:741864ea11d4 47 * Also note that while all 3 SPI pins are specified only the MOSI pin is actually needed and should connect to the data in on the LEDs
AndyA 1:741864ea11d4 48 *
AndyA 1:741864ea11d4 49 * Example code to run a single lit led along a chain
AndyA 1:741864ea11d4 50 *
AndyA 1:741864ea11d4 51 * @code
AndyA 1:741864ea11d4 52 *
AndyA 1:741864ea11d4 53 * #include "mbed.h"
AndyA 1:741864ea11d4 54 * #include "wsDrive.h"
AndyA 1:741864ea11d4 55 *
AndyA 1:741864ea11d4 56 * // update period in ms
AndyA 1:741864ea11d4 57 * #define updatePeriod 100
AndyA 1:741864ea11d4 58 * // number of LEDs
AndyA 1:741864ea11d4 59 * #define chainLen 8
AndyA 1:741864ea11d4 60 *
AndyA 1:741864ea11d4 61 * DigitalIn dummy(MOSI,PullDown); // first activate the pulldown on the pin.
AndyA 1:741864ea11d4 62 * wsDrive ledDriver(MOSI,MISO,CLK); // create the SPI bus. You can normally list the MISO and CLK as NC but some mbed library versions don't like that
AndyA 1:741864ea11d4 63 *
AndyA 1:741864ea11d4 64 * // pixel storage buffer
AndyA 1:741864ea11d4 65 * pixelInfo pixelData[chainLen];
AndyA 1:741864ea11d4 66 *
AndyA 1:741864ea11d4 67 * Timer updateRateTimer;
AndyA 1:741864ea11d4 68 *
AndyA 1:741864ea11d4 69 * void blankBuffer(pixelInfo *Ptr)
AndyA 1:741864ea11d4 70 * {
AndyA 1:741864ea11d4 71 * memset( (void *)Ptr, 0, chainLen*sizeof(pixelInfo) );
AndyA 1:741864ea11d4 72 * }
AndyA 1:741864ea11d4 73 *
AndyA 1:741864ea11d4 74 * void setPixel(unsigned int index, pixelInfo *colourToUse) {
AndyA 1:741864ea11d4 75 * if (index < chainLen) {
AndyA 1:741864ea11d4 76 * pixelData[index].R = colourToUse->R;
AndyA 1:741864ea11d4 77 * pixelData[index].G = colourToUse->G;
AndyA 1:741864ea11d4 78 * pixelData[index].B = colourToUse->B;
AndyA 1:741864ea11d4 79 * }
AndyA 1:741864ea11d4 80 * }
AndyA 1:741864ea11d4 81 *
AndyA 1:741864ea11d4 82 * void clearPixel(unsigned int index) {
AndyA 1:741864ea11d4 83 * if (index < chainLen) {
AndyA 1:741864ea11d4 84 * pixelData[index].R = 0;
AndyA 1:741864ea11d4 85 * pixelData[index].G = 0;
AndyA 1:741864ea11d4 86 * pixelData[index].B = 0;
AndyA 1:741864ea11d4 87 * }
AndyA 1:741864ea11d4 88 * }
AndyA 1:741864ea11d4 89 *
AndyA 1:741864ea11d4 90 * int main () {
AndyA 1:741864ea11d4 91 *
AndyA 1:741864ea11d4 92 * int litLed = 0;
AndyA 1:741864ea11d4 93 *
AndyA 1:741864ea11d4 94 * pixelInfo colour;
AndyA 1:741864ea11d4 95 * colour.R = 0x80;
AndyA 1:741864ea11d4 96 * colour.G = 0x00;
AndyA 1:741864ea11d4 97 * colour.B = 0x00;
AndyA 1:741864ea11d4 98 *
AndyA 1:741864ea11d4 99 * // Tell the driver where the data is stored
AndyA 1:741864ea11d4 100 * ledDriver.setData(pixelData, chainLen);
AndyA 1:741864ea11d4 101 *
AndyA 1:741864ea11d4 102 * // Set the buffer to the pattern we want
AndyA 1:741864ea11d4 103 * blankBuffer(pixelData);
AndyA 1:741864ea11d4 104 * setPixel(litLed, &colour);
AndyA 1:741864ea11d4 105 *
AndyA 1:741864ea11d4 106 * updateRateTimer.start();
AndyA 1:741864ea11d4 107 * while (true) {
AndyA 1:741864ea11d4 108 *
AndyA 1:741864ea11d4 109 * ledDriver.sendData(); // send the LED data
AndyA 1:741864ea11d4 110 *
AndyA 1:741864ea11d4 111 * // modify the buffer ready for the next update
AndyA 1:741864ea11d4 112 * clearPixel(litLed);
AndyA 1:741864ea11d4 113 * litLed++;
AndyA 1:741864ea11d4 114 * if (litLed == chainLen)
AndyA 1:741864ea11d4 115 * litLed = 0;
AndyA 1:741864ea11d4 116 * setPixel(litLed, &colour);
AndyA 1:741864ea11d4 117 *
AndyA 1:741864ea11d4 118 * // wait until the correct time since the last update...
AndyA 1:741864ea11d4 119 * while (updateRateTimer.read_ms() < updatePeriod) {
AndyA 1:741864ea11d4 120 * }
AndyA 1:741864ea11d4 121
AndyA 1:741864ea11d4 122 * updateRateTimer.reset();
AndyA 1:741864ea11d4 123 * }
AndyA 1:741864ea11d4 124 * }
AndyA 1:741864ea11d4 125 * @endcode
AndyA 1:741864ea11d4 126 *
AndyA 1:741864ea11d4 127 * Troubleshooting:
AndyA 1:741864ea11d4 128 *
AndyA 1:741864ea11d4 129 * If the LEDs aren't lighting up correctly then check that your power supply is up to the job (or decrease the brightness you are using)
AndyA 1:741864ea11d4 130 *
AndyA 1:741864ea11d4 131 * Also check the supply voltage, on paper when running off 5V the WS2812 needs 4V on the data in pin to detect a high. Mbed based boards rarely output much over 3.1V.
AndyA 1:741864ea11d4 132 * This problem is normally indicated by the very first pattern send on power up being displayed but then no further updates being recieved. Dropping the supply voltage
AndyA 1:741864ea11d4 133 * to about 4.2 - 4.3 V will normally fix this problem without any meaningful impact on the LED output.
AndyA 1:741864ea11d4 134 *
AndyA 1:741864ea11d4 135 */
AndyA 0:b3665f91bedc 136 class wsDrive : private BurstSPI
AndyA 0:b3665f91bedc 137 {
AndyA 0:b3665f91bedc 138 public:
AndyA 1:741864ea11d4 139 /** create the driver
AndyA 1:741864ea11d4 140 */
AndyA 0:b3665f91bedc 141 wsDrive(PinName mosi, PinName miso, PinName clk);
AndyA 1:741864ea11d4 142
AndyA 1:741864ea11d4 143 /** Set the data pointer
AndyA 1:741864ea11d4 144
AndyA 1:741864ea11d4 145 Before data can be sent the driver must be given a pointer to the pixel data to use.
AndyA 1:741864ea11d4 146 Setting this is normally a one time operation unless you want to switch between buffers.
AndyA 1:741864ea11d4 147
AndyA 1:741864ea11d4 148 @param dataStart The start of an array of pixelInfo items. This will be sent to the chain in order.
AndyA 1:741864ea11d4 149 @param dataLen The length of the array.
AndyA 1:741864ea11d4 150 */
AndyA 0:b3665f91bedc 151 void setData(pixelInfo *dataStart, uint16_t dataLen);
AndyA 1:741864ea11d4 152
AndyA 1:741864ea11d4 153
AndyA 1:741864ea11d4 154 /** Sends the data to the LEDs
AndyA 1:741864ea11d4 155 * setData() must be called prior to this.
AndyA 1:741864ea11d4 156 */
AndyA 0:b3665f91bedc 157 void sendData();
AndyA 1:741864ea11d4 158
AndyA 0:b3665f91bedc 159 private:
AndyA 0:b3665f91bedc 160
AndyA 0:b3665f91bedc 161 void sendByte(unsigned char value);
AndyA 0:b3665f91bedc 162 void sendPixel(pixelInfo *pixToSend);
AndyA 1:741864ea11d4 163
AndyA 0:b3665f91bedc 164 pixelInfo *pixArray;
AndyA 0:b3665f91bedc 165 uint16_t pixelLen;
AndyA 0:b3665f91bedc 166
AndyA 0:b3665f91bedc 167 };
AndyA 0:b3665f91bedc 168
AndyA 0:b3665f91bedc 169 #endif