Forum: Mikrocontroller und Digitale Elektronik ESP32 General Purpose Timer, Verständnisfrage


von Bernhard S. (b_spitzer)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen,

ich versuche gerade mich in die verschiedenen Möglichkeiten zur 
Verwendung der GP-Timer des ESP32 ein zu arbeiten. Grundfunktion, 
Vorteiler, Alarmwert ist alles soweit klar. Bei Versuchen, den 
Zählerstand in Mikrosekunden auszulesen bin ich aber auf ein Problem 
gestossen.

Zunächst habe ich nur einen Timer verwendet und mit einem Vorteiler von 
80 einen Zähltakt von 1MHz eingestellt. Mit einem Alarmwert von 
1.000.000 gibt das schön einen Interrupt pro Sekunde.

Aus Interesse wollte ich dann mal sehen, ob in der Loop delay(500) auch 
genau ist. Dabei ist mir aufgefallen, dass das Auslesen des Timers mit 
timerReadMicros(Timer) falsche Werte liefert, wenn der Timer zusätzlich 
mit Alarmwert genutzt wird.

In der Loop lasse ich eine LED mit 1Hz blinken (funktioniert in jedem 
Fall korrekt!) und lese jedesmal den Zählerstand des Timers (uint64_t) 
aus. Dann bilde ich die Differenz.

Das Setup der beiden genutzten Timer, einmal mit Alarmwert (der Reload 
beim Alarm wirft nahher Fragen auf), einmal nur als Timer mit 1MHz Takt:
1
void setup() {
2
  Serial.begin(115200);
3
  pinMode(LED, OUTPUT);
4
  state = LOW;
5
  digitalWrite(LED, state);
6
  // Timer 0 als Timer mit Alarmwert für 1s konfigurieren
7
  nextAlarm = 1000000;
8
  testTimer1 = timerBegin(0, 80, true); // Timer0, Teiler:80, Aufwärtszähler
9
  timerAlarmWrite(testTimer1, nextAlarm, false); // Alarm bei 1s, ohne Auto-Reload 
10
  timerAttachInterrupt(testTimer1, &onTimer, true); // ISR onTimer()
11
  timerAlarmEnable(testTimer1);
12
  timerStart(testTimer1);
13
  delay(10);                      // der Delay hat nachher Folgen!!
14
  // Timer 2 ohne Alarm, 1MHz Takt
15
  testTimer2 = timerBegin(1, 80, true); // Timer0, Teiler:80, Aufwärtszähler
16
  timerStart(testTimer2);
17
}
Der Alarmwert des ersten Timers wird nachher in der ISR neu gesetzt. 
Ziel ist eigentlich, dass der Zählerstand nach Alarm weiter läuft und 
der Alarmwert fortgeschrieben wird. Aber erstmal zur Endlosschleife...
1
void loop() {
2
  // Wie genau ist denn Delay...
3
  delay(500);
4
  //timerStop(testTimer1);
5
  timerValNew = timerReadMicros(testTimer1);  // mit testTimer2 funktioniert es problemlos...
6
  //timerStart(testTimer1);
7
  digitalWrite(LED, state);
8
  state=!state;
9
  Serial.printf("Zählerstand: %6d \n", timerValNew);
10
  Serial.printf("Alarmwert: %6d \n", timerAlarmRead(testTimer1));
11
  long delta = timerValNew - timerValOld;
12
  Serial.printf("Vergangene Zeit: %6d us\n", delta);
13
  timerValOld = timerValNew;
14
}
Die vergangene Zeit sollten eigentlich 500.000 sein (ich hatte da 
eigentlich mit kleinen Abweichungen gerechnet). Bei der Nutzung des 
Timers testTimer2 ohne Alarmwert und Auto-Reload bekomme ich sogar exakt 
500.000µs als Ergebnis (nice).

Wenn ich den anderen Timer testTimer1 mit Alarm und ohne AutoReload 
auslese erhalte ich aber Zeiten von rund 990ms und 10ms (?!?). Die LED 
blinkt aber korrekt im 1Hz-Takt weiter.

Den Timer vor dem Auslesen zu stoppen und nacher wieder zu starten 
ergibt fast die selben Werte, die Verschieben sich nur bei jedem 
Durchgang um 4-5µs.

Hier die Ausgaben, der nächste Alarmwert wird in der ISR erhöht.
1
Zählerstand: 32000002          <= Hier blinkt die LED
2
Alarmwert: 33000000 
3
Vergangene Zeit: 989867 us
4
Zählerstand: 32010135          <= Hier blinkt die LED
5
Alarmwert: 33000000 
6
Vergangene Zeit:  10133 us
7
Zählerstand: 33000002          <= Hier blinkt die LED
8
Alarmwert: 34000000 
9
Vergangene Zeit: 989867 us
10
Zählerstand: 33010135          <= Hier blinkt die LED
11
Alarmwert: 34000000 
12
Vergangene Zeit:  10133 us

Die kürzere Zeit ist dabei von dem delay() im Setup abhängig! Mit 
delay(33) erhalte ich dann
1
Zählerstand: 10000002 
2
Alarmwert: 11000000 
3
Vergangene Zeit: 966888 us
4
Zählerstand: 10033114 
5
Alarmwert: 11000000 
6
Vergangene Zeit:  33112 us

Wie gesagt, die LED blinkt in allen Fällen korrekt. Hat da jemand eine 
Idee, was da falsch läuft?
Arduion 1.8.13, ESP32 Version 1.0.5 und 1.0.6

gruß
Bernhard

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.