diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 8861ca4ac87ed..8e94a359ee77d 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -189,6 +189,33 @@ Use the ``machine.PWM`` class:: pwm2 = PWM(Pin(2), freq=20000, duty=512) # create and configure in one go +MCPWM (motor control pulse width modulation) +-------------------------------------------- + +MCPWM can be enabled on all output-enabled pins. The API differs slightly from `machine.PWM` to allow explicit timer selection. +Currently, this implementation only covers basic functionality. + +For more details, see Espressif's `MCPWM +`_ documentation. + + +Use the `esp32.MCPWM` class:: + + from machine import Pin + from esp32 import MCPWM + + pwm0 = PWM(0) # Create MCPWM object with timer ID (0..5) + pwm0.bind(Pin(5)) # Bind to output Pin. Output starts immediately. + + pwm0.freq(500) # Set frequency in Hz + pwm0.freq() # Get current frequency + pwm0.duty(20) # Set duty in percent + pwm0.duty() # Get current duty + + pwm0.deinit() # turn of PWM on pin + + + ADC (analog to digital conversion) ---------------------------------- diff --git a/lib/mbedtls b/lib/mbedtls index 3f8d78411a26e..c835672c51652 160000 --- a/lib/mbedtls +++ b/lib/mbedtls @@ -1 +1 @@ -Subproject commit 3f8d78411a26e833db18d9fbde0e2f0baeda87f0 +Subproject commit c835672c51652586e815c8723335f17a2641eb9e diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 7033a3dd26c27..9c96acff26183 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -345,6 +345,7 @@ SRC_C = \ esp32_partition.c \ esp32_rmt.c \ esp32_ulp.c \ + esp32_mcpwm.c \ modesp32.c \ espneopixel.c \ machine_hw_spi.c \ diff --git a/ports/esp32/esp32_mcpwm.c b/ports/esp32/esp32_mcpwm.c new file mode 100644 index 0000000000000..b5e26d9756ba6 --- /dev/null +++ b/ports/esp32/esp32_mcpwm.c @@ -0,0 +1,146 @@ +#include "py/nlr.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "py/binary.h" + +#include +#include "driver/mcpwm.h" +#include "mphalport.h" +#include "esp_err.h" + +#define MCPWM_CHANNEL_MAX (MCPWM_TIMER_MAX * MCPWM_UNIT_MAX) + +typedef struct _mcpwm_obj_t { + mp_obj_base_t base; + uint8_t id; + gpio_num_t pin_a; + gpio_num_t pin_b; + + // Derived values for easier IDF API calls. + mcpwm_unit_t unit; + mcpwm_timer_t timer; + mcpwm_io_signals_t sig_a; + mcpwm_io_signals_t sig_b; +} mcpwm_obj_t; + +// Forward dec'l +extern const mp_obj_type_t esp32_mcpwm_type; +STATIC mp_obj_t _mcpwm_deinit(mp_obj_t self_in); +STATIC mp_obj_t _mcpwm_duty(size_t n_args, const mp_obj_t *args); +STATIC mp_obj_t _mcpwm_freq(size_t n_args, const mp_obj_t *args); + +STATIC mp_obj_t mcpwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, 3, true); + + int block_id = mp_obj_get_int(args[0]); + if (block_id >= MCPWM_CHANNEL_MAX) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "bad timer id requested: %d (0~5 allowed)", block_id)); + } + + // create PWM object from the given timer block + mcpwm_obj_t *self = m_new_obj(mcpwm_obj_t); + self->base.type = &esp32_mcpwm_type; + self->id = block_id; + + self->timer = self->id % MCPWM_TIMER_MAX; + self->unit = self->id / MCPWM_TIMER_MAX; + self->sig_a = self->timer * 2; // even numbers -> A operators + self->sig_b = self->timer * 2 + 1; // odd numbers -> B operators + + mcpwm_config_t config = { + .frequency = 1000, // frequency = 1kHz + .cmpr_a = 50, // duty A = 50% + .cmpr_b = 20, // duty B = 20% + .counter_mode = MCPWM_UP_COUNTER, + .duty_mode = MCPWM_DUTY_MODE_0 + }; + + mcpwm_init(self->unit, self->timer, &config); + mp_obj_t self_out = MP_OBJ_FROM_PTR(self); + + return self_out; +} + + +STATIC void mcpwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + mcpwm_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "MCPWM(ID=%u. ", self->id); + mp_printf(print, "pin=%u, ", self->pin_a); + float duty = mcpwm_get_duty(self->unit, self->timer, MCPWM_OPR_A); + int freq = mcpwm_get_frequency(self->unit, self->timer); + mp_printf(print, "freq=%uHz, duty=%.1f%%", freq, duty); + mp_printf(print, ")"); +} + + +// BIND +STATIC mp_obj_t _mcpwm_bind(mp_obj_t self_in, mp_obj_t pin) { + mcpwm_obj_t *self = MP_OBJ_TO_PTR(self_in); + gpio_num_t pin_id = machine_pin_get_id(pin); + mcpwm_gpio_init(self->unit, self->sig_a, pin_id); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mcpwm_bind_obj, _mcpwm_bind); + + +// DEINIT +STATIC mp_obj_t _mcpwm_deinit(mp_obj_t self_in) { + mcpwm_obj_t *self = MP_OBJ_TO_PTR(self_in); + mcpwm_stop(self->unit, self->timer); + //mcpwm_set_signal_low(self->unit, self->timer, MCPWM_OPR_A); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mcpwm_deinit_obj, _mcpwm_deinit); + + +// FREQ +STATIC mp_obj_t _mcpwm_freq(size_t n_args, const mp_obj_t *args) { + mcpwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + if (n_args == 1) { + // get + return MP_OBJ_NEW_SMALL_INT(mcpwm_get_frequency(self->unit, self->timer)); + } + + // set + int tval = mp_obj_get_int(args[1]); + mcpwm_set_frequency(self->unit, self->timer, tval); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mcpwm_freq_obj, 1, 2, _mcpwm_freq); + + +// DUTY +STATIC mp_obj_t _mcpwm_duty(size_t n_args, const mp_obj_t *args) { + mcpwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + if (n_args == 1) { + // get + return mp_obj_new_float(mcpwm_get_duty(self->unit, self->timer, MCPWM_OPR_A)); + } + + // set + float tval = mp_obj_get_float(args[1]); + mcpwm_set_duty(self->unit, self->timer, MCPWM_OPR_A, tval); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mcpwm_duty_obj, 1, 2, _mcpwm_duty); + + +STATIC const mp_rom_map_elem_t mcpwm_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&mcpwm_bind_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mcpwm_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&mcpwm_duty_obj) }, + { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&mcpwm_freq_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(mcpwm_locals_dict, mcpwm_locals_dict_table); + +const mp_obj_type_t esp32_mcpwm_type = { + { &mp_type_type }, + .name = MP_QSTR_MCPWM, + .print = mcpwm_print, + .make_new = mcpwm_make_new, + .locals_dict = (mp_obj_dict_t *)&mcpwm_locals_dict, +}; diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c index 0e0a7b7dbd930..c077ada4e4be9 100644 --- a/ports/esp32/modesp32.c +++ b/ports/esp32/modesp32.c @@ -157,6 +157,7 @@ STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Partition), MP_ROM_PTR(&esp32_partition_type) }, { MP_ROM_QSTR(MP_QSTR_RMT), MP_ROM_PTR(&esp32_rmt_type) }, { MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&esp32_ulp_type) }, + { MP_ROM_QSTR(MP_QSTR_MCPWM), MP_ROM_PTR(&esp32_mcpwm_type) }, { MP_ROM_QSTR(MP_QSTR_WAKEUP_ALL_LOW), MP_ROM_FALSE }, { MP_ROM_QSTR(MP_QSTR_WAKEUP_ANY_HIGH), MP_ROM_TRUE }, diff --git a/ports/esp32/modesp32.h b/ports/esp32/modesp32.h index f4c0491f7c27f..d3195dd1fb399 100644 --- a/ports/esp32/modesp32.h +++ b/ports/esp32/modesp32.h @@ -29,5 +29,6 @@ extern const mp_obj_type_t esp32_partition_type; extern const mp_obj_type_t esp32_rmt_type; extern const mp_obj_type_t esp32_ulp_type; +extern const mp_obj_type_t esp32_mcpwm_type; #endif // MICROPY_INCLUDED_ESP32_MODESP32_H 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