Go Down

Topic: Timerfunktion (Read 156 times) previous topic - next topic

PanTau78

Hallo zusammen,

ich bin nun schon seit gestern im Netz unterwegs und suche eine Möglichkeit das nach einer Timerfunktion eine andere Funktion ausgeführt wird.
Habe hier auch einiges gefunden, aber da ich noch neu in der Arduinowelt bin habe ich mir gedacht ich frage einmal euch :)

im folgenden Sketch möchte ich, dass bei betätigen des Buttons_timer eine Funktion abläuft.
Die Funktion soll einen Timer auf das lcd Display ausgeben (frei einstellbar per "code") und bei 0 eine Funktion void_servo ausführen.
Ich habe hier schon viel versucht und gelesen, aber ich finde einfach keinen roten Faden  :smiley-eek:

Hier mein code
Code: [Select]

#define Button_timer 13
#define Button_sofort 10
#define LED_ZEIT 7
#define LED_STANDBY 1
#define LED_SOFORT 8
#include <Servo.h>
#include <LiquidCrystal.h>

Servo lichtservo;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

float pos = 0;

void setup()
{
  lichtservo.attach(6);
  pinMode(Button_sofort, INPUT);
  pinMode(LED_ZEIT, OUTPUT);
  lichtservo.write(0);
  pinMode(LED_STANDBY, OUTPUT);
 
  //Anfangszustand
  digitalWrite(LED_STANDBY, HIGH);
  lcd.begin(16,2);
  lcd.setCursor(3,1);
  lcd.print("Standby..."); 
}

void timer()
{
  if (digitalRead(Button_timer) == HIGH)
  {
    digitalWrite(LED_SOFORT, LOW);
    digitalWrite(LED_STANDBY, LOW);
    digitalWrite(LED_ZEIT, HIGH);
    lcd.begin(16,2);
    lcd.setCursor(4,1);
    lcd.print("Time:");
   
    //Timer
    //???
   
}
}

void timer_servo()
{
    lcd.setCursor(2,1);
    lcd.print("Zeitsteuerung");
    for(pos = 0; pos < 110; pos +=1)
    {
     lichtservo.write(pos);
     delay(15);
     }
  for(pos = 90; pos >=1; pos-=8)
  {
    lichtservo.write(pos);
    delay(15);
  }
    digitalWrite(LED_ZEIT, LOW);
    delay(50);
    digitalWrite(LED_STANDBY, HIGH);
    lcd.begin(16,2);
    lcd.setCursor(3,1);
    lcd.print("Standby...");
}

void sofort()
{
  if (digitalRead(Button_sofort) == HIGH)
  {
    digitalWrite(LED_SOFORT, LOW);
    digitalWrite(LED_STANDBY, LOW);
    digitalWrite(LED_SOFORT, HIGH);
    lcd.begin(16,2);   
    lcd.setCursor(5,1);
    lcd.print("Sofort");
    for(pos = 0; pos < 110; pos +=1)
    {
     lichtservo.write(pos);
     delay(15);
     }
  for(pos = 90; pos >=1; pos-=8)
  {
    lichtservo.write(pos);
    delay(15);
  }
    digitalWrite(LED_ZEIT, LOW);
    delay(50);
    digitalWrite(LED_SOFORT, HIGH);
    lcd.begin(16,2);
    lcd.setCursor(4,1);
    lcd.print("Standby...");
    digitalWrite(LED_SOFORT, LOW); 
    digitalWrite(LED_STANDBY, HIGH);   
}
}

void loop()
{
  timer();
  sofort();
}


Ich bedanke mich bis hier fürs lesen und auch schon mal Vorab für Antworten.

Gruß
André

PanTau78

#1
Oct 20, 2014, 07:46 pm Last Edit: Oct 21, 2014, 07:05 pm by PanTau78
Hallo zusammen,

da bin ich nochmal. Ich habe ein wenig weiter gesucht und bin hier auf etwas gestoßen was genau meinen Vorstellungen entspricht. (der erste Code)

http://forum.arduino.cc/index.php?PHPSESSID=ne0es2rq35tok621gil33c2ii5&topic=71395.0;wap2

Ich würde diesen Code gerne für ein kleines Projekt verwenden, allerdings stellen sich mir 3 Fragen und ich hoffe das mir hier jemand weiterhelfen kann!?

