summaryrefslogtreecommitdiff
path: root/docs/library/esp32.rst
diff options
context:
space:
mode:
authorElvis Pfutzenreuter <epxx@epxx.co>2024-11-22 20:38:58 -0300
committerDamien George <damien@micropython.org>2025-11-17 10:45:19 +1100
commit2a3b9b0b4bed6ea51f1053e224278e9dbb266c35 (patch)
tree7f87b28423868f94b5960202add77af51b8614d0 /docs/library/esp32.rst
parent27544a2d81da5b0d804a932d98d680f121a22b8f (diff)
esp32/esp32_rmt: Update RMT module to use the new RMT API.
The current `esp32.RMT` class uses a legacy API from ESP-IDF 4.x. The ESP-IDF 5.x offers a new API, which is overall better, and easier to implement the RX side in the future. This commit updates the module and the documentation, preserving the current MicroPython RMT API as much as possible. The bitstream RMT implementation was updated as well, since ESP-IDF does not allow firmware to reference legacy and new APIs at the same time (it resets right after boot with an error message, even if neither module is imported). The documentation is updated accordingly. Signed-off-by: Elvis Pfutzenreuter <elvis.pfutzenreuter@gmail.com>
Diffstat (limited to 'docs/library/esp32.rst')
-rw-r--r--docs/library/esp32.rst108
1 files changed, 78 insertions, 30 deletions
diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst
index 84f33f46e..0f0637741 100644
--- a/docs/library/esp32.rst
+++ b/docs/library/esp32.rst
@@ -362,29 +362,24 @@ used to transmit or receive many other types of digital signals::
import esp32
from machine import Pin
- r = esp32.RMT(0, pin=Pin(18), clock_div=8)
- r # RMT(channel=0, pin=18, source_freq=80000000, clock_div=8, idle_level=0)
+ r = esp32.RMT(pin=Pin(18), resolution_hz=10000000)
+ r # RMT(pin=18, source_freq=80000000, resolution_hz=10000000, idle_level=0)
# To apply a carrier frequency to the high output
- r = esp32.RMT(0, pin=Pin(18), clock_div=8, tx_carrier=(38000, 50, 1))
+ r = esp32.RMT(pin=Pin(18), resolution_hz=10000000, tx_carrier=(38000, 50, 1))
- # The channel resolution is 100ns (1/(source_freq/clock_div)).
+ # The channel resolution is 100ns (1/resolution_hz)
r.write_pulses((1, 20, 2, 40), 0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns
The input to the RMT module is an 80MHz clock (in the future it may be able to
-configure the input clock but, for now, it's fixed). ``clock_div`` *divides*
-the clock input which determines the resolution of the RMT channel. The
-numbers specified in ``write_pulses`` are multiplied by the resolution to
+configure the input clock but, for now, it's fixed). ``resolution_hz`` determines
+the resolution of the RMT channel. The numbers specified in ``write_pulses`` are
+multiplied by the resolution to
define the pulses.
-``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by
-multiplying the resolution by a 15-bit (1-``PULSE_MAX``) number. There are eight
-channels (0-7) and each can have a different clock divider.
-
-So, in the example above, the 80MHz clock is divided by 8. Thus the
-resolution is (1/(80Mhz/8)) 100ns. Since the ``start`` level is 0 and toggles
-with each number, the bitstream is ``0101`` with durations of [100ns, 2000ns,
-100ns, 4000ns].
+So, in the example above, the resolution is resolution is (1/10Mhz) = 100ns.
+Since the ``start`` level is 0 and toggles with each number, the bitstream is
+``0101`` with durations of [100ns, 2000ns, 100ns, 4000ns].
For more details see Espressif's `ESP-IDF RMT documentation.
<https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/rmt.html>`_.
@@ -395,13 +390,24 @@ For more details see Espressif's `ESP-IDF RMT documentation.
*beta feature* and the interface may change in the future.
-.. class:: RMT(channel, *, pin=None, clock_div=8, idle_level=False, tx_carrier=None)
+.. class:: RMT(channel, *, pin=None, resolution_hz=10000000, clock_div=None, idle_level=False, num_symbols=48|64, tx_carrier=None)
This class provides access to one of the eight RMT channels. *channel* is
- required and identifies which RMT channel (0-7) will be configured. *pin*,
- also required, configures which Pin is bound to the RMT channel. *clock_div*
- is an 8-bit clock divider that divides the source clock (80MHz) to the RMT
- channel allowing the resolution to be specified. *idle_level* specifies
+ optional and a dummy parameter for backward compatibility. *pin* is required
+ and configures which Pin is bound to the RMT channel.
+ *resolution_hz* defines the resolution/unit of the samples.
+ For example, 1,000,000 means the unit is microsecond. The pulse widths can
+ assume values up to *RMT.PULSE_MAX*, so the resolution should be selected
+ accordingly to the signal to be transmitted.
+ *clock_div* (deprecated) is equivalent to *resolution_hz*, but expressed as
+ a clock divider that divides the source clock (80MHz) to the RMT
+ channel allowing the resolution to be specified. Either *clock_div* and
+ *resolution_hz* may be supplied, but not both.
+ *num_symbols* specifies the
+ RMT buffer allocated for this channel (minimum 48 or 64, depending on chip), from a small pool of
+ symbols (192 to 512, depending on chip) that are shared by all channels. This buffer does not limit the
+ size of the pulse train that you can send, but bigger buffers reduce the
+ CPU load and the potential of glitches/imprecise pulse lengths. *idle_level* specifies
what level the output will be when no transmission is in progress and can
be any value that converts to a boolean, with ``True`` representing high
voltage and ``False`` representing low.
@@ -419,21 +425,52 @@ For more details see Espressif's `ESP-IDF RMT documentation.
.. method:: RMT.clock_div()
Return the clock divider. Note that the channel resolution is
- ``1 / (source_freq / clock_div)``.
+ ``1 / (source_freq / clock_div)``. (Method deprecated. The value may
+ not be faithful if resolution was supplied as *resolution_hz*.)
.. method:: RMT.wait_done(*, timeout=0)
Returns ``True`` if the channel is idle or ``False`` if a sequence of
pulses started with `RMT.write_pulses` is being transmitted. If the
*timeout* keyword argument is given then block for up to this many
- milliseconds for transmission to complete.
+ milliseconds for transmission to complete. Timeout of -1 blocks until
+ transmission is complete (and blocks forever if loop is enabled).
.. method:: RMT.loop(enable_loop)
Configure looping on the channel. *enable_loop* is bool, set to ``True`` to
enable looping on the *next* call to `RMT.write_pulses`. If called with
``False`` while a looping sequence is currently being transmitted then the
- current loop iteration will be completed and then transmission will stop.
+ transmission will stop. (Method deprecated by `RMT.loop_count`.)
+
+.. method:: RMT.loop_count(n)
+
+ Configure looping on the channel. *n* is int. Affects the *next* call to
+ `RMT.write_pulses`. Set to ``0`` to disable looping, ``-1`` to enable
+ infinite looping, or a positive number to loop for a given number of times.
+ If *n* is changed, the current transmission is stopped.
+
+ Note: looping for a finite number of times is not supported by all flavors
+ of ESP32.
+
+.. method:: RMT.active([boolean])
+
+ If called without parameters, returns *True* if there is an ongoing transmission.
+
+ If called with parameter *False*, stops the ongoing transmission.
+ This is useful to stop an infinite transmission loop.
+ The current loop is finished and transmission stops.
+ The object is not invalidated, and the RMT channel is again enabled when a new
+ transmission is started.
+
+ Calling with parameter *True* does not restart transmission. A new transmission
+ should always be initiated by *write_pulses()*.
+
+.. method:: RMT.deinit()
+
+ Release all RMT resources and invalidate the object. All subsequent method
+ calls will raise OSError. Useful to free RMT resources without having to wait
+ for the object to be garbage-collected.
.. method:: RMT.write_pulses(duration, data=True)
@@ -463,17 +500,28 @@ For more details see Espressif's `ESP-IDF RMT documentation.
new sequence of pulses. Looping sequences longer than 126 pulses is not
supported by the hardware.
+.. staticmethod:: RMT.bitstream_rmt([value])
+
+ Configure RMT usage in the `machine.bitstream` implementation.
+
+ If *value* is ``True``, bitstream tries to use RMT if possible. If *value*
+ is ``False``, bitstream sticks to the bit-banging implementation.
+
+ If no parameter is supplied, it returns the current state. The default state
+ is ``True``.
+
.. staticmethod:: RMT.bitstream_channel([value])
- Select which RMT channel is used by the `machine.bitstream` implementation.
- *value* can be ``None`` or a valid RMT channel number. The default RMT
- channel is the highest numbered one.
+ *This function is deprecated and will be replaced by `RMT.bitstream_rmt()`.*
+
+ Passing in no argument will return ``1`` if RMT was enabled for the `machine.bitstream`
+ feature, and ``None`` otherwise.
- Passing in ``None`` disables the use of RMT and instead selects a bit-banging
- implementation for `machine.bitstream`.
+ Passing any non-negative integer argument is equivalent to calling ``RMT.bitstream_rmt(True)``.
- Passing in no argument will not change the channel. This function returns
- the current channel number.
+ .. note:: In previous versions of MicroPython it was necessary to use this function to assign
+ a specific RMT channel number for the bitstream, but the channel number is now assigned
+ dynamically.
Constants
---------