Einfacher LCD Countdown Timer mit Schaltausgang

Hallo Forum!

ich habe längere Zeit damit zugebracht im Internet einen schönen Countdown Timer für ein LCD zu finden, da ich mein Belichtungsgerät nicht immer mit der Stoppuhr vom Handy bedienen wollte.

Gefunden hab ich nichts, deswegen hab ich ihn mir selbst geschrieben. Und ich denke es könnte dem einen oder anderen mal behilflich sein.

Momentan kann der Code folgendes:

  • 2 Zeiliges LC-Display mit 16 Zeichen ansteuern
  • Eingabe der Zeit erfolgt über Variablen änderung im Code
  • 1 Zeile : Beliebige beschriftung + Anzeige der voreingestellten Countdownsekunden in Minuten und Sekunden
    1. Zeile : Anzeige der aktuell ablaufenden Countdownzeit.
  • Resetbutton ( ohne Tasten entprellung ) an Pin 7 (überprüfung auf HIGH)

eingebunden ist lediglich die LiquidCrystal Library (keine Timer.h oder ähnliches)

Vorraussichtliche Verbesserungen:

  • Eingabe der Zeit über Potentiometer und AnalogIN
  • Pause Button
  • Ansteuern eines Mosfet bei 00:00 (zur Ansteuerung der UV-Röhre)
#include <LiquidCrystal.h>

//----LCD-PINS---(rs, en,d4,d5,d6,d7)----------------------// 
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 

/***************Countdownzeit HIER eintragen****************/


int const inputtime = 180;               // in Sekunden     


//------------------------ Taster -------------------------//

int buttonstate;
int const buttonPin = 7;                 // Resetbutton Pin Deklarierung

//----------------Variablen für Countdown------------------//

int long countdowntime;                  // Countdown Variable bzw. Resetwert
int val;                                 // Variable für aktuellen Zustand 
int lastval;                             // Variable für den vorherigen Zustand
int long minutes;                        // Countdown in Minuten
int long seconds;                        // Countdown in Sekunden
volatile unsigned char tick;             // Variable für den Timer


//--------------- Timer Überlauf auslesen ------------------//

ISR (TIMER2_OVF_vect)                    // Wenn Timer 1 Überläuft gib ein High über
{	                 
  -tick;	                         // tick aus.		    
}

void setup() {
  countdowntime = inputtime;
  int showminutes = inputtime/60;        // erstelle Variable für die anzuzeigenden Minuten
  int showseconds = inputtime%60;        // erstelle Variable für die anzuzeigenden Sekunden
  lcd.begin(16, 2);
  lcd.setCursor(0,0);
  lcd.print("Countdown: ");              // Beschriftung der ersten Zeile
  lcd.print(showminutes);                // Zeit wird automatisch eingetragen
  lcd.print(":");
  lcd.print(showseconds);
}

void loop()
{ 
  val = digitalRead(tick);               // Overflow des Timers auslesen

  buttonstate = digitalRead(buttonPin);  // auslesen des Digitalwertes an Pin 7
  
  if (buttonstate == HIGH)               // überprüfung auf Reset
  {
    countdowntime = inputtime;           // Resetbefehl
  }
  if (countdowntime>0)
  {
     if (val!= lastval)                  // wenn aktueller Zustand sich von Vorherigem unterscheidet dann 
      {             
        countdowntime--;                 // inkrementiere die Variable "countdowntime"
      }  
      minutes = countdowntime/60;        // Aufteilung der "countdowntime" in Minuten
      seconds = countdowntime%60;        // und Sekunden 
      lcd.setCursor(0,1);                // LCD ausgabe in Zeile 2 Zeichen 1
      if (minutes<10)
      {
        lcd.print('0');
      }
      lcd.print(minutes);                // gebe Minuten am LCD aus
      lcd.print(":");
      if (seconds<10)                    // wenn die Sekunden unter 10 kommen
      {
        lcd.print("0");                  // schreibe erst Null und dann
        lcd.print(seconds);              // die Sekunden
        lcd.write(' ');                  // entfernen der Null 
      }
      else                               // ansonsten
      {
        lcd.print(seconds);              // schreibe die Sekunden normal
      }
      delay(1000);
      val = lastval;                     // Den aktuellen Zustand merken   
  }
  else
  {
    lcd.setCursor(0,1);          
    lcd.print("00:00");                  // Null anzeigen
    buttonstate = digitalRead(buttonPin);// Überprüfung des Digitalwertes an Pin 7

    if (buttonstate == HIGH)             // Überprüfung auf Reset Befehl
    {
      countdowntime = inputtime;         // Reset ausführen
    }
  }
}