1. Wie schaffe ich es, diesen Timer per Taster zu starten?
2. Wie kann ich am Ende des Timers eine Funktion ausführen (habe ich im Code schon drin und funktioniert auch)? Macht man das so?
3. Wie setze ich den Countdown nach Ablauf der Funktion automatisch wieder auf 0, sodass nach erneutem drücken des Tasters die Funktion wieder abgespielt wird?

Hier der Code:
Code: [Select]

#include <LiquidCrystal.h>
#include <Servo.h>

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

//-------------------------Servo--------------------------//
Servo lichtservo;
float pos = 0;
float count = 0;

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


int const inputtime = 10;               // in Sekunden     


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

int buttonstate;
int const buttonPin = 13;                 // 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()
{
 lichtservo.attach(6);
 lichtservo.write(0);
 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 timer()
{
 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   
 }
 if (seconds <= 0) servo();
 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
   }
 }
}

void servo()
{
  for(pos = 0; pos < 110; pos +=1)
    {
    lichtservo.write(pos);
    delay(15);
    }
     for(pos = 90; pos >=1; pos-=8)
     {
     lichtservo.write(pos);
     delay(15);
     }
     while(1)
    {
       
    }
 }
 
 void loop()
 {
   timer();
 }




Vielen Dank Vorab und Gruß
André

jurs

im folgenden Sketch möchte ich, dass bei betätigen des Buttons_timer eine Funktion abläuft.
Die Funktion soll einen Timer auf das lcd Display ausgeben (frei einstellbar per "code") und bei 0 eine Funktion void_servo ausführen.
Ich habe hier schon viel versucht und gelesen, aber ich finde einfach keinen roten Faden  :smiley-eek:
Einen Sketch für einen "einstellbaren Kurzzeittimer mit LCD-Display" habe ich hier schon mal gepostet:
http://forum.arduino.cc/index.php?topic=231846.msg1672443#msg1672443

Dass am Ende noch entwas anderes passiert als dass der Timer 0:00 anzeigt, könnte man da natürlich leicht dranstricken.

PanTau78

Hallo Jurs,
danke für Deine Antwort.
Der Sketch ist ja nicht schlecht :) aber leider nicht ganz das was ich brauche.
Ich möchte gerne einen feste Zeit die im Code hinterlegt ist ablaufen und anzeigen lassen nach Betätigung eines Schalters!
Bitte nicht falsch verstehen, es soll mir keiner einen Code schreiben, ich bin nur auf der Suche nach ein wenig Unterstützung.

Danke
André

jurs

Der Sketch ist ja nicht schlecht :) aber leider nicht ganz das was ich brauche.
Ich möchte gerne einen feste Zeit die im Code hinterlegt ist ablaufen und anzeigen lassen nach Betätigung eines Schalters!
Das ist dann ja noch viel einfacher als der Sketch, den ich gepostet habe.
Aber die beiden Buttons zum Einstellen von Minuten und Sekunden unbeschaltet zu lassen oder diese aus dem Programm zu entfernen und die Variablendeklaration des Countdown-Timers statt mit einem Wert vorzubelegen statt mit null, dürfte ja nicht die Schwierigkeit sein:

Code: [Select]
int long countdowntime=411;
Aber Du hast natürlich Recht: Für Deine Zwecke ist das Programm schon viel zu kompliziert.


PanTau78

Ok, und wie kann ich diesen Wert nun auf null bringen und diesen an das LCD auch in den Sekunden abständen ausgeben?
Sorry, aber ich bin noch Anfänger...
Danke wieder mal und schönen Abend noch!
André
PS: Ich habe es gerade mit einer for Schleife versucht, die z.B. 10 Sekunden läuft.Die Schleife funktioniert auch, aber mein Problem ist nun die Ausgabe an das LCD :)

jurs

Ok, und wie kann ich diesen Wert nun auf null bringen und diesen an das LCD auch in den Sekunden abständen ausgeben?
Du drückst einfach den an der Schaltung angeschlossenen "start_switch" an Pin-8, und das Programm zählt die Sekunden runter bis null.

Das ist im Programm schon drin.

Was Du für Deine Programmlogik noch einbauen müßtest, wäre:
- bei Erreichen von 0:00 Deine Aktion ausführen
- und den Zähler wieder auf den Ausgangsstand setzen

PanTau78

