原文地址: Futaba S-BUS controlled by mbed
代码地址: SBUS-Library


Introduction(简介)

The Futaba S-BUS protocol is a serial protocol to control servos. Up to 16 proportional and two digital channels are available. The protocol is derived from the very known RS232 protocol used everywhere. The signal must be first inverted. The frame is 8E2.

Futaba S-BUS 协议是控制伺服系统的串口协议。
最多可以支持16个比例通道和2个数字(位)通道。
源自家喻户晓的 RS232 协议。信号必须先经过反相。
帧格式为8E28 数据位 Even 偶校验 2 停止位)。

This board provide a complete electrical separation of RC gear and mbed controller. The S-BUS serial signal is converted and isolated by optocoppler. To keep control of the plane/car/ship an additional controller (ATTINY13) is on board. It monitors a standard servo signal (Master) and sends the serial S-BUS signal either to the mbed or directly to the servos. A special ‘middle’ position sends the S-BUS data to the servos and the mbed. In this mode the mbed can check stick positions and range without sending data to servos. Because the S-BUS data contains the Master signal, mbed knows about this mode.

这块板为遥控装置和mbed控制器提供了一个完整的电气隔离。
S-BUS 串口信号被光耦合器转变和隔离。 
板上有一个额外的控制器(ATTINY13)保持对飞机、车或者船的控制。 
它监视着标准伺服信号(主),并将串行 S-BUS 信号发送到mbed或直接发送给伺服系统。 
特殊的“中间”位置将 S-BUS 数据发送到伺服系统和mbed。 
这个模式下的mbed可以检查摇杆的位置和范围而不需要发送数据给伺服系统。

S-BUS protocol(S-BUS 协议)

The protocol is 25 Byte long and is send every 14ms (analog mode) or 7ms (highspeed mode).
One Byte = 1 startbit + 8 databit + 1 paritybit + 2 stopbit (8E2), baudrate = 100’000 bit/s
The highest bit is send first. The logic is inverted (Level High = 1)

25个字节长的协议每14ms(模拟模式)或者每7ms(高速模式)发送一次。
一个字节 = 1个起始位 + 8个数据位 + 1个奇偶检验位 + 2个停止位 (8E2)。
波特率为 100 000 bit/s(100k bps)。
高位先发送。逻辑是反相的(高电平是逻辑1,RS232高电平是逻辑0)。

[startbyte] [data1] [data2] …. [data22] [flags][endbyte]

startbyte = 11110000b (0xF0)