LG M²

Du kannst es auch mit dem Countdown-Timer des Handys machen, dann brauchst Du nicht dauernd draufschauen.
Ich bin ein Fan von Scrollrädern. Darum würde ich Dir solche für die Zeiteingabe vorschlagen. Du kannst das Programm ja so schreiben, daß bei langsamer Betätigung der Wert in 1-er Schritten incrementiert wird, bei schneller Betätigung in Zehnerschritten.
Viele Grüße Uwe

Sinn und Zweck von dem Countdown ist ja eigendlich das man die Platine in das Belichtungsgerät legt.
und Die UV lampe genau dann angeht wenn man den Knopf drückt und nach der vorgegebenen Zeit wieder ausgeht.

Ich will nicht nach 3 minuten sofort zu dem Teil rennen müssen wenn man gerade nebenher noch mit ner anderen Platine beschäftigt ist(was durchaus vorkommt) nur damit man das Belichten nicht verhunzt.(wenn zu lange belichtet funktionierts nicht. zu kurz reicht nicht aus)

LG M²

Fertig!

hier der Code, Schaltplan und Layout.

/*****************************Intro************************************
///Countdowntimer version 1.0
   
   Ein einfacher Timer der mit einem LC-Display, einem 100k Potentiometer,
   einem einfachen Taster als Eingang und einem schaltenden Ausgang 
   ausgestattet ist.
   
   In dieser Konfiguration lässt sich die Zeit über den Poti an A0(PC0,Pin 23) 
   von 00:00 min bis ca. 17:05 min einstellen.
   Die Konfiguration lässt sich in "void_readAin" umstellen.
   
   Ein (nicht entprellter) Highaktiver Taster an 8(PB0,Pin 14) dient als Eingang.
   Drücken = A/D Wert des Potis übernehmen und in den Timer schreiben 
     -> negative Flanke : Timer starten/Ausgang 13(PB5,Pin 19)High setzen
   Drücken und Halten = A/D Wert einstellen
   nach ablauf des Timers = Ausgang 13(PB5,Pin 19) Low setzen
 
   Verdrahtung:
   
   Poti 100k (10Gang) = Schleifer=> A0/Pin 23; Anfang/Ende=>5V/GND
   Taster mit 10K Pulldown Widerstand => 8/Pin 14
   Ausgang => 13/Pin 19
   LCD => siehe Unten 

**********************************************************************/

#include <LiquidCrystal.h>

//----LCD-PINS---(rs, en,d4,d5,d6,d7)----------------------// 
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); 

//-------------------- Taster/Ausgänge --------------------//

int varpin = A0;
int buttonstate;
int const buttonPin = 8;                 // Resetbutton Pin Deklarierung
int uvout = 13;                          // Ausgang für UV-Licht

//----------------Variablen für Countdown------------------//

int long countdowntime;                  // Countdown Variable bzw. Resetwert
int val;                                 // Variable für aktuellen Zustand 
int lastval;                             // Variable für den vorherigen Zustand
int long minutes;                        // Countdown in Minuten
int long seconds;                        // Countdown in Sekunden
volatile unsigned char tick;             // Variable für den Timer
int inputtime ;                          // Variable für analogeingang     


//--------------- Timer Überlauf auslesen ------------------//

ISR (TIMER2_OVF_vect)                    // Wenn Timer 1 Überläuft gib ein High über
{	                 
  ++tick;	                         // tick aus.		    
}

void setup() {
  inputtime = analogRead(varpin);        // analogwert einlesen  
  countdowntime = 0;                     // Starte bei 00:00
  lcd.begin(16, 2);                      // initialisiere Display
  lcd.setCursor(0,0);                    // setze Cursor für 1. Zeile
  lcd.print("Time:");                    // Beschriftung der ersten Zeile
  readAin ();                            // Analogwert eintragen 
}


