Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2545b28

Browse files
committed
esp32: ADC driver update to the new esp_adc.
Signed-off-by: Damian Nowacki (purewack) [email protected]
1 parent d4ce717 commit 2545b28

File tree

7 files changed

+135
-114
lines changed

7 files changed

+135
-114
lines changed

ports/esp32/adc.c

Lines changed: 36 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -27,82 +27,65 @@
2727

2828
#include "py/mphal.h"
2929
#include "adc.h"
30-
#include "driver/adc.h"
30+
#include "esp_adc/adc_oneshot.h"
3131
#include "esp_adc/adc_cali_scheme.h"
3232

33-
#define DEFAULT_VREF 1100
3433

35-
void madcblock_bits_helper(machine_adc_block_obj_t *self, mp_int_t bits) {
36-
if (bits < SOC_ADC_RTC_MIN_BITWIDTH && bits > SOC_ADC_RTC_MAX_BITWIDTH) {
37-
// Invalid value for the current chip, raise exception in the switch below.
38-
bits = -1;
39-
}
40-
switch (bits) {
41-
case 9:
42-
self->width = ADC_BITWIDTH_9;
43-
break;
44-
case 10:
45-
self->width = ADC_BITWIDTH_10;
46-
break;
47-
case 11:
48-
self->width = ADC_BITWIDTH_11;
49-
break;
50-
case 12:
51-
self->width = ADC_BITWIDTH_12;
52-
break;
53-
case 13:
54-
self->width = ADC_BITWIDTH_13;
55-
break;
56-
default:
57-
mp_raise_ValueError(MP_ERROR_TEXT("invalid bits"));
58-
}
59-
self->bits = bits;
34+
static esp_err_t ensure_adc_calibration(machine_adc_block_obj_t *self, adc_atten_t atten);
6035

61-
if (self->unit_id == ADC_UNIT_1) {
62-
adc1_config_width(self->width);
63-
}
36+
37+
esp_err_t apply_self_adc_channel_atten(const machine_adc_obj_t *self, uint8_t atten){
38+
adc_oneshot_chan_cfg_t config = {
39+
.atten = atten,
40+
.bitwidth = self->block->bitwidth,
41+
};
42+
esp_err_t ret = adc_oneshot_config_channel(self->block->handle, self->channel_id, &config);
43+
return ret;
6444
}
6545

6646
mp_int_t madcblock_read_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id) {
67-
int raw = 0;
68-
if (self->unit_id == ADC_UNIT_1) {
69-
raw = adc1_get_raw(channel_id);
70-
} else {
71-
#if (SOC_ADC_PERIPH_NUM >= 2)
72-
check_esp_err(adc2_get_raw(channel_id, self->width, &raw));
73-
#endif
74-
}
75-
return raw;
47+
int reading = 0;
48+
adc_oneshot_read(self->handle, channel_id, &reading);
49+
return reading;
50+
}
51+
52+
/*
53+
During testing, it turned out that the function `adc_cali_raw_to_voltage` does not account for the lower resolution,
54+
instead it expects the full resolution value as an argument, hence the scaling applied here
55+
*/
56+
mp_int_t madcblock_read_uv_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id, adc_atten_t atten) {
57+
int raw = madcblock_read_helper(self, channel_id);
58+
int uv = 0;
59+
60+
check_esp_err(ensure_adc_calibration(self, atten));
61+
check_esp_err(adc_cali_raw_to_voltage(self->calib[atten], (raw << (ADC_WIDTH_MAX-self->bitwidth)), &uv));
62+
return (mp_int_t)uv * 1000;
7663
}
7764

