Skip to content

Commit

Permalink
feat: reading soil moisture + deep sleep
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcel Hofmann committed Jul 14, 2024
1 parent e739ef4 commit 2878cb4
Show file tree
Hide file tree
Showing 15 changed files with 255 additions and 25 deletions.
2 changes: 1 addition & 1 deletion compile_commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -1195,7 +1195,7 @@
},
{
"directory": "/Users/marcel/irrigation/build",
"command": "/Users/marcel/.espressif/tools/riscv32-esp-elf/esp-13.2.0_20230928/riscv32-esp-elf/bin/riscv32-esp-elf-gcc -DESP_PLATFORM -DIDF_VER=\\\"v5.2.2\\\" -DSOC_MMU_PAGE_SIZE=CONFIG_MMU_PAGE_SIZE -DSOC_XTAL_FREQ_MHZ=CONFIG_XTAL_FREQ -D_GLIBCXX_HAVE_POSIX_SEMAPHORE -D_GLIBCXX_USE_POSIX_SEMAPHORE -D_GNU_SOURCE -D_POSIX_READER_WRITER_LOCKS -D PROJECT_NAME=\\\"irrigation\\\" -DPROJECT_VER=\\\"v0.0.3-dirty\\\" -I/Users/marcel/irrigation/build/config -I/Users/marcel/esp/esp-idf/components/esp_app_format/include -I/Users/marcel/esp/esp-idf/components/newlib/platform_include -I/Users/marcel/esp/esp-idf/components/freertos/config/include -I/Users/marcel/esp/esp-idf/components/freertos/config/include/freertos -I/Users/marcel/esp/esp-idf/components/freertos/config/riscv/include -I/Users/marcel/esp/esp-idf/components/freertos/FreeRTOS-Kernel/include -I/Users/marcel/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/include -I/Users/marcel/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos -I/Users/marcel/esp/esp-idf/components/freertos/esp_additions/include -I/Users/marcel/esp/esp-idf/components/esp_hw_support/include -I/Users/marcel/esp/esp-idf/components/esp_hw_support/include/soc -I/Users/marcel/esp/esp-idf/components/esp_hw_support/include/soc/esp32c3 -I/Users/marcel/esp/esp-idf/components/heap/include -I/Users/marcel/esp/esp-idf/components/log/include -I/Users/marcel/esp/esp-idf/components/soc/include -I/Users/marcel/esp/esp-idf/components/soc/esp32c3 -I/Users/marcel/esp/esp-idf/components/soc/esp32c3/include -I/Users/marcel/esp/esp-idf/components/hal/platform_port/include -I/Users/marcel/esp/esp-idf/components/hal/esp32c3/include -I/Users/marcel/esp/esp-idf/components/hal/include -I/Users/marcel/esp/esp-idf/components/esp_rom/include -I/Users/marcel/esp/esp-idf/components/esp_rom/include/esp32c3 -I/Users/marcel/esp/esp-idf/components/esp_rom/esp32c3 -I/Users/marcel/esp/esp-idf/components/esp_common/include -I/Users/marcel/esp/esp-idf/components/esp_system/include -I/Users/marcel/esp/esp-idf/components/esp_system/port/soc -I/Users/marcel/esp/esp-idf/components/esp_system/port/include/riscv -I/Users/marcel/esp/esp-idf/components/esp_system/port/include/private -I/Users/marcel/esp/esp-idf/components/riscv/include -I/Users/marcel/esp/esp-idf/components/lwip/include -I/Users/marcel/esp/esp-idf/components/lwip/include/apps -I/Users/marcel/esp/esp-idf/components/lwip/include/apps/sntp -I/Users/marcel/esp/esp-idf/components/lwip/lwip/src/include -I/Users/marcel/esp/esp-idf/components/lwip/port/include -I/Users/marcel/esp/esp-idf/components/lwip/port/freertos/include -I/Users/marcel/esp/esp-idf/components/lwip/port/esp32xx/include -I/Users/marcel/esp/esp-idf/components/lwip/port/esp32xx/include/arch -I/Users/marcel/esp/esp-idf/components/lwip/port/esp32xx/include/sys -march=rv32imc_zicsr_zifencei -fdiagnostics-color=always -ffunction-sections -fdata-sections -Wall -Werror=all -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=unused-but-set-variable -Wno-error=deprecated-declarations -Wextra -Wno-unused-parameter -Wno-sign-compare -Wno-enum-conversion -gdwarf-4 -ggdb -nostartfiles -Os -freorder-blocks -fmacro-prefix-map=/Users/marcel/irrigation=. -fmacro-prefix-map=/Users/marcel/esp/esp-idf=/IDF -fstrict-volatile-bitfields -fno-jump-tables -fno-tree-switch-conversion -std=gnu17 -Wno-old-style-declaration -o esp-idf/esp_app_format/CMakeFiles/__idf_esp_app_format.dir/esp_app_desc.c.obj -c /Users/marcel/esp/esp-idf/components/esp_app_format/esp_app_desc.c",
"command": "/Users/marcel/.espressif/tools/riscv32-esp-elf/esp-13.2.0_20230928/riscv32-esp-elf/bin/riscv32-esp-elf-gcc -DESP_PLATFORM -DIDF_VER=\\\"v5.2.2\\\" -DSOC_MMU_PAGE_SIZE=CONFIG_MMU_PAGE_SIZE -DSOC_XTAL_FREQ_MHZ=CONFIG_XTAL_FREQ -D_GLIBCXX_HAVE_POSIX_SEMAPHORE -D_GLIBCXX_USE_POSIX_SEMAPHORE -D_GNU_SOURCE -D_POSIX_READER_WRITER_LOCKS -D PROJECT_NAME=\\\"irrigation\\\" -DPROJECT_VER=\\\"v0.0.5-dirty\\\" -I/Users/marcel/irrigation/build/config -I/Users/marcel/esp/esp-idf/components/esp_app_format/include -I/Users/marcel/esp/esp-idf/components/newlib/platform_include -I/Users/marcel/esp/esp-idf/components/freertos/config/include -I/Users/marcel/esp/esp-idf/components/freertos/config/include/freertos -I/Users/marcel/esp/esp-idf/components/freertos/config/riscv/include -I/Users/marcel/esp/esp-idf/components/freertos/FreeRTOS-Kernel/include -I/Users/marcel/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/include -I/Users/marcel/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/riscv/include/freertos -I/Users/marcel/esp/esp-idf/components/freertos/esp_additions/include -I/Users/marcel/esp/esp-idf/components/esp_hw_support/include -I/Users/marcel/esp/esp-idf/components/esp_hw_support/include/soc -I/Users/marcel/esp/esp-idf/components/esp_hw_support/include/soc/esp32c3 -I/Users/marcel/esp/esp-idf/components/heap/include -I/Users/marcel/esp/esp-idf/components/log/include -I/Users/marcel/esp/esp-idf/components/soc/include -I/Users/marcel/esp/esp-idf/components/soc/esp32c3 -I/Users/marcel/esp/esp-idf/components/soc/esp32c3/include -I/Users/marcel/esp/esp-idf/components/hal/platform_port/include -I/Users/marcel/esp/esp-idf/components/hal/esp32c3/include -I/Users/marcel/esp/esp-idf/components/hal/include -I/Users/marcel/esp/esp-idf/components/esp_rom/include -I/Users/marcel/esp/esp-idf/components/esp_rom/include/esp32c3 -I/Users/marcel/esp/esp-idf/components/esp_rom/esp32c3 -I/Users/marcel/esp/esp-idf/components/esp_common/include -I/Users/marcel/esp/esp-idf/components/esp_system/include -I/Users/marcel/esp/esp-idf/components/esp_system/port/soc -I/Users/marcel/esp/esp-idf/components/esp_system/port/include/riscv -I/Users/marcel/esp/esp-idf/components/esp_system/port/include/private -I/Users/marcel/esp/esp-idf/components/riscv/include -I/Users/marcel/esp/esp-idf/components/lwip/include -I/Users/marcel/esp/esp-idf/components/lwip/include/apps -I/Users/marcel/esp/esp-idf/components/lwip/include/apps/sntp -I/Users/marcel/esp/esp-idf/components/lwip/lwip/src/include -I/Users/marcel/esp/esp-idf/components/lwip/port/include -I/Users/marcel/esp/esp-idf/components/lwip/port/freertos/include -I/Users/marcel/esp/esp-idf/components/lwip/port/esp32xx/include -I/Users/marcel/esp/esp-idf/components/lwip/port/esp32xx/include/arch -I/Users/marcel/esp/esp-idf/components/lwip/port/esp32xx/include/sys -march=rv32imc_zicsr_zifencei -fdiagnostics-color=always -ffunction-sections -fdata-sections -Wall -Werror=all -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=unused-but-set-variable -Wno-error=deprecated-declarations -Wextra -Wno-unused-parameter -Wno-sign-compare -Wno-enum-conversion -gdwarf-4 -ggdb -nostartfiles -Os -freorder-blocks -fmacro-prefix-map=/Users/marcel/irrigation=. -fmacro-prefix-map=/Users/marcel/esp/esp-idf=/IDF -fstrict-volatile-bitfields -fno-jump-tables -fno-tree-switch-conversion -std=gnu17 -Wno-old-style-declaration -o esp-idf/esp_app_format/CMakeFiles/__idf_esp_app_format.dir/esp_app_desc.c.obj -c /Users/marcel/esp/esp-idf/components/esp_app_format/esp_app_desc.c",
"file": "/Users/marcel/esp/esp-idf/components/esp_app_format/esp_app_desc.c",
"output": "esp-idf/esp_app_format/CMakeFiles/__idf_esp_app_format.dir/esp_app_desc.c.obj"
},
Expand Down
2 changes: 1 addition & 1 deletion main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
idf_component_register(SRCS "main.c" "nvs_helper.c" "wifi_helper.c" "ota.c"
idf_component_register(SRCS "main.c" "nvs_helper.c" "wifi_helper.c" "ota.c" "logging.c" "read_measurements.c" "send_data.c"
INCLUDE_DIRS "." "include"
)
12 changes: 12 additions & 0 deletions main/Kconfig.projbuild
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,16 @@ config FIRMWARE_VERSION_URL
help
Enter the firmware url where the binary is uploaded to

config HOME_SERVER_IP
string "Home server IP"
default "192.168.11.30"
help
Enter the ip address of the server running in the same network

config HOME_SERVER_UDP_PORT
int "UDP Port"
default 12345
help
Enter the UDP port of the home server

endmenu
9 changes: 9 additions & 0 deletions main/include/logging.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef LOGGING_H
#define LOGGING_H

#include <stdio.h>

void udp_socket_init();
int custom_log_handler(const char *format, va_list args);

#endif // LOGGING_H
6 changes: 6 additions & 0 deletions main/include/main.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef MAIN_H
#define MAIN_H

void enter_deep_sleep();

#endif // MAIN_H
6 changes: 6 additions & 0 deletions main/include/read_measurements.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef READ_MEASUREMENTS_H
#define READ_MEASUREMENTS_H

void read_measurements_task(void *pvParameters);

#endif // READ_MEASUREMENTS_H
6 changes: 6 additions & 0 deletions main/include/send_data.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef SEND_DATA_H
#define SEND_DATA_H

void send_data_task(void *pvParameters);

#endif // SEND_DATA_H
61 changes: 61 additions & 0 deletions main/logging.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "esp_log.h"
#include "lwip/inet.h"
#include "lwip/sockets.h"
#include <stdio.h>
#include <sys/_timeval.h>

char *TAG = "LOGGING";

static struct sockaddr_in server_addr;
int udp_socket;

void udp_socket_init() {
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_socket <= 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
}

memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(CONFIG_HOME_SERVER_UDP_PORT);
inet_pton(AF_INET, CONFIG_HOME_SERVER_IP, &server_addr.sin_addr.s_addr);

ESP_LOGI(TAG, "UDP socket initialized.");
}

const char *log_level_to_str(esp_log_level_t level) {
switch (level) {
case ESP_LOG_ERROR:
return "ERROR";
case ESP_LOG_WARN:
return "WARN";
case ESP_LOG_INFO:
return "INFO";
case ESP_LOG_DEBUG:
return "DEBUG";
case ESP_LOG_VERBOSE:
return "VERBOSE";
default:
return "";
}
}

static void udp_log_handler(const char *message) {
sendto(udp_socket, message, strlen(message), 0,
(struct sockaddr *)&server_addr, sizeof(server_addr));
}

int custom_log_handler(const char *format, va_list args) {
vprintf(format, args);

char log_buffer[256];
int len = vsnprintf(log_buffer, sizeof(log_buffer), format, args);

if (len > 0) {
char message[300];
snprintf(message, sizeof(message), "2;%s", log_buffer);
udp_log_handler(message);
}

return 0;
}
74 changes: 67 additions & 7 deletions main/main.c
Original file line number Diff line number Diff line change
@@ -1,18 +1,74 @@
#include "./include/nvs_helper.h"
#include "./include/ota.h"
#include "./include/wifi_helper.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_sleep.h"
#include "freertos/FreeRTOS.h"
#include "freertos/idf_additions.h"
#include "freertos/projdefs.h"
#include "freertos/task.h"
#include "include/logging.h"
#include "include/nvs_helper.h"
#include "include/ota.h"
#include "include/read_measurements.h"
#include "include/send_data.h"
#include "include/wifi_helper.h"
#include "nvs.h"
#include "nvs_flash.h"
#include <inttypes.h>
#include <stdint.h>
#include <sys/_timeval.h>
#include <sys/time.h>

