Forum: Mikrocontroller und Digitale Elektronik Timer Probleme mit meinem Arduino UNO


von Tibo H. (dobherrmann)


Lesenswert?

Hallo,

bin neu hier in diesem Forum und habe direkt ein kleines Problem mit 
meinem Arduino, was scheinbar häufiger vorkommt. ;)

Und zwar geht es darum das ich 3 Magnetventile habe die ich gerne zu 
unterschiedlichen Zeitpunkten schalten möchte nachdem ich einmalig einen 
Taster betätigt habe. Das ganze funktioniert auch schon mittels der 
delay Funktion, nur möchte ich diese ersetzen.

Zur Umsetzung meiner Idee möchte ich meiner Hauptschleife eine feste 
Taskzeit zuweisen. Meine Idee hierfür sieht wie folgt aus:
1
void setup()   
2
{
3
  Serial.begin(9600);
4
  pinMode(ledpin, OUTPUT);
5
  Timer1.initialize(900000); // In mu sekunden
6
}
7
 
8
void blinken()
9
{
10
  digitalWrite(ledpin, digitalRead(ledpin) ^ 1);
11
}
12
13
void loop()
14
{
15
  blinken(); // Lässt eine LED blinken
16
  ultime2=ultime1; 
17
  ultime1=micros();
18
  ultime=ultime1-ultime2; // Überprüfen der Zykluszeit
19
  Serial.print(ultime);
20
  Serial.print(",");
21
  
22
  while(Timer1.iIsTimerRunning());
23
}

Die Funktion Timer1.iIsTimerRunning() hab ich eine vorhande Libary 
implemenitert. Nur bin ich mir nicht sicher wie ich bei dem MicroC das 
Überlauf Bit abfrage.
1
int TimerOne::iIsTimerRunning(){
2
  int iRet = 0;
3
  int itmp=0;
4
    
5
  itmp=(TIFR1 & 1); // Idee: Abfrage des "Überlauf Bit's" des Timer 1
6
    
7
  if(itmp==0)
8
  {
9
    iRet = 1;
10
  }
11
  return iRet;
12
}

In meinem kleinen Programm möchte ich, dass die Hauptschleife des 
Programms abgearbeitet wird und anschließend bleibt wartet das Programm 
bis der timer abgelauf ist in der while schleife. Somit kann ich über 
den Reload wert des Timers die Taskzeit der Hauptschleife einstellen.

Ein Problem das ich habe, ist das ich im Netz unterschiedliche 
Register-Positionen des Überlauf Bits gefunden habe.
Ich hoffe ihr könnt mir etwas weiter helfen oder mir einen sinnvolleren 
Ansatz nennen könnt sehe gerade den Wald vor lauter Bäumen nicht mehr;). 
Falls ihr weitere Infos benötigt schreibt es mir bitte.

Freue mich über Eure Hilfe^^

von Karol B. (johnpatcher)


Lesenswert?

Tibo H. schrieb:
> Ein Problem das ich habe, ist das ich im Netz unterschiedliche
> Register-Positionen des Überlauf Bits gefunden habe.

Man sollte nicht unbedingt wild im Netz herum suchen, sondern im 
Datenblatt. Wenn ich das jetzt richtig nachgeschlagen habe, dann werkelt 
da ein ATmega328. Das Datenblatt dazu findest du unter [1].

Nur was willst du mit der Überprüfung, ob der Timer übergelaufen ist? Du 
solltest eher mit der dazugehörigen ISR arbeiten. Dein Programm könnte 
z.B. so aussehen, dass du beim Starten eine Variable auf "false" setzt, 
und in einer zum Timer gehörigen ISR dann entsprechend auf "true". In 
der Hauptschleife brauchst du nur den Wert der Variablen einlesen.

Das ist aber ein ziemliches Standardproblem, und wird im Tutorial [2] 
auch detailliert beschrieben.

Mit freundlichen Grüßen,
Karol Babioch

[1]: http://www.atmel.com/Images/doc8161.pdf
[2]: 
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Interruptgesteuerter_Programmablauf

von Karl H. (kbuchegg)


Lesenswert?

> Und zwar geht es darum das ich 3 Magnetventile habe die ich gerne
> zu unterschiedlichen Zeitpunkten schalten möchte nachdem ich einmalig
> einen Taster betätigt habe. Das ganze funktioniert auch schon mittels
> der delay Funktion, nur möchte ich diese ersetzen.

Löblich

> Zur Umsetzung meiner Idee möchte ich meiner Hauptschleife eine
> feste Taskzeit zuweisen. Meine Idee hierfür sieht wie folgt aus:

