main/task_adc.c

changeset 0
88d965579617
child 12
7dc9003f86a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/task_adc.c	Tue Oct 08 12:00:31 2019 +0200
@@ -0,0 +1,192 @@
+/**
+ * @file task_adc.c
+ * @brief The FreeRTOS task to query the pressure sensors on 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   	64          			///< Multisampling
+
+
+#define PRESSURE_1		(CONFIG_PRESSURE_1)
+#define PRESSURE_2      	(CONFIG_PRESSURE_2)
+#define PRESSURE_3      	(CONFIG_PRESSURE_3)
+#define BATT_CHANNEL		(CONFIG_BATT_CHANNEL)
+#define	BATT_ACTOR		(CONFIG_BATT_ACTOR)
+
+
+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
+
+const int TASK_ADC_REQUEST_PRESSURE = BIT0;			///< Request temperature measurements
+const int TASK_ADC_REQUEST_DONE = BIT1;				///< Request is completed
+
+
+
+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;
+}
+
+
+/*
+static void print_char_val_type(esp_adc_cal_value_t val_type)
+{
+    if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
+        ESP_LOGI(TAG, "Characterized using Two Point Value");
+    } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
+        ESP_LOGI(TAG, "Characterized using eFuse Vref");
+    } else {
+        ESP_LOGI(TAG, "Characterized using Default Vref");
+    }
+}
+*/
+
+
+/*
+ * Task to read pressure sensors and battery voltage on request.
+ */
+void task_adc(void *pvParameter)
+{
+    int		i, adc_reading;
+    adc_atten_t	atten = ADC_ATTEN_DB_0;
+
+    ESP_LOGI(TAG, "Starting task ADC sensors");
+//    esp_log_level_set("task_adc", ESP_LOG_DEBUG);
+
+    //Check TP is burned into eFuse
+//    ESP_LOGI(TAG, "eFuse Two Point: %supported", (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) ? "S":"NOT s");
+    //Check Vref is burned into eFuse
+//    ESP_LOGI(TAG, "eFuse Vref: %supported", (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) ? "S":"NOT s");
+
+    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_2_5; // Optimal 100..1250 mV, max 1500 mV. max 4,5 bar.
+	adc_state->Pressure[i].atten = ADC_ATTEN_DB_6;   // Optimal 150..1750 mV, max 2200 mV, max 6,3 bar.
+	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;
+
+    //Characterize ADC
+    esp_adc_cal_characteristics_t *adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));    
+//    esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_6, ADC_WIDTH_BIT_11, DEFAULT_VREF, adc_chars);
+//    print_char_val_type(val_type);
+
+    /* 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) {
+
+	    adc1_config_width(ADC_WIDTH_BIT_11);
+
+	    for (i = 0; i < 3; i++) {
+		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_11, 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);
+//	printf("raw: %d atten: %d\n", raw, atten);
+//		    if (raw < 3400)
+//			break;
+
+		    if (atten == ADC_ATTEN_DB_0 && raw > 1850)
+			atten = ADC_ATTEN_DB_2_5;
+		    else if (atten == ADC_ATTEN_DB_2_5 && raw > 1850)
+			atten = ADC_ATTEN_DB_6;
+		    else if (atten == ADC_ATTEN_DB_6 && raw > 1850)
+			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++) {
+			int tmp = adc1_get_raw((adc1_channel_t)adc_state->Pressure[i].channel);
+			adc_reading += tmp;
+//			printf("%4d ", tmp);
+		    //adc_reading += adc1_get_raw((adc1_channel_t)adc_state->Pressure[i].channel);
+		}
+//		printf("\n");
+		if (adc_reading < 0) {
+		    adc_state->Pressure[i].error = ADC_ERR_READ;
+		    adc_state->Pressure[i].voltage = 0;
+		} else {
+		    adc_reading /= NO_OF_SAMPLES;
+		    if (xSemaphoreTake(xSemaphoreADC, 25) == pdTRUE) {
+		    	adc_state->Pressure[i].voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars); // voltage in mV
+			adc_state->Pressure[i].error = ADC_ERR_NONE;
+			xSemaphoreGive(xSemaphoreADC);
+		    }
+		}
+            	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);
+	    }
+
+	    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_11, DEFAULT_VREF, adc_chars);
+            adc1_config_channel_atten((adc1_channel_t)BATT_CHANNEL, atten);
+	    for (int j = 0; j < NO_OF_SAMPLES; j++) {
+            	adc_reading += adc1_get_raw((adc1_channel_t)BATT_CHANNEL);
+            }
+
+	    if (adc_reading < 0) {
+		adc_state->Batt_voltage = 0;
+		adc_state->Batt_error = ADC_ERR_READ;
+	    } else {
+	        adc_reading /= NO_OF_SAMPLES;
+	    	if (xSemaphoreTake(xSemaphoreADC, 25) == pdTRUE) {
+                    adc_state->Batt_voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars) * 2; // Chip supply voltage in mV
+                    adc_state->Batt_error = ADC_ERR_NONE;
+                    xSemaphoreGive(xSemaphoreADC);
+            	}
+	    }
+
+	    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
+	}
+	vTaskDelay( (TickType_t)10);
+    }
+}
+

mercurial