# HG changeset patch # User Michiel Broek # Date 1695732589 -7200 # Node ID 121b3fa6b8064c3c83b6a7f552f2edcd7efe75b9 # Parent 3557b91717d7491c682a48264058862090519471 Migrated ADC converter to isp-idf v5.1 diff -r 3557b91717d7 -r 121b3fa6b806 main/task_adc.c --- a/main/task_adc.c Tue Mar 21 09:25:50 2023 +0100 +++ b/main/task_adc.c Tue Sep 26 14:49:49 2023 +0200 @@ -11,7 +11,6 @@ #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 @@ -23,11 +22,16 @@ 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); +static void adc_calibration_deinit(adc_cali_handle_t handle); + void request_adc(void) { @@ -51,16 +55,22 @@ */ void task_adc(void *pvParameter) { - int i, adc_reading; - adc_atten_t atten = ADC_ATTEN_DB_0; + 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 (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; + 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; @@ -68,9 +78,6 @@ adc_state->Batt_voltage = 0; adc_state->Batt_error = ADC_ERR_NONE; - //Characterize ADC - esp_adc_cal_characteristics_t *adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t)); - /* event handler and event group for this task */ xEventGroupADC = xEventGroupCreate(); EventBits_t uxBits; @@ -85,19 +92,36 @@ if (uxBits & TASK_ADC_REQUEST_PRESSURE) { ESP_LOGD(TAG, "Requested ADC readings"); - adc1_config_width(ADC_WIDTH_BIT_12); + + 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 (i = 0; i < 3; i++) { + 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; - atten = ADC_ATTEN_DB_0; - + /* * Autoranging the ADC conversion */ while (1) { - esp_adc_cal_characterize(ADC_UNIT_1, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars); - adc1_config_channel_atten((adc1_channel_t)adc_state->Pressure[i].channel, atten); - int raw = adc1_get_raw((adc1_channel_t)adc_state->Pressure[i].channel); + + 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) @@ -112,20 +136,27 @@ * Now that he have the best attenuation, multisample the real value. */ for (int j = 0; j < NO_OF_SAMPLES; j++) { - int tmp = adc1_get_raw((adc1_channel_t)adc_state->Pressure[i].channel); - if (tmp < 0) { - adc_reading = -1; - break; - } + if (adc_oneshot_read(adc1_handle, channel, &tmp) == ESP_OK) { adc_reading += tmp; + } else { + adc_reading = -1; + break; + } } + + adc1_cali_handle = NULL; + 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_state->Pressure[i].voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars); // voltage in mV + adc_cali_raw_to_voltage(adc1_cali_handle, adc_reading, &voltage); + adc_state->Pressure[i].voltage = voltage; + //adc_state->Pressure[i].voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars); // voltage in mV +// ESP_LOGI(TAG, "Voltage %d %d", i, voltage); adc_state->Pressure[i].error = ADC_ERR_NONE; } xSemaphoreGive(xSemaphoreADC); @@ -133,7 +164,14 @@ 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); + i, adc_reading, atten, (adc_state->Pressure[i].voltage / 1000.0), adc_state->Pressure[i].error); + + //Tear Down + ESP_ERROR_CHECK(adc_oneshot_del_unit(adc1_handle)); + if (do_calibration) { + adc_calibration_deinit(adc1_cali_handle); + } + do_calibration = false; } /* @@ -141,15 +179,24 @@ */ adc_reading = 0; atten = ADC_ATTEN_DB_6; // Don't use DB_11, it has a bad linearity. - esp_adc_cal_characterize(ADC_UNIT_1, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars); - adc1_config_channel_atten((adc1_channel_t)BATT_CHANNEL, atten); + adc1_cali_handle = NULL; + 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++) { - int tmp = adc1_get_raw((adc1_channel_t)BATT_CHANNEL); - if (tmp < 0) { - adc_reading = -1; - break; - } - adc_reading += tmp; + 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) { @@ -157,7 +204,9 @@ adc_state->Batt_error = ADC_ERR_READ; } else { adc_reading /= NO_OF_SAMPLES; - adc_state->Batt_voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars) * 2; // Chip supply voltage in mV + 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); @@ -165,6 +214,12 @@ ESP_LOGE(TAG, "Missed lock 2"); } + ESP_ERROR_CHECK(adc_oneshot_del_unit(adc1_handle)); + if (do_calibration) { + adc_calibration_deinit(adc1_cali_handle); + } + do_calibration = false; + xEventGroupClearBits(xEventGroupADC, TASK_ADC_REQUEST_PRESSURE); xEventGroupSetBits(xEventGroupADC, TASK_ADC_REQUEST_DONE); #if 1 @@ -174,3 +229,41 @@ } } + +/*--------------------------------------------------------------- + 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; + esp_err_t ret = ESP_FAIL; + bool calibrated = false; + + if (!calibrated) { + adc_cali_line_fitting_config_t cali_config = { + .unit_id = unit, + .atten = atten, + .bitwidth = ADC_BITWIDTH_DEFAULT, + }; + 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; +} + + +static void adc_calibration_deinit(adc_cali_handle_t handle) +{ + ESP_ERROR_CHECK(adc_cali_delete_scheme_line_fitting(handle)); +} +