Sat, 14 Mar 2020 13:07:02 +0100
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 } } }