void loop()
{
  buttonstate = digitalRead(buttonPin);    // auslesen des Digitalwertes an Pin 7
  val = digitalRead(tick);                 // Overflow des Timers auslesen
  
if (buttonstate != HIGH)                 
{
  lcd.setCursor(0, 0);                     // erste Zeile
  lcd.print("Time:");                      // Schreibe "Time:" 
  
  if (countdowntime<=0);                   // wenn 'countdowntime 0 
  {                                        //
    digitalWrite(uvout, LOW);              // schalte UV-Licht aus 
  }                                        //
 
  if (countdowntime>0)
  {       
    if (val != lastval)                   // wenn sich 'val' von 'lastval' unterscheidet
    {                                     //
      countdowntime--;                    // inkrementiere 'countdowntime'
      digitalWrite(uvout, HIGH);          // schalte UV-Licht ein
    }                                     //
     
    lcd.setCursor(0,1);                   // Setze Cursor für Countdown
    printTime();                          // gebe Zeit aus  
        

    val = lastval;                        // aktuellen Zustand merken   
    delay(1000);                           // 1 sekunde Pause
  }
}

else
{  
  lcd.setCursor(0,0);          
  lcd.print("SET : ");                     // "Time:" zu "Set :" ändern

  lcd.setCursor(5, 0);                     // Cursor hinter "Set :" setzen
  readAin();                               // Schreibe Set-Time
  
  countdowntime = inputtime;               // reset
    
}
}



void printTime ()
{
  minutes = countdowntime/60;           // Aufteilung von 'countdowntime' in Minuten
  seconds = countdowntime%60;           // und Sekunden 
        
  if (minutes<10)                       // wenn minuten unter 10
  {                                     //   
    lcd.print('0');                     // schreibe "0" vor minuten
  }                                     //
         
  lcd.print(minutes);                   // gebe Minuten aus
  lcd.print(":");                       // schreibe ":"
      
  if (seconds<10)                       // wenn Sekunden unter 10 
  {                                     //  
    lcd.print("0");                     // schreibe erst Null und dann
    lcd.print(seconds);                 // die Sekunden
    lcd.write(' ');                     // entferne Werte nach sekunden 
  }                                     //
  else                                  //
  {                                     //
    lcd.print(seconds);                 // schreibe die Sekunden normal
    lcd.print(" ");                     //
  }                                     // 
  
}

void readAin ()
{
inputtime = analogRead(varpin);           // Analogwert in 'inputtime' schreiben 
int showminutes = inputtime /60;          // inputtime/60 = showminutes = Minuten ausrechnen
int showseconds = inputtime %60;          // inputtime%60 = showseconds = Sekunden ausrechnen

 if (showminutes<10)                      // wenn 'showminutes' unter 10
 {                                        //
   lcd.print('0');                        // schreibe erst "0" 
 }                                        //
 
lcd.print(showminutes);                   // schreibe 'showminutes'
   
lcd.print(":");                           // schreibe ":"
    
if (showseconds<10)                       // wenn 'showseconds' unter 10
 {
   lcd.print("0");                        // schreibe erst Null
   lcd.print(showseconds);                // dann die Sekunden
   lcd.write(' ');                        // entferne letzte Ziffer 
 }
 else                                     // wenn nicht
 {                                        //
   lcd.print(showseconds);                // schreibe die Sekunden normal
   lcd.print(" ");                        // und lösche die Ziffer dahinter
 }
 delay(150);                              // Verlangsame den kompletten vorgang
 
}

LCD-Countdown Timer Bestückungsplan.pdf (80.6 KB)

LCD-Countdown Timer Layout.pdf (54 KB)

LCD-Countdown Timer Schaltplan.pdf (16.4 KB)

Kompletter Code.txt (6.6 KB)

squaremeter hat sich nächtig Mühe gegeben !

Vor allem ist es mächtig durch_dokumentiert ! Und das verdient Applaus !

danke vielmals

vielleicht mach ich auch noch ein Tutorial draus mit ein paar Bildern o.ä.

Vielleicht machst du aus deinem Count-Down-Timer auch einen mit 7-Segment-LEDs.

Hallo squaremeter,

