Skip to content

ESP32 RMT Implementation #5184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
af6bb8a
First commit of RMT tx implementation
mattytrentini Sep 23, 2019
2d9f0bf
Add TODO, complete config init, add deinit method, tidy up resolution…
mattytrentini Sep 24, 2019
e7bb36f
Allow lists or tuple to be used to define tuples - throw exception if…
mattytrentini Sep 26, 2019
56ff9e1
Improved some error handling
mattytrentini Sep 29, 2019
5baff68
Make start_level an optional keyword argument.
mattytrentini Sep 29, 2019
7069370
The start of documentation for RMT
mattytrentini Sep 29, 2019
966cde8
Updated quickref, incorporating mcauser's suggestion. Also updated qu…
mattytrentini Oct 7, 2019
e6ebbdc
Set the idle output level of the RMT channel to zero.
mattytrentini Oct 9, 2019
3ac8659
Handle deinit correctly - when calling deinit on an RMT object and wh…
mattytrentini Nov 13, 2019
d6bc920
RMT.send_pulses is now non-blocking. Also fewer memory allocations, s…
mattytrentini Nov 26, 2019
b3a151d
Remove remnants of start_level to start rename.
mattytrentini Nov 28, 2019
a0ffb5f
Tidy up the ESP32 RMT docs - a clearer description in the quickref
mattytrentini Dec 5, 2019
78998de
Add wait_done to allow user to query whether pulses are currently bei…
mattytrentini Dec 6, 2019
fd7f6ad
Added a simplistic way to enabled loop tx
mattytrentini Dec 6, 2019
06e3497
Provide accessors for the clock divider and source clock. Remove reso…
mattytrentini Dec 14, 2019
9a6038d
Update RMT documentation
mattytrentini Dec 16, 2019
4430e61
Rename clock_divider->clock_div, make it an optional keyword paramete…
mattytrentini Dec 16, 2019
6f39223
Provide more explanation of RMT in the reference documentation, movin…
mattytrentini Dec 16, 2019
801507e
Remove debug printf's
mattytrentini Dec 16, 2019
ab45deb
Prefer to use the non-legacy type checks
mattytrentini Dec 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/esp32/general.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ For your convenience, some of technical specifications are provided below:
* I2S: 2
* ADC: 12-bit SAR ADC up to 18 channels
* DAC: 2 8-bit DACs
* RMT: 8 channels allowing accurate pulse transmit/receive
* Programming: using BootROM bootloader from UART - due to external FlashROM
and always-available BootROM bootloader, the ESP32 is not brickable

Expand Down
17 changes: 17 additions & 0 deletions docs/esp32/quickref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,23 @@ Notes:

p1 = Pin(4, Pin.OUT, None)

RMT
---

See :ref:`esp32.RMT <esp32.RMT>`

The RMT is ESP32-specific and allows generation of accurate digital pulses with
12.5ns resolution. Usage is::

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)
# The channel resolution is 100ns (1/(source_freq/clock_div)).
r.send_pulses((1, 20, 2, 40), start=0) # Send 0 for 100ns, 1 for 2000ns, 0 for 200ns, 1 for 4000ns


OneWire driver
--------------

Expand Down
85 changes: 85 additions & 0 deletions docs/library/esp32.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. currentmodule:: esp32

:mod:`esp32` --- functionality specific to the ESP32
====================================================

Expand Down Expand Up @@ -101,6 +103,89 @@ The Ultra-Low-Power co-processor

Start the ULP running at the given *entry_point*.

.. _esp32.RMT:

RMT
---

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here could go some background info about it, moved from the quickref.

The RMT (Remote Control) module, specific to the ESP32, was originally designed
to send and receive infrared remote control signals. However, due to a flexible
design and very accurate (as low as 12.5ns) pulse generation, it can also be
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)
# The channel resolution is 100ns (1/(source_freq/clock_div)).
r.send_pulses((1, 20, 2, 40), start=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 specificed in ``send_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 (0-32,768) 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].

For more details see Espressif's `ESP-IDF RMT documentation.
<https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/rmt.html>`_.

.. Warning::
The current MicroPython RMT implementation lacks some features, most notably
receiving pulses and carrier transmit. RMT can also be considered a *beta
feature* and the interface may change in the future.


.. class:: RMT(channel, pin, clock_div=8)

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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolution shouldn't be in *'s because it's not a parameter.


.. method:: RMT.source_freq()

Returns the source clock frequency. Currently the source clock is not
configurable so this will always return 80MHz.

.. method:: RMT.clock_div()

Return the clock divider. Note that the channel resolution is
``1/(source_freq/clock_div)``.

.. method:: RMT.wait_done(timeout=0)

Returns True if ``send_pulses`` has completed.

If *timeout* (defined in ticks of ``source_freq/clock_div``) is specified
the method will wait for *timeout* or until ``send_pulses`` is complete,
returning False if the channel continues to transmit.

.. Warning::
Avoid using ``wait_done()`` if looping is enabled.

.. method:: RMT.loop(enable_loop)

Configure looping on the channel, allowing a stream of pulses to be
indefinitely repeated. *enable_loop* is bool, set to True to enable looping.

.. method:: RMT.send_pulses(pulses, start)

Begin sending *pulses*, a list or tuple defining the stream of pulses. The
length of each pulse is defined by a number to be multiplied by the channel
resolution (1/(source_freq/clock_div)). *start* defines whether the stream
starts at 0 or 1.


Constants
---------
Expand Down
1 change: 1 addition & 0 deletions ports/esp32/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ SRC_C = \
modesp.c \
esp32_partition.c \
esp32_ulp.c \
esp32_rmt.c \
modesp32.c \
espneopixel.c \
machine_hw_spi.c \
Expand Down
Loading