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