From: jweigele Date: Wed, 20 Mar 2024 05:32:19 +0000 (-0700) Subject: Add CO2 PWM sensor reads and clean up dependencies X-Git-Url: http://git.hexthepla.net/?a=commitdiff_plain;h=28c292eda4f296af1da1260c4ca4d8d6775abe77;p=esp32projects Add CO2 PWM sensor reads and clean up dependencies * CO2 PWM counts for 10 seconds and then averages PPM values by formula using one pin * Kconfig now has a bunch of depends to clean up cruft on the screen * Move some variables around to prevent issues with unused warnings --- diff --git a/aqi/dependencies.lock b/aqi/dependencies.lock index fd71409..3705fbd 100644 --- a/aqi/dependencies.lock +++ b/aqi/dependencies.lock @@ -9,7 +9,7 @@ dependencies: component_hash: null source: type: idf - version: 5.2.0 + version: 5.2.1 manifest_hash: fe84d3cba19d4dc50bbd18a9bed2d19eaa863b4be82668f06a4725d7b974e0c1 target: esp32h2 version: 1.0.0 diff --git a/aqi/main/Kconfig b/aqi/main/Kconfig index e4fbdd3..be79340 100644 --- a/aqi/main/Kconfig +++ b/aqi/main/Kconfig @@ -8,6 +8,7 @@ config TEMP_ENABLED config TEMP_PIN int "If using temperature, on which GPIO?" default 4 + depends on TEMP_ENABLED help Gets passed and used later for includes config EEPY_DEVICE @@ -17,6 +18,7 @@ config EEPY_DEVICE Working on this config LIGHT_SLEEP_ENABLED bool "Actually go into light sleep between polls?" + depends on EEPY_DEVICE default n help Not very well tested yet @@ -39,7 +41,16 @@ config AQI_RX_PIN help Gets passed and used later for includes -config CO2_ENABLED +config CO2_PWM_ENABLED + bool "Fetch and report CO2 from PWM?" + default n + +config CO2_PWM_PIN + int "PWM RX pin for CO2" + depends on CO2_PWM_ENABLED + default 0 + +config CO2_UART_ENABLED bool "Fetch and report CO2 from UART?" default n help @@ -48,18 +59,17 @@ config CO2_ENABLED config CO2_TX_PIN int "UART TX pin for CO2" default 22 + depends on CO2_UART_ENABLED help Gets passed and used later for includes config CO2_RX_PIN int "UART RX pin for CO2" default 25 + depends on CO2_UART_ENABLED help Gets passed and used later for includes - - - config WIFI_ENABLED bool "Are we using wifi association and MQTT" default n @@ -82,6 +92,7 @@ config MOTION_FIRST_ENABLED Gets passed and used later for includes config MOTION_FIRST_PIN int "If using motion, on which GPIO?" + depends on MOTION_FIRST_ENABLED default 22 help Gets passed and used later for includes @@ -93,6 +104,7 @@ config MOTION_SECOND_ENABLED Gets passed and used later for includes config MOTION_SECOND_PIN int "If using motion, on which GPIO?" + depends on MOTION_SECOND_ENABLED default 22 help Gets passed and used later for includes @@ -110,33 +122,41 @@ config PWM_ENABLED config PWM_TOPIC string "Topic to listen on for PWM data" default "esp32/pwm/default" + depends on PWM_ENABLED config PWM_TARGET_PERCENT int "Target percentage for PWM" + depends on PWM_ENABLED default 50 config PWM_R1_GPIO int "Red 1 GPIO LED, -1 for disabled" + depends on PWM_ENABLED default -1 config PWM_G1_GPIO int "Green 1 GPIO LED, -1 for disabled" + depends on PWM_ENABLED default -1 config PWM_B1_GPIO int "Blue 1 GPIO LED, -1 for disabled" + depends on PWM_ENABLED default -1 config PWM_R2_GPIO int "Red 2 GPIO LED, -1 for disabled" + depends on PWM_ENABLED default -1 config PWM_G2_GPIO int "Green 2 GPIO LED, -1 for disabled" + depends on PWM_ENABLED default -1 config PWM_B2_GPIO int "Blue 2 GPIO LED, -1 for disabled" + depends on PWM_ENABLED default -1 diff --git a/aqi/main/aqi.c b/aqi/main/aqi.c index 4cead69..0dfae01 100644 --- a/aqi/main/aqi.c +++ b/aqi/main/aqi.c @@ -46,7 +46,7 @@ typedef struct report_data_s { uint16_t pm25; float aqi; #endif -#ifdef CONFIG_CO2_ENABLED +#if defined(CONFIG_CO2_UART_ENABLED) || defined(CONFIG_CO2_PWM_ENABLED) int16_t co2_ppm; #endif #ifdef CONFIG_TEMP_ENABLED @@ -62,7 +62,6 @@ typedef struct report_data_s { } report_data_t; // end report data - static temperature_sensor_handle_t temp_handle; static QueueHandle_t event_queue; static QueueHandle_t send_queue; @@ -628,7 +627,7 @@ void init_uart_aqi(void) { } #endif -#ifdef CONFIG_CO2_ENABLED +#ifdef CONFIG_CO2_UART_ENABLED // hardcoded given the co2 device we expect to find void init_uart_co2(void) { const uart_config_t uart_config = { @@ -709,9 +708,80 @@ int16_t co2_read_sensor(void){ // we read the correct number of bytes in response, now need to parse and return return co2_parse_sensor_data(co2_data); } +#endif // CONFIG_CO2_UART_ENABLED -#endif +#ifdef CONFIG_CO2_PWM_ENABLED +static void co2_pwm_task(void* discard){ + TickType_t xLastWakeTime; + const TickType_t xFrequency = pdMS_TO_TICKS(10); //1/portTICK_PERIOD_MS; + + // Initialise the xLastWakeTime variable with the current time. + xLastWakeTime = xTaskGetTickCount(); + int counter = 0; + int total_high = 0; + int total_low = 0; + int total_ppm = 0; + int level = 0; + + //zero-initialize the config structure. + gpio_config_t io_conf = {}; + + // GPIO interrupt on either rising or falling edge + io_conf.intr_type = GPIO_INTR_DISABLE; + // bit mask of the pins, set to nothing at the start + io_conf.pin_bit_mask = 0; + io_conf.pin_bit_mask |= (1ULL << CONFIG_CO2_PWM_PIN ); + + //set as input mode + io_conf.mode = GPIO_MODE_INPUT; + // enable pull-down mode + io_conf.pull_down_en = 1; + io_conf.pull_up_en = 0; + // hysteresis separates the thresholds for high/low so we don't have a lot of toggling in between + io_conf.hys_ctrl_mode = GPIO_HYS_SOFT_ENABLE; + gpio_config(&io_conf); + + + // this will loop every 10 seconds and slur out a little less than 10 1004ms periods + // but that's okay, since we expect CO2 to mostly stay the same and anyway this will be an average of the cycle + // the _important_ bit is just to be consistent on delay, so using vTaskDelayUntil helps there + // + // see MH-Z19B datasheet for more details + for( ;; ){ + // each period is 1004ms, so we'll just count up to that to keep the formula the same + if (counter > 1003){ + // formula from the datasheet + total_ppm = (5000*(total_high-2))/(total_high+total_low-4); + // 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.co2_ppm = total_ppm; + xSemaphoreGive(report_data.mutex); + + total_high = 0; + total_low = 0; + counter = 0; + } + + // get the + level = gpio_get_level(CONFIG_CO2_PWM_PIN); + + if (level == 1){ + total_high += 1; + } else { + total_low += 1; + } + + // Wait for the next cycle. + vTaskDelayUntil( &xLastWakeTime, xFrequency ); + counter+=1; + + // Perform action here. + } +} + +#endif // CONFIG_CO2_PWM_ENABLED // this task sends identifying information over mqtt, sleeps an hour, then repeats @@ -843,7 +913,8 @@ 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_CO2_ENABLED +#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 if (report_data.co2_ppm != -1 && report_data.co2_ppm != 0){ cJSON_AddNumberToObject(root, "co2", report_data.co2_ppm); @@ -1343,15 +1414,13 @@ static void motion_task(void* discard){ static void monitoring_task(void* discard) { -short temp_avg = 0; #ifdef CONFIG_TEMP_ENABLED + short temp_avg = 0; init_temp(); #endif #ifdef CONFIG_AQI_ENABLED - uint16_t set_pm10; - uint16_t set_pm25; float cur_aqi_pm25 = 0.0; float cur_aqi_pm10 = 0.0; int length = 0; @@ -1439,17 +1508,15 @@ short temp_avg = 0; #endif #endif // end AQI UART section -#ifdef CONFIG_CO2_ENABLED +#ifdef CONFIG_CO2_UART_ENABLED int16_t co2_ppm = co2_read_sensor(); if (co2_ppm != -1 ){ xSemaphoreTake(report_data.mutex, portMAX_DELAY); report_data.co2_ppm = co2_ppm; xSemaphoreGive(report_data.mutex); } - #endif // end CO2 UART section - temp_avg = 0; #ifdef CONFIG_TEMP_ENABLED // Temperature fetch/calculation/report temp_avg = new_temp_average(get_temp()); @@ -1751,9 +1818,12 @@ void app_main(void) init_uart_aqi(); init_pmbuffer(); #endif -#ifdef CONFIG_CO2_ENABLED +#ifdef CONFIG_CO2_UART_ENABLED init_uart_co2(); #endif +#ifdef CONFIG_CO2_PWM_ENABLED + xTaskCreate(co2_pwm_task, "co2_pwm_task", 4096, NULL, 2, NULL); +#endif #ifdef CONFIG_TEMP_ENABLED init_tempbuffer(); #endif diff --git a/aqi/main/aqi.h b/aqi/main/aqi.h index 0f2c25d..06087f0 100644 --- a/aqi/main/aqi.h +++ b/aqi/main/aqi.h @@ -106,7 +106,7 @@ static const char *TAG = "aqi"; #define MAX_TEMP_VALUE 12500 #endif -#ifdef CONFIG_CO2_ENABLED +#ifdef CONFIG_CO2_UART_ENABLED // 8 bytes + 1 checksum, defined by manufacturer // we should expect 9 bytes in return #define CO2_FETCH {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}