From 51184d7d8a48c9b0dd5ba0e9545f52aa51271cbf Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Fri, 18 Oct 2019 01:20:58 +0300 Subject: [PATCH 1/4] Use IDF's ADC Driver and Add analogReadMilliVolts --- cores/esp32/esp32-hal-adc.c | 231 ++++++++++++++++-------------------- cores/esp32/esp32-hal-adc.h | 40 +------ 2 files changed, 104 insertions(+), 167 deletions(-) diff --git a/cores/esp32/esp32-hal-adc.c b/cores/esp32/esp32-hal-adc.c index b578fb597d9..851f11ddcb2 100644 --- a/cores/esp32/esp32-hal-adc.c +++ b/cores/esp32/esp32-hal-adc.c @@ -22,14 +22,16 @@ #include "soc/rtc_cntl_reg.h" #include "soc/sens_reg.h" +#include "driver/adc.h" +#include "esp_adc_cal.h" + +#define DEFAULT_VREF 1100 +static esp_adc_cal_characteristics_t *__analogCharacteristics[2] = {NULL, NULL}; static uint8_t __analogAttenuation = 3;//11db static uint8_t __analogWidth = 3;//12 bits -static uint8_t __analogCycles = 8; -static uint8_t __analogSamples = 0;//1 sample static uint8_t __analogClockDiv = 1; - -// Width of returned answer () -static uint8_t __analogReturnedWidth = 12; +static uint16_t __analogVRef = 0; +static uint8_t __analogVRefPin = 0; void __analogSetWidth(uint8_t bits){ if(bits < 9){ @@ -37,81 +39,31 @@ void __analogSetWidth(uint8_t bits){ } else if(bits > 12){ bits = 12; } - __analogReturnedWidth = bits; __analogWidth = bits - 9; - SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR1_BIT_WIDTH, __analogWidth, SENS_SAR1_BIT_WIDTH_S); - SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_BIT, __analogWidth, SENS_SAR1_SAMPLE_BIT_S); - - SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR2_BIT_WIDTH, __analogWidth, SENS_SAR2_BIT_WIDTH_S); - SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_BIT, __analogWidth, SENS_SAR2_SAMPLE_BIT_S); -} - -void __analogSetCycles(uint8_t cycles){ - __analogCycles = cycles; - SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_CYCLE, __analogCycles, SENS_SAR1_SAMPLE_CYCLE_S); - SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_CYCLE, __analogCycles, SENS_SAR2_SAMPLE_CYCLE_S); -} - -void __analogSetSamples(uint8_t samples){ - if(!samples){ - return; - } - __analogSamples = samples - 1; - SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_NUM, __analogSamples, SENS_SAR1_SAMPLE_NUM_S); - SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_NUM, __analogSamples, SENS_SAR2_SAMPLE_NUM_S); + adc1_config_width(__analogWidth); } void __analogSetClockDiv(uint8_t clockDiv){ if(!clockDiv){ - return; + clockDiv = 1; } __analogClockDiv = clockDiv; - SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_CLK_DIV, __analogClockDiv, SENS_SAR1_CLK_DIV_S); - SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_CLK_DIV, __analogClockDiv, SENS_SAR2_CLK_DIV_S); + adc_set_clk_div(__analogClockDiv); } void __analogSetAttenuation(adc_attenuation_t attenuation) { __analogAttenuation = attenuation & 3; - uint32_t att_data = 0; - int i = 10; - while(i--){ - att_data |= __analogAttenuation << (i * 2); - } - WRITE_PERI_REG(SENS_SAR_ATTEN1_REG, att_data & 0xFFFF);//ADC1 has 8 channels - WRITE_PERI_REG(SENS_SAR_ATTEN2_REG, att_data); } -void IRAM_ATTR __analogInit(){ +void __analogInit(){ static bool initialized = false; if(initialized){ return; } - - __analogSetAttenuation(__analogAttenuation); - __analogSetCycles(__analogCycles); - __analogSetSamples(__analogSamples + 1);//in samples + initialized = true; __analogSetClockDiv(__analogClockDiv); __analogSetWidth(__analogWidth + 9);//in bits - - SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DATA_INV); - SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV); - - SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_FORCE_M); //SAR ADC1 controller (in RTC) is started by SW - SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD_FORCE_M); //SAR ADC1 pad enable bitmap is controlled by SW - SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_FORCE_M); //SAR ADC2 controller (in RTC) is started by SW - SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD_FORCE_M); //SAR ADC2 pad enable bitmap is controlled by SW - - CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR_M); //force XPD_SAR=0, use XPD_FSM - SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_AMP, 0x2, SENS_FORCE_XPD_AMP_S); //force XPD_AMP=0 - - CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_CTRL_REG, 0xfff << SENS_AMP_RST_FB_FSM_S); //clear FSM - SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT1, 0x1, SENS_SAR_AMP_WAIT1_S); - SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT2, 0x1, SENS_SAR_AMP_WAIT2_S); - SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_SAR_AMP_WAIT3, 0x1, SENS_SAR_AMP_WAIT3_S); - while (GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR1_REG, 0x7, SENS_MEAS_STATUS_S) != 0); //wait det_fsm== - - initialized = true; } void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation) @@ -120,21 +72,20 @@ void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation) if(channel < 0 || attenuation > 3){ return ; } - __analogInit(); - if(channel > 7){ - SET_PERI_REG_BITS(SENS_SAR_ATTEN2_REG, 3, attenuation, ((channel - 10) * 2)); + if(channel > 9){ + adc2_config_channel_atten(channel - 10, attenuation); } else { - SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, 3, attenuation, (channel * 2)); + adc1_config_channel_atten(channel, attenuation); } + __analogInit(); } -bool IRAM_ATTR __adcAttachPin(uint8_t pin){ - +bool __adcAttachPin(uint8_t pin){ int8_t channel = digitalPinToAnalogChannel(pin); if(channel < 0){ - return false;//not adc pin + log_e("Pin %u is not ADC pin!", pin); + return false; } - int8_t pad = digitalPinToTouchChannel(pin); if(pad >= 0){ uint32_t touch = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG); @@ -151,86 +102,106 @@ bool IRAM_ATTR __adcAttachPin(uint8_t pin){ } pinMode(pin, ANALOG); - - __analogInit(); + __analogSetPinAttenuation(pin, __analogAttenuation); return true; } -bool IRAM_ATTR __adcStart(uint8_t pin){ +void __analogReadResolution(uint8_t bits) +{ + if(!bits || bits > 16){ + return; + } + __analogSetWidth(bits); // hadware from 9 to 12 +} +uint16_t __analogRead(uint8_t pin) +{ int8_t channel = digitalPinToAnalogChannel(pin); + int value = 0; + esp_err_t r = ESP_OK; if(channel < 0){ - return false;//not adc pin + log_e("Pin %u is not ADC pin!", pin); + return value; } - + __adcAttachPin(pin); if(channel > 9){ channel -= 10; - CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M); - SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD, (1 << channel), SENS_SAR2_EN_PAD_S); - SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M); + r = adc2_get_raw( channel, __analogWidth, &value); + if ( r == ESP_OK ) { + return value; + } else if ( r == ESP_ERR_INVALID_STATE ) { + log_e("%s: ADC2 not initialized yet.", esp_err_to_name(r)); + } else if ( r == ESP_ERR_TIMEOUT ) { + log_e("%s: ADC2 is in use by Wi-Fi.", esp_err_to_name(r)); + } else { + log_e("%s", esp_err_to_name(r)); + } } else { - CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M); - SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD, (1 << channel), SENS_SAR1_EN_PAD_S); - SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M); + return adc1_get_raw(channel); } - return true; + return value; } -bool IRAM_ATTR __adcBusy(uint8_t pin){ - - int8_t channel = digitalPinToAnalogChannel(pin); - if(channel < 0){ - return false;//not adc pin - } - - if(channel > 7){ - return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0); +void __analogSetVRefPin(uint8_t pin){ + if(pin <25 || pin > 27){ + pin = 0; } - return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0); + __analogVRefPin = pin; } -uint16_t IRAM_ATTR __adcEnd(uint8_t pin) -{ - - uint16_t value = 0; +uint32_t __analogReadMilliVolts(uint8_t pin){ int8_t channel = digitalPinToAnalogChannel(pin); if(channel < 0){ - return 0;//not adc pin - } - if(channel > 7){ - while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0); //wait for conversion - value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DATA_SAR, SENS_MEAS2_DATA_SAR_S); - } else { - while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0); //wait for conversion - value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DATA_SAR, SENS_MEAS1_DATA_SAR_S); - } - - // Shift result if necessary - uint8_t from = __analogWidth + 9; - if (from == __analogReturnedWidth) { - return value; + log_e("Pin %u is not ADC pin!", pin); + return 0; } - if (from > __analogReturnedWidth) { - return value >> (from - __analogReturnedWidth); + if(!__analogVRef){ + if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) { + log_d("eFuse Two Point: Supported"); + __analogVRef = DEFAULT_VREF; + } + if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) { + log_d("eFuse Vref: Supported"); + __analogVRef = DEFAULT_VREF; + } + if(!__analogVRef){ + __analogVRef = DEFAULT_VREF; + if(__analogVRefPin > 24 && __analogVRefPin << 28){ + esp_adc_cal_characteristics_t * chars = calloc(1, sizeof(esp_adc_cal_characteristics_t)); + if(chars != NULL){ + if(adc2_vref_to_gpio(__analogVRefPin) == ESP_OK){ + __analogVRef = __analogRead(__analogVRefPin); + esp_adc_cal_characterize(1, __analogAttenuation, __analogWidth, DEFAULT_VREF, chars); + __analogVRef = esp_adc_cal_raw_to_voltage(__analogVRef, chars); + log_d("Vref to GPIO%u: %u", __analogVRefPin, __analogVRef); + } + free(chars); + } + } + } } - return value << (__analogReturnedWidth - from); -} - -uint16_t IRAM_ATTR __analogRead(uint8_t pin) -{ - if(!__adcAttachPin(pin) || !__adcStart(pin)){ - return 0; + uint8_t unit = 1; + if(channel > 9){ + unit = 2; } - return __adcEnd(pin); -} - -void __analogReadResolution(uint8_t bits) -{ - if(!bits || bits > 16){ - return; + uint16_t adc_reading = __analogRead(pin); + if(__analogCharacteristics[unit - 1] == NULL){ + __analogCharacteristics[unit - 1] = calloc(1, sizeof(esp_adc_cal_characteristics_t)); + if(__analogCharacteristics[unit - 1] == NULL){ + return 0; + } + esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, __analogAttenuation, __analogWidth, __analogVRef, __analogCharacteristics[unit - 1]); + if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) { + log_i("ADC%u: Characterized using Two Point Value: %u\n", unit, __analogCharacteristics[unit - 1]->vref); + } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) { + log_i("ADC%u: Characterized using eFuse Vref: %u\n", unit, __analogCharacteristics[unit - 1]->vref); + } else if(__analogVRef != DEFAULT_VREF){ + log_i("ADC%u: Characterized using Vref to GPIO%u: %u\n", unit, __analogVRefPin, __analogCharacteristics[unit - 1]->vref); + } else { + log_i("ADC%u: Characterized using Default Vref: %u\n", unit, __analogCharacteristics[unit - 1]->vref); + } } - __analogSetWidth(bits); // hadware from 9 to 12 - __analogReturnedWidth = bits; // software from 1 to 16 + return esp_adc_cal_raw_to_voltage(adc_reading, __analogCharacteristics[unit - 1]); } int __hallRead() //hall sensor without LNA @@ -260,14 +231,12 @@ int __hallRead() //hall sensor without LNA extern uint16_t analogRead(uint8_t pin) __attribute__ ((weak, alias("__analogRead"))); extern void analogReadResolution(uint8_t bits) __attribute__ ((weak, alias("__analogReadResolution"))); extern void analogSetWidth(uint8_t bits) __attribute__ ((weak, alias("__analogSetWidth"))); -extern void analogSetCycles(uint8_t cycles) __attribute__ ((weak, alias("__analogSetCycles"))); -extern void analogSetSamples(uint8_t samples) __attribute__ ((weak, alias("__analogSetSamples"))); extern void analogSetClockDiv(uint8_t clockDiv) __attribute__ ((weak, alias("__analogSetClockDiv"))); extern void analogSetAttenuation(adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetAttenuation"))); extern void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetPinAttenuation"))); extern int hallRead() __attribute__ ((weak, alias("__hallRead"))); extern bool adcAttachPin(uint8_t pin) __attribute__ ((weak, alias("__adcAttachPin"))); -extern bool adcStart(uint8_t pin) __attribute__ ((weak, alias("__adcStart"))); -extern bool adcBusy(uint8_t pin) __attribute__ ((weak, alias("__adcBusy"))); -extern uint16_t adcEnd(uint8_t pin) __attribute__ ((weak, alias("__adcEnd"))); + +extern void analogSetVRefPin(uint8_t pin) __attribute__ ((weak, alias("__analogSetVRefPin"))); +extern uint32_t analogReadMilliVolts(uint8_t pin) __attribute__ ((weak, alias("__analogReadMilliVolts"))); diff --git a/cores/esp32/esp32-hal-adc.h b/cores/esp32/esp32-hal-adc.h index ab751df4975..bba56fdcd4f 100644 --- a/cores/esp32/esp32-hal-adc.h +++ b/cores/esp32/esp32-hal-adc.h @@ -54,24 +54,6 @@ void analogReadResolution(uint8_t bits); * */ void analogSetWidth(uint8_t bits); -/* - * Set number of cycles per sample - * Default is 8 and seems to do well - * Range is 1 - 255 - * */ -void analogSetCycles(uint8_t cycles); - -/* - * Set number of samples in the range. - * Default is 1 - * Range is 1 - 255 - * This setting splits the range into - * "samples" pieces, which could look - * like the sensitivity has been multiplied - * that many times - * */ -void analogSetSamples(uint8_t samples); - /* * Set the divider for the ADC clock. * Default is 1 @@ -97,34 +79,20 @@ void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation); * */ int hallRead(); -/* - * Non-Blocking API (almost) - * - * Note: ADC conversion can run only for single pin at a time. - * That means that if you want to run ADC on two pins on the same bus, - * you need to run them one after another. Probably the best use would be - * to start conversion on both buses in parallel. - * */ - /* * Attach pin to ADC (will also clear any other analog mode that could be on) * */ bool adcAttachPin(uint8_t pin); /* - * Start ADC conversion on attached pin's bus - * */ -bool adcStart(uint8_t pin); - -/* - * Check if conversion on the pin's ADC bus is currently running + * Set pin to use for ADC calibration if the esp is not already calibrated (25, 26 or 27) * */ -bool adcBusy(uint8_t pin); +void analogSetVRefPin(uint8_t pin); /* - * Get the result of the conversion (will wait if it have not finished) + * Get MilliVolts value for pin * */ -uint16_t adcEnd(uint8_t pin); +uint32_t analogReadMilliVolts(uint8_t pin); #ifdef __cplusplus } From 45b869c6fa69c491fbc0f828cc0bd736d0c6927c Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Fri, 18 Oct 2019 01:40:18 +0300 Subject: [PATCH 2/4] add pin num to errors --- cores/esp32/esp32-hal-adc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cores/esp32/esp32-hal-adc.c b/cores/esp32/esp32-hal-adc.c index 851f11ddcb2..32aa4c11177 100644 --- a/cores/esp32/esp32-hal-adc.c +++ b/cores/esp32/esp32-hal-adc.c @@ -130,11 +130,11 @@ uint16_t __analogRead(uint8_t pin) if ( r == ESP_OK ) { return value; } else if ( r == ESP_ERR_INVALID_STATE ) { - log_e("%s: ADC2 not initialized yet.", esp_err_to_name(r)); + log_e("GPIO%u: %s: ADC2 not initialized yet.", pin, esp_err_to_name(r)); } else if ( r == ESP_ERR_TIMEOUT ) { - log_e("%s: ADC2 is in use by Wi-Fi.", esp_err_to_name(r)); + log_e("GPIO%u: %s: ADC2 is in use by Wi-Fi.", pin, esp_err_to_name(r)); } else { - log_e("%s", esp_err_to_name(r)); + log_e("GPIO%u: %s", pin, esp_err_to_name(r)); } } else { return adc1_get_raw(channel); From 762a9181ae8c07c5482a27b8943b4b0432ca8d55 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Fri, 18 Oct 2019 01:46:17 +0300 Subject: [PATCH 3/4] Update esp32-hal-adc.c --- cores/esp32/esp32-hal-adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp32/esp32-hal-adc.c b/cores/esp32/esp32-hal-adc.c index 32aa4c11177..d5dd1259e26 100644 --- a/cores/esp32/esp32-hal-adc.c +++ b/cores/esp32/esp32-hal-adc.c @@ -166,7 +166,7 @@ uint32_t __analogReadMilliVolts(uint8_t pin){ } if(!__analogVRef){ __analogVRef = DEFAULT_VREF; - if(__analogVRefPin > 24 && __analogVRefPin << 28){ + if(__analogVRefPin > 24 && __analogVRefPin < 28){ esp_adc_cal_characteristics_t * chars = calloc(1, sizeof(esp_adc_cal_characteristics_t)); if(chars != NULL){ if(adc2_vref_to_gpio(__analogVRefPin) == ESP_OK){ From 2304fcdecbf9d5de209fd1ec7152ed5b80d7a9a1 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Fri, 18 Oct 2019 02:01:23 +0300 Subject: [PATCH 4/4] Update esp32-hal-adc.c --- cores/esp32/esp32-hal-adc.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/cores/esp32/esp32-hal-adc.c b/cores/esp32/esp32-hal-adc.c index d5dd1259e26..ab9e7622c3a 100644 --- a/cores/esp32/esp32-hal-adc.c +++ b/cores/esp32/esp32-hal-adc.c @@ -166,16 +166,13 @@ uint32_t __analogReadMilliVolts(uint8_t pin){ } if(!__analogVRef){ __analogVRef = DEFAULT_VREF; - if(__analogVRefPin > 24 && __analogVRefPin < 28){ - esp_adc_cal_characteristics_t * chars = calloc(1, sizeof(esp_adc_cal_characteristics_t)); - if(chars != NULL){ - if(adc2_vref_to_gpio(__analogVRefPin) == ESP_OK){ - __analogVRef = __analogRead(__analogVRefPin); - esp_adc_cal_characterize(1, __analogAttenuation, __analogWidth, DEFAULT_VREF, chars); - __analogVRef = esp_adc_cal_raw_to_voltage(__analogVRef, chars); - log_d("Vref to GPIO%u: %u", __analogVRefPin, __analogVRef); - } - free(chars); + if(__analogVRefPin){ + esp_adc_cal_characteristics_t chars; + if(adc2_vref_to_gpio(__analogVRefPin) == ESP_OK){ + __analogVRef = __analogRead(__analogVRefPin); + esp_adc_cal_characterize(1, __analogAttenuation, __analogWidth, DEFAULT_VREF, &chars); + __analogVRef = esp_adc_cal_raw_to_voltage(__analogVRef, &chars); + log_d("Vref to GPIO%u: %u", __analogVRefPin, __analogVRef); } } }