TempTrack-ESP/src/main.cpp
2023-06-01 22:54:13 +02:00

150 lines
4.2 KiB
C++

#include <Arduino.h>
#include <esp_wifi.h>
#include <driver/rtc_io.h>
#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();
}
}