Machs nicht so kompliziert.
Das Arduino Basissystem stellt dir in Form der Funktion millis() schon 
alles zur Verfügung was du brauchst. Du musst nur weg vom Gedankengang 
des 'Zeiten werden gemessen, indem man so lange Däumchen dreht'.
Statt dessen benutzt du millis() genauso wie du die Sache mit einer Uhr 
mit Sekundenzeiger angehen würdest. Kommt das StartEreignis genau dann, 
wenn der Sekundenzeiger auf 28 steht, dann kannst du dir ausrechnen, 
dass bei einer gewünschten Einschaltdauer von zb 8 Sekunden du bei 28 + 
8 gleich 36 wieder ausschalten musst. Und genau das tust du dann 
laufend: Neben anderen Dingen beobschtest du auch immer kurz den 
Sekundenzeiger und wenn der auf 36 steht, dann schaltest du wieder aus.
1
unsigned long Zeit1;
2
unsigned long Zeit2;
3
4
void loop()
5
{
6
  unsigned long now = millis();
7
8
  if( now > Zeit1 )
9
  {
10
    digitalWrite(ledpin1, digitalRead(ledpin1) ^ 1);
11
    Zeit1 = now + 2000;
12
  }
13
14
  if( now > Zeit2 )
15
  {
16
    digitalWrite(ledpin2, digitalRead(ledpin2) ^ 1);
17
    Zeit1 = now + 3000;
18
  }
19
}

Im Beispiel blinken die LED alle 2 Sekunden bzw. 3 Sekunden, weil bei 
jedem Umschalten der LED berechnet wird, zu welchem Zeitpunkt die LED 
das nächste mal umzuschalten ist. Und das eine mal ist das dann eben 2 
Sekunden (2000 Millisekunden) später und bei der anderen LED sind es 
eben 3 Sekunden (3000 Millisekunden).

Die Hauptschleife loop hat dann nur noch die Aufgabe laufend zu 
überprüfen, ob die so errechneten Zeitpunkte erreicht sind und wenn ja 
die entsprechenden Aktionen einzuleiten.

eine andere Technik, die weniger Probleme beim Rollover von millis() 
haben wird, ist die, dass du die Differenz zum Startzeitpunkt 
feststellst und wenn die die von dir gewünschte Zeitdauer erreicht hat, 
schaltest du wieder ab.
1
unsigned long Zeit1;
2
unsigned long Zeit2;
3
4
void loop()
5
{
6
  unsigned long now = millis();
7
8
  if( ( now - Zeit1 ) >= 2000 )
9
  {
10
    digitalWrite(ledpin1, digitalRead(ledpin1) ^ 1);
11
    Zeit1 = now;
12
  }
13
14
  if( ( now - Zeit2 ) >= 3000 )
15
  {
16
    digitalWrite(ledpin2, digitalRead(ledpin2) ^ 1);
17
    Zeit2 = now;
18
  }
19
}

Jetzt gibt es dann auch keine Probleme mehr, wenn nach rund 49 Tagen der 
Zahlenwert von millis() auf einen Schlag von "sehr groß" auf 0 
überläuft. Die unsigned Rechnung gleicht das wieder aus, die Differenz 
stimmt trotz dieses Überlaufs immer noch.


Und weil du jetzt keine Warteschleifen mehr hast, kannst du jetzt neben 
(in diesem Beispiel) den beiden LED noch andere Sachen machen. Die LED 
blinken trotzdem im vorgegebenen Takt weiter. Bei dir ist das dann eben 
eine Einmalaktion und es sind keine LED sondern Ventile, aber die 
grundlegende Technik, wie man Zeiten abarbeitet, ist genau die gleiche.

von Tibo H. (dobherrmann)


Lesenswert?

Hey danke euch beiden schon einmal für eure Hilfe;)

Muss mir eingestehen das die Idee das Problem über die Funktion millis() 
zu lösen sehr einfach und angnehm ist. Werde es auf jedenfall mal so 
umsetzen.

Bei interesse kann ich euch wenn das gesamte Projekt fertiggestellt ist 
euch dieses einmal vorstellen. Woran ich gerade arbeite ist ein kleiner 
Teil ein Anlage zur High-Speedfotografie (ja ich weiß schon wieder einer 
:P)

Danke nochmals, falls diese Variante nicht den gewünschten Effekt 
erzielt versuche ich es nochmal über den Timer, mit hoffentlich etwas 
mehr Erfolg als gestern abend.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.