ESPShell for Arduino :: Pulse Generator

[ На русском ] ↔ [ English ]

PULSE PATTERN GENERATION

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.

BASIC CONCEPT: "TICK", "LEVEL", AND "PULSE"

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.

SENDING PULSE SEQUENCES

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.

BITS TO LEVELS, BITS TO PULSES

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

MODULATION AND END-OF-TRANSMISSION

TBD

DISPLAYING INFORMATION

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#>

EXAMPLES

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).