Skip to content

Commit d8b2098

Browse files
authored
Use IDF's ADC Driver and Add analogReadMilliVolts (#3377)
1 parent 3fc974f commit d8b2098

File tree

2 files changed

+101
-167
lines changed

2 files changed

+101
-167
lines changed

Diff for: cores/esp32/esp32-hal-adc.c

+97-131
Original file line numberDiff line numberDiff line change
@@ -22,96 +22,48 @@
2222
#include "soc/rtc_cntl_reg.h"
2323
#include "soc/sens_reg.h"
2424

25+
#include "driver/adc.h"
26+
#include "esp_adc_cal.h"
27+
28+
#define DEFAULT_VREF 1100
29+
static esp_adc_cal_characteristics_t *__analogCharacteristics[2] = {NULL, NULL};
2530
static uint8_t __analogAttenuation = 3;//11db
2631
static uint8_t __analogWidth = 3;//12 bits
27-
static uint8_t __analogCycles = 8;
28-
static uint8_t __analogSamples = 0;//1 sample
2932
static uint8_t __analogClockDiv = 1;
30-
31-
// Width of returned answer ()
32-
static uint8_t __analogReturnedWidth = 12;
33+
static uint16_t __analogVRef = 0;
34+
static uint8_t __analogVRefPin = 0;
3335

3436
void __analogSetWidth(uint8_t bits){
3537
if(bits < 9){
3638
bits = 9;
3739
} else if(bits > 12){
3840
bits = 12;
3941
}
40-
__analogReturnedWidth = bits;
4142
__analogWidth = bits - 9;
42-
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR1_BIT_WIDTH, __analogWidth, SENS_SAR1_BIT_WIDTH_S);
43-
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_BIT, __analogWidth, SENS_SAR1_SAMPLE_BIT_S);
44-
45-
SET_PERI_REG_BITS(SENS_SAR_START_FORCE_REG, SENS_SAR2_BIT_WIDTH, __analogWidth, SENS_SAR2_BIT_WIDTH_S);
46-
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_BIT, __analogWidth, SENS_SAR2_SAMPLE_BIT_S);
47-
}
48-
49-
void __analogSetCycles(uint8_t cycles){
50-
__analogCycles = cycles;
51-
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_CYCLE, __analogCycles, SENS_SAR1_SAMPLE_CYCLE_S);
52-
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_CYCLE, __analogCycles, SENS_SAR2_SAMPLE_CYCLE_S);
53-
}
54-
55-
void __analogSetSamples(uint8_t samples){
56-
if(!samples){
57-
return;
58-
}
59-
__analogSamples = samples - 1;
60-
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_SAMPLE_NUM, __analogSamples, SENS_SAR1_SAMPLE_NUM_S);
61-
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_SAMPLE_NUM, __analogSamples, SENS_SAR2_SAMPLE_NUM_S);
43+
adc1_config_width(__analogWidth);
6244
}
6345

6446
void __analogSetClockDiv(uint8_t clockDiv){
6547
if(!clockDiv){
66-
return;
48+
clockDiv = 1;
6749
}
6850
__analogClockDiv = clockDiv;
69-
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL_REG, SENS_SAR1_CLK_DIV, __analogClockDiv, SENS_SAR1_CLK_DIV_S);
70-
SET_PERI_REG_BITS(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_CLK_DIV, __analogClockDiv, SENS_SAR2_CLK_DIV_S);
51+
adc_set_clk_div(__analogClockDiv);
7152
}
7253

7354
void __analogSetAttenuation(adc_attenuation_t attenuation)
7455
{
7556
__analogAttenuation = attenuation & 3;
76-
uint32_t att_data = 0;
77-
int i = 10;
78-
while(i--){
79-
att_data |= __analogAttenuation << (i * 2);
80-
}
81-
WRITE_PERI_REG(SENS_SAR_ATTEN1_REG, att_data & 0xFFFF);//ADC1 has 8 channels
82-
WRITE_PERI_REG(SENS_SAR_ATTEN2_REG, att_data);
8357
}
8458

