This short writeup servers as a response to discussion 17284
The basic question here is how to pass a MicroPython object to a C function in a custom C module. In this case a PWM object.
The end result use case will be is something like this:
>>> from machine import Pin, PWM
>>> pwm = PWM(Pin(18), freq=5000, duty_u16=32768)
>>> import mypwm
>>> mypwm.channel(pwm)
The C module mypwm
has a function channel
. It takes the PWM object pwm
as parameter.
There are probably many ways to do this. Here is my way of doing it. It may not be the right way, and it may not follow best practices, but it works for me.
Create a C file and possibly a header file. You may want to read the Micropython source files to see how things are done. The header and program files are in the "xmod" directory.
You need to use a modified "esp32_common.cmake". Save the original file.
cp esp32_common.cmake esp32_common.cmake-ORIG
cp esp32_common.cmake esp32_common.cmake-TEST
The file we want to change is "esp32_common.cmake-TEST". In this file we add a line "xmod/my_pwm.c" this is at the last entry to "list(APPEND MICROPY_SOURCE_PORT" right after "modespnow.c".
To make the build process easier, we create an executable bash script "mpb_esp32_generic.sh". Just run this script to build the firmware.
Lastly, flash the firmware and test our new module in a script.
MPY: soft reboot
MicroPython v1.26.0-preview.82.gae6062a45.kaki5 on 2025-05-12; Generic ESP32 module with ESP32
Type "help()" for more information.
>>>
MPY: soft reboot
MicroPython v1.26.0-preview.82.gae6062a45.kaki5 on 2025-05-12; Generic ESP32 module with ESP32
Type "help()" for more information.
>>> from machine import Pin, PWM
>>> pwm = PWM(Pin(18), freq=5000, duty_u16=32768)
>>> pwm.
deinit duty duty_ns duty_u16
freq init
>>> import mypwm
>>> mypwm.channel(pwm)
0
>>>
The pwm object does not have a channel method. We build a custom firmware that includes a user C module called "mypwm" and this module provides us with a "channel" method.
The module here does not give us any significant new functionality. The main purpose here is to show the process of including a custom C module that takes a MicroPython object as a parameter.
Hope this is useful to someone.