Tolles Project!
Bin auch gerade an einem UV-Belichter für das Maskien meiner PCB's dran
und auf der suche nach einem LCD count-down timer.
Da meine Codier Kenntnisse noch nicht ausreichen werde ich mal deinen Code (ausprobieren=auseinander nehmen), danke fürs posten, dein sehr gut dokumentierter Code wird mir sicherlich weiter helfen.
Die Lösung mit dem Poti finde ich persönlich nicht so gut, ich werde probieren den durch zwei Taster zu Ersätzen.
Schicker wäre aber ein Incremental geber, mal schauen was machbar ist.

Danke nochmals, tolle Sache!

Feine Sache wenn's funktioniert - Glückwunsch!

Ich halte die 3000 µF nach dem Gleichrichter aber für völlig übertrieben - hast Du dafür einen Grund oder sollen die Netzausfälle kurzfristig auffangen?

Hallo squaremeter,

das Projekt hat mir sehr gut gefallen und ich habe es nachgebaut.
Auch ich suchte schon lange einen Timer mit Sekunden und Schaltausgang für meine Platinen.

Nun habe ich aber ein Problem.
Die Zeit wir im Display angezeigt und ich kann auch die Dauer verändern.
Aber ich weiß nicht wie ich den Timer starten soll.
Das mit der negativen Flanke habe ich nicht verstanden.
Ich würde mich freuen wenn ich eine Nachricht bekomme was ich falsch mache
bzw was ich machen muß damit der Timer startet.

squaremeter:
Fertig!

hier der Code, Schaltplan und Layout.

/*****************************Intro************************************

///Countdowntimer version 1.0
 
  Ein einfacher Timer der mit einem LC-Display, einem 100k Potentiometer,
  einem einfachen Taster als Eingang und einem schaltenden Ausgang
  ausgestattet ist.
 
  In dieser Konfiguration lässt sich die Zeit über den Poti an A0(PC0,Pin 23)
  von 00:00 min bis ca. 17:05 min einstellen.
  Die Konfiguration lässt sich in "void_readAin" umstellen.
 
  Ein (nicht entprellter) Highaktiver Taster an 8(PB0,Pin 14) dient als Eingang.
  Drücken = A/D Wert des Potis übernehmen und in den Timer schreiben
    -> negative Flanke : Timer starten/Ausgang 13(PB5,Pin 19)High setzen
  Drücken und Halten = A/D Wert einstellen
  nach ablauf des Timers = Ausgang 13(PB5,Pin 19) Low setzen

Verdrahtung:
 
  Poti 100k (10Gang) = Schleifer=> A0/Pin 23; Anfang/Ende=>5V/GND
  Taster mit 10K Pulldown Widerstand => 8/Pin 14
  Ausgang => 13/Pin 19
  LCD => siehe Unten

**********************************************************************/

#include <LiquidCrystal.h>

//----LCD-PINS---(rs, en,d4,d5,d6,d7)----------------------//
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

//-------------------- Taster/Ausgänge --------------------//

int varpin = A0;
int buttonstate;
int const buttonPin = 8;                 // Resetbutton Pin Deklarierung
int uvout = 13;                          // Ausgang für UV-Licht

//----------------Variablen für Countdown------------------//

int long countdowntime;                  // Countdown Variable bzw. Resetwert
int val;                                 // Variable für aktuellen Zustand
int lastval;                             // Variable für den vorherigen Zustand
int long minutes;                        // Countdown in Minuten
int long seconds;                        // Countdown in Sekunden
volatile unsigned char tick;             // Variable für den Timer
int inputtime ;                          // Variable für analogeingang

//--------------- Timer Überlauf auslesen ------------------//

ISR (TIMER2_OVF_vect)                    // Wenn Timer 1 Überläuft gib ein High über
{                
 ++tick;                         // tick aus.    
}

void setup() {
 inputtime = analogRead(varpin);        // analogwert einlesen  
 countdowntime = 0;                     // Starte bei 00:00
 lcd.begin(16, 2);                      // initialisiere Display
 lcd.setCursor(0,0);                    // setze Cursor für 1. Zeile
 lcd.print("Time:");                    // Beschriftung der ersten Zeile
 readAin ();                            // Analogwert eintragen
}

