Tue, 03 Oct 2023 17:24:06 +0200
Version 0.3.0. Backported network code from experimental roaming project. Will now connect after reset to the strongest AP. Id the signal level drops below -67, extra scans are done to see for a better AP. Nothing is done yet. Removed config.conf file, all info is taken from the project menu and live tests. Better log the board type and send it via json mqtt. Send bssid and current channel too.
/** * @file task_adc.c * @brief The FreeRTOS task to query the pressure sensors connected to ADC inputs. * The task will update the ADC_State structure. */ #include "config.h" #define DEFAULT_VREF 1093 ///< Use adc2_vref_to_gpio() to obtain a better estimate #define NO_OF_SAMPLES 128 ///< Multisampling #define PRESSURE_1 (CONFIG_PRESSURE_1) ///< ADC channel pressure sensor 1 #define PRESSURE_2 (CONFIG_PRESSURE_2) ///< ADC channel pressure sensor 2 #define PRESSURE_3 (CONFIG_PRESSURE_3) ///< ADC channel pressure sensor 3 #define BATT_CHANNEL (CONFIG_BATT_CHANNEL) ///< ADC channel half battery voltage static const char *TAG = "task_adc"; SemaphoreHandle_t xSemaphoreADC = NULL; ///< Semaphire ADC task EventGroupHandle_t xEventGroupADC; ///< Events ADC task ADC_State *adc_state; ///< Public state for other tasks bool do_calibration = false; const int TASK_ADC_REQUEST_PRESSURE = BIT0; ///< Request temperature measurements const int TASK_ADC_REQUEST_DONE = BIT1; ///< Request is completed static bool adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle); void request_adc(void) { xEventGroupClearBits(xEventGroupADC, TASK_ADC_REQUEST_DONE); xEventGroupSetBits(xEventGroupADC, TASK_ADC_REQUEST_PRESSURE); } bool ready_adc(void) { if (xEventGroupGetBits(xEventGroupADC) & TASK_ADC_REQUEST_DONE) return true; return false; } /* * Task to read pressure sensors and battery voltage on request. */ void task_adc(void *pvParameter) { adc_cali_handle_t adc1_cali_handle = NULL; adc_unit_t channel; adc_oneshot_chan_cfg_t config_adc = { .bitwidth = ADC_BITWIDTH_DEFAULT, .atten = ADC_ATTEN_DB_0, }; ESP_LOGI(TAG, "Starting task ADC sensors"); adc_state = malloc(sizeof(ADC_State)); for (int i = 0; i < 3; i++) { adc_state->Pressure[i].valid = false; adc_state->Pressure[i].atten = ADC_ATTEN_DB_0; adc_state->Pressure[i].voltage = 0; adc_state->Pressure[i].error = ADC_ERR_NONE; } adc_state->Pressure[0].channel = PRESSURE_1; adc_state->Pressure[1].channel = PRESSURE_2; adc_state->Pressure[2].channel = PRESSURE_3; adc_state->Batt_voltage = 0; adc_state->Batt_error = ADC_ERR_NONE; /* event handler and event group for this task */ xEventGroupADC = xEventGroupCreate(); EventBits_t uxBits; /* * Task loop forever. */ while (1) { uxBits = xEventGroupWaitBits(xEventGroupADC, TASK_ADC_REQUEST_PRESSURE, pdFALSE, pdFALSE, portMAX_DELAY ); if (uxBits & TASK_ADC_REQUEST_PRESSURE) { ESP_LOGD(TAG, "Requested ADC readings"); int adc_reading, raw, tmp, voltage; adc_atten_t atten = ADC_ATTEN_DB_0; adc_oneshot_unit_handle_t adc1_handle; adc_oneshot_unit_init_cfg_t init_config1 = { .unit_id = ADC_UNIT_1, }; for (int i = 0; i < 3; i++) { ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle)); atten = config_adc.atten = ADC_ATTEN_DB_0, channel = adc_state->Pressure[i].channel; ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, channel, &config_adc)); adc_reading = 0; /* * Autoranging the ADC conversion */ while (1) { config_adc.bitwidth = ADC_BITWIDTH_DEFAULT; config_adc.atten = atten; adc_oneshot_config_channel(adc1_handle, channel, &config_adc); ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, channel, &raw)); // ESP_LOGI(TAG, "bottle %d channel %d raw %d atten %d", i, channel, raw, atten); if (atten == ADC_ATTEN_DB_0 && raw > 3700) atten = ADC_ATTEN_DB_2_5; else if (atten == ADC_ATTEN_DB_2_5 && raw > 3700) atten = ADC_ATTEN_DB_6; else if (atten == ADC_ATTEN_DB_6 && raw > 3700) atten = ADC_ATTEN_DB_11; else break; } /* * Now that he have the best attenuation, multisample the real value. */ for (int j = 0; j < NO_OF_SAMPLES; j++) { if (adc_oneshot_read(adc1_handle, channel, &tmp) == ESP_OK) { adc_reading += tmp; } else { adc_reading = -1; break; } } do_calibration = adc_calibration_init(ADC_UNIT_1, atten, &adc1_cali_handle); if (xSemaphoreTake(xSemaphoreADC, 10) == pdTRUE) { if (adc_reading < 0) { adc_state->Pressure[i].error = ADC_ERR_READ; adc_state->Pressure[i].voltage = 0; } else { adc_reading /= NO_OF_SAMPLES; adc_cali_raw_to_voltage(adc1_cali_handle, adc_reading, &voltage); // voltage in mV adc_state->Pressure[i].voltage = voltage; adc_state->Pressure[i].error = ADC_ERR_NONE; } xSemaphoreGive(xSemaphoreADC); } else { ESP_LOGE(TAG, "Missed lock 1"); } ESP_LOGI(TAG, "Pressure %d raw: %4d, atten: %d, %.3f volt, error: %d", i, adc_reading, atten, (adc_state->Pressure[i].voltage / 1000.0), adc_state->Pressure[i].error); //Tear Down adc_oneshot_del_unit(adc1_handle); if (do_calibration) { adc_cali_delete_scheme_line_fitting(adc1_cali_handle); } do_calibration = false; } /* * Read VDD by reading 1/2 VDD from a precision ladder. */ adc_reading = 0; atten = ADC_ATTEN_DB_6; // Don't use DB_11, it has a bad linearity. channel = (adc_unit_t)BATT_CHANNEL; ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle)); do_calibration = adc_calibration_init(ADC_UNIT_1, atten, &adc1_cali_handle); config_adc.bitwidth = ADC_BITWIDTH_DEFAULT; config_adc.atten = atten; adc_oneshot_config_channel(adc1_handle, (adc_unit_t)BATT_CHANNEL, &config_adc); ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, (adc_unit_t)BATT_CHANNEL, &raw)); for (int j = 0; j < NO_OF_SAMPLES; j++) { if (adc_oneshot_read(adc1_handle, channel, &tmp) == ESP_OK) { adc_reading += tmp; } else { adc_reading = -1; break; } } if (xSemaphoreTake(xSemaphoreADC, 10) == pdTRUE) { if (adc_reading < 0) { adc_state->Batt_voltage = 3.3; adc_state->Batt_error = ADC_ERR_READ; } else { adc_reading /= NO_OF_SAMPLES; adc_cali_raw_to_voltage(adc1_cali_handle, adc_reading, &voltage); /* Multiply by 2, measured on a ladder. */ adc_state->Batt_voltage = voltage * 2; // Chip supply voltage in mV adc_state->Batt_error = ADC_ERR_NONE; } xSemaphoreGive(xSemaphoreADC); } else { ESP_LOGE(TAG, "Missed lock 2"); } adc_oneshot_del_unit(adc1_handle); if (do_calibration) { adc_cali_delete_scheme_line_fitting(adc1_cali_handle); } do_calibration = false; xEventGroupClearBits(xEventGroupADC, TASK_ADC_REQUEST_PRESSURE); xEventGroupSetBits(xEventGroupADC, TASK_ADC_REQUEST_DONE); #if 1 ESP_LOGI(TAG, "Battery raw: %4d, atten: %d %.3f volt, error: %d", adc_reading, atten, adc_state->Batt_voltage / 1000.0, adc_state->Batt_error); #endif } } } /*--------------------------------------------------------------- ADC Calibration ---------------------------------------------------------------*/ static bool adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle) { adc_cali_handle_t handle = NULL; bool calibrated = false; adc_cali_line_fitting_config_t cali_config = { .unit_id = unit, .atten = atten, .bitwidth = ADC_BITWIDTH_DEFAULT, }; esp_err_t ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle); if (ret == ESP_OK) { calibrated = true; } *out_handle = handle; if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) { ESP_LOGW(TAG, "eFuse not burnt, skip software calibration"); } else if (ret != ESP_OK) { ESP_LOGE(TAG, "Invalid arg or no memory"); } return calibrated; }