#include "SAMDTimerInterrupt.h" #include "SAMD_ISR_Timer.h" SAMDTimer TaskTimer(TIMER_TC3); SAMD_ISR_Timer TasksISRs; enum { TEMPERATURE = 0, HUMIDITY, PRESSURE, SENSORS }; // COUNTDOWN is effectively multiplied by METRONOME_INTERVAL const int COUNTDOWN = 600; // INTERVALS and TIMESHARES given in [ms] const uint TASK_HANDLER_INTERVAL = 20; const uint METRONOME_INTERVAL = 1000; const uint SENSOR_INTERVAL = 1000; const uint SENSOR_TIMESHARE[SENSORS] = {90000, 20000, 10000}; // FREQUENCY in [Hz] const uint BUZZER_FREQ = 300; const uint BUTTON_PIN = 6; const uint BUTTON_LED_PIN = 5; const uint BUZZER_PIN = 0; /* Metronome state is expressed by countdown: -1 - IDLE 0 - BEATING >0 - COUNTDOWN Unless metronome is in COUNTDOWN mode, display rotates through sensor readings. */ volatile int countdown = -1; // Units: temperature [C], humidity [%], pressure [P] volatile float sensorValue[SENSORS] = {}; volatile uint displaySensor = TEMPERATURE; volatile bool displayNeedsUpdate = false; volatile bool tubeRotated = false; int tubeTimerID; void TasksHandler(void) { TasksISRs.run(); if (displayNeedsUpdate || tubeRotated) updateTube(); if (tubeRotated) { TasksISRs.changeInterval(tubeTimerID, SENSOR_TIMESHARE[displaySensor]); tubeRotated = false; } } void setup() { initButton(); initBME280(); initBuzzer(); initTube(); readSensors(); updateTube(); TaskTimer.attachInterruptInterval_MS(TASK_HANDLER_INTERVAL, TasksHandler); TasksISRs.setInterval(METRONOME_INTERVAL, runMetronome); TasksISRs.setInterval(SENSOR_INTERVAL, readSensors); tubeTimerID = TasksISRs.setInterval(SENSOR_TIMESHARE[displaySensor], rotateTube); } void runMetronome() { if (countdown > 0) { countdown -= 1; digitalWrite(BUTTON_LED_PIN, countdown % 2 ? HIGH : LOW); displayNeedsUpdate = true; } else if (countdown == 0) { TasksISRs.setTimeout(100, noBuzz); buzz(); } } void loop() {}