Skip to content

Chapter 4: SBUS RC Receiver

4.1 Key Points

  • SBUS frame format: 25 bytes, 100000 baud, 8E2, inverted signal
  • 16-channel 11-bit bitfield unpacking
  • ESP-IDF UART configuration and line inversion
  • Failsafe and lost-frame flag handling

4.2 Course Content

SBUS is a digital RC protocol widely used in RC vehicles and robots. It transmits 16 analog channels and two digital channels through a single serial line. Each frame is 25 bytes. OSRCORE receives SBUS on UART0 GPIO44.

4.3 Basic Learning

SBUS Frame Format

text
Byte 0:  0x0F frame header
Byte 1-22: packed channel data, 16 channels × 11 bits = 176 bits
Byte 23: flags
  bit2 = failsafe
  bit3 = lost_frame
Byte 24: 0x00 frame end

Typical channel values range from about 240 to 1810, with neutral near 1024.

Bitfield Unpacking

The 16 channels are tightly packed into 22 bytes:

c
ch[0] = ((buf[1]      | buf[2]  << 8) & 0x07FF);
ch[1] = ((buf[2] >> 3 | buf[3]  << 5) & 0x07FF);
ch[2] = ((buf[3] >> 6 | buf[4]  << 2 | buf[5] << 10) & 0x07FF);
// Continue the same pattern for all 16 channels.

UART Configuration

SBUS uses 100000 baud, even parity, two stop bits, and inverted signaling. ESP-IDF can handle inversion with uart_set_line_inverse().

4.4 Program Study

UART initialization:

c
uart_config_t cfg = {
    .baud_rate  = 100000,
    .data_bits  = UART_DATA_8_BITS,
    .parity     = UART_PARITY_EVEN,
    .stop_bits  = UART_STOP_BITS_2,
    .flow_ctrl  = UART_HW_FLOWCTRL_DISABLE,
    .source_clk = UART_SCLK_DEFAULT,
};
uart_driver_install(UART_NUM_0, 256, 0, 0, NULL, 0);
uart_param_config(UART_NUM_0, &cfg);
uart_set_pin(UART_NUM_0, 43, 44, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_set_line_inverse(UART_NUM_0, UART_SIGNAL_RXD_INV | UART_SIGNAL_TXD_INV);

Frame synchronization and parsing:

c
uint8_t byte;
do {
    uart_read_bytes(UART_NUM_0, &byte, 1, portMAX_DELAY);
} while (byte != 0x0F);

buf[0] = byte;
int got = uart_read_bytes(UART_NUM_0, buf + 1, 24, pdMS_TO_TICKS(10));
if (got == 24 && sbus_parse(buf, &data)) {
    if (!data.failsafe) {
        // Process channel values here.
    }
}

Convert SBUS channel values to PWM pulse width:

c
#define SBUS_TO_US(v) ((uint32_t)(((v) - 240) * 1000 / 1570 + 1000))

4.5 Summary

This chapter covered SBUS framing, channel unpacking, UART 8E2 configuration, and failsafe handling. SBUS input becomes the remote-control source for the full robot example.


Built for OSRCORE robot development board.