MIDI Piano Lighting (8 / 11 steg)
Steg 8: Programvara: Timers och avbryter
Jag vet inte vilka bilder att lägga upp för att förklara programvaran, så självklart, förmodligen bättre att bara posta en bild med en katt. Dessutom finns full arduino koden att ladda ner ovan. (lbdOrganPWM.ino)
Timers och avbryter
Använda hårdvaran PWM i sekvens med ac linjen utlöser, allt vi behöver göra är att se till den räknare som används för att mata PWM värdet återställs i noll-korsningen av AC nätspänningen. Med den utlösande kretsen förklarade i steg 7, lägger vi ett maskinvaruavbrott att detta stift att nollställa räknarna när det utlöser.
Varje tidtagare är starta i början av programmet till vågform generation-läge för snabb PWM mode med ICRn som högsta värde. Denna timer-läge är det som gör med hjälp av hårdvara PWM möjligt.
Eftersom vi har 7-bitars upplösning i hastigheten av MIDI-Obs, vill vi komma ganska nära denna resolution för glödlampa intensiteten. Ärligt talat, allt ovan 16 steg är ganska försumbar, men eftersom vi kan vi kanske också. Så om vi prescaler av timers 1024 (sida 161 i Atmega2560 datablad), sedan har vi 16 Mhz / 1024 för våra timer clock = 15625 Hz. Våra mål för vår totala PWM vågform är 120Hz, motsvara halva cykeln av nätspänningen 60Hz. Så, vi dela upp 15626/120 för att få ~ 130. Det innebär att om vi sätter våra ICRn register to130, vi kommer att få en frekvens på linje frekvensen med ~ 130 steg. Det är perfekt eftersom vi har 128 steg i MIDI-hastigheten!
Efter att ha provat ut det här, det finns viss variation i linje frekvens och så jag slutade med ett högsta värde (ICRn) av 122. Detta kändes som en säker tillräckligt värde där jag skulle se till att jag skulle stänga av triac på noll-korset. Om du går för långt förbi noll-cross tröskeln, du missa det och ljuset aldrig släcks eller tonas ned.
Sista, om Timer config är PWM polariteten. Eftersom när timern får sin slutpunkt vi vill se till att triac inaktiverar (detta betyder att vi är nära noll-korset), vi måste använda inverterad funktionsläget av PWM stift, så att när timern = 0, PIN-koden är låg. Det betyder bara när vi får en hastighet värdet 100, vi verkligen vill ange PWM registret till 127-100 = 27.
För hantering av noll-korset, har arduino biblioteket en inbyggd funktion för detta med hjälp av maskinvaruavbrott:
attachInterrupt(5,zeroCrossDetect,FALLING);
Om 5 avbrottsnummer (pin 18 på Mega), fallande anger det utlöses endast på fallande kanten (1 -> 0, inte 0 -> 1) av avbryta pin, och zeroCrossDetect är funktionen nedan.
Det fungerar genom att ange alla räknare som används av specifika PWM stift har jag valt till noll på noll korset. Det sätter också upp prescaler och vågform generationen läget för varje timer, anledningen till detta är så att timern startar på AC-cycle i början av programmet, se till att det finns ingen förskjutning från början.
void zeroCrossDetect() {
TCNT1 = 0;
TCNT3 = 0;
TCNT4 = 0;
TCNT5 = 0;
TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS10) | (1 << CS12);
TCCR3B = (1 << WGM32) | (1 << WGM33) | (1 << CS30) | (1 << CS32);
TCCR4B = (1 << WGM42) | (1 << WGM43) | (1 << CS40) | (1 << CS42);
TCCR5B = (1 << WGM52) | (1 << WGM53) | (1 << CS50) | (1 << CS52);
}