150 lines
4.2 KiB
C++
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();
|
|
}
|
|
} |