Fix display freeze: move I2C work out of interrupt context #8
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
32
metronom.ino
32
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;
|
||||
}
|
||||
}
|
||||
|
||||
6
tube.ino
6
tube.ino
@@ -6,7 +6,11 @@ char tubeText[5] = "";
|
||||
void initTube() {
|
||||
// Wire initialized by BME280 sensor
|
||||
tube.setTubeType(TYPE_4, TYPE_4_DEFAULT_I2C_ADDR);
|
||||
tube.setBrightness(15);
|
||||
// Brightness drives LED current. The freeze correlates with '8' on the last
|
||||
// multiplexed digit (most segments lit -> peak current) at full brightness 15,
|
||||
// which points at a supply/I2C-bus glitch. Lowered to probe that hypothesis;
|
||||
// raise back toward 15 if the display is too dim and freezes don't return.
|
||||
tube.setBrightness(4);
|
||||
tube.setBlinkRate(BLINK_OFF);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user