void loop()
{
 buttonstate = digitalRead(buttonPin);    // auslesen des Digitalwertes an Pin 7
 val = digitalRead(tick);                 // Overflow des Timers auslesen
 
if (buttonstate != HIGH)                
{
 lcd.setCursor(0, 0);                     // erste Zeile
 lcd.print("Time:");                      // Schreibe "Time:"
 
 if (countdowntime<=0);                   // wenn 'countdowntime 0
 {                                        //
   digitalWrite(uvout, LOW);              // schalte UV-Licht aus
 }                                        //

if (countdowntime>0)
 {      
   if (val != lastval)                   // wenn sich 'val' von 'lastval' unterscheidet
   {                                     //
     countdowntime--;                    // inkrementiere 'countdowntime'
     digitalWrite(uvout, HIGH);          // schalte UV-Licht ein
   }                                     //
   
   lcd.setCursor(0,1);                   // Setze Cursor für Countdown
   printTime();                          // gebe Zeit aus

val = lastval;                        // aktuellen Zustand merken  
   delay(1000);                           // 1 sekunde Pause
 }
}

else
{  
 lcd.setCursor(0,0);          
 lcd.print("SET : ");                     // "Time:" zu "Set :" ändern

lcd.setCursor(5, 0);                     // Cursor hinter "Set :" setzen
 readAin();                               // Schreibe Set-Time
 
 countdowntime = inputtime;               // reset
   
}
}

void printTime ()
{
 minutes = countdowntime/60;           // Aufteilung von 'countdowntime' in Minuten
 seconds = countdowntime%60;           // und Sekunden
       
 if (minutes<10)                       // wenn minuten unter 10
 {                                     //  
   lcd.print('0');                     // schreibe "0" vor minuten
 }                                     //
       
 lcd.print(minutes);                   // gebe Minuten aus
 lcd.print(":");                       // schreibe ":"
     
 if (seconds<10)                       // wenn Sekunden unter 10
 {                                     //  
   lcd.print("0");                     // schreibe erst Null und dann
   lcd.print(seconds);                 // die Sekunden
   lcd.write(' ');                     // entferne Werte nach sekunden
 }                                     //
 else                                  //
 {                                     //
   lcd.print(seconds);                 // schreibe die Sekunden normal
   lcd.print(" ");                     //
 }                                     //
 
}

void readAin ()
{
inputtime = analogRead(varpin);           // Analogwert in 'inputtime' schreiben
int showminutes = inputtime /60;          // inputtime/60 = showminutes = Minuten ausrechnen
int showseconds = inputtime %60;          // inputtime%60 = showseconds = Sekunden ausrechnen

if (showminutes<10)                      // wenn 'showminutes' unter 10
{                                        //
  lcd.print('0');                        // schreibe erst "0"
}                                        //

lcd.print(showminutes);                   // schreibe 'showminutes'
 
lcd.print(":");                           // schreibe ":"
   
if (showseconds<10)                       // wenn 'showseconds' unter 10
{
  lcd.print("0");                        // schreibe erst Null
  lcd.print(showseconds);                // dann die Sekunden
  lcd.write(' ');                        // entferne letzte Ziffer
}
else                                     // wenn nicht
{                                        //
  lcd.print(showseconds);                // schreibe die Sekunden normal
  lcd.print(" ");                        // und lösche die Ziffer dahinter
}
delay(150);                              // Verlangsame den kompletten vorgang

}

Ihr wisst, dass der thread schon ein paar Jährchen auf dem Buckel hat?

nordcap:
Hallo squaremeter,

das Projekt hat mir sehr gut gefallen und ich habe es nachgebaut.
Auch ich suchte schon lange einen Timer mit Sekunden und Schaltausgang für meine Platinen.

Nun habe ich aber ein Problem.
Die Zeit wir im Display angezeigt und ich kann auch die Dauer verändern.
Aber ich weiß nicht wie ich den Timer starten soll.
Das mit der negativen Flanke habe ich nicht verstanden.
Ich würde mich freuen wenn ich eine Nachricht bekomme was ich falsch mache
bzw was ich machen muß damit der Timer startet.

Ich bin zwar nicht squaremeter, aber dessen letztes Post ist schon ein paar Jahre her. Wer weiß, ob er hier noch mitliest.

