Skip to content

Commit 4edc241

Browse files
committed
esp32: ADC driver update to the new esp_adc.
Signed-off-by: Damian Nowacki (purewack) bobimaster15@gmail.com
1 parent c69f0e4 commit 4edc241

File tree

8 files changed

+146
-115
lines changed

8 files changed

+146
-115
lines changed

docs/esp32/quickref.rst

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,14 +442,27 @@ Legacy methods:
442442

443443
Equivalent to ``ADC.block().init(bits=bits)``.
444444

445+
The only chip that can switch resolution to a lower one is the normal esp32.
446+
The C2 & S3 are stuck at 12 bits, while the S2 is at 13 bits.
447+
445448
For compatibility, the ``ADC`` object also provides constants matching the
446-
supported ADC resolutions:
449+
supported ADC resolutions, per chip:
447450

451+
ESP32:
448452
- ``ADC.WIDTH_9BIT`` = 9
449453
- ``ADC.WIDTH_10BIT`` = 10
450454
- ``ADC.WIDTH_11BIT`` = 11
451455
- ``ADC.WIDTH_12BIT`` = 12
452456

457+
ESP32 C3 & S3:
458+
- ``ADC.WIDTH_12BIT`` = 12
459+
460+
ESP32 S2:
461+
- ``ADC.WIDTH_13BIT`` = 13
462+
463+
.. method:: ADC.deinit()
464+
465+
Provided to deinit the adc driver.
453466

454467
Software SPI bus
455468
----------------

ports/esp32/adc.c

Lines changed: 33 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -27,82 +27,61 @@
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
33+
static esp_err_t ensure_adc_calibration(machine_adc_block_obj_t *self, adc_atten_t atten);
3434

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;
60-
61-
if (self->unit_id == ADC_UNIT_1) {
62-
adc1_config_width(self->width);
63-
}
35+
esp_err_t apply_self_adc_channel_atten(const machine_adc_obj_t *self, uint8_t atten) {
36+
adc_oneshot_chan_cfg_t config = {
37+
.atten = atten,
38+
.bitwidth = self->block->bitwidth,
39+
};
40+
esp_err_t ret = adc_oneshot_config_channel(self->block->handle, self->channel_id, &config);
41+
return ret;
6442
}
6543

6644
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;
45+
int reading = 0;
46+
adc_oneshot_read(self->handle, channel_id, &reading);
47+
return reading;
48+
}
49+
50+
/*
51+
During testing, it turned out that the function `adc_cali_raw_to_voltage` does not account for the lower resolution,
52+
instead it expects the full resolution value as an argument, hence the scaling applied here
53+
*/
54+
mp_int_t madcblock_read_uv_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id, adc_atten_t atten) {
55+
int raw = madcblock_read_helper(self, channel_id);
56+
int uv = 0;
57+
58+
check_esp_err(ensure_adc_calibration(self, atten));
59+
check_esp_err(adc_cali_raw_to_voltage(self->calib[atten], (raw << (ADC_WIDTH_MAX - self->bitwidth)), &uv));
60+
return (mp_int_t)uv * 1000;
7661
}
7762

7863
static esp_err_t ensure_adc_calibration(machine_adc_block_obj_t *self, adc_atten_t atten) {
79-
if (self->handle[atten] != NULL) {
64+
if (self->calib[atten] != NULL) {
8065
return ESP_OK;
8166
}
8267

68+
esp_err_t ret = ESP_OK;
69+
8370
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
8471
adc_cali_curve_fitting_config_t cali_config = {
8572
.unit_id = self->unit_id,
8673
.atten = atten,
87-
.bitwidth = self->width,
74+
.bitwidth = self->bitwidth,
8875
};
89-
return adc_cali_create_scheme_curve_fitting(&cali_config, &self->handle[atten]);
76+
ret = adc_cali_create_scheme_curve_fitting(&cali_config, &self->calib[atten]);
9077
#else
9178
adc_cali_line_fitting_config_t cali_config = {
9279
.unit_id = self->unit_id,
9380
.atten = atten,
94-
.bitwidth = self->width,
81+
.bitwidth = self->bitwidth,
9582
};
96-
return adc_cali_create_scheme_line_fitting(&cali_config, &self->handle[atten]);
83+
ret = adc_cali_create_scheme_line_fitting(&cali_config, &self->calib[atten]);
9784
#endif
98-
}
9985

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;
86+
return ret;
10887
}

