Skip to content

Commit

Permalink
Using std::array for passing around SBUS data and commands
Browse files Browse the repository at this point in the history
  • Loading branch information
flybrianfly committed Dec 17, 2021
1 parent 8fe02a0 commit ddd6984
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 64 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## v7.0.0
- Using std::array for passing around SBUS data and commands

## v6.0.3
- Cleaned up folder structure after merge
- Pulling in mcu-support repo for CMake builds
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ if (DEFINED MCU)
set(CMAKE_TOOLCHAIN_FILE "${mcu_support_SOURCE_DIR}/cmake/cortex.cmake")
# Project information
project(Sbus
VERSION 6.0.3
VERSION 7.0.0
DESCRIPTION "SBUS encoder and decoder"
LANGUAGES C CXX
)
Expand Down
58 changes: 39 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
![Bolder Flight Systems Logo](img/logo-words_75.png)     ![Arduino Logo](img/arduino_logo_75.png)

# Sbus
This library communicates with SBUS receivers and servos and is compatible with Arduino and CMake build systems.
This library communicates with SBUS receivers and servos and is compatible with Arduino ARM and CMake build systems.
* [License](LICENSE.md)
* [Changelog](CHANGELOG.md)
* [Contributing guide](CONTRIBUTING.md)

# Description
SBUS is a bus protocol for receivers to send commands to servos. Unlike PWM, SBUS uses a bus architecture where a single serial line can be connected with up to 16 servos with each receiving a unique command.
Expand All @@ -20,7 +21,7 @@ The SBUS protocol uses an inverted serial logic with a baud rate of 100000, 8 da
* Bit 3: failsafe activated (0x08)
* Byte[24]: SBUS footer

Note that lost frame is indicated when a frame is lost between the transmitter and receiver. Failsafe activation typically requires that many frames are lost in a row and indicates that the receiver has moved into failsafe mode. Packets are sent approximately every 10 ms or 20 ms.
Note that lost frame is indicated when a frame is lost between the transmitter and receiver. Failsafe activation typically requires that many frames are lost in a row and indicates that the receiver has moved into failsafe mode. Packets are sent approximately every 10 ms or 20 ms, depending on the system configuration.

**Note on CH17 and CH18:** Channel 17 and channel 18 are digital on/off channels. These are not universally available on all SBUS receivers and servos.

Expand Down Expand Up @@ -50,6 +51,8 @@ Simply clone or download and extract the zipped library into your Arduino/librar
#include "sbus.h"
```

An example is located in *examples/arduino/sbus_example/sbus_example.ino*. This library is tested with Teensy 3.x, 4.x, and LC devices and should work with other ARM devices. It is **not** expected to work with AVR due to the use of std::array.

## CMake
CMake is used to build this library, which is exported as a library target called *sbus*. The header is added as:

Expand Down Expand Up @@ -84,7 +87,7 @@ This class is used for receiving SBUS data from an SBUS capable receiver.
**SbusRx(HardwareSerial *bus)** Creates an SbusRx object. A pointer to the Serial object corresponding to the serial port used is passed. The RX pin of the serial port will receive SBUS packets.

```C++
SbusRx sbus(&Serial1);
bfs::SbusRx sbus(&Serial1);
```
**void Begin()** Initializes SBUS communication.
Expand All @@ -105,17 +108,10 @@ if (sbus.Read()) {

**static constexpr int8_t NUM_CH()** A constant defining the number of SBUS channels (i.e. 16), useful for defining arrays to read the data into.

**int8_t ch(int16_t * const data, const int8_t len)** Copys the array of received channel data given a pointer to a destination, *data*, and length of the destination array *len*. Returns the number of channels copied on success or -1 on failure. Note that the maximum number of channels is the smaller of the *len* or *NUM_CH* (i.e. 16).
**std::array<int16_t, NUM_SBUS_CH_> ch()** Returns an array of received channel data.

```C++
int16_t rx_ch[bfs::SbusRx::NUM_CH];
sbus.ch(rx_ch, bfs::SbusRx::NUM_CH);
```

**int16_t ch(const int8_t idx)** Returns received channel data given the channel index.

```C++
int16_t ch3_data = sbus.ch(3);
std::array<int16_t, bfs::SbusRx::NUM_CH()> rx_ch = sbus.ch();
```

**bool ch17()** Returns the value of channel 17.
Expand Down Expand Up @@ -148,7 +144,7 @@ This class is used for transmitting SBUS data to SBUS capable servos.
**SbusTx(HardwareSerial &ast;bus)** Creates an SbusTx object. A pointer to the Serial object corresponding to the serial port used is passed. The TX pin of the serial port will transmit SBUS packets.

```C++
SbusTx sbus(&Serial1);
bfs::SbusTx sbus(&Serial1);
```
**void Begin()** Initializes SBUS communication.
Expand Down Expand Up @@ -191,16 +187,40 @@ sbus.lost_frame(true);
sbus.failsafe(true);
```

