sbusparser_web_logo

SbusParser C++ library

v1.0.0

Table of contents

Overview

The SbusParser is a C++ library designed for encoding and decoding SBUS protocol data. The library includes basic methods for preparing SBUS data buffer (encoding) and interpreting SBUS data buffer (decoding). It utilizes C++17 standard. The library provides simple interface and doesn’t have third party dependencies. Also, the library provides test application that uses a serial port. The library doesn’t have third-party dependencies, but test application depends on SerialPort library (provides methods to work with serial ports, source code included, Apache 2.0 license).

Versions

Table 1 - Library versions.

Version Release date What’s new
1.0.0 30.05.2024 - First version.

Library files

The library is supplied only by source code. The user is given a set of files in the form of a CMake project (repository). The repository structure is shown below:

CMakeLists.txt -------------- Main CMake file of the library.
src  ------------------------ Folder with library source code.
    CMakeLists.txt ---------- CMake file of the library.
    SbusParser.h ------------ Main library header file.
    SbusParserVersion.h ----- Header file with library version.
    SbusParserVersion.h.in -- Service CMake file to generate version header.
    SbusParser.cpp ---------- C++ implementation file.
test ------------------------ Folder for test application files.
    3rdparty ---------------- Folder with third-party libraries.
        CMakeLists.txt ------ CMake file to include third-party libraries.
        SerialPort ---------- Folder with SerialPort library source code.
    CMakeLists.txt ---------- CMake file for test application.
    main.cpp ---------------- Source C++ file of test application.

SbusParser class description

Class declaration

class SbusParser
{
public:

    /// Get library version.
    static std::string getVersion();

    /// Encode SBUS packet.
    bool encode(uint8_t *buffer, SbusData &sbusData);

    /// Decode SBUS packet byte-by-byte.
    bool decode(uint8_t nextByte, SbusData &sbusData);
};

getVersion method

The getVersion() method return string of current SbusParser class version. Method declaration:

static std::string getVersion();

Method can be used without SbusParser class instance:

cout << "SbusParser version: " << cr::clib::SbusParser::getVersion();

Console output:

SbusParser version: 1.0.0

encode method

The encode(…) method encodes SbusData struct into buffer that can be used by SBUS protocol. Command encoding example shows usage of command. Method declaration:

bool encode(uint8_t *buffer, SbusData &sbusData);
Parameter Value
buffer Address of buffer for encoded data. Buffer size should be 25 bytes.
sbusData Reference to SbusData struct that holds Sbus channels.

Returns: TRUE if data encoded or FALSE if not (not valid id, not valid parameters).

decode method

The decode(…) method decodes Sbus buffer into SbusData. See the Response decoding example. Once the data from the serial port has been read the user must pass it to the method byte-by-byte (each byte separately in sequence). The library has an internal buffer. When the user passes another byte to the method, the library shifts the buffer by one byte and copies the new byte to the end of the buffer. If the library detects a valid Sbus frame in internal buffer, it returns true and fills channels into SbusData object. In all other cases, the library returns false. Method declaration:

bool decode(uint8_t nextByte, SbusData &sbusData);
Parameter Value
nextByte Next read byte from serial port.
sbusData Reference to SbusData struct.

Returns: TRUE if Sbus frame detected or FALSE.

Data structures

SbusData struct

SbusData includes values of control channels (16 channels with values from 0 to 2048 and two logical channels). The definition of SbusData struct is as follows:

struct SbusData
{
    /// Channels. Value : 0 - 2048.
    uint16_t ch[16] {0};
    /// Channel 16.
    bool ch16 {false};
    /// Channel 17.
    bool ch17 {false};
    /// Fail safe.
    bool failSafe {false};
    /// Frame lost.
    bool frameLost {false};
};

Examples

Response decoding example

Below is an example of decoding Sbus buffer.

