MSP430 RGB flower pot

Project: LED Flowerpot retrofit

Purpose: Some one had bought me a color changing flowerpot, on clearance :), and when i got it, it failed to work. Like any good hacker or well tinker, i took it apart to find out what was in it and try to fix it. well that didn’t work out so well, those lovely epoxy covered parts and unlabeled SMTs, but what can you expect from cheap gadgets from across the seas.

Parts:

  • R1-R3 100 Ohms
  • R4 1M ohm
  • R5 470 ohm
  • L1 RGB LED common cathode
  • Q1-Q3 2n2222 NPN transistor
  • SW1 Common push button
  • PCB or perf board
  • misc wires
  • MSP430G2211

schematic:

Code concept: What I wanted is a RGB led that faded through different colors like the original was supposed to be, At first i was starting to use Timer A for creating a PWM to fade the different colors, but i had a limitation on how many capture compare registers there were. MSP430G22xx only allows for 2 hardware driven PWM, and I needed 3. so i had to look for another way to create a PWM output that could handle more then 3 different PWM signals. I chose to use the WDT+ interval timer for my base period, and used increment and logic to create a second timer for the duty cycle.

code flow

  1. low level init, goes to main(), sets up pins and WDT
  2. jmps to no exec or end of code, main() stops running and CPU shuts off
  3. WDT expires after .064ms, enough instruction time to run a decent amount of logic
  4. runs preiod logic-> timer 1 increments if it equals the Period resets to 0 changes all pins back to there original state
  5. duty cycle logic, duty cycle is compared to timer 1 – if its equal to the timer Pin state changes
  6. interrupt is serviced and goes to low power mode till the next interval interrupt is called

Code:


//includes
#include <msp430x20x2.h>
#include <signal.h> //add for interrupt
//Defines
#define UP 0x00
#define DOWN 0x01
#define HOLD 0x02
#define PERIOD 200 //sets period length-- PERIOD x interval length
//variables
volatile  int millsecs = 0;
volatile  int counter2 = 0;
//volatile  int counter3 = 0;
volatile  int led_red = 1;
volatile  int led_green = 1;
volatile  int led_blue = 1;
volatile  int red = UP;
volatile  int blue = HOLD;
volatile  int green = HOLD;
//start of main
void main(void)
{
//set WDT to interval mode
WDTCTL = WDT_MDLY_0_064;
//pin setup
P1DIR |= BIT5 + BIT4 + BIT3;
P1OUT |= BIT5 + BIT4 + BIT3;
//set interrupts
IE1 |= WDTIE;
eint();
//turn off CPU
_BIS_SR(CPUOFF);
}//end main
//WDT interval interrupt SR
interrupt(WDT_VECTOR) watchdog_timer(void)
{
++millsecs;//period and dutycycle counter
//period logic
if (millsecs == PERIOD) { millsecs= 0; P1OUT |= BIT5 + BIT4 + BIT3; ++counter2; }
//Duty cycle logic
if (millsecs == led_red ) { P1OUT ^= BIT3; }
if (millsecs == led_green) { P1OUT ^= BIT4; }
if (millsecs == led_blue ) { P1OUT ^= BIT5; }
//fade logic
if (counter2 == 254 ) { counter2 =0; //++counter3;
//power timer or how long till it turns off
//if (counter3 == 1000) { P1OUT = 0; _BIS_SR(LPM4_bits);}
switch (red){
case UP: ++led_red;
if (led_red == 199) {red = HOLD; green = UP; blue = DOWN;}
break;
case DOWN: --led_red;
if (led_red == 0) {red = HOLD;}
break;
case HOLD: break;
}//end switch
switch (blue){
case UP:  ++led_blue;
if (led_blue == 199) {blue = HOLD; green = DOWN; red = UP;}
break;
case DOWN: --led_blue;
if (led_blue == 0) {blue = HOLD;}
break;
case HOLD: break;
}//end switch
switch (green){
case UP: ++led_green;
if (led_green == 199) {green = HOLD; red = DOWN; blue = UP;}
break;
case DOWN: --led_green;
if (led_green == 0) {green = HOLD;}
break;
case HOLD: break;
}//end switch
}//end if
}//end interrupt

videos of project in action at different parts of the construction process

Files
all code is written for mspgcc
To compile with CCS or IAR you will have to change the Header files and change the WDT interrupt to the correct format for those programs. one last thing you may need to change is how it calls for low power mode.
OldRGB.tar
RGB.2.tar//removed sleep mode



7 Responses to MSP430 RGB flower pot

  1. Hello, I am very interested in trying this code, but when I attempted to compile it in CCSv4 i get the following errors:

    “../main.c”, line 54: warning: function declared implicitly
    “../main.c”, line 59: error: expected an identifier
    “../main.c”, line 59: error: the modifier “interrupt” is not allowed on this declaration
    “../main.c”, line 59: error: expected a “;”
    At end of source: warning: parsing restarts here after previous syntax error
    3 errors detected in the compilation of “../main.c”.

    any help would be appreciated!

    • Im sorry i should have mentioned that i used mspgcc to compile it
      give me a day and i will try to make it more CCS friendly

      thanks for your interest

      • you will need to change the header files for your chip and you will have to change the WDT interrupt to #pragma vector=WDT_VECTOR
        __interrupt void watchdog_timer(void) {}

        i think thats how it goes, but not quite sure, i dont use CCS or IAR

  2. Any reason you picked the WDT interrupt instead of any of the others?

    • I chose wdt because of ease of setup, and wanted another way to use the wdt, It will also allow me to use timer a for other time sensitive activities.
      timer a is a lot more flexible and would work just as well, next time i re-evaluate the code I will probably be switching to timer a, and adding more functionality, like different patterns, color hold and possible serial interface.

  3. I believe there is a mistake in your BOM- you state that you used a common cathode, but your circuit diagram shows a common anode!