Skip to content

Instantly share code, notes, and snippets.

@Lukelectro
Created November 6, 2021 21:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Lukelectro/c6a49b52870fc314b36e4cb70d53a205 to your computer and use it in GitHub Desktop.
Save Lukelectro/c6a49b52870fc314b36e4cb70d53a205 to your computer and use it in GitHub Desktop.
Solar lamp msp430
#include <msp430.h>
#include <stdbool.h>
/**
* slim solarlampje.
* Doel:
* aan net voor zonsopgang tot zonsopgang,
* aan na zonsondergang, maar beperkte tijd (niet hele nacht)
* dus de "vorige" zonsondergang/opgang onthouden.
*
* tellertje van langer dan 24 uur, en steeds resetten bij zonsopgang
* dan dus bij zonsondergang aan en teller opslaan, bij donkerteller+ietsvan2uur weer uit
* Als het licht is uit en tellerwaarde opslaan en daarna teller resetten naar 0
* Dan bij lichtteller-ietsvan2uur aan. En bij licht weer uit ^
*
* zonnepaneel om te bepalen of het donker is. Met hysterese van I/O pin en spanningsdeler.
* (Als dat niet werkt, kan het nog met de ADC)
*
*/
/* 1 tick = approximately 1,3 -ish seconds. */
#define BEFORESUNRISE 6000 /* ticks before sunrise that LED should turn on. */
/* - previous sunrise is used for this and it waits untill actual sunrise, so it might be on longer */
#define AFTERSUNDOWN 6000 /* Ticks that LED should stay ON after sundown (unless sunrise happens first)*/
#define SUNSTATETICKS 15 /* ticks that sun needs to be up/down cumulative before changing state*/
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
P1DIR = 0x41; // configure P1.0 and P1.6 as output
// only use pull-up when testing with switch, not with actual solar panel
//P1REN = (1<<3); // enable resistor on P1.3 (switch)
//P1OUT |= (1<<3); // pull-up switch
P2DIR = 0xFF;
P2OUT = 0x00;
/* set up timer A for compare interrupt each 1.01s (but clock is variable, so approx 1 s)*/
TACCR0 = 190; // Compare value. 12kHz/8/8/190 ~ 1 Hz
TACCTL0 = CCIE; // enable compare interrupt
TACTL = TASSEL_1 | ID_3 | MC_1; // ACLK /8, count up to TACCR0
unsigned long tick, sunup_anticipate=12,sundown_timer=52; /* with tick at 1s and starting from sunup, */
unsigned int sunstate=SUNSTATETICKS;
bool onceatsunrise=true, onceatsundown=true, IsSunUp=true;
/* switch clock from default 1.1M DCO tot 12 kHz VLOVLK (for low power)
* and divide by 8 (max division) to slow loop down (and even lower power)
*
* So MCU and pheripherals run at 12/8=1.5 kHz
* */
BCSCTL1 = XT2OFF | DIVA_3;
BCSCTL2 = SELM_3 | DIVM_3 | DIVS_3 | SELS; /* VLOCLK/8 for MCLK and SMCLK */
BCSCTL3 = LFXT1S_2; /* VLOCLK (XTS==0)*/
while(1)
{
//P1OUT ^= (1<<0); /* toggle P1.0 for debug*/
P1OUT = P1OUT&0xFE | IsSunUp; /* P1.0 shows if sun is up or down, for debug */
tick++;
if(IsSunUp && onceatsunrise){
sunup_anticipate = tick - BEFORESUNRISE;
P1OUT &= ~(1<<6); // uit bij zonsopgang
tick = 0; /* sync timer to sun */
onceatsunrise = false; /* do not keep resetting */
onceatsundown = true; /* prime for sundown */
}
if(!IsSunUp && onceatsundown){
sundown_timer = tick + AFTERSUNDOWN;
P1OUT |= (1<<6); /* LED on after sundown */
onceatsundown = false; /* do not keep setting timer / resetting timer */
onceatsunrise = true; /* prime for sunrise */
}
if((onceatsundown==false) && (onceatsunrise==false)){ /* if ever a cosmic ray or EMC or anything causes both to be false, set both true*/
onceatsunrise = true;
onceatsundown = true;
}
if(tick==sundown_timer){
P1OUT &= ~(1<<6); // off
}
if((tick==sunup_anticipate)&&(IsSunUp==false)){
P1OUT |= (1<<6); // on
}
/* determine if sun is up or down (and filter out clouds etc by needing TBD ticks (30? 60?) of accumulated light or dark). */
if( (P1IN & 1<<3)==0)
{ /* for now, use I/O with its pin hysteresis as a comparator. If needed, ADC could be used instead, but rather not */
if(sunstate>0) sunstate--;
}
else
{
if(sunstate<SUNSTATETICKS) sunstate++;
}
if(sunstate>=SUNSTATETICKS-1) IsSunUp = true; else if(sunstate<2) IsSunUp = false;
__bis_SR_register(LPM3_bits + GIE); // Enter LPM3 (Untill timer interrupt, so: sleep for approximately 1 s. This makes each tick about 1,3 s.)
/*TODO: disable this sleep-mode by commenting above line for faster testing.*/
}
}
#pragma vector=TIMERA0_VECTOR
__interrupt void timera (void)
{
__bic_SR_register_on_exit(LPM3_bits); // Clear LPM3 bits from 0(SR)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment