From 55102027c136171e3e66cde9a19f8abbdd9a503d Mon Sep 17 00:00:00 2001 From: Conner Date: Mon, 14 Oct 2024 00:31:33 +0200 Subject: [PATCH] frankensteins monster --- embedded/components/README.md | 31 ++++ embedded/components/ds18b20/component.mk | 5 + embedded/components/ds18b20/ds18b20.c | 120 ++++++++++++++++ embedded/components/ds18b20/ds18b20.h | 97 +++++++++++++ embedded/components/onewire/component.mk | 5 + embedded/components/onewire/onewire.c | 175 +++++++++++++++++++++++ embedded/components/onewire/onewire.h | 121 ++++++++++++++++ embedded/main/apple.c | 57 ++++++-- 8 files changed, 603 insertions(+), 8 deletions(-) create mode 100644 embedded/components/README.md create mode 100755 embedded/components/ds18b20/component.mk create mode 100755 embedded/components/ds18b20/ds18b20.c create mode 100755 embedded/components/ds18b20/ds18b20.h create mode 100755 embedded/components/onewire/component.mk create mode 100755 embedded/components/onewire/onewire.c create mode 100755 embedded/components/onewire/onewire.h diff --git a/embedded/components/README.md b/embedded/components/README.md new file mode 100644 index 0000000..1af318f --- /dev/null +++ b/embedded/components/README.md @@ -0,0 +1,31 @@ +# DS18B20 Component +Simple DS18B20 temperature sensor library for [ESP8266 RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK) for reading Celsius temperature with different resolutions from singular device. + +## Usage +``` +// Create variable for handler +ds18b20_handler_t sensor; + +// Check for any initialization failures +if (!ds18b20_init(&sensor, GPIO_NUM_12, TEMP_RES_12_BIT)) +{ + ESP_LOGE("TAG", "Failed to initalize DS18B20!"); + + return 0; // Exit +} + +float temp = 0; + +// Initalize conversion +ds18b20_convert_temp(&sensor); + +// If you doesn't convert temperature you may read 85.0 Celsius, +// as it is default temperature set by DS18B20 if convert command wasn't issued. +temp = ds18b20_read_temp(&sensor); // Read temperature + +// Print temperature with 4 decimal places +// (12 bit resolution measurement accuracy is 0.0625 Celsius) +ESP_LOGI("TAG", "Temperature = %.4f", temp); +``` + +> **_NOTE:_** If last statement doesn't print temperature you may have to disable Newlib nano in `menuconfig` of RTOS SDK. \ No newline at end of file diff --git a/embedded/components/ds18b20/component.mk b/embedded/components/ds18b20/component.mk new file mode 100755 index 0000000..f941c9f --- /dev/null +++ b/embedded/components/ds18b20/component.mk @@ -0,0 +1,5 @@ +# +# Component Makefile +# + +COMPONENT_ADD_INCLUDEDIRS := . \ No newline at end of file diff --git a/embedded/components/ds18b20/ds18b20.c b/embedded/components/ds18b20/ds18b20.c new file mode 100755 index 0000000..9ae31eb --- /dev/null +++ b/embedded/components/ds18b20/ds18b20.c @@ -0,0 +1,120 @@ +#include "ds18b20.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" + +static const char* TAG_DS18B20 = "DS18B20"; +static const uint16_t ds18b20_temp_conv_time[] = {94, 188, 375, 750}; // ms +static const uint16_t ds18b20_resolution_val[] = {0x1F, 0x3F, 0x5F, 0x7F}; + +uint8_t ds18b20_init(ds18b20_handler_t *device, gpio_num_t pin, ds18b20_temp_res_t resolution) +{ + if (!device) + { + ESP_LOGW(TAG_DS18B20, "device is null!"); + + return 0; + } + + if (!onewire_init(&device->bus, pin, NULL)) + { + ESP_LOGW(TAG_DS18B20, "Failed to initialize onewire bus"); + + return 0; + } + + device->res = resolution; + + // Configure resolution + ds18b20_write_scratchpad(device); + ds18b20_read_scratchpad(device); + + return 1; +} + +void ds18b20_send_command(ds18b20_handler_t *device, ds18b20_commands_t command) +{ + uint8_t payload = 0x0 ^ command; + + onewire_write_byte(&device->bus, payload); +} + +void ds18b20_convert_temp(ds18b20_handler_t *device) +{ + onewire_reset(&device->bus); + onewire_send_command(&device->bus, _ROM_SKIP); + + ds18b20_send_command(device, _CONVERT_T); + + vTaskDelay(pdMS_TO_TICKS(ds18b20_temp_conv_time[device->res])); +} + +void ds18b20_write_scratchpad(ds18b20_handler_t *device) +{ + onewire_reset(&device->bus); + onewire_send_command(&device->bus, _ROM_SKIP); + + ds18b20_send_command(device, _SCRATCH_WRITE); + + // Th and Tl registers + onewire_write_byte(&device->bus, 0); + onewire_write_byte(&device->bus, 0); + // Resolution value + onewire_write_byte(&device->bus, ds18b20_resolution_val[device->res]); +} + +void ds18b20_copy_scratchpad(ds18b20_handler_t *device) +{ + onewire_reset(&device->bus); + onewire_send_command(&device->bus, _ROM_SKIP); + + ds18b20_send_command(device, _SCRATCH_COPY); +} + +void ds18b20_read_scratchpad(ds18b20_handler_t *device) +{ + onewire_reset(&device->bus); + onewire_send_command(&device->bus, _ROM_SKIP); + + ds18b20_send_command(device, _SCRATCH_READ); + + uint8_t i; + for (i = 0; i < 9; i++) + { + device->scratchpad[i] = onewire_read_byte(&device->bus); + } +} + +void ds18b20_print_scratchpad(ds18b20_handler_t *device) +{ + uint8_t i; + for (i = 0; i < 9; i++) + { + printf("%x ", device->scratchpad[i]); + } + + printf("\n"); +} + +float ds18b20_read_temp(ds18b20_handler_t *device) +{ + ds18b20_read_scratchpad(device); + + uint8_t sign = 0x0; + uint8_t lsb = device->scratchpad[0]; + uint8_t mask = 0xFF << (TEMP_RES_12_BIT - device->res); + lsb &= mask; // Mask out last 3 bits accordingly + uint8_t msb = device->scratchpad[1]; + + sign = msb & 0x80; + int16_t temp = 0x0; + + temp = lsb + (msb << 8); + + if (sign) + { + temp = ~(-temp) + 1; // Convert signed two complement's + } + + return temp / 16.0; +} \ No newline at end of file diff --git a/embedded/components/ds18b20/ds18b20.h b/embedded/components/ds18b20/ds18b20.h new file mode 100755 index 0000000..fa21886 --- /dev/null +++ b/embedded/components/ds18b20/ds18b20.h @@ -0,0 +1,97 @@ +#ifndef DS18B20_H +#define DS18B20_H + +#include "onewire.h" + +typedef enum { + TEMP_RES_9_BIT = 0, + TEMP_RES_10_BIT = 1, + TEMP_RES_11_BIT = 2, + TEMP_RES_12_BIT = 3 +} ds18b20_temp_res_t; + +typedef enum { + _SCRATCH_WRITE = 0x4E, + _SCRATCH_READ = 0xBE, + _SCRATCH_COPY = 0x48, + _CONVERT_T = 0x44 +} ds18b20_commands_t; + +typedef uint8_t ds18b20_scratchpad_t[9]; + +typedef struct { + onewire_bus_handle_t bus; + ds18b20_temp_res_t res; + ds18b20_scratchpad_t scratchpad; +} ds18b20_handler_t; + +/** + * @brief Initialize DS18B20 + * + * @param device DS18B20 handler + * @param pin Data pin + * @param resolution Temperature resolution + * + * @retval 1: Success + * @retval 0: Incorrect pin or gpio configuration failed (Logs tells which happened) + */ +uint8_t ds18b20_init(ds18b20_handler_t *device, gpio_num_t pin, ds18b20_temp_res_t resolution); + +/** + * @brief Send command to DS18B20 + * + * @param device DS18B20 handler + * @param command Function command + */ +void ds18b20_send_command(ds18b20_handler_t *device, ds18b20_commands_t command); + +/** + * @brief Write to scratchpad + * + * @param device DS18B20 handler + */ +void ds18b20_write_scratchpad(ds18b20_handler_t *device); + +/** + * @brief Read from scratchpad + * + * @param device DS18B20 handler + */ +void ds18b20_read_scratchpad(ds18b20_handler_t *device); + +/** + * @brief Copy to scratchpad + * + * @param device DS18B20 handler + */ +void ds18b20_copy_scratchpad(ds18b20_handler_t *device); + +/** + * @brief Print scratchpad bytes + * + * @param device DS18B20 handler + */ +void ds18b20_print_scratchpad(ds18b20_handler_t *device); + +/** + * @brief Initialize temperature conversion and wait for conversion + * + * Function sends CONV_T command and waits for X ms according to `ds18b20_temp_conv_time` static array + * + * @warning Should be called before `ds18b20_convert_temp()` function + * + * @param device DS18B20 handler + */ +void ds18b20_convert_temp(ds18b20_handler_t *device); + +/** + * @brief Read temperature from scratchpad + * + * Function reads temperature from scratchpad and converts it to Celsius. + * @warning `ds18b20_convert_temp()` have to be called before for updated temperature. + * + * @param device DS18B20 handler + */ +float ds18b20_read_temp(ds18b20_handler_t *device); + +#endif \ No newline at end of file diff --git a/embedded/components/onewire/component.mk b/embedded/components/onewire/component.mk new file mode 100755 index 0000000..f941c9f --- /dev/null +++ b/embedded/components/onewire/component.mk @@ -0,0 +1,5 @@ +# +# Component Makefile +# + +COMPONENT_ADD_INCLUDEDIRS := . \ No newline at end of file diff --git a/embedded/components/onewire/onewire.c b/embedded/components/onewire/onewire.c new file mode 100755 index 0000000..9ebc03f --- /dev/null +++ b/embedded/components/onewire/onewire.c @@ -0,0 +1,175 @@ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "rom/ets_sys.h" +#include "onewire.h" + +uint8_t onewire_configure_gpio(gpio_num_t pin, gpio_config_t *custom_config) +{ + if (!GPIO_IS_VALID_GPIO(pin)) + { + ESP_LOGE(TAG_ONEWIRE, "Provided pin is incorrect!"); + + return 0; + } + + gpio_config_t config = {}; + + if (!custom_config) + { + config.intr_type = GPIO_INTR_DISABLE; + config.mode = GPIO_MODE_OUTPUT_OD; + config.pin_bit_mask = ((uint32_t) 1 << pin); + config.pull_down_en = 0; + config.pull_up_en = 0; + } + else + { + config = *custom_config; + } + + if (gpio_config(&config) != ESP_OK) + { + return 0; + } + + return 1; +} + +uint8_t onewire_init(onewire_bus_handle_t *bus, gpio_num_t bus_pin, gpio_config_t *custom_config) +{ + if (!bus) + { + ESP_LOGW(TAG_ONEWIRE, "bus is null! (onewire_init)"); + + return 0; + } + + bus->pin = bus_pin; + bus->mutex = xSemaphoreCreateMutex(); + + // configure GPIO + if(!onewire_configure_gpio(bus_pin, custom_config)) + { + return 0; + } + + return 1; +} + +uint8_t onewire_reset(onewire_bus_handle_t *bus) +{ + uint8_t presence; + + if (xSemaphoreTake(bus->mutex, _BLOCK_TIME)) + { + gpio_set_level(bus->pin, 0); // Send reset pulse + ets_delay_us(_ONEWIRE_RESET_WAIT); + + gpio_set_level(bus->pin, 1); // Leave floating + ets_delay_us(_ONEWIRE_PRESENCE_WAIT); + + presence = !gpio_get_level(bus->pin); + + xSemaphoreGive(bus->mutex); + } + else + { + ESP_LOGE(TAG_ONEWIRE, _SEMFAIL_MSG, "onewire_reset"); + + return -1; + } + + ets_delay_us(_ONEWIRE_RESET_RECOVERY); + + return presence; +} + +void onewire_write_bit(onewire_bus_handle_t *bus, uint8_t bit) +{ + if (xSemaphoreTake(bus->mutex, _BLOCK_TIME)) + { + if (bit) + { + // Write 1 + gpio_set_level(bus->pin, 0); + ets_delay_us(_ONEWIRE_WRITE1_LOW); + + gpio_set_level(bus->pin, 1); + ets_delay_us(_ONEWIRE_WRITE1_WAIT); + } + else + { + // Write 0 + gpio_set_level(bus->pin, 0); + ets_delay_us(_ONEWIRE_WRITE0_LOW); + + gpio_set_level(bus->pin, 1); + ets_delay_us(_ONEWIRE_WRITE0_WAIT); + } + + xSemaphoreGive(bus->mutex); + } + else + { + ESP_LOGE(TAG_ONEWIRE, _SEMFAIL_MSG, "onewire_write_bit"); + } +} + +uint8_t onewire_read_bit(onewire_bus_handle_t *bus) +{ + uint8_t bit; + + if (xSemaphoreTake(bus->mutex, _BLOCK_TIME)) + { + gpio_set_level(bus->pin, 0); + ets_delay_us(_ONEWIRE_WRITE1_LOW); + + gpio_set_level(bus->pin, 1); + ets_delay_us(_ONEWIRE_READ_WAIT); + + bit = !gpio_get_level(bus->pin); + + xSemaphoreGive(bus->mutex); + + ets_delay_us(_ONEWIRE_READ_RECOVERY); + } + else + { + ESP_LOGE(TAG_ONEWIRE, _SEMFAIL_MSG, "onewire_read_bit"); + + return -1; + } + + return bit; +} + +void onewire_write_byte(onewire_bus_handle_t *bus, uint8_t byte) +{ + uint8_t i; + + for (i = 0; i < 8; i++) + { + onewire_write_bit(bus, (byte >> i) & 0x01); + } +} + +uint8_t onewire_read_byte(onewire_bus_handle_t *bus) +{ + uint8_t i; + uint8_t byte = 0x0; + + for (i = 0; i < 8; i++) + { + byte |= (!onewire_read_bit(bus) << i); + } + + return byte; +} + +void onewire_send_command(onewire_bus_handle_t *bus, onewire_rom_commands_t command) +{ + uint8_t payload = 0x0 ^ command; + + onewire_write_byte(bus, payload); +} \ No newline at end of file diff --git a/embedded/components/onewire/onewire.h b/embedded/components/onewire/onewire.h new file mode 100755 index 0000000..f919017 --- /dev/null +++ b/embedded/components/onewire/onewire.h @@ -0,0 +1,121 @@ +#ifndef ONEWIRE_H +#define ONEWIRE_H + +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "driver/gpio.h" +#include "esp_types.h" +#include "esp_err.h" + +#define _ONEWIRE_WRITE1_LOW 6 +#define _ONEWIRE_WRITE1_WAIT 64 +#define _ONEWIRE_WRITE0_LOW 60 +#define _ONEWIRE_WRITE0_WAIT 10 +#define _ONEWIRE_READ_WAIT 9 +#define _ONEWIRE_READ_RECOVERY 55 +#define _ONEWIRE_RESET_WAIT 480 +#define _ONEWIRE_PRESENCE_WAIT 70 +#define _ONEWIRE_RESET_RECOVERY 410 + +#define _BLOCK_TIME pdMS_TO_TICKS(1000) +#define _SEMFAIL_MSG "Failed to obtain semaphore. (%s)" + +static const char *TAG_ONEWIRE = "ONEWIRE"; + +typedef enum { + _ROM_READ = 0x33, + _ROM_SEARCH = 0xF0, + _ROM_MATCH = 0x55, + _ROM_SKIP = 0xCC +} onewire_rom_commands_t; + +typedef struct { + gpio_num_t pin; + SemaphoreHandle_t mutex; +} onewire_bus_handle_t; + +/** + * @brief Configure gpio pins for onewire communication + * + * Set `custom_config` to NULL for default config. + * + * @param pin Bus pin + * @param custom_config Custom gpio config + * + * @retval 1: Success + * @retval 0: Incorrect pin or gpio configuration failed (Logs tells which happened) + */ +uint8_t onewire_configure_gpio(gpio_num_t pin, gpio_config_t *custom_config); + +/** + * @brief Initalize onewire bus + * + * Set `custom_config` to NULL for default config. + * @warning MUST be called before any other library function! + * + * @param bus Bus handle + * @param pin Bus pin + * @param custom_config Custom gpio config + * + * @retval 1: Success + * @retval 0: `bus` is NULL or gpio configuration failed (Logs tells which happened) + */ +uint8_t onewire_init(onewire_bus_handle_t *bus, gpio_num_t bus_pin, gpio_config_t *custom_config); + +/** + * @brief Send reset pulse + * + * @param bus Bus handle + * + * @retval 1: Success (device sent presence pulse) + * @retval -1: Failed to obtain semaphore for gpio handling + * @retval 0: Device failed to return presence pulse + */ +uint8_t onewire_reset(onewire_bus_handle_t *bus); + +/** + * @brief Write bit + * + * @param bus Bus handle + * @param bit Bit to send + */ +void onewire_write_bit(onewire_bus_handle_t *bus, uint8_t bit); + +/** + * @brief Write byte + * + * @param bus Bus handle + * @param bit Byte to send + */ +void onewire_write_byte(onewire_bus_handle_t *bus, uint8_t byte); + +/** + * @brief Read bit + * + * @param bus Bus handle + * + * @retval 1: Device returned 1 + * @retval 0: Device returned 0 + * @retval -1: Failed to obtain semaphore for gpio handling + */ +uint8_t onewire_read_bit(onewire_bus_handle_t *bus); + +/** + * @brief Read bit + * + * @param bus Bus handle + * + * @return Byte returned by device + */ +uint8_t onewire_read_byte(onewire_bus_handle_t *bus); + +/** + * @brief Send command to device + * + * @param bus Bus handle + * @param command Onewire rom command + * + */ +void onewire_send_command(onewire_bus_handle_t *bus, onewire_rom_commands_t command); + +#endif \ No newline at end of file diff --git a/embedded/main/apple.c b/embedded/main/apple.c index 4478f7a..d64674e 100644 --- a/embedded/main/apple.c +++ b/embedded/main/apple.c @@ -5,7 +5,7 @@ #include "lwip/sockets.h" #include -#define EXIT_NODE a +// #define EXIT_NODE #ifdef EXIT_NODE #define TAG "TCP" @@ -23,6 +23,7 @@ void zh_network_event_handler(void *arg, esp_event_base_t event_base, int32_t ev uint8_t broadcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t test[6] = {0x09, 0xF2, 0x69, 0x42, 0x11, 0xA9}; +uint8_t _self_mac[6] = {0}; typedef struct { @@ -51,6 +52,7 @@ void app_main(void) wifi_init_config_t wifi_init_config = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&wifi_init_config); esp_wifi_set_mode(WIFI_MODE_STA); + esp_read_mac(_self_mac, WIFI_MODE_STA); #ifdef EXIT_NODE wifi_config_t wifi_config = { @@ -107,10 +109,9 @@ void app_main(void) for (;;) { tcp_message_t packet; - memcpy(packet.mac, test, 6); - packet.battery_voltage = 3.3f; - packet.temperature = 21.2f; - packet.up_time = 213273948; + memcpy(packet.mac, _self_mac, 6); + packet.battery_voltage = 3.3f packet.temperature = getTemp(); + packet.up_time = getUpTime(); vTaskDelay(10000 / portTICK_PERIOD_MS); zh_network_send(broadcast, (uint8_t *)&data, sizeof(data)); int err = send(sock, (uint8_t *)&packet, sizeof(tcp_message_t), 0); @@ -147,8 +148,11 @@ void zh_network_event_handler(void *arg, esp_event_base_t event_base, int32_t ev } #else heap_caps_free(recv_data->data); - // READ DATA - zh_network_send(recv_data->mac_addr, ) + sensor_message_t message = {0}; + message.temperature = getTemp(); + message.battery_voltage = 3.3f; + message.up_time = getUpTime(); + zh_network_send(recv_data->mac_addr, (uint8_t *)&message, sizeof(message)); #endif case ZH_NETWORK_ON_SEND_EVENT:; zh_network_event_on_send_t *send_data = event_data; @@ -164,4 +168,41 @@ void zh_network_event_handler(void *arg, esp_event_base_t event_base, int32_t ev default: break; } -} \ No newline at end of file +} + +// BoskoopBase + +int getUpTime() +{ + // Get system uptime in milliseconds + int uptime = (xTaskGetTickCount() * (1000 / configTICK_RATE_HZ)); + return uptime; +} + +float getTemp() +{ + float temp = 0.0; + ds18b20_handler_t sensor; + + // Initialize DS18B20 sensor + if (!ds18b20_init(&sensor, GPIO_NUM_2, TEMP_RES_12_BIT)) + { + ESP_LOGE("DS18B20", "Failed to initialize DS18B20 sensor!"); + return -1.0; // Indicate an error with a negative value + } + + // Convert temperature + ds18b20_convert_temp(&sensor); + + // Read the temperature + temp = ds18b20_read_temp(&sensor); + + // Check if the temperature is within a reasonable range for DS18B20 + if (temp < -55.0 || temp > 125.0) + { + ESP_LOGE("DS18B20", "Temperature reading out of range: %.2f", temp); + return -1.0; // Indicate invalid reading + } + + return temp; +}