**bool ch(const int8_t idx, const int16_t val)** Sets the channel data to be transmitted, given a channel index and corresponding value. Returns true on success and false on failure.
**void ch(const std::array<int16_t, NUM_SBUS_CH_> &cmd)** Sets the channel data to be transmitted given an array of SBUS commands.

```C++
/* Set channel 3 to a value of 1200 */
sbus.ch(3, 1200);
/* Set SBUS commands */
std::array<int16_t, bfs::SbusTx::NUM_CH()> cmd;
sbus.ch(cmd);
```

**bool ch17()** Returns the CH17 data to be transmitted.

```C++
bool ch17 = sbus.ch17();
```

**bool ch18()** Returns the CH18 data to be transmitted.

```C++
bool ch18 = sbus.ch18();
```

**bool lost_frame()** Returns the lost frame flag to be transmitted.

```C++
bool lost_frame = sbus.lost_frame();
```

**bool failsafe()** Returns the failsafe flag to be transmitted.

```C++
bool failsafe = sbus.failsafe();
```

**int8_t ch(int16_t const * const data, const int8_t len)** Sets the channel data to be transmitted given a pointer to an array of commands, *data*, and the array length, *len*. Returns the number of channels copied on success or -1 on failure. Note that the maximum number of channels is the smaller of the *len* or *NUM_CH* (i.e. 16).
**std::array<int16_t, NUM_SBUS_CH_> ch()** Returns the channel data to be transmitted.

```C++
int16_t cmd[bfs::SbusTx::NUM_CH()];
sbus.ch(cmd, bfs::SbusTx::NUM_CH());
std::array<int16_t, bfs::SbusRx::NUM_CH()> rx_ch = sbus.ch();
```
7 changes: 4 additions & 3 deletions examples/arduino/sbus_example/sbus_example.ino
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ bfs::SbusRx sbus_rx(&Serial1);
/* SbusTx object on Serial1 */
bfs::SbusTx sbus_tx(&Serial1);
/* Array for storing SBUS data */
int16_t sbus_data[bfs::SbusRx::NUM_CH()];
std::array<int16_t, bfs::SbusRx::NUM_CH()> sbus_data;