// Decode incoming data.
uint8_t buffer[128];
int bytesRead = serialPortIn.read(buffer, 128);
cr::clib::SbusData sbusDataIn;
for (int i = 0; i < bytesRead; i++)
{
    if (sbusParser.decode(buffer[i], sbusDataIn))
    {
        // Sbus data detected.
        std::cout << "Sbus data detected: " << sbusDataDetected << std::endl;
        std::cout << "Ch0: " << sbusDataIn.ch[0] << std::endl;
        std::cout << "Ch1: " << sbusDataIn.ch[1] << std::endl;
        std::cout << "Ch2: " << sbusDataIn.ch[2] << std::endl;
        std::cout << "Ch3: " << sbusDataIn.ch[3] << std::endl;
        std::cout << "Ch4: " << sbusDataIn.ch[4] << std::endl;
        std::cout << "Ch5: " << sbusDataIn.ch[5] << std::endl;
        std::cout << "Ch6: " << sbusDataIn.ch[6] << std::endl;
        std::cout << "Ch7: " << sbusDataIn.ch[7] << std::endl;
        std::cout << "Ch8: " << sbusDataIn.ch[8] << std::endl;
        std::cout << "Ch9: " << sbusDataIn.ch[9] << std::endl;
        std::cout << "Ch10: " << sbusDataIn.ch[10] << std::endl;
        std::cout << "Ch11: " << sbusDataIn.ch[11] << std::endl;
        std::cout << "Ch12: " << sbusDataIn.ch[12] << std::endl;
        std::cout << "Ch13: " << sbusDataIn.ch[13] << std::endl;
        std::cout << "Ch14: " << sbusDataIn.ch[14] << std::endl;
        std::cout << "Ch15: " << sbusDataIn.ch[15] << std::endl;
        std::cout << "Ch16: " << (sbusDataIn.ch16 ? "true" : "false") << std::endl;
        std::cout << "Ch17: " << (sbusDataIn.ch17 ? "true" : "false") << std::endl;
    }
}

Command encoding example

Below is an example of encoding Sbus buffer.

cr::clib::SbusData sbusDataOut;
for (int i = 0; i < 16; i++)
    sbusDataOut.ch[i] = 1024;
sbusDataOut.ch16 = true;
sbusDataOut.ch17 = false;

// Encode outgoing data.
uint8_t bufferOut[25];
if (!sbusParser.encode(bufferOut, sbusDataOut))
    std::cout << "Error encoding data." << std::endl;

// Write outgoing data.
if (serialPortOut.write(bufferOut, 25) != 25)
    std::cout << "Error writing data to serial port." << std::endl;

Test application

Folder SbusParser/test contains the test application files. The test application read Sbus buffer from serial port and decode it. The decoded data is printed to the console. The test application also encodes SbusData struct and writes it back to serial port. The test application uses SerialPort. When test application started, it will prompt to enter serial port name.

Build and connect to your project

Typical commands to build SbusParser library:

cd SbusParser
git submodule update --init --recursive
mkdir build
cd build
cmake ..
make

If you want to connect SbusParser library to your CMake project as source code you can make the following. For example, if your repository has structure:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp

Create folder 3rdparty and copy folder of SbusParser repository there. New structure of your repository:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp
3rdparty
    SbusParser

Create CMakeLists.txt file in 3rdparty folder. CMakeLists.txt should contain:

cmake_minimum_required(VERSION 3.13)

################################################################################
## 3RD-PARTY
## dependencies for the project
################################################################################
project(3rdparty LANGUAGES CXX)

################################################################################
## SETTINGS
## basic 3rd-party settings before use
################################################################################
# To inherit the top-level architecture when the project is used as a submodule.
SET(PARENT ${PARENT}_YOUR_PROJECT_3RDPARTY)
# Disable self-overwriting of parameters inside included subdirectories.
SET(${PARENT}_SUBMODULE_CACHE_OVERWRITE OFF CACHE BOOL "" FORCE)

################################################################################
## CONFIGURATION
## 3rd-party submodules configuration
################################################################################
SET(${PARENT}_SUBMODULE_SBUS_PARSER                      ON  CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_SBUS_PARSER)
    SET(${PARENT}_SBUS_PARSER                            ON  CACHE BOOL "" FORCE)
    SET(${PARENT}_SBUS_PARSER_TEST                       OFF CACHE BOOL "" FORCE)
endif()

################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
if (${PARENT}_SUBMODULE_SBUS_PARSER)
    add_subdirectory(SbusParser)
endif()

File 3rdparty/CMakeLists.txt adds folder SbusParser to your project and excludes test application and example from compiling. Your repository new structure will be:

CMakeLists.txt
src
    CMakeList.txt
    yourLib.h
    yourLib.cpp
3rdparty
    CMakeLists.txt
    SbusParser

Next you need include folder 3rdparty in main CMakeLists.txt file of your repository. Add string at the end of your main CMakeLists.txt:

add_subdirectory(3rdparty)

Next you have to include SbusParser library in your src/CMakeLists.txt file:

target_link_libraries(${PROJECT_NAME} SbusParser)

Done!