7865
static esp_err_t ensure_adc_calibration(machine_adc_block_obj_t *self, adc_atten_t atten) {
79-
if (self->handle[atten] != NULL) {
66+
if (self->calib[atten] != NULL) {
8067
return ESP_OK;
8168
}
8269

70+
esp_err_t ret = ESP_OK;
71+
8372
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
8473
adc_cali_curve_fitting_config_t cali_config = {
8574
.unit_id = self->unit_id,
8675
.atten = atten,
87-
.bitwidth = self->width,
76+
.bitwidth = self->bitwidth,
8877
};
89-
return adc_cali_create_scheme_curve_fitting(&cali_config, &self->handle[atten]);
78+
ret = adc_cali_create_scheme_curve_fitting(&cali_config, &self->calib[atten]);
9079
#else
9180
adc_cali_line_fitting_config_t cali_config = {
9281
.unit_id = self->unit_id,
9382
.atten = atten,
94-
.bitwidth = self->width,
83+
.bitwidth = self->bitwidth,
9584
};
96-
return adc_cali_create_scheme_line_fitting(&cali_config, &self->handle[atten]);
85+
ret = adc_cali_create_scheme_line_fitting(&cali_config, &self->calib[atten]);
9786
#endif
98-
}
9987

100-
mp_int_t madcblock_read_uv_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id, adc_atten_t atten) {
101-
int raw = madcblock_read_helper(self, channel_id);
102-
int uv;
103-
104-
check_esp_err(ensure_adc_calibration(self, atten));
105-
check_esp_err(adc_cali_raw_to_voltage(self->handle[atten], raw, &uv));
106-
107-
return (mp_int_t)uv * 1000;
88+
89+
return ret;
10890
}
91+

ports/esp32/adc.h

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,68 @@
2929
#define MICROPY_INCLUDED_ESP32_ADC_H
3030

3131
#include "py/runtime.h"
32-
#include "esp_adc_cal.h"
32+
#include "esp_adc/adc_oneshot.h"
3333
#include "esp_adc/adc_cali_scheme.h"
3434

35-
#define ADC_ATTEN_MAX SOC_ADC_ATTEN_NUM
35+
#define ADC_ATTEN_COUNT SOC_ADC_ATTEN_NUM
36+
#define ADC_ATTEN_MIN ADC_ATTEN_DB_0
37+
#define ADC_ATTEN_MAX ADC_ATTEN_DB_11
38+
39+
/*
40+
https://github.com/espressif/esp-idf/issues/13128
41+
https://github.com/espressif/esp-idf/blob/release/v5.2/components/soc/esp32s3/include/soc/soc_caps.h
42+
https://docs.espressif.com/projects/esp-chip-errata/en/latest/esp32s2/03-errata-description/index.html
43+
https://docs.espressif.com/projects/esp-idf/en/v4.2/esp32/api-reference/peripherals/adc.html
44+
45+
Looks like only the original esp32 is capable of bitwidth adjustment, all others are stuck at 12 bits,
46+
except the S2, which is locked at 13 bits, otherwise attenuation doesn't work.
47+
*/
48+
#if CONFIG_IDF_TARGET_ESP32S2
49+
50+
#define ADC_WIDTH_MIN ADC_BITWIDTH_13
51+
#define ADC_WIDTH_MAX ADC_BITWIDTH_13
52+
53+
#elif CONFIG_IDF_TARGET_ESP32
54+
55+
#define ADC_WIDTH_MIN ADC_BITWIDTH_9
56+
#define ADC_WIDTH_MAX ADC_BITWIDTH_12
57+
58+
#else
59+
60+
#define ADC_WIDTH_MIN ADC_BITWIDTH_12
61+
#define ADC_WIDTH_MAX ADC_BITWIDTH_12
62+
63+
#endif
3664

3765
typedef struct _machine_adc_block_obj_t {
3866
mp_obj_base_t base;
3967
adc_unit_t unit_id;
40-
mp_int_t bits;
41-
adc_bits_width_t width;
42-
adc_cali_handle_t handle[ADC_ATTEN_MAX];
68+
adc_oneshot_unit_handle_t handle;
69+
adc_cali_handle_t calib[ADC_ATTEN_COUNT];
70+
adc_bitwidth_t bitwidth;
4371
} machine_adc_block_obj_t;
4472

