SBUS Driver in Simple System Manager
This page is all about the configuration of SBUS driver and how to use it in the Simple System Manager.
IOC. Config
Key Parameter Setting
DMA Setting
Enable both rx and tx DMA line
Set the Mode to be “Circular“
Enable the NVIC uart global interrupt
Examplation
The uart used here is USART2, but it can be any uart connectivity as long as the code stays coherent with itself.
One uart is configured such that the rx is used for the receiver and tx is used for the sender. Both receiver and sender sharing the same uart wouldn’t cause any collision.
The driver also allows the user to use separate uarts for the receiver and sender. It just needs an appropriate reason to use two uarts.
Struct
SBus
struct SBus{
uint16_t ch[SBUS_INPUT_CHANNELS]; //value from 192 - 1792, can be littel off
bool lost_frame;
bool failsafe;
bool ch17, ch18;
bool new_data;
};
The SBus struct contains the data for 16 different RC channels with other flags. This is a representation of the unprocessed sbus data
RCControl
//the background work that allows a variable name refer to the same memory to an array element
template<uint8_t Index, class T>
struct ControlRef
{
operator T&() // allows: double d = object.Member;
{
return ((T*)(this))[Index];
}
T &operator=(T const &rhs) // allows: object.member = 1.0;
{
T &me = ((T*)(this))[Index];
me = rhs;
return me;
}
T* operator&() // allows: double *p = &object.Member;
{
return &((T*)(this))[Index];
}
bool operator<(T const &rhs) // allows: if(object.Member < 1.0)
{
return ((T*)(this))[Index] < rhs;
}
};
/* a struct for control signal channel mapping and attribute values*/
/* for now, the value range is 0 to 100 float*/
struct RCControl{
union{
float ControlSignals[16];
ControlRef<0, float> roll;
ControlRef<1, float> pitch;
ControlRef<2, float> throttle;
ControlRef<3, float> yaw;
ControlRef<4, float> arm;
ControlRef<5, float> vtx;
ControlRef<6, float> led;
ControlRef<7, float> mode;
ControlRef<8, float> nonconfigch9;
ControlRef<9, float> nonconfigch10;
ControlRef<10, float> nonconfigch11;
ControlRef<11, float> nonconfigch12;
ControlRef<12, float> nonconfigch13;
ControlRef<13, float> nonconfigch14;
ControlRef<14, float> nonconfigch15;
ControlRef<15, float> nonconfigch16;
};
float &operator[] (int i) { return ControlSignals[i]; }
/* initial values*/
RCControl()
{
ControlSignals[0] = 50.0f;
ControlSignals[1] = 50.0f;
ControlSignals[2] = 0.0f;
ControlSignals[3] = 50.0f;
ControlSignals[4] = 0.0f;
ControlSignals[5] = 0.0f;
ControlSignals[6] = 0.0f;
ControlSignals[7] = 0.0f;
ControlSignals[8] = 0.0f;
ControlSignals[9] = 0.0f;
ControlSignals[10] = 0.0f;
ControlSignals[11] = 0.0f;
ControlSignals[12] = 0.0f;
ControlSignals[13] = 0.0f;
ControlSignals[14] = 0.0f;
ControlSignals[15] = 0.0f;
}
};
This struct represents the RC Controller in percentage after mapping the value. I used some code from the internet so essentially what this long code does is that both the array index and a specific name point to the same address of the value. I hope by using this structure, it can be easier for the people who develop the software to use each of the parameters while being able to manipulate them as an array.
Methods
SBUS_Receiver
class SBUSReceiver{
public:
/*
serve for singleton structure application
the code doesn't allow the class to make copy of its instance
*/
SBUSReceiver (const SBUSReceiver*) = delete;
SBUSReceiver &operator= (const SBUSReceiver&) = delete;
static SBUSReceiver* getInstance(UART_HandleTypeDef* uart);
/*
get the sbus data
@return SBus struct
*/
SBus GetSBUS();
/*
get the RCControl data that is parsed from sbus
more readable data that varies from 0 to 100
@return RCControl struct
*/
RCControl GetRCControl();
void parse();
/*
public variable
*/
uint8_t raw_sbus_[SBUS_FRAME_SIZE];
private:
/*
object constructor
@param uart instance ie. &huart1
*/
SBUSReceiver(UART_HandleTypeDef* uart);
// member variables
static SBUSReceiver* singleton_;
UART_HandleTypeDef* uart_;
SBus received_sbus_;
RCControl received_rccontrol_;
//private functions
void read();
void cast_rccontrol();
float sbus_to_rccontrol(uint16_t channel_value);
};