ADC und Timer am Uno Board

Hallo,
ich hab ein Arduino Uno Rev1 und ein LCD Shield - DFRobot (DFR0009)
Übe die tasten am Analog Eingang möchte ich einen Timer (Countdown) einstellen.
Jetzt hab ich erst mal zwei Scripte zusammengewürfelt.
Einmal die Tastenabfrage am ADC und einmal die Timerfunktion mit dem Timer2
der mir jede Sekunde die Uhr um einen herunter zählt.
Jedes Script funktioniert nur wenn ich beide zusammen lege,
bleibt die Uhr nach 3 Sec stehen nach einer ganzen weile
wird dann eine neue Uhrzeit angezeigt.
Ich vermute mal das sich der Interupt für den Timer mit
dem ADC harkt. Hier mal das gesamte Script.

#include <LiquidCrystal.h>

unsigned int tcnt2;
int int_counter = 0;

int minute = 59;
int sekunde = 60;

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


//Key message
char msgs[5][15] = {"Right Key OK ", 
                    "Up Key OK    ", 
                    "Down Key OK  ", 
                    "Left Key OK  ", 
                    "Select Key OK" };
                    
char hmenue[2][15] = {"Setup       ", 
                    "Start        "};
                   
                    
int  adc_key_val[5] ={30, 150, 360, 535, 760 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;
int selMenue=0; //menue Start position
int selMenueMax=1; //menue Start position
int selMenueMin=0; //menue Start position
int Minute=2;
int Secunden=30;

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;    
 lcd.begin(16, 2);
  anzeige("Hallo!", 0);
  delay(2000);
  lcd.clear();
  TCNT2 = tcnt2;  
  TIMSK2 |= (1<<TOIE2);  
}

void loop()
{
  adc_key_in = analogRead(0);    // read the value from the sensor
   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);
   } 
   key = get_key(adc_key_in);		        // convert into key press
   if (key== -1){
   lcd.setCursor(0,0);
   lcd.print(key);
   }
   else{
   lcd.setCursor(0,0);
   lcd.print(" ");
   lcd.print(key);
   }
}

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;

 
}

// Convert ADC value to key number
int get_key(unsigned int input){
  int k;
  for (k = 0; k < NUM_KEYS; k++){
    if (input < adc_key_val[k]){
      return k;
    }
  }
  if (k >= NUM_KEYS){
    k = -1;     // No valid key pressed
    return k;
  }
}

Ich hoffe Ihr habt einen Tipp für mich

Gruß Ingo

Wieso benutzt Du einen Timer und nicht millis()?
grüße Uwe

Danke für den Denkanstoß,

ich dachte millis() ist eine abwndlung von Delay, also das Programm bleibt in der zeit stehen.
Werde es mir glich noch mal genauer anschauen.
Gruß Ingo

Es gibt einen schönes Beispiel BlinkWithoutDelay, da wird mit millis gearbeitet, eben um die Unterbrechung durch ein delay zu vermeiden. Von daher ist dies die einfachere Variante, zumindest einfacher als die Verwendung eines Timers.

Scotch:
Danke für den Denkanstoß,

ich dachte millis() ist eine abwndlung von Delay, also das Programm bleibt in der zeit stehen.
Werde es mir glich noch mal genauer anschauen.
Gruß Ingo

millis()ist eine Funktion die Dir die Anzahl der vergangenen Millisekunden ab einschalten zurückgibt. Die Funktion läuft im Hintergrund Timergesteuert. Nach 49 und etwas Tagen gibt es einen Überlauf der aber bei richtiger Kontrollbedingung keinen Fehler in der Zeitdifferenz gibt. Die Wartezeit darf nur nicht über diese 49 Tage dauern.
Grüße Uwe

So hab den Code mal auf millis() umgeschrieben und klapt hervorragend :slight_smile:

Anbei der geänderte Code.
Mal schauen wie ich das mit den Stellen mache.

#include <LiquidCrystal.h>
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

unsigned long currentTime;
unsigned long loopTime;

// read the buttons
int read_LCD_buttons()
{
 adc_key_in = analogRead(0);      // read the value from the sensor
 // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
 // we add approx 50 to those values and check to see if we are close
 if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
 if (adc_key_in < 50)   return btnRIGHT; 
 if (adc_key_in < 195)  return btnUP;
 if (adc_key_in < 380)  return btnDOWN;
 if (adc_key_in < 555)  return btnLEFT;
 if (adc_key_in < 790)  return btnSELECT;  
 return btnNONE;  // when all others fail, return this...
}

int int_counter = 0;
int minute = 59;
int sekunde = 60;

void setup() 
{ 
  currentTime = millis();
  loopTime = currentTime;   
  lcd.begin(16, 2);
  anzeige("Hallo!", 0);
  delay(2000);
  lcd.clear(); 
} 

void loop()
{
  //Taster auslesen und ausgeben
  taste();
  //
  currentTime = millis();
  if(currentTime >= (loopTime + 1000)){  
    loopTime = currentTime;  // Updates loopTime
    uhr();
  }
}

//Eingestelte Zeiht runterzählen und ausgeben
void uhr()
{
  int_counter = 0;
  sekunde--;
  //Wenn Sec 0 dann Min -1, Sec wieder auf 59
  if (sekunde == 0) 
  {
    minute--;
    sekunde = 59;
  }
  
  lcd.setCursor(0,1);
  lcd.print("Zeit:");
  lcd.setCursor(11,1);
  
  //wenn Minuten einstellig dann einen 0 vorweg ausgeben
  if (minute < 10) 
  {
    lcd.print(0);
  }
  
  lcd.print(minute);
  lcd.print(":");
  
  //wenn Secunde einstellig dann eine 0 vorweg ausgeben
  if (sekunde < 10) 
  {
    lcd.print(0);
  }
  
  lcd.print(sekunde);
}    

//hier werden die Tasten am Analogport ausgelesen und an hand des 
//gemessenden Wertes am ADC0 einem Namen zugewisen und am LCD angezeigt 
 void taste(){
   lcd_key = read_LCD_buttons();  // read the buttons
   lcd.setCursor(0,0);
   switch (lcd_key)               // depending on which button was pushed, we perform an action
   {
     case btnRIGHT:
     {
       lcd.print("RIGHT ");
       break;
     }
     case btnLEFT:
     {
       lcd.print("LEFT   ");
       break;
     }
     case btnUP:
     {
       lcd.print("UP    ");
       break;
     }
     case btnDOWN:
     {
       lcd.print("DOWN  ");
       break;
     }
     case btnSELECT:
     {
       lcd.print("SELECT");
       break;
     }
       case btnNONE:
     {
       lcd.print("NONE  ");
       break;
     }
   }
 }
 

void anzeige(char* s, byte zeile) 
{
  lcd.setCursor(0,zeile);
  lcd.print(s);
}