Skip to content

Chapter 1: WS2812B RGB LED (RMT Driver)

1.1 Key Points

  • WS2812B single-wire timing: T0H, T0L, T1H, T1L, and reset
  • ESP-IDF v5.x RMT TX API usage
  • Custom rmt_encoder_t implementation
  • GRB byte order and color mapping

1.2 Course Content

WS2812B is an RGB LED with an integrated driver IC. It receives GRB color data through a single data line. ESP32-S3's RMT peripheral can generate the precise pulse timing required by WS2812B without keeping the CPU busy.

The example cycles through red, green, blue, and off, switching color every 500 ms.

1.3 Basic Learning

WS2812B Timing

WS2812B uses NRZ coding. Each bit is represented by a high-level duration followed by a low-level duration.

SymbolHigh LevelLow LevelMeaning
0 bit400 ns850 nsLogic 0
1 bit800 ns450 nsLogic 1
Reset≥ 50 µsFrame end

Each LED receives 24 bits in GRB order, MSB first. In a daisy chain, each LED consumes the first 24 bits and forwards the rest.

With an RMT resolution of 80 MHz, one tick is 12.5 ns:

text
T0H = 32 ticks  T0L = 68 ticks
T1H = 64 ticks  T1L = 36 ticks
Reset = 4000 ticks (50 µs)

RMT Encoder Architecture

ESP-IDF v5.x RMT uses composable encoders:

  • rmt_bytes_encoder: expands bytes into RMT symbols bit by bit.
  • rmt_copy_encoder: copies a predefined symbol sequence, such as the reset pulse.
  • A custom encoder combines both to create a complete WS2812B frame.

1.4 Program Study

Create the TX channel and byte encoder:

c
rmt_tx_channel_config_t ch_cfg = {
    .gpio_num          = 45,
    .clk_src           = RMT_CLK_SRC_DEFAULT,
    .resolution_hz     = 80000000,
    .mem_block_symbols = 64,
    .trans_queue_depth = 4,
};
rmt_new_tx_channel(&ch_cfg, &s_channel);

rmt_bytes_encoder_config_t bcfg = {
    .bit0 = { .level0=1, .duration0=32, .level1=0, .duration1=68 },
    .bit1 = { .level0=1, .duration0=64, .level1=0, .duration1=36 },
    .flags.msb_first = 1,
};
rmt_new_bytes_encoder(&bcfg, &ws->bytes_encoder);
rmt_enable(s_channel);

Send one RGB color in GRB order:

c
static void led_set(uint8_t r, uint8_t g, uint8_t b)
{
    uint8_t grb[3] = { g, r, b };
    rmt_transmit_config_t tx_cfg = { .loop_count = 0 };
    rmt_transmit(s_channel, s_encoder, grb, sizeof(grb), &tx_cfg);
    rmt_tx_wait_all_done(s_channel, portMAX_DELAY);
}

1.5 Summary

This chapter explained WS2812B timing and the ESP-IDF RMT TX API. The same RMT encoder approach can be extended from one onboard LED to a full LED strip.


Built for OSRCORE robot development board.