static const char *TAG = "MAIN";

TaskHandle_t ota_task_handle = NULL;
TaskHandle_t read_measurements_task_handle = NULL;
TaskHandle_t send_data_task_handle = NULL;

QueueHandle_t measurements_queue;

static RTC_DATA_ATTR struct timeval sleep_enter_time;

void enter_deep_sleep() {
ESP_LOGI(TAG, "Entering deep sleep zzz... zzz... zzz...");
gettimeofday(&sleep_enter_time, NULL);

esp_deep_sleep_start();
}

void start_tasks() {
struct timeval now;
gettimeofday(&now, NULL);
int sleep_time_mins = (now.tv_sec - sleep_enter_time.tv_sec) / 60 +
(now.tv_usec - sleep_enter_time.tv_usec) / 1000000 / 60;

esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();

if (cause == ESP_SLEEP_WAKEUP_TIMER) {
ESP_LOGI(TAG, "Wake up from timer. Time spent in deep sleep: %d mins",
sleep_time_mins);
} else {
ESP_LOGW(TAG,
"Unexpected wakeup cause: %d Time spent in deep sleep: %d mins",
cause, sleep_time_mins);
}

xTaskCreate(&ota_update_task, "ota_task", 4096, NULL, 5, &ota_task_handle);
xTaskCreate(&read_measurements_task, "read_measurements_task", 4096, NULL, 4,
&read_measurements_task_handle);
xTaskCreate(&send_data_task, "send_data_task", 4096, NULL, 5,
&send_data_task_handle);
}

