A while ago I modified a little 8-gram servo I had lying around for constant rotation and attached it to the blade pitch adjust(is thats what you call it!? 😕 ) mechanism in my blinds. I’ve been meaning to build a simple controller for it for ages, so the other night I grabbed my MSP430 launchpad and some G2001 chips I had lying around. This was the result:
The servo is powered of the 5v from the usb port which seems to run it just fine, and the servo control pin is connected to P1.0 on the device.
This little G2001 only has 0.5kb or 512 BYTES!! of memory, So I stated off with a very minimal program just to get the servo spinning in each direction at the push of a button. After I had decided it was possible to do it with the limited code-space available I set about adding an interrupt vector that fires when the button is pressed and then spends the next second or so spinning the blind in the opposite direction to the previous press.(The fact I do all the heavy lifting from within the interrupt means I dont need to worry about switch de-bounce issues 😀 ) Once the code returns to the main loop, the device goes into the lowest power mode possible using almost no energy! 😀 I managed to get the final compiled codesize down to 378 Bytes! (I was proud of myself 8) )
I may still try add some functionality to the code, perhaps switch to a bigger processor and use the capacitive touch booster pack to make the blinds adjustable. I also plan on adding a mosfet to the servo that disconnects it from the supply when the processor is sleeping for even better efficiency. 😀
Here’s the code:
/*
* main.c - Servo Blind Controller
* - Robthepyro www.rambo.co.za
* - January 2012
*
* Connect the servo control pin ot port P1.0, Servo needs to be modified for continual rotation
* pushing the button on the launchpad connected to P1.3 alternatively opens and closes the blinds
*/
#include “msp430g2001.h”
#include “stdbool.h”
#define BTN BIT3
#define ServoPin 10
// Random defines
#define HIGH 1
#define LOW 0
#define OUTPUT 1
#define INPUT 0
// Arduino-ish functions
#define mSdelay(milliseconds) for(int x=0;x #define pinMode(pin, mode) {if(mode){P1DIR|=(1< #define digitalWrite(pin, mode) {if(mode){P1OUT |= (1< #define digitalRead(pin) (P1IN & pinBit(pin) ? HIGH : LOW)
const unsigned int moveTime = 100; // defines how much time the servo spends moving
unsigned char i; // used for loops
bool f = false; // determines the open or closed state of the blinds
void open(){ //opens the blinds, ~0.5ms pulses on servo every ~10ms
for(i = 0; i < moveTime; i++){
digitalWrite(ServoPin, HIGH);
__delay_cycles (600);
digitalWrite(ServoPin, LOW);
__delay_cycles (10000);
}
}
void close(){ // closes blinds, ~2.5ms pulses on servo every ~10ms
for(i = 0; i < moveTime; i++){ digitalWrite(ServoPin, HIGH); __delay_cycles (2600); digitalWrite(ServoPin, LOW); __delay_cycles (10000); } } #pragma vector = PORT1_VECTOR // interupt for button __interrupt void P1_ISR(void) { switch(P1IFG&BTN) { case BIT3:// if button is pressed if(f) { close(); f = false; } else { open(); f = true; } P1IFG &= ~BTN; // clear the interrupt flag return; default: P1IFG = 0; // probably unnecessary, but if another flag occurs // in P1, this will clear it. No error handling is // provided this way, though. return; } } // P1_ISR void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer P1DIR |= (BIT0); // servopin output P1DIR &= ~BIT3; // switch input P1OUT |= BIT6; P1OUT &= ~BIT0; P1IES |= BIT3; // high -> low is selected with IES.x = 1.
P1IFG &= ~BIT3; // To prevent an immediate interrupt, clear the flag for
// P1.3 before enabling the interrupt.
P1IE |= BIT3; // Enable interrupts for P1.3
BCSCTL1 = CALBC1_1MHZ; // Set range
DCOCTL = CALDCO_1MHZ;
_BIS_SR(LPM4_bits + GIE);// enable interupts and go into lowest power mode
while(1)
{
// do nothing. cpu shut down
}
}
Leave a Reply