gwdeveloper 275 Posted October 4, 2011 Share Posted October 4, 2011 Hey guys, just to break the programming monotony and get the kiddo more interested in electronics, we ported the Arduino code over to control the WS2801 RGB Led Strip from Sparkfun. http://www.sparkfun.com/products/10312 We scored one of these from their 'scratch & dent' sales a while back at half price. It's not waterproof but rainbow lights entertain an 8 year girl like nothing else. It runs fine at 3.3v but the Launchpad does not supply enough current to run the strip so we're using a breadboard power supply as well. The software is running on a G2553 plugged into the LP but running at 1MHz. The SPI is bit banged so it should load fine on other devices as well. The goal with this is to mount it above her bedroom window, tape a thermistor to the window and provide ambient light based on temperature as well as using a rotary encoder to allow her to set the color on demand. Now I think I want another to cut down into a matrix for simple animations. http://www.youtube.com/watch?v=4qlUw-dbkew /****************************************************************/ /* Greg Whitmore */ /* greg@gwdeveloper.net */ /* www.gwdeveloper.net */ /****************************************************************/ /* released under the "Use at your own risk" license */ /* use it how you want, where you want and have fun */ /* debugging the code. */ /* MSP430 spi bit bang WS2801 RGB LED strip */ /****************************************************************/ /* code was translated from adafruit ws2801 arduino library */ /* https://github.com/adafruit/WS2801-Library */ #include // constant defines #define DATA BIT7 #define CLOCK BIT6 #define NUMLEDS 32 // wdt delay constants #define MCLK_FREQUENCY 1000000 #define WDT_DIVIDER 512 const unsigned long WDT_FREQUENCY = MCLK_FREQUENCY / WDT_DIVIDER; volatile unsigned long wdtCounter = 0; // data arrays unsigned long pixels[NUMLEDS]; //incrementers int p; long i; // prototypes void init(void); void display(void); unsigned long color(unsigned char r, unsigned char g, unsigned char ; void setPixelS(unsigned int n, unsigned long c); void setPixel(unsigned int n, unsigned char r, unsigned char g, unsigned char ; unsigned long wheel(unsigned char wheelpos); // pattern functions void copcar(void); void goJoe(unsigned long time); // larger time value is slower chase void randomdance(void); void solidblink(unsigned long c); void colorwipe(unsigned long c); void rainbowcycle(void); void showrainbow(void); // random function and delay millis borrowed from NatureTM.com // random generator slightly modified to create 32bit value unsigned long adcGenRand32(void); void delayMillis(unsigned long milliseconds); // main colors unsigned long clear = 0x000000; unsigned long red = 0xFF0000; unsigned long green = 0x00FF00; unsigned long blue = 0x0000FF; unsigned long white = 0x80FFFF; // red is half strenght; full strength yields pink instead of white unsigned long randomcolor; void main(void) { //WDTCTL = WDTPW + WDTHOLD; // use 1MHz calibrated values DCOCTL = CALDCO_1MHZ; BCSCTL1 = CALBC1_1MHZ; // wdt set as interval WDTCTL = WDTPW + WDTTMSEL + WDTIS1; // wdt interrupt IE1 |= WDTIE; // enable global interrupts using intrinsic __enable_interrupt(); // initialize pins for SPI init(); colorwipe(clear); // clear led strip while (1) { int x; // run demos for display for (x = 0; x < 3; x++) { copcar(); } for (x = 0; x < 3; x++) { goJoe(50); } for (x = 0; x < 5; x++) { randomdance(); } colorwipe(clear); for (x = 0; x < 3; x++) { solidblink(green); } for (x = 0; x < 2; x++) { rainbowcycle(); } } } /* use functions */ // police light bar chaser void copcar(void) { int m; int middle = NUMLEDS / 2 ; colorwipe(clear); for ( m = 0; m < NUMLEDS; m++ ) { if ( m <= middle ) { pixels[m] = red; pixels[m - 2] = clear; pixels[NUMLEDS - m] = blue; pixels[NUMLEDS - m + 2] = clear; } display(); if ( m >= middle ) { pixels[m] = blue; pixels[m - 2] = clear; pixels[NUMLEDS - m] = red; pixels[NUMLEDS - m + 2] = clear; } display(); } } // red white and blue chasers void goJoe(unsigned long time) { int m; colorwipe(clear); // clear display from existing patterns for ( m = 0; m < NUMLEDS; m++ ) { pixels[m] = blue; pixels[m - 1] = red; pixels[m - 2] = white; pixels[m - 3] = clear; display(); delayMillis(time); } for ( m = NUMLEDS; m >= 0; m-- ) { pixels[m] = clear; pixels[m - 1] = white; pixels[m - 2] = red; pixels[m - 3] = blue; display(); delayMillis(time); } } // send random colors down each pixel void randomdance(void) { int m; for ( m = 0; m < NUMLEDS; m++ ) { pixels[m] = adcGenRand32(); display(); } } // blink solid color void solidblink(unsigned long c) { colorwipe(c); delayMillis(500); colorwipe(clear); } // animate fading rainbow cycle void rainbowcycle(void) { int k, j; for ( j=0; j<256; j++ ) { for ( k=0; k < NUMLEDS; k++ ) { setPixelS(k, wheel( ( k+j) % 255 ) ); } display(); delayMillis(100); } } // display static rainbow void showrainbow(void) { int k, j; for ( j=0; j < 256 * 5; j++ ) { for ( k=0; k < NUMLEDS; k++ ) { setPixelS(k, wheel( ((k * 256 / NUMLEDS ) + j) % 255) ); } } display(); delayMillis(100); } // wipe strip to selected color void colorwipe(unsigned long c) { int v; for ( v=0; v < NUMLEDS; v++) setPixelS(v, c); display(); //delayMillis(100); } /* library functions */ //initialization void init(void) { P1DIR |= DATA + CLOCK; // set data and clock pins to output } // send data to led strip; create patten with a 'use' function then send with display void display(void) { unsigned long data; P1OUT &= ~CLOCK; delayMillis(1); // send all the pixels for ( p=0; p < NUMLEDS ; p++ ) { data = pixels[p]; // 24 bits of data per pixel for ( i=0x800000; i>0 ; i>>=1 ) { P1OUT &= ~CLOCK; if (data & i) { P1OUT |= DATA; } else { P1OUT &= ~DATA; } P1OUT |= CLOCK; // latch on clock rise } } // toggle clock low to display data P1OUT &= ~CLOCK; delayMillis(1); } // create 24bit color value unsigned long color(unsigned char r, unsigned char g, unsigned char { unsigned long c; c = r; c <<= 8; c |= g; c <<= 8; c |= b; return c; } // set pixel to specified color void setPixel(unsigned int n, unsigned char r, unsigned char g, unsigned char { unsigned long data; if (n > NUMLEDS) return; data = g; data <<= 8; data |= b; data <<= 8; data |= r; pixels[n] = data; } //set pixel to color by function void setPixelS(unsigned int n, unsigned long c) { if ( n > NUMLEDS ) return; pixels[n] = c & 0xFFFFFF; } // rotate colorwheel for rainbows unsigned long wheel(unsigned char wheelpos) { if (wheelpos <85) { return color( wheelpos * 3, 255 - wheelpos * 3, 0 ); } else if ( wheelpos < 170 ) { return color( 255 - wheelpos * 3, 0, wheelpos * 3 ); } else { wheelpos -= 170; return color( 0, wheelpos * 3, 255 - wheelpos * 3 ); } } // generate random 32bit number using ADC10 channel 5; leave P1.4 & P1.5 floating unsigned long adcGenRand32(void) { char bit; unsigned long random; for(bit = 0; bit < 32; bit++){ ADC10CTL1 |= INCH_5; ADC10CTL0 |= SREF_1 + ADC10SHT_1 + REFON + ADC10ON; ADC10CTL0 |= ENC + ADC10SC; while(ADC10CTL1 & ADC10BUSY); random <<= 1; random |= (ADC10MEM & 0x01); } return random; } // millisecond delay counter using WDT void delayMillis(unsigned long milliseconds){ unsigned long wakeTime = wdtCounter + (milliseconds * WDT_FREQUENCY / 1000); while(wdtCounter < wakeTime); } // wdt isr #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void){ wdtCounter++; } zborgerd, gordon, bluehash and 1 other 4 Quote Link to post Share on other sites
bluehash 1,581 Posted October 4, 2011 Share Posted October 4, 2011 Hell, I get excited by cop lights. Psychedelic. Now make them move. I might steal your bitbang code for an RTC interface. Quote Link to post Share on other sites
gwdeveloper 275 Posted October 4, 2011 Author Share Posted October 4, 2011 Haha, I do too! Go ahead, it's all under the "use at your own risk" license. I taught myself the bit bang SPI method the other day to drive a single 7 segment led with a 74hc595. Everyone else has been using 2,4 or 8 digit displays. I just needed to flash error codes on a single and got a little lost. Now it's working great. Quote Link to post Share on other sites
zborgerd 62 Posted October 4, 2011 Share Posted October 4, 2011 Nice work. Just out of curiosity, how much work was it to port the code? Quote Link to post Share on other sites
gwdeveloper 275 Posted October 4, 2011 Author Share Posted October 4, 2011 Thanks. Not too much. Pencil and paper to sort out what each function was doing. And then relate the different Arduino functions like pinMode and digitalWrite over to MSP430 code. ie; pinMode = PxDIR, digitalWrite = PxOUT. Then add the bits for HIGH or LOWS. After that is was sorting out the different typedefs (uint32_t = unsigned long, byte = unsigned char...) The arduino declares them in different places and I didn't want to include the overhead of stdint.h. As of now, the whole program is under 1K. Quote Link to post Share on other sites
gwdeveloper 275 Posted October 4, 2011 Author Share Posted October 4, 2011 @bluehash You beat me to posting it on sparkfun! haha Going to post it there and scrolled to the bottom to see you. Nice. Quote Link to post Share on other sites
bluehash 1,581 Posted October 4, 2011 Share Posted October 4, 2011 oops.. sorry. Was not intending to to steal your limelight. I cannot delete it, I tried. Quote Link to post Share on other sites
gwdeveloper 275 Posted October 4, 2011 Author Share Posted October 4, 2011 No worries at all. It was more about sharing and getting people away from thinking the Arduino was the only mcu that can make cool blinky lights. It links here and that's all that matters. $4.30 Launchpad vs. $29.95 Arduino Launchpad FTW! Quote Link to post Share on other sites
gwdeveloper 275 Posted October 5, 2011 Author Share Posted October 5, 2011 It now has a few animations. I updated the code above and posted 2 more videos of demos running. @Bluehash This one is for you: http://www.youtube.com/watch?v=05PP9gl7BnY The 2nd animation display (goJoe function) has a red, white and blue chaser which the camera has issues capturing. The rainbow fading function has a small glitch for some reason and sends a blue chaser in reverse after full red is achieved. http://www.youtube.com/watch?v=JRe-rayffxA Quote Link to post Share on other sites
bluehash 1,581 Posted October 5, 2011 Share Posted October 5, 2011 Hehe awesome. Appreciate it! Quote Link to post Share on other sites
NullColaShip 14 Posted January 8, 2012 Share Posted January 8, 2012 Hi all, I've been working on getting Adafruit's newer LPD8806-based RGB LED strips working with an MSP430 - using this code as a base and Adafruit's LPD8806 Arduino library as a reference, I've managed to achieve control of the strip. Next up is a followup based on the LED array version of this, expanded to a larger display - I'm aiming to create a larger (primarily text-based) display, as I have a larger quantity of the strips than gwdeveloper made use of here. Quote Link to post Share on other sites
kathy82 0 Posted July 31, 2013 Share Posted July 31, 2013 I got my ws2801 strip from http://www.lightingnext.com/ws2801-digital-addressable-rgb-led-strips.html, and used WS2801 library (https://github.com/adafruit/WS2801-Library) in the following program, however I still don't know how to change the last 6 LED into red before turning them off. Even I don't know whether it is possible or not. Can anyone let me know? #include "SPI.h" #include "WS2801.h" int SDI = 2; // Serial gray scale data input int CKI = 3; // Data clock input WS2801 strip = WS2801(32, SDI, CKI); void setup() { strip.begin(); strip.show(); } void loop() { colorAppear (Color(255, 250, 250), 50); colorAppear (Color(0, 0, 0), 5000); } void colorAppear (uint32_t c, uint8_t wait) { for (int i=0; i < strip.numPixels(); i++) { strip.setPixelColor(i, c); strip.show(); delay(wait); } } // Creating a 24 bit color value from R,G,B uint32_t Color(byte r, byte g, byte { uint32_t c; c = r; c <<= 8; c |= g; c <<= 8; c |= b; return c; } Quote Link to post Share on other sites
roadrunner84 466 Posted July 31, 2013 Share Posted July 31, 2013 Your question isn't clear to me, do you want to set all but the last 6 LEDs to a certain color, and those last 6 to red. Then thereafter turn all LEDs off? void loop() { int32_t c; c = Color(255,0,0); for (int i=0; i < 6; i++) { strip.setPixelColor(i, c); strip.show(); delay(50); } c = Color(255,250,250); for (int i=6; i < strip.numPixels(); i++) { strip.setPixelColor(i, c); strip.show(); delay(50); } c = Color(0,0,0); for (int i=0; i < strip.numPixels(); i++) { strip.setPixelColor(i, c); strip.show(); delay(5000); } } like this? Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.