main/task_adc.c

Sat, 14 Mar 2020 13:07:02 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 14 Mar 2020 13:07:02 +0100
changeset 47
1ab1f4a8c328
parent 44
e52d11b8f252
child 68
121b3fa6b806
permissions
-rw-r--r--

Version 0.2.2 Changed to use a permanent network and WiFi connection. Removed three mainloop stages. Removed MQTT sequence counter that was not used. Update WiFi rssi status during eacht measure cycle. Changed FreeRTOS schedulng to 500 Hz.

/**
 * @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

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;
}



/*
 * 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");
    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;
    }
    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));    

    /* 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");
	    adc1_config_width(ADC_WIDTH_BIT_12);

	    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_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);
		    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++) {
			int tmp = adc1_get_raw((adc1_channel_t)adc_state->Pressure[i].channel);
			if (tmp < 0) {
			    adc_reading = -1;
			    break;
			}
			adc_reading += tmp;
		}
		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_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);
	    }

	    /*
	     * 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.
	    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);
	    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 (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_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);
	    } else {
		ESP_LOGE(TAG, "Missed lock 2");
	    }

	    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
	}
    }
}

mercurial