Im Code gibt es ein paar Fehler, die dazu führen, dass das Programm (zumindest mit einem Arduino) nicht optimal funktioniert:

a) Der wesentlichste: der Ausgang "uvout" ist nicht als Output deklariert.
Es fehlt also in Setup folgendes:

 pinMode(uvout, OUTPUT);

b) Hier muss das Semikolon in der ersten Zeile gelöscht werden:

if (countdowntime <= 0);                 // wenn 'countdowntime 0
  {
    digitalWrite(uvout, LOW);              // schalte UV-Licht aus
  }

denn sonst bleibt die Bedingung ohne Auswirkungen und uvout wird immer LOW.
Das hat zwar auf den ersten Blick keine gravierenden Auswirkungen, denn ein paar Programmzeilen später wird uvout gleich wieder HIGH, aber der Ausgang wird dadurch in schneller Folge ein- und wieder ausgeschalten, je nachdem was da dran hängt kann das möglicherweise Probleme machen.

c) Arduino Pin D13 für den Schalt-Ausgang zu verwenden - wie hier der Fall - ist keine sehr gute Idee. Der Bootloader des Arduinos sorgt dafür, dass D13 beim "Einschalten" des Ardino mehrmals blinkt. Eine hier angeschlossene UV-Lampe (oder was auch immer) wird dann ebenfalls mehrmals ein- und ausgeschalten. Da würde ich also auf jeden Fall einen anderen Pin verwenden.

d) Was das soll erschließt sich mir nicht:

val = digitalRead(tick);                 // Overflow des Timers auslesen

aber es richtet wohl auch keinen Schaden an :slight_smile:

Zu deiner Frage, wie du den Timer starten sollst:
Es steht eigentlich in der Beschreibung, ist aber möglicherweise etwas missverständlich.
So ist es jedenfalls gedacht:
Du drückst und hältst den Tasters gedrückt: Die gewünschte Zeit kannst du jetzt am Poti einstellen - falls du möchtest. Die Anzeige der gewählten Zeit erfolgt am LCD.

Sobald du den Taster loslässt (das ist mit "negativer Flanke" gemeint), startet der Countdown und der Ausgang "uvout" wird HIGH. Am LCD wird die Zeit heruntergezählt, beim Erreichen von 0 wird "uvout" wieder LOW.

Wichtig ist auch, dass du den Schaltplan beachtest. Der Taster braucht einen "Pulldown-Widerstand" (im Schaltplan: R1, 10 Kiloohm) und tastet gegen 5 Volt: beim Betätigen des Tasters liegt also 5 Volt am "buttonPin".

Hallo UXOMM,

danke für Deine Antwort.
Ich hatte kaum damit gerechnet das noch jemand nach so langer Zeit antwortet.
Die Änderung im Code hab ich gemacht.
Das mit dem Starten hatte ich auch so gedacht wie Du geschrieben hast.
Bei mir ist das Problem das ich die Zeit mit dem Potentiometer einstellen kann
aber es wird nicht heruntergezählt.
In der ersten Zeile steht z.b. TIME 3:15 dann drücke ich den Taster und die Aufforderung SET kommt.
Ich lasse den Taster los und habe in der zweiten Zeile auch die 3:15 stehen mehr tut sich nicht.-
Die Schaltung habe ich 3x aufgebaut einmal mit dem Layout von squaremeter einmal hab ich selbst eine Platine geätzt und einmal auf dem Breadboard immer mit dem gleichen Ergebnis.

Vielen Dank nochmal
nordcap

Hi

val = digitalRead(tick);

Sicher, daß Das SO im Original steht?
(okok ... habe nachgeschaut, steht tatsächlich SO da drin ... ist aber trotzdem falsch)
Das würde, wenn tick==1 ist, den Pin 1 abfragen, bei tick==2, den Pin 2, ... kann mir nur schwer vorstellen, daß Das so gewollt ist.

Da der Timer tick alle Sekunde (denke ich jetzt Mal) um 1 hoch zählt, soll Da wohl eher val=tick; stehen, oder?

Hast Du Mal, spaßeshalber, diverse
Serial.print("Zeile ");Serial.println(LINE);
in Deinem Sketch verteilt, damit Du siehst, wo sich Dein Sketch rum drückt/wo Er hängen bleibt?

MfG