void setup() {
/* Serial to display the received data */
Expand All @@ -53,9 +53,10 @@ void setup() {

void loop() {
if (sbus_rx.Read()) {
/* Grab the received data */
sbus_data = sbus_rx.ch();
/* Display the received data */
for (int8_t i = 0; i < bfs::SbusRx::NUM_CH(); i++) {
sbus_data[i] = sbus_rx.ch(i);
Serial.print(sbus_data[i]);
Serial.print("\t");
}
Expand All @@ -64,7 +65,7 @@ void loop() {
Serial.print("\t");
Serial.println(sbus_rx.failsafe());
/* Set the SBUS TX data to the received data */
sbus_tx.ch(sbus_data, bfs::SbusRx::NUM_CH());
sbus_tx.ch(sbus_data);
/* Write the data to the servos */
sbus_tx.Write();
}
Expand Down
7 changes: 4 additions & 3 deletions examples/cmake/sbus_example.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ bfs::SbusRx sbus_rx(&Serial1);
/* SBUS object, writing SBUS */
bfs::SbusTx sbus_tx(&Serial1);
/* Array for storing SBUS data */
int16_t sbus_data[bfs::SbusRx::NUM_CH()];
std::array<int16_t, bfs::SbusRx::NUM_CH()> sbus_data;

int main() {
/* Serial to display data */
Expand All @@ -41,9 +41,10 @@ int main() {
sbus_tx.Begin();
while (1) {
if (sbus_rx.Read()) {
/* Grab the received data */
sbus_data = sbus_rx.ch();
/* Display the received data */
for (int8_t i = 0; i < bfs::SbusRx::NUM_CH(); i++) {
sbus_data[i] = sbus_rx.ch(i);
Serial.print(sbus_data[i]);
Serial.print("\t");
}
Expand All @@ -52,7 +53,7 @@ int main() {
Serial.print("\t");
Serial.println(sbus_rx.failsafe());
/* Set the SBUS TX data to the received data */
sbus_tx.ch(sbus_data, bfs::SbusRx::NUM_CH());
sbus_tx.ch(sbus_data);
/* Write the data to the servos */
sbus_tx.Write();
}
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=Bolder Flight Systems SBUS
version=6.0.3
version=7.0.0
author=Brian Taylor <[email protected]>
maintainer=Brian Taylor <[email protected]>
sentence=Library for communicating with SBUS receivers and servos.
Expand Down
34 changes: 4 additions & 30 deletions src/sbus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@
#if defined(ARDUINO)
#include <Arduino.h>
#else
#include <algorithm>
#include "core/core.h"
#endif
#include <cstddef>
#include <cstdint>
#include <cmath>
#include <array>

namespace bfs {

Expand Down Expand Up @@ -107,20 +110,6 @@ bool SbusRx::Read() {
}
return new_data_;
}
int8_t SbusRx::ch(int16_t * const data, const int8_t len) {
if (!data) {return -1;}
#if defined(ARDUINO)
int8_t cpy_len = min(NUM_SBUS_CH_, len);
#else
int8_t cpy_len = std::min(NUM_SBUS_CH_, len);
#endif
memcpy(data, ch_, cpy_len * sizeof(int16_t));
return cpy_len;
}
int16_t SbusRx::ch(const int8_t idx) {
if ((idx < 0) || (idx >= NUM_SBUS_CH_)) {return -1;}
return ch_[idx];
}
bool SbusRx::Parse() {
/* Parse messages */
while (uart_->available()) {
Expand Down Expand Up @@ -242,20 +231,5 @@ void SbusTx::Write() {
uart_->write(buf_, sizeof(buf_));
#endif
}
bool SbusTx::ch(const int8_t idx, const int16_t val) {
if ((idx < 0) || (idx >= NUM_SBUS_CH_)) {return false;}
ch_[idx] = val;
return true;
}
int8_t SbusTx::ch(int16_t const * const data, const int8_t len) {
if (!data) {return -1;}
#if defined(ARDUINO)
int8_t cpy_len = min(NUM_SBUS_CH_, len);
#else
int8_t cpy_len = std::min(NUM_SBUS_CH_, len);
#endif
memcpy(ch_, data, cpy_len * sizeof(int16_t));
return cpy_len;
}

} // namespace bfs
20 changes: 13 additions & 7 deletions src/sbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,12 @@
#if defined(ARDUINO)
#include <Arduino.h>
#else
#include <algorithm>
#include "core/core.h"
#endif
#include <cstddef>
#include <cstdint>
#include <cmath>
#include <array>

namespace bfs {

Expand Down Expand Up @@ -59,7 +62,7 @@ class SbusRx {
uint8_t buf_[BUF_LEN_];
/* Data */
bool new_data_;
int16_t ch_[NUM_SBUS_CH_];
std::array<int16_t, NUM_SBUS_CH_> ch_;
bool failsafe_ = false, lost_frame_ = false, ch17_ = false, ch18_ = false;
bool Parse();

Expand All @@ -72,8 +75,7 @@ class SbusRx {
#endif
bool Read();
static constexpr int8_t NUM_CH() {return NUM_SBUS_CH_;}
int8_t ch(int16_t * const data, const int8_t len);
int16_t ch(const int8_t idx);
inline std::array<int16_t, NUM_SBUS_CH_> ch() const {return ch_;}
inline bool failsafe() const {return failsafe_;}
inline bool lost_frame() const {return lost_frame_;}
inline bool ch17() const {return ch17_;}
Expand All @@ -98,7 +100,7 @@ class SbusTx {
static constexpr uint8_t FAILSAFE_MASK_ = 0x08;
/* Data */
uint8_t buf_[BUF_LEN_];
int16_t ch_[NUM_SBUS_CH_];
std::array<int16_t, NUM_SBUS_CH_> ch_;
bool failsafe_ = false, lost_frame_ = false, ch17_ = false, ch18_ = false;

public:
Expand All @@ -114,8 +116,12 @@ class SbusTx {
inline void lost_frame(const bool val) {lost_frame_ = val;}
inline void ch17(const bool val) {ch17_ = val;}
inline void ch18(const bool val) {ch18_ = val;}
bool ch(const int8_t idx, const int16_t val);
int8_t ch(int16_t const * const data, const int8_t len);
inline void ch(const std::array<int16_t, NUM_SBUS_CH_> &cmd) {ch_ = cmd;}
inline std::array<int16_t, NUM_SBUS_CH_> ch() const {return ch_;}
inline bool failsafe() const {return failsafe_;}
inline bool lost_frame() const {return lost_frame_;}
inline bool ch17() const {return ch17_;}
inline bool ch18() const {return ch18_;}
};

} // namespace bfs
Expand Down

0 comments on commit ddd6984

Please sign in to comment.