diff --git a/button.ino b/button.ino index b422bda..88e8bb8 100644 --- a/button.ino +++ b/button.ino @@ -18,11 +18,11 @@ void buttonISRstate() { else if (countdown == 0) { // TODO: restart metronome timer to align countdown countdown = COUNTDOWN; - updateTube(); + displayNeedsUpdate = true; } else { countdown = -1; digitalWrite(BUTTON_LED_PIN, LOW); - updateTube(); + displayNeedsUpdate = true; // TODO: disable metronome timer } } diff --git a/metronom.ino b/metronom.ino index f6e8db9..67b9f41 100644 --- a/metronom.ino +++ b/metronom.ino @@ -37,18 +37,19 @@ volatile float sensorValue[SENSORS] = {}; volatile uint displaySensor = TEMPERATURE; volatile bool displayNeedsUpdate = false; volatile bool tubeRotated = false; +volatile bool sensorsDue = false; int tubeTimerID; +/* I2C (BME280 reads, tube writes) must never run in interrupt context: + both libraries call delay(), which inside an ISR can spin forever + because SysTick (millis/micros) is blocked. ISRs only raise flags; + loop() does the actual bus work. */ void TasksHandler(void) { TasksISRs.run(); +} - if (displayNeedsUpdate || tubeRotated) - updateTube(); - - if (tubeRotated) { - TasksISRs.changeInterval(tubeTimerID, SENSOR_TIMESHARE[displaySensor]); - tubeRotated = false; - } +void scheduleSensors() { + sensorsDue = true; } void setup() { @@ -62,7 +63,7 @@ void setup() { TaskTimer.attachInterruptInterval_MS(TASK_HANDLER_INTERVAL, TasksHandler); TasksISRs.setInterval(METRONOME_INTERVAL, runMetronome); - TasksISRs.setInterval(SENSOR_INTERVAL, readSensors); + TasksISRs.setInterval(SENSOR_INTERVAL, scheduleSensors); tubeTimerID = TasksISRs.setInterval(SENSOR_TIMESHARE[displaySensor], rotateTube); } @@ -79,4 +80,17 @@ void runMetronome() { } } -void loop() {} +void loop() { + if (sensorsDue) { + sensorsDue = false; + readSensors(); + } + + if (displayNeedsUpdate || tubeRotated) + updateTube(); + + if (tubeRotated) { + TasksISRs.changeInterval(tubeTimerID, SENSOR_TIMESHARE[displaySensor]); + tubeRotated = false; + } +}