85-
void IRAM_ATTR __analogInit(){
59+
void __analogInit(){
8660
static bool initialized = false;
8761
if(initialized){
8862
return;
8963
}
90-
91-
__analogSetAttenuation(__analogAttenuation);
92-
__analogSetCycles(__analogCycles);
93-
__analogSetSamples(__analogSamples + 1);//in samples
64+
initialized = true;
9465
__analogSetClockDiv(__analogClockDiv);
9566
__analogSetWidth(__analogWidth + 9);//in bits
96-
97-
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DATA_INV);
98-
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DATA_INV);
99-
100-
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_FORCE_M); //SAR ADC1 controller (in RTC) is started by SW
101-
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD_FORCE_M); //SAR ADC1 pad enable bitmap is controlled by SW
102-
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_FORCE_M); //SAR ADC2 controller (in RTC) is started by SW
103-
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD_FORCE_M); //SAR ADC2 pad enable bitmap is controlled by SW
104-
105-
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR_M); //force XPD_SAR=0, use XPD_FSM
106-
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_AMP, 0x2, SENS_FORCE_XPD_AMP_S); //force XPD_AMP=0
107-
108-
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_CTRL_REG, 0xfff << SENS_AMP_RST_FB_FSM_S); //clear FSM
109-
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT1, 0x1, SENS_SAR_AMP_WAIT1_S);
110-
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT1_REG, SENS_SAR_AMP_WAIT2, 0x1, SENS_SAR_AMP_WAIT2_S);
111-
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_SAR_AMP_WAIT3, 0x1, SENS_SAR_AMP_WAIT3_S);
112-
while (GET_PERI_REG_BITS2(SENS_SAR_SLAVE_ADDR1_REG, 0x7, SENS_MEAS_STATUS_S) != 0); //wait det_fsm==
113-
114-
initialized = true;
11567
}
11668

11769
void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation)
@@ -120,21 +72,20 @@ void __analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation)
12072
if(channel < 0 || attenuation > 3){
12173
return ;
12274
}
123-
__analogInit();
124-
if(channel > 7){
125-
SET_PERI_REG_BITS(SENS_SAR_ATTEN2_REG, 3, attenuation, ((channel - 10) * 2));
75+
if(channel > 9){
76+
adc2_config_channel_atten(channel - 10, attenuation);
12677
} else {
127-
SET_PERI_REG_BITS(SENS_SAR_ATTEN1_REG, 3, attenuation, (channel * 2));
78+
adc1_config_channel_atten(channel, attenuation);
12879
}
80+
__analogInit();
12981
}
13082

131-
bool IRAM_ATTR __adcAttachPin(uint8_t pin){
132-
83+
bool __adcAttachPin(uint8_t pin){
13384
int8_t channel = digitalPinToAnalogChannel(pin);
13485
if(channel < 0){
135-
return false;//not adc pin
86+
log_e("Pin %u is not ADC pin!", pin);
87+
return false;
13688
}
137-
13889
int8_t pad = digitalPinToTouchChannel(pin);
13990
if(pad >= 0){
14091
uint32_t touch = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
@@ -151,86 +102,103 @@ bool IRAM_ATTR __adcAttachPin(uint8_t pin){
151102
}
152103

153104
pinMode(pin, ANALOG);
154-
155-
__analogInit();
105+
__analogSetPinAttenuation(pin, __analogAttenuation);
156106
return true;
157107
}
158108

159-
bool IRAM_ATTR __adcStart(uint8_t pin){
109+
void __analogReadResolution(uint8_t bits)
110+
{
111+
if(!bits || bits > 16){
112+
return;
113+
}
114+
__analogSetWidth(bits); // hadware from 9 to 12
115+
}
160116

117+
uint16_t __analogRead(uint8_t pin)
118+
{
161119
int8_t channel = digitalPinToAnalogChannel(pin);
120+
int value = 0;
121+
esp_err_t r = ESP_OK;
162122
if(channel < 0){
163-
return false;//not adc pin
123+
log_e("Pin %u is not ADC pin!", pin);
124+
return value;
164125
}
165-
126+
__adcAttachPin(pin);
166127
if(channel > 9){
167128
channel -= 10;
168-
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M);
169-
SET_PERI_REG_BITS(SENS_SAR_MEAS_START2_REG, SENS_SAR2_EN_PAD, (1 << channel), SENS_SAR2_EN_PAD_S);
170-
SET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_START_SAR_M);
129+
r = adc2_get_raw( channel, __analogWidth, &value);
130+
if ( r == ESP_OK ) {
131+
return value;
132+
} else if ( r == ESP_ERR_INVALID_STATE ) {
133+
log_e("GPIO%u: %s: ADC2 not initialized yet.", pin, esp_err_to_name(r));
134+
} else if ( r == ESP_ERR_TIMEOUT ) {
135+
log_e("GPIO%u: %s: ADC2 is in use by Wi-Fi.", pin, esp_err_to_name(r));
136+
} else {
137+
log_e("GPIO%u: %s", pin, esp_err_to_name(r));
138+
}
171139
} else {
172-
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
173-
SET_PERI_REG_BITS(SENS_SAR_MEAS_START1_REG, SENS_SAR1_EN_PAD, (1 << channel), SENS_SAR1_EN_PAD_S);
174-
SET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_START_SAR_M);
140+
return adc1_get_raw(channel);
175141
}
176-
return true;
142+
return value;
177143
}
178144

