Created
July 20, 2019 05:46
-
-
Save futureshocked/5327bec254a9d5afcc91fa0b673442b6 to your computer and use it in GitHub Desktop.
ESP32 timer interrupts, how to change duration in the loop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const byte LED_GPIO = 2; | |
volatile int interruptCounter; // When this is not zero, we'll take a reading from the sensor | |
// The interrupt service routine will increment it. | |
// When the sensor is read, this variable is decremented. | |
volatile int blinkCounter = 0; | |
// The hardware timer pointer | |
hw_timer_t * timer = NULL; | |
// This variable is used for syncronisation | |
// We use it to ensure that the ISR and the loop | |
// do not try to access the interruptCounter variable | |
// at the same time. | |
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; | |
void IRAM_ATTR onTimer() { | |
portENTER_CRITICAL_ISR(&timerMux); | |
interruptCounter++; | |
blinkCounter++; | |
portEXIT_CRITICAL_ISR(&timerMux); | |
} | |
void setup() { | |
Serial.begin(9600); | |
pinMode(LED_GPIO, OUTPUT); | |
// Initilise the timer. | |
// Parameter 1 is the timer we want to use. Valid: 0, 1, 2, 3 (total 4 timers) | |
// Parameter 2 is the prescaler. The ESP32 default clock is at 80MhZ. The value "80" will | |
// divide the clock by 80, giving us 1,000,000 ticks per second. | |
// Parameter 3 is true means this counter will count up, instead of down (false). | |
timer = timerBegin(0, 80, true); | |
// Attach the timer to the interrupt service routine named "onTimer". | |
// The 3rd parameter is set to "true" to indicate that we want to use the "edge" type (instead of "flat"). | |
timerAttachInterrupt(timer, &onTimer, true); | |
// This is where we indicate the frequency of the interrupts. | |
// The value "1000000" (because of the prescaler we set in timerBegin) will produce | |
// one interrupt every second. | |
// The 3rd parameter is true so that the counter reloads when it fires an interrupt, and so we | |
// can get periodic interrupts (instead of a single interrupt). | |
timerAlarmWrite(timer, 1000000, true); | |
// Start the timer | |
timerAlarmEnable(timer); | |
} | |
void loop() { | |
if (interruptCounter > 0) { | |
Serial.print(blinkCounter); | |
Serial.print(" "); | |
portENTER_CRITICAL(&timerMux); | |
interruptCounter--; | |
// timerAlarmDisable(timer); | |
if (blinkCounter % 2 == 0) | |
{ | |
timerAlarmWrite(timer, 5000000, true); | |
Serial.println("5000000"); | |
} | |
else | |
{ | |
timerAlarmWrite(timer, 500000, true); | |
Serial.println("500000"); | |
} | |
// timerAlarmEnable(timer); | |
portEXIT_CRITICAL(&timerMux); | |
toggleLED(); // Access the sensor and print the values | |
} | |
} | |
void toggleLED() { | |
digitalWrite(LED_GPIO, HIGH); // turn the LED on (HIGH is the voltage level) | |
delay(50); // wait for a second | |
digitalWrite(LED_GPIO, LOW); // turn the LED off by making the voltage LOW | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
#include "esp32-hal-timer.h"
hw_timer_t * timer1 = NULL;
volatile bool isr = false;
void ARDUINO_ISR_ATTR onTimer1() {
isr = true;
/*
É uma boa prática evitar chamadas como Serial.println() dentro de uma ISR (Interrupt Service Routine) no ESP32, pois elas podem causar instabilidade devido à execução de operações não seguras para interrupção ou que demandam muito tempo.
No seu código revisado, você usou a abordagem correta ao definir uma flag volatile chamada isr na ISR e manipular qualquer comunicação serial ou lógica mais complexa no loop principal. Essa é a maneira recomendada de lidar com interrupções, especialmente em plataformas sensíveis ao tempo como o ESP32. Isso evita problemas com watchdog timers e garante que a ISR seja o mais rápida e leve possível.
Além disso, você utilizou timerWrite(timer1, 0) e timerAlarmEnable(timer1) para reiniciar o timer a partir do loop principal, o que é uma excelente maneira de controlar quando o timer deve começar a contar novamente, evitando manipulações desnecessárias na ISR.
*/
}
void setup() {
Serial.begin(115200);
timer1 = timerBegin(0, 80, true);
timerAttachInterrupt(timer1, &onTimer1, true);
// Configura o Timer 1 para o primeiro disparo
timerAlarmWrite(timer1, 5000000, false);
timerAlarmEnable(timer1);
// setupTimer1();
}
void loop() {
// Suponha que, baseado em alguma condição, você quer reiniciar o Timer 1 para um novo disparo único
// Aqui, usamos uma entrada Serial simples para o exemplo
if (Serial.available() > 0) {
char c = Serial.read();
if (c == 'r') { // Se o caractere 'r' for recebido, reinicie o timer
timerWrite(timer1, 0);
timerAlarmEnable(timer1);
Serial.println("Timer 1 reiniciado para um novo disparo único.");
}
}
if (isr) {
isr=false;
Serial.println("Timer 1 foi disparado");
}
}