Hallo,
ich habe ein Problem mit Timer Interrupts auf einem Duemilanove (Atmega 328). Folgendes Programm:
#include <Servo.h>
#include <LiquidCrystal.h>
unsigned int tcnt2;
int int_counter = 0;
int minute = 59;
int sekunde = 60;
Servo myservo;
LiquidCrystal lcd(12, 6, 5, 4, 3, 2);
int p1 = 0;
int p2 = 0;
int p3 = 0;
int p4 = 0;
boolean kiste = false;
void setup()
{
/* First disable the timer overflow interrupt while we're configuring */
TIMSK2 &= ~(1<<TOIE2);
/* Configure timer2 in normal mode (pure counting, no PWM etc.) */
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
TCCR2B &= ~(1<<WGM22);
/* Select clock source: internal I/O clock */
ASSR &= ~(1<<AS2);
/* Disable Compare Match A interrupt enable (only want overflow) */
TIMSK2 &= ~(1<<OCIE2A);
/* Now configure the prescaler to CPU clock divided by 128 */
TCCR2B |= (1<<CS22) | (1<<CS20); // Set bits
TCCR2B &= ~(1<<CS21); // Clear bit
/* We need to calculate a proper value to load the timer counter.
* The following loads the value 131 into the Timer 2 counter register
* The math behind this is:
* (CPU frequency) / (prescaler value) = 125000 Hz = 8us.
* (desired period) / 8us = 125.
* MAX(uint8) + 1 - 125 = 131;
*/
/* Save value globally for later reload in ISR */
tcnt2 = 131;
myservo.attach(9); // attaches the servo on pin 9 to the servo object
kisteZu();
lcd.begin(16, 2);
anzeige("Hallo!", 0);
delay(2000);
anzeige("Herzlichen", 1);
delay(2000);
anzeige("Glueckwunsch!", 1);
delay(2000);
lcd.clear();
anzeige("Findet den Code", 0);
anzeige("und oeffnet die", 1);
delay(3000);
lcd.clear();
anzeige("Kiste. Ihr habt", 0);
anzeige("aber nur eine", 1);
delay(3000);
lcd.clear();
anzeige("Stunde Zeit.", 0);
anzeige("Also beeilt Euch", 1);
delay(3000);
lcd.clear();
/* Finally load end enable the timer */
TCNT2 = tcnt2;
TIMSK2 |= (1<<TOIE2);
}
void loop()
{
if (!kiste) {
p1 = lesePoti(0);
p2 = lesePoti(1);
p3 = lesePoti(2);
p4 = lesePoti(3);
lcd.setCursor(0,0);
lcd.print("Code: ");
lcd.print(p1, DEC);
lcd.print(":");
lcd.print(p2, DEC);
lcd.print(":");
lcd.print(p3, DEC);
lcd.print(":");
lcd.print(p4, DEC);
if (p1 == 1 && p2 ==2 && p3 == 3 && p4 == 4) {
kisteAuf();
}
delay(100);
} else {
anzeige("Geschafft!", 0);
delay(10000);
}
}
void kisteAuf()
{
// disable timer
TIMSK2 &= ~(1<<TOIE2);
lcd.clear();
kiste = true;
lcd.setCursor(0,1);
lcd.print("Kiste ist: auf");
myservo.write(0);
delay(2000);
}
void kisteZu()
{
lcd.setCursor(0,1);
lcd.print("Kiste ist: zu ");
myservo.write(45);
}
int lesePoti(int nr)
{
int val = analogRead(nr);
delay(10);
return map(val, 0, 1023, 0, 9);
}
void anzeige(char* s, byte zeile)
{
lcd.setCursor(0,zeile);
lcd.print(s);
}
ISR(TIMER2_OVF_vect) {
/* Reload the timer */
TCNT2 = tcnt2;
int_counter += 1;
if (int_counter == 1000) {
int_counter = 0;
sekunde--;
if (sekunde == 0) {
minute--;
sekunde = 59;
}
lcd.setCursor(0,1);
lcd.print("Zeit:");
lcd.setCursor(11,1);
if (minute < 10) {
lcd.print(0);
}
lcd.print(minute);
lcd.print(":");
if (sekunde < 10) {
lcd.print(0);
}
lcd.print(sekunde);
}
}
Ist der Timer aus läuft alles wunderbar. In der ersten Zeile auf dem LCD-Display wird der Wert von 4 Potis angezeigt, in der zweiten Zeile läuft eine Uhr rückwärts.
Ist der Interrupt aktiv läuft das Programm auch ordentlich an, aber nach ca. 10-60 Sekunden (unbestimmte Zeit) wird auf dem LCD nur noch Schrott angezeigt (komische Zeichen, blinkender Cursor usw.):
Offenbar gibt es einen Konflikt zwischen dem Timer und irgendeiner anderen Arduino-Funktion. Aber wo? Und wie kann ich das Problem lösen?
Danke für jede Hilfe, das ganze muss in 4 Tagen laufen (Geburtstagsgeschenk).