Final version 1:
reads data every 15 minutes saves data persistently every 24h writes out the contents every measure. goes in deep sleep so very low power consumption. (reason removal task system)
This commit is contained in:
404
main/main.c
404
main/main.c
@@ -1,10 +1,10 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include "esp_spiffs.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -16,18 +16,19 @@
|
||||
#include "esp_flash.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_spiffs.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/rtc_io.h"
|
||||
|
||||
#define PRINT_DEBUG false
|
||||
#define WIPE_MEMORY false
|
||||
|
||||
#define DHT11_GPIO 0
|
||||
#define BUTTON_PIN 9 // BOOT button on ESP32-C3 SuperMini
|
||||
#define BLINK_GPIO 8
|
||||
|
||||
#define DATA_BUFFER_SIZE 100
|
||||
#define MAX_MEASUREMENTS_PER_DAY 96 // 96 * 15 minutes = 24 hours
|
||||
static int measurement_count = 0;
|
||||
QueueHandle_t sensor_data_queue;
|
||||
SemaphoreHandle_t xMutex;
|
||||
|
||||
typedef struct {
|
||||
char timestamp[64];
|
||||
@@ -35,50 +36,59 @@ typedef struct {
|
||||
float temperature;
|
||||
} SensorData;
|
||||
|
||||
TaskHandle_t file_handler_task_handle;
|
||||
// RTC buffer to store time
|
||||
RTC_DATA_ATTR time_t rtc_unix_time = 0;
|
||||
RTC_DATA_ATTR bool rtc_time_initialized = false;
|
||||
|
||||
// RTC buffer to store measurements
|
||||
RTC_DATA_ATTR SensorData rtc_measurement_buffer[DATA_BUFFER_SIZE];
|
||||
RTC_DATA_ATTR int rtc_buffer_index = 0;
|
||||
|
||||
// ############### Base Setup ###############
|
||||
|
||||
void set_system_time_from_compiler() {
|
||||
// Parse __DATE__: "Mmm dd yyyy"
|
||||
char date[] = __DATE__;
|
||||
char time[] = __TIME__;
|
||||
void set_system_time() {
|
||||
if (!rtc_time_initialized) {
|
||||
// First boot: use compile time
|
||||
struct tm tm = {0};
|
||||
char month[4];
|
||||
int day, year, hour, min, sec;
|
||||
|
||||
struct tm tm = {0};
|
||||
char month[4];
|
||||
int day, year;
|
||||
int hour, min, sec;
|
||||
sscanf(__DATE__, "%3s %d %d", month, &day, &year);
|
||||
sscanf(__TIME__, "%d:%d:%d", &hour, &min, &sec);
|
||||
|
||||
// Parse date
|
||||
sscanf(date, "%3s %d %d", month, &day, &year);
|
||||
|
||||
// Parse time
|
||||
sscanf(time, "%d:%d:%d", &hour, &min, &sec);
|
||||
|
||||
// Convert month abbreviation to number
|
||||
const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (strcmp(month, months[i]) == 0) {
|
||||
tm.tm_mon = i;
|
||||
break;
|
||||
const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (strcmp(month, months[i]) == 0) {
|
||||
tm.tm_mon = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
tm.tm_mday = day;
|
||||
tm.tm_year = year - 1900; // Years since 1900
|
||||
tm.tm_hour = hour;
|
||||
tm.tm_min = min;
|
||||
tm.tm_sec = sec;
|
||||
tm.tm_isdst = -1; // Let system determine daylight saving time
|
||||
tm.tm_mday = day;
|
||||
tm.tm_year = year - 1900;
|
||||
tm.tm_hour = hour;
|
||||
tm.tm_min = min;
|
||||
tm.tm_sec = sec;
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
// Set system time
|
||||
struct timeval tv = { .tv_sec = mktime(&tm), .tv_usec = 0 };
|
||||
rtc_unix_time = mktime(&tm);
|
||||
rtc_time_initialized = true;
|
||||
}
|
||||
|
||||
// Set system time from RTC
|
||||
struct timeval tv = { .tv_sec = rtc_unix_time, .tv_usec = 0 };
|
||||
settimeofday(&tv, NULL);
|
||||
}
|
||||
|
||||
void print_chip_info(){
|
||||
/* Print chip information */
|
||||
#if PRINT_DEBUG
|
||||
void get_current_time(char* time_string, size_t size) {
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(time_string, size, "%Y-%m-%d %H:%M:%S", &timeinfo);
|
||||
}
|
||||
|
||||
void print_chip_info() {
|
||||
esp_chip_info_t chip_info;
|
||||
uint32_t flash_size;
|
||||
esp_chip_info(&chip_info);
|
||||
@@ -97,135 +107,96 @@ void print_chip_info(){
|
||||
printf("Get flash size failed");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),
|
||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
|
||||
|
||||
printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());
|
||||
#endif
|
||||
}
|
||||
|
||||
// ############### Measurement task ###############
|
||||
// ############### Status indicator ###############
|
||||
|
||||
void get_current_time(char* time_string, size_t size) {
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(time_string, size, "%Y-%m-%d %H:%M:%S", &timeinfo);
|
||||
void init_led() {
|
||||
gpio_reset_pin(BLINK_GPIO);
|
||||
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(BLINK_GPIO, 1);
|
||||
}
|
||||
|
||||
void led_flicker(int times, bool fast) {
|
||||
for(u_int8_t i = 0; i < times; i++) {
|
||||
gpio_set_level(BLINK_GPIO, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(fast ? 250 : 500));
|
||||
gpio_set_level(BLINK_GPIO, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(fast ? 250 : 500));
|
||||
}
|
||||
}
|
||||
|
||||
// ############### Measurement ###############
|
||||
|
||||
void read_dht11(float *humidity, float *temperature) {
|
||||
uint8_t data[5] = {0};
|
||||
|
||||
// Send start signal: pull the line low for 20ms
|
||||
gpio_set_direction(DHT11_GPIO, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(DHT11_GPIO, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
|
||||
// Release the line and wait for sensor response
|
||||
gpio_set_level(DHT11_GPIO, 1);
|
||||
gpio_set_direction(DHT11_GPIO, GPIO_MODE_INPUT);
|
||||
|
||||
// Wait for the sensor to pull the line low (~20-40us)
|
||||
while (gpio_get_level(DHT11_GPIO) == 1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(0.1));
|
||||
}
|
||||
while (gpio_get_level(DHT11_GPIO) == 1) vTaskDelay(pdMS_TO_TICKS(0.1));
|
||||
while (gpio_get_level(DHT11_GPIO) == 0) vTaskDelay(pdMS_TO_TICKS(0.1));
|
||||
|
||||
// Wait for the sensor to pull the line high (~80us)
|
||||
while (gpio_get_level(DHT11_GPIO) == 0) {
|
||||
vTaskDelay(pdMS_TO_TICKS(0.1));
|
||||
}
|
||||
|
||||
// Read 40 bits of data
|
||||
for (int i = 0; i < 40; i++) {
|
||||
// Wait for the start of the bit (low for ~50us)
|
||||
while (gpio_get_level(DHT11_GPIO) == 1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(0.1));
|
||||
}
|
||||
while (gpio_get_level(DHT11_GPIO) == 0) {
|
||||
vTaskDelay(pdMS_TO_TICKS(0.1));
|
||||
}
|
||||
while (gpio_get_level(DHT11_GPIO) == 1) vTaskDelay(pdMS_TO_TICKS(0.1));
|
||||
while (gpio_get_level(DHT11_GPIO) == 0) vTaskDelay(pdMS_TO_TICKS(0.1));
|
||||
|
||||
// Measure the length of the high pulse
|
||||
uint32_t pulse_start = esp_timer_get_time();
|
||||
while (gpio_get_level(DHT11_GPIO) == 1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(0.1));
|
||||
}
|
||||
while (gpio_get_level(DHT11_GPIO) == 1) vTaskDelay(pdMS_TO_TICKS(0.1));
|
||||
uint32_t pulse_end = esp_timer_get_time();
|
||||
|
||||
// Determine if the bit is 0 or 1
|
||||
uint8_t bit = (pulse_end - pulse_start) > 50 ? 1 : 0;
|
||||
data[i / 8] <<= 1;
|
||||
data[i / 8] |= bit;
|
||||
}
|
||||
|
||||
// Parse the data
|
||||
uint8_t humidity_int = data[0];
|
||||
uint8_t humidity_dec = data[1]; // Decimal part (0-9)
|
||||
int8_t temperature_int = (data[2]); // signed value
|
||||
uint8_t temperature_dec = data[3]; // Decimal part (0-9)
|
||||
uint8_t humidity_dec = data[1];
|
||||
int8_t temperature_int = (data[2]);
|
||||
uint8_t temperature_dec = data[3];
|
||||
uint8_t checksum = data[4];
|
||||
|
||||
#if PRINT_DEBUG
|
||||
printf("\nReadout values: [hi: %d, hd: %d, ti %d, td %d, c: %d]\n", humidity_int, humidity_dec, temperature_int, temperature_dec, checksum);
|
||||
#endif
|
||||
|
||||
// Validate checksum
|
||||
uint8_t sum = humidity_int + humidity_dec + temperature_int + temperature_dec;
|
||||
if (sum != checksum) {
|
||||
#if PRINT_DEBUG
|
||||
printf("Checksum failed! Retrying...\n");
|
||||
#if PRINT_DEBUG
|
||||
printf("Checksum failed! Retrying...\n");
|
||||
#endif
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
read_dht11(humidity, temperature);
|
||||
return;
|
||||
}
|
||||
#if PRINT_DEBUG
|
||||
printf("Checksum checks out!\n");
|
||||
#endif
|
||||
|
||||
// Calculate humidity and temperature
|
||||
*humidity = (float)humidity_int + (float)humidity_dec / 10.0f;
|
||||
*temperature = (float)temperature_int + (float)temperature_dec / 10.0f;
|
||||
}
|
||||
|
||||
void measure_task(void *pvParameters){
|
||||
while (1) {
|
||||
float humidity, temperature;
|
||||
read_dht11(&humidity, &temperature);
|
||||
|
||||
char time_string[64] = {0};
|
||||
get_current_time(time_string, sizeof(time_string));
|
||||
void make_measurement() {
|
||||
float humidity, temperature;
|
||||
read_dht11(&humidity, &temperature);
|
||||
|
||||
#if PRINT_DEBUG
|
||||
printf("Measurment: [%s, %.1f%%, %.1f°C]\n", time_string, humidity, temperature);
|
||||
#endif
|
||||
char time_string[64] = {0};
|
||||
get_current_time(time_string, sizeof(time_string));
|
||||
|
||||
SensorData data;
|
||||
strncpy(data.timestamp, time_string, sizeof(data.timestamp));
|
||||
data.humidity = humidity;
|
||||
data.temperature = temperature;
|
||||
#if PRINT_DEBUG
|
||||
printf("Measurement: [%s, %.1f%%, %.1f°C]\n", time_string, humidity, temperature);
|
||||
#endif
|
||||
|
||||
// Send data to the queue
|
||||
if (xQueueSend(sensor_data_queue, &data, pdMS_TO_TICKS(100)) != pdPASS) {
|
||||
#if PRINT_DEBUG
|
||||
printf("Failed to add measurement to queue!\n");
|
||||
#endif
|
||||
} else {
|
||||
measurement_count++;
|
||||
if (measurement_count >= MAX_MEASUREMENTS_PER_DAY) {
|
||||
// Signal the file handler to write and reset
|
||||
xTaskNotifyGive(file_handler_task_handle);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait 15 minute before next read
|
||||
vTaskDelay(pdMS_TO_TICKS(15 * 60 * 1000));
|
||||
// Store in RTC buffer
|
||||
if (rtc_buffer_index < DATA_BUFFER_SIZE) {
|
||||
strncpy(rtc_measurement_buffer[rtc_buffer_index].timestamp, time_string, sizeof(time_string));
|
||||
rtc_measurement_buffer[rtc_buffer_index].humidity = humidity;
|
||||
rtc_measurement_buffer[rtc_buffer_index].temperature = temperature;
|
||||
rtc_buffer_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// ############### Filehandling task ###############
|
||||
// ############### IO operations ###############
|
||||
|
||||
void init_filesystem() {
|
||||
esp_vfs_spiffs_conf_t conf = {
|
||||
@@ -237,13 +208,7 @@ void init_filesystem() {
|
||||
esp_err_t ret = esp_vfs_spiffs_register(&conf);
|
||||
if (ret != ESP_OK) {
|
||||
#if PRINT_DEBUG
|
||||
if (ret == ESP_FAIL) {
|
||||
printf("Failed to mount or format filesystem\n");
|
||||
} else if (ret == ESP_ERR_NOT_FOUND) {
|
||||
printf("Failed to find SPIFFS partition\n");
|
||||
} else {
|
||||
printf("Failed to initialize SPIFFS (%s)\n", esp_err_to_name(ret));
|
||||
}
|
||||
printf("Failed to initialize SPIFFS (%s)\n", esp_err_to_name(ret));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -252,145 +217,96 @@ void init_filesystem() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void file_handler_task(void *pvParameters) {
|
||||
while (1) {
|
||||
// Wait for notification from measurement task
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
void save_buffer_to_persistent(){
|
||||
FILE *f = fopen("/spiffs/measurements.csv", "a");
|
||||
if (f == NULL) {
|
||||
printf("Failed to open CSV file!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SensorData data;
|
||||
FILE *f = NULL;
|
||||
|
||||
xSemaphoreTake(xMutex, portMAX_DELAY);
|
||||
f = fopen("/spiffs/measurements.csv", "a");
|
||||
if (f == NULL) {
|
||||
#if PRINT_DEBUG
|
||||
printf("Failed to open CSV file!\n");
|
||||
#endif
|
||||
xSemaphoreGive(xMutex);
|
||||
continue;
|
||||
}
|
||||
// Write header if file is empty
|
||||
fseek(f, 0, SEEK_END);
|
||||
if (ftell(f) == 0) {
|
||||
fprintf(f, "Timestamp,Humidity,Temperature\n");
|
||||
}
|
||||
|
||||
// Write header if file is empty
|
||||
fseek(f, 0, SEEK_END);
|
||||
if (ftell(f) == 0) {
|
||||
fprintf(f, "Timestamp,Humidity,Temperature\n");
|
||||
}
|
||||
|
||||
// Read all data from the queue and write to CSV
|
||||
while (xQueueReceive(sensor_data_queue, &data, 0) == pdPASS) {
|
||||
fprintf(f, "%s,%.1f,%.1f\n", data.timestamp, data.humidity, data.temperature);
|
||||
#if PRINT_DEBUG
|
||||
printf("%s,%.1f,%.1f\n", data.timestamp, data.humidity, data.temperature);
|
||||
#endif
|
||||
}
|
||||
// Write all buffered measurements
|
||||
for (int i = 0; i < rtc_buffer_index; i++) {
|
||||
fprintf(f, "%s,%.1f,%.1f\n",
|
||||
rtc_measurement_buffer[i].timestamp,
|
||||
rtc_measurement_buffer[i].humidity,
|
||||
rtc_measurement_buffer[i].temperature);
|
||||
}
|
||||
fclose(f);
|
||||
rtc_buffer_index = 0; // Reset buffer
|
||||
#if PRINT_DEBUG
|
||||
printf("CSV file updated with %d measurements!\n", DATA_BUFFER_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void clear_file(){
|
||||
led_flicker(10, false);
|
||||
FILE *f = fopen("/spiffs/measurements.csv", "w");
|
||||
if (f) {
|
||||
fprintf(f, "Timestamp,Humidity,Temperature\n");
|
||||
fclose(f);
|
||||
measurement_count = 0;
|
||||
#if PRINT_DEBUG
|
||||
printf("CSV file updated!\n");
|
||||
#endif
|
||||
xSemaphoreGive(xMutex);
|
||||
}
|
||||
}
|
||||
|
||||
// ############### Button task ###############
|
||||
|
||||
void button_task(void *pvParameters) {
|
||||
// Configure BOOT button (GPIO9, active low with internal pullup)
|
||||
gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);
|
||||
gpio_set_pull_mode(BUTTON_PIN, GPIO_PULLUP_ONLY);
|
||||
|
||||
uint32_t last_press_tick = 0;
|
||||
bool waiting_for_double = false;
|
||||
|
||||
while (1) {
|
||||
if (gpio_get_level(BUTTON_PIN) == 0) { // Button pressed (active low)
|
||||
vTaskDelay(pdMS_TO_TICKS(50)); // Debounce
|
||||
if (gpio_get_level(BUTTON_PIN) == 0) {
|
||||
uint32_t press_start = xTaskGetTickCount();
|
||||
|
||||
// Wait for release
|
||||
while (gpio_get_level(BUTTON_PIN) == 0) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(50)); // Debounce release
|
||||
uint32_t press_duration = xTaskGetTickCount() - press_start;
|
||||
|
||||
// Only count short presses (< 500ms)
|
||||
if (press_duration < pdMS_TO_TICKS(500)) {
|
||||
if (waiting_for_double) {
|
||||
// ===== DOUBLE PRESS: Reset CSV =====
|
||||
xSemaphoreTake(xMutex, portMAX_DELAY);
|
||||
FILE *f = fopen("/spiffs/measurements.csv", "w");
|
||||
if (f) {
|
||||
fprintf(f, "Timestamp,Humidity,Temperature\n");
|
||||
fclose(f);
|
||||
}
|
||||
xSemaphoreGive(xMutex);
|
||||
waiting_for_double = false;
|
||||
} else {
|
||||
// ===== FIRST PRESS: Wait for possible double press =====
|
||||
waiting_for_double = true;
|
||||
last_press_tick = press_start;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check if double-press window expired
|
||||
if (waiting_for_double && (xTaskGetTickCount() - last_press_tick) > pdMS_TO_TICKS(500)) {
|
||||
xTaskNotifyGive(file_handler_task_handle);
|
||||
// ===== SINGLE PRESS: Print CSV contents (via USB CDC) =====
|
||||
xSemaphoreTake(xMutex, portMAX_DELAY);
|
||||
FILE *f = fopen("/spiffs/measurements.csv", "r");
|
||||
if (f) {
|
||||
char line[256];
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
printf("%s", line); // Goes to USB CDC (/dev/ttyACM0)
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
xSemaphoreGive(xMutex);
|
||||
waiting_for_double = false;
|
||||
}
|
||||
void readout_persistent_as_csv(){
|
||||
FILE *f = fopen("/spiffs/measurements.csv", "r");
|
||||
if (f) {
|
||||
char line[256];
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
printf("%s", line);
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
// ############### Shared buffer ###############
|
||||
// ############### Buffer operations ###############
|
||||
|
||||
void init_shared_buffer() {
|
||||
sensor_data_queue = xQueueCreate(DATA_BUFFER_SIZE, sizeof(SensorData));
|
||||
xMutex = xSemaphoreCreateMutex();
|
||||
if (sensor_data_queue == NULL || xMutex == NULL) {
|
||||
#if PRINT_DEBUG
|
||||
printf("Failed to create queue or mutex!\n");
|
||||
#endif
|
||||
void readout_buffer_as_csv(){
|
||||
for (int i = 0; i < rtc_buffer_index; i++) {
|
||||
printf("%s,%.1f,%.1f\n",
|
||||
rtc_measurement_buffer[i].timestamp,
|
||||
rtc_measurement_buffer[i].humidity,
|
||||
rtc_measurement_buffer[i].temperature);
|
||||
}
|
||||
}
|
||||
|
||||
// ############### Main thread ###############
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
// Setup
|
||||
setlocale(LC_ALL, "C"); // Use ASCII for text
|
||||
set_system_time_from_compiler();
|
||||
init_shared_buffer();
|
||||
const uint16_t sleep_time_seconds = 15 * 60; // Measurement frequency
|
||||
|
||||
void app_main() {
|
||||
setlocale(LC_ALL, "C");
|
||||
set_system_time();
|
||||
|
||||
init_led();
|
||||
init_filesystem();
|
||||
|
||||
// Intro
|
||||
led_flicker(3, true);
|
||||
|
||||
#if PRINT_DEBUG
|
||||
printf("DHT11 temperature and humidity sensor\n");
|
||||
char start_time[64] = {0};
|
||||
get_current_time(start_time, sizeof(start_time));
|
||||
printf("Program started at: %s\n", start_time);
|
||||
print_chip_info();
|
||||
printf("\n\n=============\n\n");
|
||||
#endif
|
||||
|
||||
// Run tasks
|
||||
xTaskCreate(measure_task, "MeasureTask", 4096, NULL, 3, NULL);
|
||||
xTaskCreate(file_handler_task, "FileHandlerTask", 4096, NULL, 4, &file_handler_task_handle);
|
||||
xTaskCreate(button_task, "ButtonTask", 2048, NULL, 2, NULL);
|
||||
}
|
||||
|
||||
make_measurement();
|
||||
if (rtc_buffer_index >= DATA_BUFFER_SIZE) {
|
||||
save_buffer_to_persistent();
|
||||
}
|
||||
readout_persistent_as_csv();
|
||||
readout_buffer_as_csv();
|
||||
#if WIPE_MEMORY
|
||||
clear_file();
|
||||
#endif
|
||||
|
||||
rtc_unix_time += sleep_time_seconds;
|
||||
esp_sleep_enable_timer_wakeup(sleep_time_seconds * 1000000);
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
Reference in New Issue
Block a user