data 1-22 = [ch1, 11bit][ch2, 11bit] …. [ch16, 11bit] (ch# = 0 bis 2047)
channel 1 uses 8 bits from data1 and 3 bits from data2
channel 2 uses last 5 bits from data2 and 6 bits from data3
etc.

flags =
bit7 = ch17 = digital channel (0x80)
bit6 = ch18 = digital channel (0x40)
bit5 = Frame lost, equivalent red LED on receiver (0x20)
bit4 = failsafe activated (0x10)
bit3 = n/a
bit2 = n/a
bit1 = n/a
bit0 = n/a

endbyte = 00000000b

[起始字节] [数据1] [数据2] .... [数据22] [标志][结束字节]
起始字节 = 11110000b (0xF0)
数据1-22 = [通道1, 11位][ch2, 11bit] .... [ch16, 11bit] (ch# = 0 - 2047)
通道1使用数据1里的8位和数据2里的3位。
通道2使用数据2中的最后5位和数据3中的6位。
以此类推。

让我为你们举几个例子。
channel1有11位数据,用第0~A位表示,则收到的数据为 76543210(data1) xxxxxA98(data2)
channel2有11位数据,用第0~A位表示,则收到的数据为 43210xxx(data2) xxA98765(data3)
channel3有11位数据,用第0~A位表示,则收到的数据为 10xxxxxx(data3) 98765432(data4) xxxxxxxA(data5)
channel4有11位数据,用第0~A位表示,则收到的数据为 6543210x(data5) xxxxA987(data6)
channel5有11位数据,用第0~A位表示,则收到的数据为 3210xxxx(data6) xA987654(data7)
channel6有11位数据,用第0~A位表示,则收到的数据为 0xxxxxxx(data7) 87654321(data8) xxxxxxA9(data9)
etc.

flags = 
位7 = 通道17 = 数字(位)通道 (0x80)
位6 = 通道18 = 数字(位)通道 (0x40)
位5 = 丢帧, 接收机上有相同意义的红灯 (0x20)
位4 = 失效保护被激活 (0x10)
bit3 = n/a
bit2 = n/a
bit1 = n/a
bit0 = n/a

结束字节 = 00000000b

S-BUS Library(S-BUS 库)

void FutabaSBUS::update_channels(void) {
    // Read all received data and calculate channel data
    uint8_t i;
    uint8_t sbus_pointer = 0;
    while (sbus_.readable()) {
        uint8_t data = sbus_.getc(); // get data from serial rx buffer
        switch (sbus_pointer) {
            case 0: // Byte 1
                if (data==0x0f) {
                    sbus_data[sbus_pointer] = data;
                    sbus_pointer++;
                }
                break;

            case 24:    // Byte 25 >> if last byte == 0x00 >> convert data
                if (data==0x00) {
                    sbus_data[sbus_pointer] = data;
                    // clear channels[]
                    for (i=0; i<16; i++) {channels[i] = 0;}

                    // reset counters
                    uint8_t byte_in_sbus = 1;
                    uint8_t bit_in_sbus = 0;
                    uint8_t ch = 0;
                    uint8_t bit_in_channel = 0;

                    // process actual sbus data
                    for (i=0; i<176; i++) {
                        if (sbus_data[byte_in_sbus] & (1<<bit_in_sbus)) {
                            channels[ch] |= (1<<bit_in_channel);
                        }
                        bit_in_sbus++;
                        bit_in_channel++;

                        if (bit_in_sbus == 8) {
                            bit_in_sbus =0;
                            byte_in_sbus++;
                        }
                        if (bit_in_channel == 11) {
                            bit_in_channel =0;
                            ch++;
                        }
                    }
                    // DigiChannel 1
                    if (sbus_data[23] & (1<<0)) {
                        channels[16] = 1;
                    }else{
                        channels[16] = 0;
                    }
                    // DigiChannel 2
                    if (sbus_data[23] & (1<<1)) {
                        channels[17] = 1;
                    }else{
                        channels[17] = 0;
                    }
                    // Failsafe
                    failsafe_status = SBUS_SIGNAL_OK;
                    if (sbus_data[23] & (1<<2)) {
                        failsafe_status = SBUS_SIGNAL_LOST;
                    }
                    if (sbus_data[23] & (1<<3)) {
                        failsafe_status = SBUS_SIGNAL_FAILSAFE;
                    }
                }
                break;

            default:  // collect Channel data (11bit) / Failsafe information
                sbus_data[sbus_pointer] = data;
                sbus_pointer++;
        }
    }
}
void FutabaSBUS::update_servos(void) {
    // Send data to servos
    // Passtrough mode = false >> send own servo data
    // Passtrough mode = true >> send received channel data
    uint8_t i;
    if (!sbus_passthrough) {
        // clear received channel data
        for (i=1; i<24; i++) {
            sbus_data[i] = 0;
        }

        // reset counters
        uint8_t ch = 0;
        uint8_t bit_in_servo = 0;
        uint8_t byte_in_sbus = 1;
        uint8_t bit_in_sbus = 0;

        // store servo data
        for (i=0; i<176; i++) {
            if (servos[ch] & (1<<bit_in_servo)) {
                sbus_data[byte_in_sbus] |= (1<<bit_in_sbus);
            }
            bit_in_sbus++;
            bit_in_servo++;

            if (bit_in_sbus == 8) {
                bit_in_sbus =0;
                byte_in_sbus++;
            }
            if (bit_in_servo == 11) {
                bit_in_servo =0;
                ch++;
            }
        }

        // DigiChannel 1
        if (channels[16] == 1) {
            sbus_data[23] |= (1<<0);
        }
        // DigiChannel 2
        if (channels[17] == 1) {
            sbus_data[23] |= (1<<1);
        }        

        // Failsafe
        if (failsafe_status == SBUS_SIGNAL_LOST) {
            sbus_data[23] |= (1<<2);
        }

        if (failsafe_status == SBUS_SIGNAL_FAILSAFE) {
            sbus_data[23] |= (1<<2);
            sbus_data[23] |= (1<<3);
        }
    }
    // send data out
    for (i=0;i<25;i++) {
        sbus_.putc(sbus_data[i]);
    }
}
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