From 33693f135381da6063735da712fc3064d0a12059 Mon Sep 17 00:00:00 2001 From: jweigele Date: Fri, 12 Apr 2024 18:44:35 -0700 Subject: [PATCH] RHT data reads and reporting humidity * Also reads temp, but not reporting that just because it's so different from the current sensors we have?? why?? * Lots of debug info for now, probably best to clean up * Unknown if regular temp still works since I refactored a bunch of functions --- aqi/main/Kconfig | 19 ++++ aqi/main/aqi.c | 219 +++++++++++++++++++++++++++++++++++++---------- aqi/main/aqi.h | 8 ++ 3 files changed, 199 insertions(+), 47 deletions(-) diff --git a/aqi/main/Kconfig b/aqi/main/Kconfig index 308e358..9b75c42 100644 --- a/aqi/main/Kconfig +++ b/aqi/main/Kconfig @@ -41,6 +41,25 @@ config AQI_RX_PIN help Gets passed and used later for includes +config RHT_ENABLED + bool "Fetch and report humidity + temp from RHT sensor?" + default n + +config RHT_SCL_PIN + int "RHT I2C clock pin" + depends on RHT_ENABLED + default 0 + +config RHT_SDA_PIN + int "RHT I2C SDA PIN" + depends on RHT_ENABLED + default 0 + +config RHT_ADDRESS + int "RHT I2C address in hex" + depends on RHT_ENABLED + default "68" + config CO2_PWM_ENABLED bool "Fetch and report CO2 from PWM?" default n diff --git a/aqi/main/aqi.c b/aqi/main/aqi.c index dc7ddf3..b27f5b4 100644 --- a/aqi/main/aqi.c +++ b/aqi/main/aqi.c @@ -49,7 +49,10 @@ typedef struct report_data_s { #if defined(CONFIG_CO2_UART_ENABLED) || defined(CONFIG_CO2_PWM_ENABLED) int16_t co2_ppm; #endif -#ifdef CONFIG_TEMP_ENABLED +#ifdef CONFIG_RHT_ENABLED + float humidity; +#endif +#if defined(CONFIG_TEMP_ENABLED) || defined(CONFIG_RHT_ENABLED) uint16_t temperature; #endif #if defined(CONFIG_MOTION_FIRST_ENABLED) || defined(CONFIG_MOTION_SECOND_ENABLED) @@ -93,12 +96,18 @@ static QueueHandle_t pwm_queue; // for tracking and reporting device uptime static uint32_t device_uptime_seconds = 0; -#ifdef CONFIG_TEMP_ENABLED +#if defined(CONFIG_TEMP_ENABLED) || defined(CONFIG_RHT_ENABLED) static int tempbuffer[TEMPBUFFERSIZE]; static int tempbufferindex = 0; -static OW ow; +#endif +#ifdef CONFIG_RHT_ENABLED +static i2c_master_dev_handle_t rht_handle; +#endif + +#ifdef CONFIG_TEMP_ENABLED +static OW ow; #endif #ifdef CONFIG_LED_ENABLED @@ -461,9 +470,10 @@ void init_led(){ #endif + #ifdef CONFIG_TEMP_ENABLED -bool init_temp(){ +bool init_temp_ow(){ bool err = ow_init(&ow, CONFIG_TEMP_PIN); if (err){ ESP_LOGI(TAG, "there was an error initing ow"); @@ -471,51 +481,11 @@ bool init_temp(){ return err; } -int new_temp_average(short new_val){ - tempbuffer[tempbufferindex++] = new_val; - // rollover - if (tempbufferindex == TEMPBUFFERSIZE){ - tempbufferindex = 0; - } - - int total = 0; - int count = 0; - for (int i = 0; i < TEMPBUFFERSIZE; i++ ){ - // ignore invalid - if ( tempbuffer[i] != 0x8000 ){ - if (tempbuffer[i] > MIN_TEMP_VALUE && tempbuffer[i] < MAX_TEMP_VALUE){ - total += tempbuffer[i]; - count++; - } else { - ESP_LOGW(TAG, "temp value outside configured range, ignoring (value: %d min: %d max: %d)", - tempbuffer[i], MIN_TEMP_VALUE, MAX_TEMP_VALUE); - } - } - } - int retval; - // we should only get here if all values are added are 0x8000 (aka no read) - // but it's still important to fill out just so we don't crash - // mainly, when ds18b20 is not connected or sensing properly - if (count == 0){ - retval = 0x8000; - } else { - retval = (int)(total/count); - } - ESP_LOGI(TAG, "returning average temp to send: %d", retval); - return retval; - -} - -void init_tempbuffer(){ - for (int i = 0; i < TEMPBUFFERSIZE; i++){ - tempbuffer[i] = 0x8000; - } -} // fetches temperature from any attached ds18b20 devices // returns as value * 100 (so that we can get 2 decimal places by later /100 // without dealing with float nonsense now) -static short get_temp(){ +static short get_temp_ow(){ if (ow_reset (&ow)) { // scan bus for devices uint64_t romcode[MAXDEVS]; @@ -554,7 +524,155 @@ static short get_temp(){ } } +#endif + +#ifdef CONFIG_RHT_ENABLED + +bool init_rht(){ + report_data.humidity = 0; + i2c_master_bus_config_t i2c_mst_config = { + .clk_source = I2C_CLK_SRC_DEFAULT, + .i2c_port = 0, + .scl_io_num = CONFIG_RHT_SCL_PIN, + .sda_io_num = CONFIG_RHT_SDA_PIN, + .glitch_ignore_cnt = 0, + .flags.enable_internal_pullup = false, //true, + }; + + i2c_master_bus_handle_t bus_handle; + ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle)); + + esp_err_t check = i2c_master_probe(bus_handle, CONFIG_RHT_ADDRESS, -1); + if (check != ESP_OK){ + ESP_LOGE(TAG, "unable to find RHT device at address 0x%02x, error!", CONFIG_RHT_ADDRESS); + return false; + } + + ESP_LOGI(TAG, "i2c RHT sensor found at address 0x%02x", CONFIG_RHT_ADDRESS); + + i2c_device_config_t dev_cfg = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = CONFIG_RHT_ADDRESS, + .scl_speed_hz = 400000, + }; + + ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &rht_handle)); + return true; + +} + + +static short get_data_rht(){ + uint8_t send_cmd[1] = CMD_HIGH_PRECISION_READ; + uint8_t buf[8]; + memset(buf, 0, 8); + + ESP_LOGI(TAG, "fetching rht data"); + //ESP_ERROR_CHECK(i2c_master_transmit_receive(rht_handle, send_cmd, 2, buf, 6, -1)); + esp_err_t tx_check = i2c_master_transmit(rht_handle, send_cmd, sizeof(send_cmd), -1); + ESP_LOGE(TAG, "i2c transmit status is %s", esp_err_to_name(tx_check)); + if (tx_check != ESP_OK){ + return -1; + } + // delay to allow measurement time to finish + vTaskDelay( pdMS_TO_TICKS(10) ); + esp_err_t rx_check = i2c_master_receive(rht_handle, buf, 6, -1); + ESP_LOGE(TAG, "i2c receive status is %s", esp_err_to_name(rx_check)); + if (rx_check != ESP_OK){ + return -1; + } + + ESP_LOG_BUFFER_HEXDUMP(TAG, buf, sizeof(buf), ESP_LOG_INFO); + + uint16_t sensor_data_temp = (buf[0] << 8) | buf[1]; + float sensor_temp = (-49+(175 * (sensor_data_temp/65535.0))); + ESP_LOGI(TAG, "i2c sensor temp %f", sensor_temp); + uint16_t sensor_data_rh = (buf[3] << 8) | buf[4]; + float sensor_rh = (-6 + (125 * (sensor_data_rh/65535.0))); + ESP_LOGI(TAG, "i2c sensor rh %f", sensor_rh); + + // doesn't really matter when we start the counting loop, so just block until we have the semaphore + // (should only be unavailable if another task is updating, or more likely we're generating the report) + xSemaphoreTake(report_data.mutex, portMAX_DELAY); + report_data.humidity = sensor_rh; + xSemaphoreGive(report_data.mutex); + + + return -1; + +} +#endif + +#if defined(CONFIG_TEMP_ENABLED) || defined(CONFIG_RHT_ENABLED) + +short get_temp(){ +#ifdef CONFIG_TEMP_ENABLED + return get_temp_ow(); +#endif +#ifdef CONFIG_RHT_ENABLED + return get_data_rht(); +#endif +} + +bool init_temp(){ + // initialize one wire temperature if enabled +#ifdef CONFIG_TEMP_ENABLED + if (!init_temp_ow()){ + return false; + } +#endif + // initialize RHT if enabled +#ifdef CONFIG_RHT_ENABLED + if (!init_rht()){ + return false; + } +#endif + // all configured sensors init + ESP_LOGI(TAG, "temperature init successfully!"); + return true; +} + +int new_temp_average(short new_val){ + tempbuffer[tempbufferindex++] = new_val; + // rollover + if (tempbufferindex == TEMPBUFFERSIZE){ + tempbufferindex = 0; + } + + int total = 0; + int count = 0; + for (int i = 0; i < TEMPBUFFERSIZE; i++ ){ + // ignore invalid + if ( tempbuffer[i] != 0x8000 ){ + if (tempbuffer[i] > MIN_TEMP_VALUE && tempbuffer[i] < MAX_TEMP_VALUE){ + total += tempbuffer[i]; + count++; + } else { + ESP_LOGW(TAG, "temp value outside configured range, ignoring (value: %d min: %d max: %d)", + tempbuffer[i], MIN_TEMP_VALUE, MAX_TEMP_VALUE); + } + } + } + int retval; + // we should only get here if all values are added are 0x8000 (aka no read) + // but it's still important to fill out just so we don't crash + // mainly, when ds18b20 is not connected or sensing properly + if (count == 0){ + retval = 0x8000; + } else { + retval = (int)(total/count); + } + ESP_LOGI(TAG, "returning average temp to send: %d", retval); + return retval; + +} + +void init_tempbuffer(){ + for (int i = 0; i < TEMPBUFFERSIZE; i++){ + tempbuffer[i] = 0x8000; + } +} #endif // most conditional stuff done by now @@ -931,6 +1049,13 @@ static void send_report_summary(report_data_t report_data){ cJSON_AddNumberToObject(root, "pm25", ((float)report_data.pm25/100)); cJSON_AddNumberToObject(root, "aqi", report_data.aqi); #endif +#ifdef CONFIG_RHT_ENABLED + char* rh = malloc(10); + memset(rh, 0, 10); + snprintf(rh, 10, "%.02f", report_data.humidity); + cJSON_AddStringToObject(root, "rh", rh); + free(rh); +#endif #if defined(CONFIG_CO2_UART_ENABLED) || defined(CONFIG_CO2_PWM_ENABLED) // -1 is what we use for errors, 0 seems to be the device just isn't yet init @@ -1436,7 +1561,7 @@ static void motion_task(void* discard){ static void monitoring_task(void* discard) { -#ifdef CONFIG_TEMP_ENABLED +#if defined(CONFIG_TEMP_ENABLED) || defined(CONFIG_RHT_ENABLED) short temp_avg = 0; init_temp(); #endif @@ -1537,7 +1662,7 @@ static void monitoring_task(void* discard) } #endif // end CO2 UART section -#ifdef CONFIG_TEMP_ENABLED +#if defined(CONFIG_TEMP_ENABLED) || defined(CONFIG_RHT_ENABLED) // Temperature fetch/calculation/report temp_avg = new_temp_average(get_temp()); xSemaphoreTake(report_data.mutex, portMAX_DELAY); diff --git a/aqi/main/aqi.h b/aqi/main/aqi.h index 1389310..57e1a45 100644 --- a/aqi/main/aqi.h +++ b/aqi/main/aqi.h @@ -102,10 +102,18 @@ static const char *TAG = "aqi"; #ifdef CONFIG_TEMP_ENABLED #include "onewire.h" +#endif +#if defined(CONFIG_TEMP_ENABLED) || defined(CONFIG_RHT_ENABLED) #define MIN_TEMP_VALUE -5500 #define MAX_TEMP_VALUE 12500 #endif + +#ifdef CONFIG_RHT_ENABLED +#include "driver/i2c_master.h" +#define CMD_HIGH_PRECISION_READ {0xFD} +#endif + #ifdef CONFIG_CO2_UART_ENABLED // 8 bytes + 1 checksum, defined by manufacturer // we should expect 9 bytes in return -- 2.30.2