void register_rtc_timer_deep_sleep() {
const long long wakeup_time_sec = 60 * 60;
ESP_LOGI(TAG, "Enabling timer wakeup, %llds", wakeup_time_sec);
ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000));
}

void app_main(void) {
ESP_LOGI(TAG, "Hello from irrigation!");

// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
Expand All @@ -29,9 +85,13 @@ void app_main(void) {

wifi_init_sta(ssid, password);

xTaskCreate(&ota_update_task, "ota_task", 8192, NULL, 5, NULL);
udp_socket_init();
esp_log_set_vprintf(custom_log_handler);

while (1) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
measurements_queue = xQueueCreate(5, sizeof(float));

register_rtc_timer_deep_sleep();

// Only this should be triggered when woken up
start_tasks();
}
16 changes: 8 additions & 8 deletions main/nvs_helper.c
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
#include "esp_log.h"
#include "nvs.h"

char *TAG = "NVS_HELPER";
char *N_TAG = "NVS_HELPER";

void store_wifi_credentials(const char *ssid, const char *password) {
nvs_handle_t nvs_handle;

esp_err_t err = nvs_open("storage", NVS_READWRITE, &nvs_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error (%s) opening NVS handle", esp_err_to_name(err));
ESP_LOGE(N_TAG, "Error (%s) opening NVS handle", esp_err_to_name(err));
return;
}

err = nvs_set_str(nvs_handle, "ssid", ssid);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to write SSID: %s", esp_err_to_name(err));
ESP_LOGE(N_TAG, "Failed to write SSID: %s", esp_err_to_name(err));
}

err = nvs_set_str(nvs_handle, "password", password);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to write password: %s", esp_err_to_name(err));
ESP_LOGE(N_TAG, "Failed to write password: %s", esp_err_to_name(err));
}

err = nvs_commit(nvs_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to commit NVS: %s", esp_err_to_name(err));
ESP_LOGE(N_TAG, "Failed to commit NVS: %s", esp_err_to_name(err));
}

