#include "CO2_Sense.h" #include #include "configuration.h" #include "freertos/FreeRTOS.h" #include "freertos/portmacro.h" #include "freertos/task.h" #include #include "hal/gpio_types.h" #include "nvs_flash.h" #include "lwip/err.h" #include "lwip/sys.h" #include "esp_log.h" #include "esp_sleep.h" #include "esp_pm.h" #include "driver/gpio.h" #include "driver/i2c.h" #include "esp_adc/adc_oneshot.h" #include "ledController.h" #include "scd4x_i2c.h" #include "sdkconfig.h" #include "sensirion_i2c_hal.h" #include "scd4x_data.h" #include "BTlib_nimble.h" #include "MMC56x3.h" void app_main(void){ init_nvs(); // setup GPIOs gpio_config_t VBAT_OK_c = { GPIO_NUM_3, GPIO_MODE_INPUT, GPIO_PULLUP_DISABLE, GPIO_PULLDOWN_DISABLE, GPIO_INTR_DISABLE, }; ESP_ERROR_CHECK(gpio_config(&VBAT_OK_c)); esp_pm_config_esp32c3_t pm_config = { .max_freq_mhz = 80, .min_freq_mhz = 40, .light_sleep_enable = true, // enable light sleep }; //ESP_ERROR_CHECK(esp_pm_configure(&pm_config)); configuration_data_t* conf = malloc(sizeof(configuration_data_t)); init_conf_from_nvs(conf); // init LEDs driver init_led_driver(conf->leds, conf->led_nb); // init BLE initBle(conf); // start sensor init_i2c(); init_scd4x(); init_battery_level_adc(conf->battery_conf); TaskHandle_t battms_update_handle; xTaskCreate(update_battery_level, "BATTMS_update", 4096, conf->battery_conf, tskIDLE_PRIORITY, &battms_update_handle); uint8_t id=0; MMC56x3_get_product_ID(&id); ESP_LOGI("MAIN", "MMC5603 product id %d", id); switch(conf->sensor->mode){ case SCD4X_NORMAL_MODE: ESP_ERROR_CHECK(scd4x_start_periodic_measurement()); ESP_LOGI("scd4x init","started in normal mode"); break; case SCD4X_LP_MODE: ESP_ERROR_CHECK(scd4x_start_low_power_periodic_measurement()); ESP_LOGI("scd4x init","started in low power mode"); break; } if(conf->sensor->mode & SCD4X_CAPTURE_ENABLED){ TaskHandle_t sensor_fetch_handle; xTaskCreate(fetch_sensor_task, "FETCH_SENSOR", 4096, conf, tskIDLE_PRIORITY, &sensor_fetch_handle); } while(1){ vTaskDelay(1000 / portTICK_PERIOD_MS); } } void fetch_sensor_task(void* pvParameters){ configuration_data_t* mainConf = (configuration_data_t*) pvParameters; scd4x_config_t* conf = mainConf->sensor; scd4x_data_t* measures = conf->measure; while(1){ if(conf->mode == SCD4X_SS_MODE) scd4x_measure_single_shot(); vTaskDelay(conf->delay * 1000 / portTICK_PERIOD_MS); uint16_t dataReady; scd4x_get_data_ready_status(&dataReady); if(!(dataReady & 0x07FF)) continue; int16_t error = scd4x_read_measurement(&measures->co2, &measures->temperature, &measures->humidity); if (error) ESP_LOGE("sensor fetch", "Error executing scd4x_read_measurement(): %i\n", error); update_led_status(mainConf->leds, mainConf->led_nb, conf->measure->co2); ble_sensor_notify(); ESP_LOGI("MAIN", "co2 : %u ppm, temp : %ld m°C, hum : %ld mRH", conf->measure->co2, conf->measure->temperature, conf->measure->humidity); } } void init_nvs(void){ esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); } void init_i2c(){ int i2c_master_port = I2C_NUM_0; i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = CONFIG_SDA_PIN, .sda_pullup_en = GPIO_PULLUP_DISABLE, .scl_io_num = CONFIG_SCL_PIN, .scl_pullup_en = GPIO_PULLUP_DISABLE, .master.clk_speed = 10000, // .clk_flags = 0, /*!< Optional, you can use I2C_SCLK_SRC_FLAG_* flags to choose i2c source clock here. */ }; i2c_param_config(i2c_master_port, &conf); i2c_driver_install(i2c_master_port, I2C_MODE_MASTER, 0, 0, 0); } void init_scd4x(){ scd4x_wake_up(); scd4x_stop_periodic_measurement(); scd4x_reinit(); } void init_battery_level_adc(battery_conf_t* batt_conf){ adc_oneshot_unit_init_cfg_t init_config1 = { .unit_id = ADC_UNIT_1, .ulp_mode = ADC_ULP_MODE_DISABLE, }; ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, batt_conf->adc_handle)); adc_oneshot_chan_cfg_t config = { .bitwidth = ADC_BITWIDTH_DEFAULT, .atten = ADC_ATTEN_DB_11, }; ESP_ERROR_CHECK(adc_oneshot_config_channel(*batt_conf->adc_handle, batt_conf->adc_channel, &config)); } void update_battery_level(void* pvParameters){// battery_data_t* data, uint8_t channel, adc_oneshot_unit_handle_t* handle){ battery_conf_t* batt_conf = pvParameters; int val_raw = 0; while(1){ esp_err_t res = adc_oneshot_read(*(batt_conf->adc_handle), batt_conf->adc_channel, &val_raw); if(res != ESP_ERR_TIMEOUT){ // valeur invalide ESP_ERROR_CHECK(res); battery_data_t* data = batt_conf->data; data->battery_percent = (val_raw - data->min_raw) * data->scale; ESP_LOGI("BATTMS", "raw : %d, percent : %d", val_raw, data->battery_percent); } vTaskDelay(batt_conf->poll_delay / portTICK_PERIOD_MS); } }