#7
Oct 22, 2014, 04:05 pm Last Edit: Oct 22, 2014, 04:08 pm by PanTau78
Gut, soweit verstanden.
Habe es nun so, dass er mir die Ausgabe auf dem LCD ausgibt, allerdings habe ich ein kleines Problem mit dem ausführen der Servofunktion. Er macht es zwar bei null, aber bleibt dann auch nach Ablauf dort stehen und nichts geht mehr. Ich habe z.B. noch einen Schalter mit sofort belegt, also das der Servo sofort ausgelöst wird. Bevor ich den Timer starte, kann ich den Servo mit entsprechenden Taster auch beliebig oft schalten, doch nach Ablauf des Timers und der Funktion geht nichts mehr. Liegt es an While (1) oder lediglich darin, dass ich nach Ablauf des Timers den Anfangszustand wieder herstellen muss ? Also den Timer resetten?
Code: [Select]
void servo()
{
      for(pos = 0; pos < 110; pos +=1)
    {
     lichtservo.write(pos);
     delay(15);
     }
  for(pos = 90; pos >=1; pos-=8)
  {
    lichtservo.write(pos);
    delay(15);
  }
    digitalWrite(LED_ZEIT, LOW);
    delay(50);
    digitalWrite(LED_STANDBY, HIGH);
    lcd.begin(16,2);
    lcd.setCursor(3,1);
    lcd.print("Standby...");
    while(1);
    {
    }
}

void lcd_ausgabe()
{
  int minuten=timerLaufzeit/60; // Ganzzahldivision durch 60
  int sekunden=timerLaufzeit%60;// Modulo-Divisionsrecht bei geteilt durch 60
  lcd.setCursor(0, 1);
  if (minuten < 10) lcd.print("0");
  lcd.print(minuten);
  lcd.print(":");
  if (sekunden < 10) lcd.print("0");
  lcd.print(sekunden);
  if(sekunden<=0) servo();
 
}

jurs

Liegt es an While (1)
Ja, "while(1);" ist die typische Endlosschleife.
Und nur Chuck Norris kann eine Endlosschleife beenden.



Mein Vorschlag für Variablen, mit denen eine blockierungsfreie Drehaktion des Servos gesteuert werden kann:
Code: [Select]

unsigned long servoStartzeit;
boolean servoAktiv;
int servoPosition=90;


Wenn der Timer abläuft, setzt Du:
Code: [Select]

  servoStartzeit=millis();
  servoAktiv=true;


In der Verarbeitungsroutine rechnest Du die Servoposition aus, ausgehend von der servoStartzeit und ob der Servo aktiv ist.
Code: [Select]

  if (servoAktiv)
  {
     long time= millis()-servoStartzeit; // hier steht jetzt die Zeit, wie lange der Servo bereits aktiv ist
     if (time<2000) servoPosition=10; // Servo-Sollposition für 2 s = 2000 ms
     else
     {
        servoAktiv=false;  // den Servo wieder auf inaktiv setzen
        servoPosition=90; // und als Servo-Sollposition wieder die Ausgangslage setzen
        // hier ggf. den Timer zurück auf Startwert setzen
        // falls er erst nach dem Drehen zurückgesetzt werden soll
      }
  }



Und in der Ausgaberoutine setzt Du:
Code: [Select]

  lichtservo.write(servoPosition);

PanTau78

#9
Oct 22, 2014, 07:27 pm Last Edit: Oct 22, 2014, 08:15 pm by PanTau78
Puuh, ich danke Dir für deine Unterstützung!
Diese Weise werde ich auf jeden Fall auch versuchen :) nur wie Du schon schreibst, muss ich den Timer zurücksetzen, nur wie ist die Frage ;)
Kann man nicht einfach das while weglassen und dort dann den Timer auf Anfang zurücksetzen? So wird die for Schleife auch nur einmal abgefahren, oder ?
Sorry, aber ich bin wirklich noch neu in der Arduinowelt :(
Die Weise in der Du vorgehst, ist mir leider noch etwas fremd. Ich verstehe zwar die Zusammenhänge (auch Dank Deiner Hilfe und der Kommentare) aber mir fehlt da noch ein wenig Praxis zu.

Danke nochmal bis hierher !!!!

Quote
[font=TyponineSans Regular 18]Ja, "while(1);" ist die typische Endlosschleife.[/font]
[font=TyponineSans Regular 18]Und nur Chuck Norris kann eine Endlosschleife beenden.[/font]
:D sehr gut :D

Go Up