ESP32 features a dedicated peripheral called RMT (Remote Control) for pulse train generation. Its primary purpose is to produce arbitrary signal patterns with high precision - down to 0.0125 microseconds.
It can be used as a general-purpose signal generator or for IR remote signal generation.
Pulse pattern generation is controlled using the "sequence SEQ_ID" and "pin PIN seq SEQ_ID" commands. The former defines a sequence of pulses to generate, while the latter transmits it. The sequence number (SEQ_ID) must be in the range 0-9, allowing up to 10 different sequences to be created. If more are needed, one can modify the SEQUENCE_NUM macro in espshell.h.
Before diving into commands and examples, let's clarify some terminology used throughout this document:
Let's solve a simple task: suppose we want to generate a series of pulses on pin 2:
"Set pin 2 HIGH for 10 us, then LOW for 20 us, then HIGH for 30 us, and finally LOW for 100 us."
We begin by entering sequence configuration mode:
esp32#>sequence 0 esp32-seq0>
The command "sequence 0" creates an empty Sequence0 and enters sequence configuration mode. The shell prompt changes to "esp32-seq0>" to indicate the new mode. To exit, use "exit" or press Ctrl+Z.
First, set the resolution for the sequence - the so-called tick length:
esp32#>sequence 0 esp32-seq0>tick 1
By default, sequences are created with a 1 us tick, so the "tick 1" command is optional.
Now, input the sequence as a series of levels:
esp32#>sequence 0 esp32-seq0>tick 1 esp32-seq0>levels 1/10 0/20 1/30 0/100
The "levels" command accepts arguments in the form "A/B", where A is "1" or "0", and B is the duration (1-32767 ticks). Use "show" to inspect the total sequence duration in ticks and microseconds. Tip: "1//" is a shorthand for "1/32767".
The command above means: set output HIGH for 10 ticks, LOW for 20 ticks, etc. Since we use a 1 us tick, the durations directly match the microsecond values.
Now that sequence 0 is configured, let's send it on GPIO2:
esp32#>sequence 0 esp32-seq0>tick 1 esp32-seq0>levels 1/10 0/20 1/30 0/100 esp32-seq0>exit esp32#>pin 2 seq 0
To send it 4 times in a row:
esp32#>sequence 0 esp32-seq0>tick 1 esp32-seq0>levels 1/10 0/20 1/30 0/100 esp32-seq0>exit esp32#>pin 2 seq 0 esp32#>pin 2 seq 0 seq 0 seq 0 seq 0
NOTE: An alternative is to use the "pin 2 seq 0 loop 4" command.
While you can define all levels manually, it becomes impractical for longer sequences. Instead, use the "bits", "one", and "zero" commands.
The "bits" command defines the bit stream, while "one" and "zero" specify how logic 1 and 0 are represented in terms of HIGH/LOW durations. Let's recreate the earlier pulse sequence:
"HIGH for 10 us, LOW 20 us, HIGH 30 us, LOW 100 us"
Shell commands:
esp32#>sequence 0 esp32-seq0>bits 1001110000000000 esp32-seq0>one 1/10 esp32-seq0>zero 0/10
"One" defines logic 1 as HIGH for 10 us, and "zero" defines logic 0 as LOW for 10 us. The bit stream encodes timing as follows:
1 - HIGH for 10 us 00 - LOW for 20 us 111 - HIGH for 30 us 0000000000 - LOW for 100 us
The "bits" command clears any previously set "levels", and vice versa. Once tick, bits, one, and zero are configured, levels are generated automatically and shown via "show":
esp32-seq0>show % % Sequence #0: % Resolution : 1.0000uS (Frequency: 1000000 Hz) % Levels are : % 1/10, 0/10, 0/10, 1/10, 1/10, 1/10 ....
The ESP32 RMT peripheral is designed for IR protocol encoding, where 1 and 0 are typically pulses rather than static levels. Pulses can be defined using "one" and "zero" with two durations each. For example, to encode:
esp32#>seq 0 esp32-seq0>tick 1 esp32-seq0>one 1/150 0/50 esp32-seq0>zero 1/50 0/150 esp32-seq0>bits 100111 esp32-seq0>show % % Sequence #0: % Resolution : 1.0000uS (Frequency: 1000000 Hz) % Levels are : % 1/150, 0/50, 1/50, 0/150, 1/50, 0/150, 1/150, 0/50, % 1/150, 0/50, 1/150, 0/50, % Total: 12 levels, duration: 1200 ticks, (~1200 uS) ← total sequence time
TBD
Use the "show sequence NUM" command to view a configured sequence. The command requires a sequence number (0-9).
Example output:
esp32#>sh seq 0 % % Sequence #0: % Resolution : 1.0000uS (Frequency: 1000000 Hz) % Levels are % 1/50, 0/20, 1/100, 0/20, 1/100, 0/20, 1/50, 0/20, % 1/50, 0/20, 1/50, 0/20, 1/50, 0/20, 1/100, 0/20, % 1/50, 0/20, 1/100, 0/20, 1/50, 0/20, 1/50, 0/20, % 1/50, 0/20, 1/50, 0/20, % Total: 28 levels, duration: 1180 ticks, (~1180 uS) % Modulation : yes, "LOW" are modulated at 100Hz, duty 30.00% % Bit sequence is : (14 bits) "10011110101111" % Zero is 1/100 0/20 % One is 1/50 0/20 % Hold LOW after transmission is done esp32#>
Example: Blink an LED connected to GPIO2 at ~1 Hz.
Given a 1 Hz frequency, choose the longest possible tick and level durations. The maximum tick is 3.2 us. Define "one" and "zero" with the maximum length:
esp32-seq0>tick 3.2 esp32-seq0>one 1// esp32-seq0>zero 0// esp32-seq0>bits 111111111000000000111111111000000000
Note: The "/" symbol is a shortcut for "32767"
Exit sequence mode using "exit" or Ctrl+Z. You can also use short forms like "seq" and "ex".
To play the sequence (e.g., blink the LED on GPIO2):
esp32-seq0>ex esp32#>pin 2 seq 0 % Sending sequence 0 over GPIO 2
Several additional "sequence" commands are not covered here. Type "?" before a command name to explore further.
NOTE: By default, the "pin X sequence Y" command is blocking. To make it non-blocking, append the "&" flag (run in background).