4573
typedef struct _machine_adc_obj_t {
4674
mp_obj_base_t base;
4775
machine_adc_block_obj_t *block;
4876
adc_channel_t channel_id;
49-
gpio_num_t gpio_id;
77+
gpio_num_t gpio_id;
5078
} machine_adc_obj_t;
5179

5280
extern machine_adc_block_obj_t madcblock_obj[];
5381

54-
void madcblock_bits_helper(machine_adc_block_obj_t *self, mp_int_t bits);
82+
esp_err_t apply_self_adc_channel_atten(const machine_adc_obj_t *self, uint8_t atten);
83+
5584
mp_int_t madcblock_read_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id);
5685
mp_int_t madcblock_read_uv_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id, adc_atten_t atten);
5786

5887
const machine_adc_obj_t *madc_search_helper(machine_adc_block_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id);
5988
void madc_init_helper(const machine_adc_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
6089

90+
mp_int_t mp_machine_adc_atten_get_helper(const machine_adc_obj_t *self);
91+
void mp_machine_adc_atten_set_helper(const machine_adc_obj_t *self, mp_int_t atten);
92+
93+
mp_int_t mp_machine_adc_width_get_helper(const machine_adc_obj_t *self);
94+
void mp_machine_adc_block_width_set_helper(machine_adc_block_obj_t *self, mp_int_t width);
95+
6196
#endif // MICROPY_INCLUDED_ESP32_ADC_H

ports/esp32/boards/sdkconfig.base

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ CONFIG_ADC_CAL_LUT_ENABLE=y
115115
CONFIG_UART_ISR_IN_IRAM=y
116116

117117
# IDF 5 deprecated
118-
CONFIG_ADC_SUPPRESS_DEPRECATE_WARN=y
118+
CONFIG_ADC_SUPPRESS_DEPRECATE_WARN=n
119119
CONFIG_RMT_SUPPRESS_DEPRECATE_WARN=y
120120

121121
CONFIG_ETH_USE_SPI_ETHERNET=y

ports/esp32/machine_adc.c

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
#include "py/mphal.h"
3232
#include "adc.h"
33-
#include "driver/adc.h"
33+
#include "esp_adc/adc_oneshot.h"
3434

3535
#define ADCBLOCK1 (&madcblock_obj[0])
3636
#define ADCBLOCK2 (&madcblock_obj[1])
@@ -126,20 +126,8 @@ static const machine_adc_obj_t madc_obj[] = {
126126
#endif
127127
};
128128

129-
// These values are initialised to 0, which means the corresponding ADC channel is not initialised.
130-
// The madc_atten_get/madc_atten_set functions store (atten+1) here so that the uninitialised state
131-
// can be distinguished from the initialised state.
132129
static uint8_t madc_obj_atten[MP_ARRAY_SIZE(madc_obj)];
133130

134-
static inline adc_atten_t madc_atten_get(const machine_adc_obj_t *self) {
135-
uint8_t value = madc_obj_atten[self - &madc_obj[0]];
136-
return value == 0 ? ADC_ATTEN_MAX : value - 1;
137-
}
138-
139-
static inline void madc_atten_set(const machine_adc_obj_t *self, adc_atten_t atten) {
140-
madc_obj_atten[self - &madc_obj[0]] = atten + 1;
141-
}
142-
143131
const machine_adc_obj_t *madc_search_helper(machine_adc_block_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id) {
144132
for (int i = 0; i < MP_ARRAY_SIZE(madc_obj); i++) {
145133
const machine_adc_obj_t *adc = &madc_obj[i];
@@ -152,22 +140,7 @@ const machine_adc_obj_t *madc_search_helper(machine_adc_block_obj_t *block, adc_
152140

153141
static void mp_machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
154142
const machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
155-
mp_printf(print, "ADC(Pin(%u), atten=%u)", self->gpio_id, madc_atten_get(self));
156-
}
157-
158-
static void madc_atten_helper(const machine_adc_obj_t *self, mp_int_t atten) {
159-
esp_err_t err = ESP_FAIL;
160-
if (self->block->unit_id == ADC_UNIT_1) {
161-
err = adc1_config_channel_atten(self->channel_id, atten);
162-
} else {
163-
#if SOC_ADC_PERIPH_NUM >= 2
164-
err = adc2_config_channel_atten(self->channel_id, atten);
165-
#endif
166-
}
167-
if (err != ESP_OK) {
168-
mp_raise_ValueError(MP_ERROR_TEXT("invalid atten"));
169-
}
170-
madc_atten_set(self, atten);
143+
mp_printf(print, "ADC(Pin(%u), atten=%u)", self->gpio_id, mp_machine_adc_atten_get_helper(self));
171144
}
172145

173146
void madc_init_helper(const machine_adc_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -182,18 +155,30 @@ void madc_init_helper(const machine_adc_obj_t *self, size_t n_pos_args, const mp
182155
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
183156
mp_arg_parse_all(n_pos_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
184157

185-
mp_int_t atten = args[ARG_atten].u_int;
186-
if (atten != -1) {
187-
madc_atten_helper(self, atten);
188-
} else if (madc_atten_get(self) == ADC_ATTEN_MAX) {
189-
madc_atten_helper(self, ADC_ATTEN_DB_0);
158+
159+
if(!self->block->handle){
160+
adc_oneshot_unit_init_cfg_t init_config = {
161+
.unit_id = self->block->unit_id
162+
};
163+
check_esp_err(adc_oneshot_new_unit(&init_config, &self->block->handle));
190164
}
165+
166+
mp_int_t atten = args[ARG_atten].u_int;
167+
mp_machine_adc_atten_set_helper(self, atten != -1 ? atten : ADC_ATTEN_MAX);
168+
mp_machine_adc_block_width_set_helper(self->block, ADC_WIDTH_MAX);
169+
apply_self_adc_channel_atten(self,mp_machine_adc_atten_get_helper(self));
170+
191171
}
192172

193173
static void mp_machine_adc_init_helper(machine_adc_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
194174
madc_init_helper(self, n_pos_args, pos_args, kw_args);
195175
}
196176

177+
static void mp_machine_adc_deinit(machine_adc_obj_t *self){
178+
if(self->block->handle)
179+
check_esp_err(adc_oneshot_del_unit(self->block->handle));
180+
}
181+
197182
static mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_pos_args, size_t n_kw_args, const mp_obj_t *args) {
198183
mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true);
199184
gpio_num_t gpio_id = machine_pin_get_id(args[0]);
@@ -202,10 +187,6 @@ static mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_pos_
202187
mp_raise_ValueError(MP_ERROR_TEXT("invalid pin"));
203188
}
204189

205-
if (self->block->width == -1) {
206-
madcblock_bits_helper(self->block, self->block->bits);
207-
}
208-
209190
mp_map_t kw_args;
210191
mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args);
211192
madc_init_helper(self, n_pos_args - 1, args + 1, &kw_args);
@@ -225,20 +206,44 @@ static mp_int_t mp_machine_adc_read(machine_adc_obj_t *self) {
225206
static mp_int_t mp_machine_adc_read_u16(machine_adc_obj_t *self) {
226207
mp_uint_t raw = madcblock_read_helper(self->block, self->channel_id);
227208
// Scale raw reading to 16 bit value using a Taylor expansion (for 8 <= bits <= 16)
228-
mp_int_t bits = self->block->bits;
209+
mp_int_t bits = mp_machine_adc_width_get_helper(self);
229210
mp_uint_t u16 = raw << (16 - bits) | raw >> (2 * bits - 16);
230211
return u16;
231212
}
232213

233214
static mp_int_t mp_machine_adc_read_uv(machine_adc_obj_t *self) {
234-
adc_atten_t atten = madc_atten_get(self);
235-
return madcblock_read_uv_helper(self->block, self->channel_id, atten);
215+
return madcblock_read_uv_helper(self->block, self->channel_id, mp_machine_adc_atten_get_helper(self));
236216
}
237217

218+
219+
mp_int_t mp_machine_adc_atten_get_helper(const machine_adc_obj_t *self){
220+
uint8_t value = madc_obj_atten[self - &madc_obj[0]];
221+
return value == 0 ? ADC_ATTEN_MAX : value - 1;
222+
}
223+
void mp_machine_adc_atten_set_helper(const machine_adc_obj_t *self, mp_int_t atten) {
224+
if(atten < ADC_ATTEN_MIN || atten > ADC_ATTEN_MAX)
225+
mp_raise_ValueError(MP_ERROR_TEXT("invalid attenuation"));
226+
227+
madc_obj_atten[self - &madc_obj[0]] = atten + 1;
228+
}
238229
static void mp_machine_adc_atten_set(machine_adc_obj_t *self, mp_int_t atten) {
239-
madc_atten_helper(self, atten);
230+
mp_machine_adc_atten_set_helper(self,atten);
231+
apply_self_adc_channel_atten(self,mp_machine_adc_atten_get_helper(self));
232+
}
233+
234+
235+
mp_int_t mp_machine_adc_width_get_helper(const machine_adc_obj_t *self){
236+
return self->block->bitwidth;
237+
}
238+
void mp_machine_adc_block_width_set_helper(machine_adc_block_obj_t *self, mp_int_t width) {
239+
if(width < ADC_WIDTH_MIN || width > ADC_WIDTH_MAX)
240+
mp_raise_ValueError(MP_ERROR_TEXT("invalid bit-width"));
241+
242+
self->bitwidth = width;
243+
DEBUG_printf("wd%d\n",width);
240244
}
241245

242246
static void mp_machine_adc_width_set(machine_adc_obj_t *self, mp_int_t width) {
243-
madcblock_bits_helper(self->block, width);
247+
mp_machine_adc_block_width_set_helper(self->block,width);
248+
apply_self_adc_channel_atten(self,mp_machine_adc_atten_get_helper(self));
244249
}

ports/esp32/machine_adc_block.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,21 @@
2929

3030
#include "py/mphal.h"
3131
#include "adc.h"
32-
#include "driver/adc.h"
32+
#include "esp_adc/adc_oneshot.h"
3333

3434
machine_adc_block_obj_t madcblock_obj[] = {
35-
{{&machine_adc_block_type}, ADC_UNIT_1, SOC_ADC_RTC_MAX_BITWIDTH, -1, {0}},
35+
{{&machine_adc_block_type}, ADC_UNIT_1, NULL},
3636
#if SOC_ADC_PERIPH_NUM > 1
37-
{{&machine_adc_block_type}, ADC_UNIT_2, SOC_ADC_RTC_MAX_BITWIDTH, -1, {0}},
37+
{{&machine_adc_block_type}, ADC_UNIT_2, NULL},
3838
#endif
3939
};
4040

4141
static void mp_machine_adc_block_print(const mp_print_t *print, machine_adc_block_obj_t *self) {
42-
mp_printf(print, "ADCBlock(%u, bits=%u)", self->unit_id, self->bits);
42+
mp_printf(print, "ADCBlock(%u, bits=%u)", self->unit_id, self->bitwidth);
4343
}
4444

4545
static void mp_machine_adc_block_bits_set(machine_adc_block_obj_t *self, mp_int_t bits) {
46-
if (bits != -1) {
47-
madcblock_bits_helper(self, bits);
48-
} else if (self->width == -1) {
49-
madcblock_bits_helper(self, self->bits);
50-
}
46+
mp_machine_adc_block_width_set_helper(self, bits);
5147
}
5248

5349
static machine_adc_block_obj_t *mp_machine_adc_block_get(mp_int_t unit) {

ports/esp32/modesp32.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include <time.h>
3131
#include <sys/time.h>
3232
#include "driver/gpio.h"
33-
#include "driver/adc.h"
3433
#include "esp_heap_caps.h"
3534
#include "multi_heap.h"
3635

0 commit comments

Comments
 (0)