ports/esp32/adc.h

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,45 @@
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_bitwidth_t bitwidth;
70+
adc_cali_handle_t calib[ADC_ATTEN_COUNT];
4371
} machine_adc_block_obj_t;
4472

4573
typedef struct _machine_adc_obj_t {
@@ -51,11 +79,18 @@ typedef struct _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: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ 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
119118
CONFIG_RMT_SUPPRESS_DEPRECATE_WARN=y
120119

121120
CONFIG_ETH_USE_SPI_ETHERNET=y

ports/esp32/machine_adc.c

Lines changed: 52 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,32 @@ 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+
self->block->handle = NULL;
181+
}
182+
}
183+
197184
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) {
198185
mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true);
199186
gpio_num_t gpio_id = machine_pin_get_id(args[0]);
@@ -202,10 +189,6 @@ static mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_pos_
202189
mp_raise_ValueError(MP_ERROR_TEXT("invalid pin"));
203190
}
204191

205-
if (self->block->width == -1) {
206-
madcblock_bits_helper(self->block, self->block->bits);
207-
}
208-
209192
mp_map_t kw_args;
210193
mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args);
211194
madc_init_helper(self, n_pos_args - 1, args + 1, &kw_args);
@@ -225,20 +208,46 @@ static mp_int_t mp_machine_adc_read(machine_adc_obj_t *self) {
225208
static mp_int_t mp_machine_adc_read_u16(machine_adc_obj_t *self) {
226209
mp_uint_t raw = madcblock_read_helper(self->block, self->channel_id);
227210
// Scale raw reading to 16 bit value using a Taylor expansion (for 8 <= bits <= 16)
228-
mp_int_t bits = self->block->bits;
211+
mp_int_t bits = mp_machine_adc_width_get_helper(self);
229212
mp_uint_t u16 = raw << (16 - bits) | raw >> (2 * bits - 16);
230213
return u16;
231214
}
232215

233216
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);
217+
return madcblock_read_uv_helper(self->block, self->channel_id, mp_machine_adc_atten_get_helper(self));
218+
}
219+
220+
mp_int_t mp_machine_adc_atten_get_helper(const machine_adc_obj_t *self) {
221+
uint8_t value = madc_obj_atten[self - &madc_obj[0]];
222+
return value == 0 ? ADC_ATTEN_MAX : value - 1;
223+
}
224+
225+
void mp_machine_adc_atten_set_helper(const machine_adc_obj_t *self, mp_int_t atten) {
226+
if (atten < ADC_ATTEN_MIN || atten > ADC_ATTEN_MAX) {
227+
mp_raise_ValueError(MP_ERROR_TEXT("invalid attenuation"));
228+
}
229+
230+
madc_obj_atten[self - &madc_obj[0]] = atten + 1;
236231
}
237232

238233
static void mp_machine_adc_atten_set(machine_adc_obj_t *self, mp_int_t atten) {
239-
madc_atten_helper(self, atten);
234+
mp_machine_adc_atten_set_helper(self, atten);
235+
apply_self_adc_channel_atten(self, mp_machine_adc_atten_get_helper(self));
236+
}
237+
238+
mp_int_t mp_machine_adc_width_get_helper(const machine_adc_obj_t *self) {
239+
return self->block->bitwidth;
240+
}
241+
242+
void mp_machine_adc_block_width_set_helper(machine_adc_block_obj_t *self, mp_int_t width) {
243+
if (width < ADC_WIDTH_MIN || width > ADC_WIDTH_MAX) {
244+
mp_raise_ValueError(MP_ERROR_TEXT("invalid bit-width"));
245+
}
246+
247+
self->bitwidth = width;
240248
}
241249

242250
static void mp_machine_adc_width_set(machine_adc_obj_t *self, mp_int_t width) {
243-
madcblock_bits_helper(self->block, width);
251+
mp_machine_adc_block_width_set_helper(self->block, width);
252+
apply_self_adc_channel_atten(self, mp_machine_adc_atten_get_helper(self));
244253
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy