Tue, 08 Oct 2019 12:00:31 +0200
Initial import of the CO2 meter application.
/** * @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); } }