Blå LED gryningssimulatorn för Soleil Sun Alarm (9 / 11 steg)
Steg 9: Programmet mikrokontroller
Koden och makefile skrivs att arbeta med avr-gcc. Kortfattat, det beräknar intermittensen från klockan beräknar önskad LED kontrollnivå och spottar ut en PWM-signal. Det finns vissa genomsnitt av inkommande och utgående värden att minska oönskade blinkande lysdiod (som när de just har börjat en soluppgång). I huvudsak fungerar mikrokontroller som en icke-linjär PWM filter.Kod: (ladda ner filen .c snarare än att klippa och klistra in denna text, det finns vissa formateringsproblem med syntax)
/ * LED microcontroller dimmer för användning med Soleil Sun AlarmWritten för Atmel ATMega8 och avr-gccEric J. WilhelmSquid Labs, LLCAttribution-NonCommercial-ShareAlike 2.5You är gratis: * för att kopiera, distribuera, Visa och framföra verket * att göra härledda worksUnder följande villkor: av erkännande. Du måste tillskriva arbetet på det sätt som anges av upphovsmannen eller licensgivaren. Ickekommersiell. Du får inte använda detta arbete för kommersiella ändamål. Dela lika. Om du ändra, förändra eller bygga vidare på detta arbete, får du distribuera det resulterande arbetet endast under en licens som är identisk med denna. * För återanvändning eller distribution, måste du göra klart för andra licensvillkoren för detta arbete. * Något av dessa villkor kan göras om du få tillstånd från copyright holder.* / #include < inttypes.h > < avr/io.h > < avr/interrupt.h > < avr/signal.h > < math.h > #include #include #include #include # define OC1 PB1 # define DDROC DDRB # define OCR OCR1Avolatile uint16_t xtimer; flyktiga uint16_t timer0; flyktiga uint8_t status; SIGNAL(SIG_OVERFLOW0) {timer0 ++; TCNT0 = 96. förspänning timern med 96 för att göra detta avbrott inträffar varje 20 US.} SIGNAL(SIG_OVERFLOW1) {//The avbryter inte fungera utan denna definition.} fallande kant PWM-signal (stigande kanten på klockan, vänt på grund av optoisolator)SIGNAL(SIG_INTERRUPT1) {/ / noll timer0 räkna längden på positiv puls timer0 = 0; status = 1;} stigande kanten PWM-signal (falling edge på klockan, vänt på grund av optoisolator)SIGNAL(SIG_INTERRUPT0) {//record längden på positiva pwm signalen i xtimer / / om timer0 är större än ca 263 (på 20 US per avbrott) än pulsen var missade if(timer0<270) xtimer = timer0; status = 0;} voidioinit (void) {/ / Timer1 gör ~ 16-bitars PWM TCCR1A = _BV (COM1B1) | _BV (WGM11) | _BV (COM1A1); TCCR1B = _BV (WGM13) | _BV (WGM12) | _BV (CS10); ICR1 = 65535; Timer0 räknar TCCR0 = _BV (CS00); TCNT0 = 96. timer0 = 0; som PWM värde till 0 OCR = 0; aktiverar OC1 som utgång DDROC = _BV (OC1); Aktivera extern avbryter GICR = _BV (INT1) | _BV (INT0); INT0 ökar kant, INT1 är fallande kant MCUCR = _BV (ISC01) | _BV (ISC00) | _BV(ISC11); xtimer = 0; status = 0; aktiverar timers timer_enable_int (_BV (TOIE1) | _BV (TOIE0)); Aktivera avbrott (sei);} intmain (void) {#define B-0.00325 #define C-11.09 #define D 0.396503 int i, å = 0, oncounter = 0; unsigned int x(100), y, långa t(100), u, ioinit (); för (;) {//average xtimer över prover eftersom det hoppar runt en hel del för (jag = 99; jag > 0; i--) {x(i) = x(i-1);} x(0) = xtimer, y = 0; för (jag = 0; jag < 100; i ++) {y = y+x(i);} y = y/100; //divide av 5 eftersom klockan har 120 amerikanska upplösning på dess PWM y = y/5; / / genomsnittlig utdata så att det inte hoppa runt för (jag = 99; jag > 0; i--) {t(i) = t(i-1);} //determine vad du gör om (timer0 > 270 & & status == 1 & & å == 1) {//Turn ljus på t(0) = 0; i = 1;} else om (timer0 > 270 & & status == 0) {//Turn ljus av t(0) = 65535; xtimer = 0; i = 0; oncounter = 0;} annat if(timer0<270) {t(0) = 65535 * (1-exp ((B * y + D) * y + C)); if(t(0) > 65535) t(0) = 65535; if(t(0) < 0) t(0) = 0;} //oncounter hindrar ljus från att vrida på plötsligt från en av staten om timer0 > 270, men det finns en positiv puls på PWM //this händer under början av en soluppgång, när klockan är PWM inte har helt aktiverad på rätt frekvens annat om (timer0 > 270 & & status == 1) {if(++oncounter==5) {on = 1; oncounter = 0;}} / / genomsnittlig utdata så att det inte hoppa runt u = 0; för (jag = 0; jag < 100; i ++) {u=u+t(i);} //Change utgång PWM OCR = u/100; {} återvända (0);}