Created
November 6, 2021 21:07
-
-
Save Lukelectro/c6a49b52870fc314b36e4cb70d53a205 to your computer and use it in GitHub Desktop.
Solar lamp msp430
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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