#include #include #include #include "config.h" #include "bluetooth.h" #include "storage.h" #include "temperature.h" Temperature samples[temperatureSensorCount]; // Indicate when the next temperature measurement should be performed // Time is measured in seconds since power-on via RTC clock RTC_DATA_ATTR uint32_t nextTimeToMeasureTemperatureSeconds = 0; // Indicate the time until the device should stay awake // Updated when button is pressed uint32_t timeUntilSleep = 0; /** * @brief Check if enough time has passed for the next temperature measurement * * @return true A measurement should be performed * @return false Wait until more time has elapsed */ bool shouldMeasureTemperature() { return time(NULL) >= nextTimeToMeasureTemperatureSeconds; } /** * @brief Set the next time when temperatures should be measured */ void setNextTemperatureMeasurementInterval() { nextTimeToMeasureTemperatureSeconds += temperatureMeasurementIntervalSeconds; } /** * @brief Check how long to wait until the next temperature measurement * * @return uint32_t The number of seconds to wait */ uint32_t secondsUntilNextTemperatureMeasurement() { // Time in seconds since power on time_t currentTime = time(NULL); if (currentTime >= nextTimeToMeasureTemperatureSeconds) { return 0; } return nextTimeToMeasureTemperatureSeconds - currentTime; } void deepSleepUntilNextTemperatureMeasurement() { uint32_t seconds = secondsUntilNextTemperatureMeasurement(); if (seconds == 0) { // The time until next measurement is too short, // so don't sleep and just wait a little // May run the loop multiple times until the time is elapsed delay(100); } else { esp_deep_sleep(seconds * 1000000); } } /** * @brief Check if the button is pressed * * This indicates that the device should stay awake and that Bluetooth should be enabled. * * @return true The button is pressed * @return false The button is not pressed */ bool wakeupButtonIsPressed() { return gpio_get_level(wakeupButtonPin) == 0; } void updateStayAwakeTime() { timeUntilSleep = time(NULL) + wakeupDurationAfterButtonPress; } bool shouldStayAwakeDueToActivity() { if (timeUntilSleep > time(NULL)) { return true; } return bluetoothIsConnected(); } void enableLED() { // Configure LED pin // Equivalent to: pinMode(1, OUTPUT); gpio_config_t ledConfig; ledConfig.pin_bit_mask = (1ULL << 1); ledConfig.mode = GPIO_MODE_OUTPUT; gpio_config(&ledConfig); // Enable LED, as long as ESP is awake // Equivalent to: digitalWrite(1, LOW); gpio_set_level(GPIO_NUM_1, 0); // For this led, low means on } void setup() { Serial.begin(serialBaudRate); // LED useless inside case //enableLED(); // Configure button pin to wake up ESP from deep sleep on low signal with pullup rtc_gpio_pullup_en(wakeupButtonPin); esp_sleep_enable_ext0_wakeup(wakeupButtonPin, 0); // Enable EEPROM to persist measurements // Only needed if sufficient measurements are in RTC memory storageConfigure(); // Configure bluetooth if wake button was pressed if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_EXT0) { Serial.println("Wake after button press"); bluetoothConfigure(); updateStayAwakeTime(); } // Configure the temperature sensors // Happens only once per power cycle temperatureConfigure(); // TODO: Remove Serial.println("Setup complete"); } void loop() { if (shouldMeasureTemperature()) { Serial.println("Measuring"); temperaturePerformUpdate(samples); saveTemperatures(samples); setNextTemperatureMeasurementInterval(); } if (wakeupButtonIsPressed()) { bluetoothConfigure(); // Only done once internally updateStayAwakeTime(); } if (!shouldStayAwakeDueToActivity()) { Serial.print("Sleeping for "); Serial.print(secondsUntilNextTemperatureMeasurement()); Serial.println(" seconds"); // May return, if less then one second to wait // Otherwise control flow starts with setup() again deepSleepUntilNextTemperatureMeasurement(); } }