Migrated ADC converter to isp-idf v5.1

Tue, 26 Sep 2023 14:49:49 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Tue, 26 Sep 2023 14:49:49 +0200
changeset 68
121b3fa6b806
parent 66
3557b91717d7
child 69
5437e0514d59

Migrated ADC converter to isp-idf v5.1

main/task_adc.c file | annotate | diff | comparison | revisions
--- 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));
+}
+

mercurial