nvs_close(nvs_handle);
Expand All @@ -35,17 +35,17 @@ void read_wifi_credentials(char *ssid, size_t ssid_len, char *password,
nvs_handle_t nvs_handle;
esp_err_t err = nvs_open("storage", NVS_READONLY, &nvs_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error (%s) opening NVS handle", esp_err_to_name(err));
ESP_LOGE(N_TAG, "Error (%s) opening NVS handle", esp_err_to_name(err));
return;
}

err = nvs_get_str(nvs_handle, "ssid", ssid, &ssid_len);
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) {
ESP_LOGE(TAG, "Error reading SSID: %s", esp_err_to_name(err));
ESP_LOGE(N_TAG, "Error reading SSID: %s", esp_err_to_name(err));
}
err = nvs_get_str(nvs_handle, "password", password, &password_len);
if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) {
ESP_LOGE(TAG, "Error reading password: %s", esp_err_to_name(err));
ESP_LOGE(N_TAG, "Error reading password: %s", esp_err_to_name(err));
}

nvs_close(nvs_handle);
Expand Down
7 changes: 2 additions & 5 deletions main/ota.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void perform_ota() {
}

void ota_update_task(void *pvParameters) {
ESP_LOGI(TAG, "Starting OTA example task");
ESP_LOGI(TAG, "Starting OTA task");

const esp_partition_t *running = esp_ota_get_running_partition();
esp_app_desc_t running_app_info;
Expand Down Expand Up @@ -211,8 +211,5 @@ void ota_update_task(void *pvParameters) {
free(current_version);
free(latest_version);
perform_ota();

while (1) {
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
44 changes: 44 additions & 0 deletions main/read_measurements.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "esp_adc/adc_oneshot.h"
#include "esp_log.h"
#include "freertos/idf_additions.h"
#include "freertos/projdefs.h"
static const char *R_TAG = "READ_MEASUREMENTS";

static int adc_raw;

extern QueueHandle_t measurements_queue;
extern TaskHandle_t send_data_task_handle;

void read_measurements_task(void *pvParameters) {
adc_oneshot_unit_handle_t adc1_handle;
adc_oneshot_unit_init_cfg_t init_config = {.unit_id = ADC_UNIT_1};
adc_oneshot_chan_cfg_t config = {.bitwidth = ADC_BITWIDTH_DEFAULT,
.atten = ADC_ATTEN_DB_12};

ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc1_handle));

ESP_ERROR_CHECK(
adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_2, &config));

float moisture_percent;
float sum = 0.0;

for (int i = 0; i < 5; i++) {
ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, ADC_CHANNEL_2, &adc_raw));
ESP_LOGI(R_TAG, "Moisture raw data: %d", adc_raw);

moisture_percent = 100.0 - ((float)adc_raw / 4095.0 * 100.0);
ESP_LOGI(R_TAG, "Moisture percentage %.2f", moisture_percent);

sum = sum + moisture_percent;
vTaskDelay(pdMS_TO_TICKS(500));
}

float avg = sum / 5;
ESP_LOGI(R_TAG, "Moisture average %.2f", avg);

ESP_ERROR_CHECK(adc_oneshot_del_unit(adc1_handle));

xQueueSend(measurements_queue, &avg, 0);
vTaskDelete(NULL);
}
23 changes: 23 additions & 0 deletions main/send_data.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "send_data.h"
#include "FreeRTOSConfig.h"
#include "esp_log.h"
#include "freertos/idf_additions.h"
#include "freertos/projdefs.h"
#include "include/main.h"
#include "portmacro.h"
#include <sys/time.h>

extern QueueHandle_t measurements_queue;

static const char *S_TAG = "SEND_DATA";

void send_data_task(void *pvParameters) {
float measurement;

if (xQueueReceive(measurements_queue, &measurement, portMAX_DELAY) ==
pdTRUE) {
ESP_LOGI(S_TAG, "Received measurement %0.2f", measurement);
}

enter_deep_sleep();
}
2 changes: 2 additions & 0 deletions sdkconfig
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,8 @@ CONFIG_PARTITION_TABLE_MD5=y
CONFIG_WIFI_MAX_RETRIES=5
CONFIG_FIRMWARE_URL="https://github.com/marcelhfm/irrigation/releases/latest/download/irrigation.bin"
CONFIG_FIRMWARE_VERSION_URL="https://api.github.com/repos/marcelhfm/irrigation/releases/latest"
CONFIG_HOME_SERVER_IP="192.168.11.30"
CONFIG_HOME_SERVER_UDP_PORT=12345
# end of Irrigation Configuration

#
Expand Down
Loading

0 comments on commit 2878cb4

Please sign in to comment.