179-
bool IRAM_ATTR __adcBusy(uint8_t pin){
180-
181-
int8_t channel = digitalPinToAnalogChannel(pin);
182-
if(channel < 0){
183-
return false;//not adc pin
184-
}
185-
186-
if(channel > 7){
187-
return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0);
145+
void __analogSetVRefPin(uint8_t pin){
146+
if(pin <25 || pin > 27){
147+
pin = 0;
188148
}
189-
return (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0);
149+
__analogVRefPin = pin;
190150
}
191151

192-
uint16_t IRAM_ATTR __adcEnd(uint8_t pin)
193-
{
194-
195-
uint16_t value = 0;
152+
uint32_t __analogReadMilliVolts(uint8_t pin){
196153
int8_t channel = digitalPinToAnalogChannel(pin);
197154
if(channel < 0){
198-
return 0;//not adc pin
199-
}
200-
if(channel > 7){
201-
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DONE_SAR) == 0); //wait for conversion
202-
value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START2_REG, SENS_MEAS2_DATA_SAR, SENS_MEAS2_DATA_SAR_S);
203-
} else {
204-
while (GET_PERI_REG_MASK(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DONE_SAR) == 0); //wait for conversion
205-
value = GET_PERI_REG_BITS2(SENS_SAR_MEAS_START1_REG, SENS_MEAS1_DATA_SAR, SENS_MEAS1_DATA_SAR_S);
206-
}
207-
208-
// Shift result if necessary
209-
uint8_t from = __analogWidth + 9;
210-
if (from == __analogReturnedWidth) {
211-
return value;
155+
log_e("Pin %u is not ADC pin!", pin);
156+
return 0;
212157
}
213-
if (from > __analogReturnedWidth) {
214-
return value >> (from - __analogReturnedWidth);
158+
if(!__analogVRef){
159+
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
160+
log_d("eFuse Two Point: Supported");
161+
__analogVRef = DEFAULT_VREF;
162+
}
163+
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
164+
log_d("eFuse Vref: Supported");
165+
__analogVRef = DEFAULT_VREF;
166+
}
167+
if(!__analogVRef){
168+
__analogVRef = DEFAULT_VREF;
169+
if(__analogVRefPin){
170+
esp_adc_cal_characteristics_t chars;
171+
if(adc2_vref_to_gpio(__analogVRefPin) == ESP_OK){
172+
__analogVRef = __analogRead(__analogVRefPin);
173+
esp_adc_cal_characterize(1, __analogAttenuation, __analogWidth, DEFAULT_VREF, &chars);
174+
__analogVRef = esp_adc_cal_raw_to_voltage(__analogVRef, &chars);
175+
log_d("Vref to GPIO%u: %u", __analogVRefPin, __analogVRef);
176+
}
177+
}
178+
}
215179
}
216-
return value << (__analogReturnedWidth - from);
217-
}
218-
219-
uint16_t IRAM_ATTR __analogRead(uint8_t pin)
220-
{
221-
if(!__adcAttachPin(pin) || !__adcStart(pin)){
222-
return 0;
180+
uint8_t unit = 1;
181+
if(channel > 9){
182+
unit = 2;
223183
}
224-
return __adcEnd(pin);
225-
}
226-
227-
void __analogReadResolution(uint8_t bits)
228-
{
229-
if(!bits || bits > 16){
230-
return;
184+
uint16_t adc_reading = __analogRead(pin);
185+
if(__analogCharacteristics[unit - 1] == NULL){
186+
__analogCharacteristics[unit - 1] = calloc(1, sizeof(esp_adc_cal_characteristics_t));
187+
if(__analogCharacteristics[unit - 1] == NULL){
188+
return 0;
189+
}
190+
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, __analogAttenuation, __analogWidth, __analogVRef, __analogCharacteristics[unit - 1]);
191+
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
192+
log_i("ADC%u: Characterized using Two Point Value: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
193+
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
194+
log_i("ADC%u: Characterized using eFuse Vref: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
195+
} else if(__analogVRef != DEFAULT_VREF){
196+
log_i("ADC%u: Characterized using Vref to GPIO%u: %u\n", unit, __analogVRefPin, __analogCharacteristics[unit - 1]->vref);
197+
} else {
198+
log_i("ADC%u: Characterized using Default Vref: %u\n", unit, __analogCharacteristics[unit - 1]->vref);
199+
}
231200
}
232-
__analogSetWidth(bits); // hadware from 9 to 12
233-
__analogReturnedWidth = bits; // software from 1 to 16
201+
return esp_adc_cal_raw_to_voltage(adc_reading, __analogCharacteristics[unit - 1]);
234202
}
235203

236204
int __hallRead() //hall sensor without LNA
@@ -260,14 +228,12 @@ int __hallRead() //hall sensor without LNA
260228
extern uint16_t analogRead(uint8_t pin) __attribute__ ((weak, alias("__analogRead")));
261229
extern void analogReadResolution(uint8_t bits) __attribute__ ((weak, alias("__analogReadResolution")));
262230
extern void analogSetWidth(uint8_t bits) __attribute__ ((weak, alias("__analogSetWidth")));
263-
extern void analogSetCycles(uint8_t cycles) __attribute__ ((weak, alias("__analogSetCycles")));
264-
extern void analogSetSamples(uint8_t samples) __attribute__ ((weak, alias("__analogSetSamples")));
265231
extern void analogSetClockDiv(uint8_t clockDiv) __attribute__ ((weak, alias("__analogSetClockDiv")));
266232
extern void analogSetAttenuation(adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetAttenuation")));
267233
extern void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation) __attribute__ ((weak, alias("__analogSetPinAttenuation")));
268234
extern int hallRead() __attribute__ ((weak, alias("__hallRead")));
269235

270236
extern bool adcAttachPin(uint8_t pin) __attribute__ ((weak, alias("__adcAttachPin")));
271-
extern bool adcStart(uint8_t pin) __attribute__ ((weak, alias("__adcStart")));
272-
extern bool adcBusy(uint8_t pin) __attribute__ ((weak, alias("__adcBusy")));
273-
extern uint16_t adcEnd(uint8_t pin) __attribute__ ((weak, alias("__adcEnd")));
237+
238+
extern void analogSetVRefPin(uint8_t pin) __attribute__ ((weak, alias("__analogSetVRefPin")));
239+
extern uint32_t analogReadMilliVolts(uint8_t pin) __attribute__ ((weak, alias("__analogReadMilliVolts")));

Diff for: cores/esp32/esp32-hal-adc.h

+4-36
Original file line numberDiff line numberDiff line change
@@ -54,24 +54,6 @@ void analogReadResolution(uint8_t bits);
5454
* */
5555
void analogSetWidth(uint8_t bits);
5656

57-
/*
58-
* Set number of cycles per sample
59-
* Default is 8 and seems to do well
60-
* Range is 1 - 255
61-
* */
62-
void analogSetCycles(uint8_t cycles);
63-
64-
/*
65-
* Set number of samples in the range.
66-
* Default is 1
67-
* Range is 1 - 255
68-
* This setting splits the range into
69-
* "samples" pieces, which could look
70-
* like the sensitivity has been multiplied
71-
* that many times
72-
* */
73-
void analogSetSamples(uint8_t samples);
74-
7557
/*
7658
* Set the divider for the ADC clock.
7759
* Default is 1
@@ -97,34 +79,20 @@ void analogSetPinAttenuation(uint8_t pin, adc_attenuation_t attenuation);
9779
* */
9880
int hallRead();
9981

100-
/*
101-
* Non-Blocking API (almost)
102-
*
103-
* Note: ADC conversion can run only for single pin at a time.
104-
* That means that if you want to run ADC on two pins on the same bus,
105-
* you need to run them one after another. Probably the best use would be
106-
* to start conversion on both buses in parallel.
107-
* */
108-
10982
/*
11083
* Attach pin to ADC (will also clear any other analog mode that could be on)
11184
* */
11285
bool adcAttachPin(uint8_t pin);
11386

11487
/*
115-
* Start ADC conversion on attached pin's bus
116-
* */
117-
bool adcStart(uint8_t pin);
118-
119-
/*
120-
* Check if conversion on the pin's ADC bus is currently running
88+
* Set pin to use for ADC calibration if the esp is not already calibrated (25, 26 or 27)
12189
* */
122-
bool adcBusy(uint8_t pin);
90+
void analogSetVRefPin(uint8_t pin);
12391

12492
/*
125-
* Get the result of the conversion (will wait if it have not finished)
93+
* Get MilliVolts value for pin
12694
* */
127-
uint16_t adcEnd(uint8_t pin);
95+
uint32_t analogReadMilliVolts(uint8_t pin);
12896

12997
#ifdef __cplusplus
13098
}

0 commit comments

Comments
 (0)