Help integrating SBUS library for teensy?

Status
Not open for further replies.

Geekness

Well-known member
I have found this SBUS library, and was wondering if its possible to use with a teensy 3.2?
I want to use pots/switches to generate the signal, similar to how the PPM library works.

If it is possible, is there any example code I could see?
 
I'm biased, but I would recommend my company's library:
https://forum.pjrc.com/threads/36106-SBUS-Library

It works with all Teensy 3.x and LC devices. There are functions to parse SBUS packets from receivers or, in your case, write SBUS packets to servos. You would just need to define how your switches and pots map to the 16 channels. Please let me know if you have any questions, encounter any issues, or see a need for additional functionality.

Brian
 
Thanks brtaylor. I will make some effort to integrate it into my project.
I have a teensy 3.2 with a number of pots and switches connected to the analog pins. I will be using these to set the sbus channel values.
The generated sbus signal will be connected to a DTFUHF transmitter (ground station) and sent to my aircraft receiver.

I was using the ppm library, but have recently felt like changing it up to a serial protocol.

Does it matter which pins I use for my pots or switches, or the the sbus output?
 
Thanks brtaylor. I will make some effort to integrate it into my project.
I have a teensy 3.2 with a number of pots and switches connected to the analog pins. I will be using these to set the sbus channel values.
The generated sbus signal will be connected to a DTFUHF transmitter (ground station) and sent to my aircraft receiver.

I was using the ppm library, but have recently felt like changing it up to a serial protocol.

Does it matter which pins I use for my pots or switches, or the the sbus output?

The only requirement I can think of is that SBUS output needs to be on one of the Teensy hardware serial ports.
 
@brtaylor,

as im a total noob at coding, are you able to explain what I need to change from my PPM code to output SBUS instead?
This SBUS is a little incomplete as you'll see, but im hoping I can use this to start my SBUS code.

Code:
#include <PulsePosition.h>

PulsePositionOutput myOut(RISING);
int CH01 = 0; //Roll
int CH02 = 0; //Pitch
int CH03 = 0; //Throttle
int CH04 = 0; //Yaw
int CH05 = 0; //Mode Selector
int CH06 = 0; //Usage configurable in Mission Planner
int CH07 = 0; //OSD Selector
int CH08 = 0; //Usage configurable in Mission Planner
int CH09 = 0; //Camera Selector
int CH10 = 0; //Camera Shutter
int CH11 = 0; //Gimbal Pitch
int CH12 = 0; //Not used

void setup() {
  myOut.begin(0);
  Serial.begin(38400);
  
  }

void loop() {
  CH01 = analogRead(1);
  myOut.write(1, CH01);
  Serial.print("Roll: ");
  Serial.println(CH01);
  
  CH02 = analogRead(2);
  myOut.write(2, CH02);
  Serial.print("Pitch: ");
  Serial.println(CH02);
   
  CH03 = analogRead(3);
  myOut.write(3, CH03);
  Serial.print("Throttle: ");
  Serial.println(CH03);
  
  CH04 = analogRead(4);
  myOut.write(4, CH04);
  Serial.print("Yaw: ");
  Serial.println(CH04);

  CH05 = 

  CH06 = analogRead(6);
  myOut.write(6, CH06);
  Serial.print("CH6: ");
  Serial.println(CH06);

  CH07 = analogRead(7);
  myOut.write(7, CH07);
  Serial.print("CH07: ");
  Serial.println(CH07);

  CH08 = analogRead(8);
  myOut.write(8, CH08);
  Serial.print("CH08: ");
  Serial.println(CH08);

  CH09 = analogRead(9);
  myOut.write(9, CH09);
  Serial.print("CH09: ");
  Serial.println(CH09);
  
  CH10 = analogRead(10);
  myOut.write(10, CH10);
  Serial.print("CH10: ");
  Serial.println(CH10);
  
  CH11 = analogRead(11);
  myOut.write(11, CH11);
  Serial.print("CH11: ");
  Serial.println(CH11);
  
  CH12 = analogRead(12);
  myOut.write(12, CH12);
  Serial.print("CH12: ");
  Serial.println(CH12);
}
 
@brtaylor

I have a few questions:

  1. In the example you gave on github where you have:
    Code:
    // read the analog inputs
      	for(uint8_t i = 14; i < 24; i++) {
      		ain[i-14] = analogRead(i);
    If I want to have 15 inputs, how do I write this part of the code to include the specific inputs?
  2. Is there a way for a single input to be wired to 6 different momentary switches (all outputting a different voltage), to be used for a single SBUS channel?
    These 6 switches will be for selecting my different flight modes.
    I can workout the hardware side with resistors and such (I'll probably use a variable resistor to get the correct voltage), but need help with code.
    The hard part for me here is that they will be momentary switches, and I need that channel to remain at the selected output level until another one of these switches is pressed.
    I need the channel to start at a given output (low, like 1050) when everything is powered up, then go up to a given value dependent on which switch is pressed/pulled
  3. How would I get 8x3mm LEDs to turn on dependent on position of 8 switches (3 channels)?
    2x on/on switches for 2 different channels (I can likely do this with hardware in series, but I'd like it to be done on code so I know what's being output)
    6x on/(on) switches mapped for a single channel (as mentioned above)
  4. Is there a way to map the different input pins to specific channels in the SBUS output signal? eg pin 17 to SBUS channel 1
    Or are the channels decided in order of pin number?
  5. My set up, if I can get all the above working, is 15 analog inputs (switches and pots), outputting a 15 channel SBUS stream and 8 LEDs. Does Teensy3.2 have enough pins to do this, or should I upgrade to Teensy3.6?
  6. What is the reason for sending packets every 9ms?
  7. Can I reverse the direction of an output channel? ie, if a pot is going counterclockwise, can I choose to reverse the output channel, depending on the use case?

I really appreciate any help you can provide. I'm terrible at code, and my hardware is 99% complete, so getting these last issues would make me so damn happy. Thanks.
 
Last edited:
@brtaylor

I have a few questions:

  1. In the example you gave on github where you have:
    Code:
    // read the analog inputs
      	for(uint8_t i = 14; i < 24; i++) {
      		ain[i-14] = analogRead(i);
    If I want to have 15 inputs, how do I write this part of the code to include the specific inputs?
  2. Is there a way for a single input to be wired to 6 different momentary switches (all outputting a different voltage), to be used for a single SBUS channel?
    These 6 switches will be for selecting my different flight modes.
    I can workout the hardware side with resistors and such (I'll probably use a variable resistor to get the correct voltage), but need help with code.
    The hard part for me here is that they will be momentary switches, and I need that channel to remain at the selected output level until another one of these switches is pressed.
    I need the channel to start at a given output (low, like 1050) when everything is powered up, then go up to a given value dependent on which switch is pressed/pulled
  3. How would I get 8x3mm LEDs to turn on dependent on position of 8 switches (3 channels)?
    2x on/on switches for 2 different channels (I can likely do this with hardware in series, but I'd like it to be done on code so I know what's being output)
    6x on/(on) switches mapped for a single channel (as mentioned above)
  4. Is there a way to map the different input pins to specific channels in the SBUS output signal? eg pin 17 to SBUS channel 1
    Or are the channels decided in order of pin number?
  5. My set up, if I can get all the above working, is 15 analog inputs (switches and pots), outputting a 15 channel SBUS stream and 8 LEDs. Does Teensy3.2 have enough pins to do this, or should I upgrade to Teensy3.6?
  6. What is the reason for sending packets every 9ms?
  7. Can I reverse the direction of an output channel? ie, if a pot is going counterclockwise, can I choose to reverse the output channel, depending on the use case?

I really appreciate any help you can provide. I'm terrible at code, and my hardware is 99% complete, so getting these last issues would make me so damn happy. Thanks.

Sorry, I don't have the time at the moment to go through and code all of that. But hopefully this will help:
1. I would create a vector of pin numbers like:
Code:
int pins[15] = {14,15,16,17,18,19,20,21,22,23,26,27,28,29,30};

Then the code to read the analog input would be:
Code:
// read the analog inputs
for(uint8_t i = 0; i < 15; i++) {
    ain[i] = analogRead(pins(i));
}

This also solves your question #4. By rearranging the pins array, you would be changing the mapping of analog input pin to SBUS channel.

2. Sure, do a series of 6 if else statements based on ranges of values for the analog input that your switches are hooked up to. Making them work with momentary switches is fun, might have to use a digital input connected in addition to the analog input pin. Then you could have the momentary switch press trigger the digital input and read the analog voltage value within the function attached to the digital input. Look at the arduino attachInterrupt function and probably trigger on a rising edge.
3. You would use 8 digital outputs and write high or low to them:
https://www.pjrc.com/teensy/td_digital.html
5. Not without accessing the surface mount pads on the back of Teensy. You can compare using this chart:
https://www.pjrc.com/teensy/pinout.html

Notice, you only have 10 pins of analog input on the Teensy 3.2 headers.
6. That's the timing that I've measured FrSky receivers sending packets to SBUS servos. There's some variation between FrSky receivers and Futaba receivers in terms of the timing, but that's a value I know the SBUS servos will work well with.
7. Yes, you can just change the POT wiring (switch the power and ground). Or in software, change the mapping between analog input to SBUS channel on line 73 of the example I posted:
https://github.com/bolderflight/SBUS/blob/master/examples/AIN_SBUS_example/AIN_SBUS_example.ino#L73

I would suggest trying to code something up and posting it here if you run into any issues, since it will give us something concrete to work with.

Brian
 
@brtaylor, thanks for the info.

I've been building my schematic and have changed my plan somewhat.
I will now have:
10 Analog inputs for pots/gimbals/3-way switches (A0-A9)
10 Digital inputs for 2-way switches (2,7,11,12,24,26,27,28,29,30)
8 digital PWM LED outputs (3,4,5,6,9,10,25,32)
1 serial output/input for debugging (0,1)
1 serial output for SBUS stream (8)
1 analog output for PPM stream (A14)

3 digital spares (13,31,33)
4 analog Spares (A10,A11,A12,A13)

I'll run 5V into the Teensy through Vin & AGND, then 3.3V to all the switches/pots from 3.3V & GND
This will greatly simplify my wiring/PCB and hopefully make the code a bit simpler and faster.

Will get some code written up and post it back here for review.
Would it be OK if you review my PCB schematic also?
 
Last edited:
@brtaylor,

How can I read a value from a specific channel output from the SBUS stream?
I want to do a number of if statements to say if channel x == Y then turn on the LED at pin Z
 
@brtaylor,

How can I read a value from a specific channel output from the SBUS stream?
I want to do a number of if statements to say if channel x == Y then turn on the LED at pin Z

I'm a little confused, I thought you were building an SBUS packet to send to servos? In that case, you are writing the SBUS packet based on the gimbals and POTS and you would know the channel value (i.e. channels[0] for writing to SBUS channel 0). In the example on line 73, I am setting all of the channel values:
https://github.com/bolderflight/SBUS/blob/master/examples/AIN_SBUS_example/AIN_SBUS_example.ino#L73

Then on line 80, when write is called, those values are bit packed and the appropriate header and footer bytes are added to make it an SBUS packet and the packet is sent over serial:
https://github.com/bolderflight/SBUS/blob/master/examples/AIN_SBUS_example/AIN_SBUS_example.ino#L80

If you had another device and wanted to read a channel in that packet, or if you had an SBUS receiver and you wanted to decode the SBUS packet the receiver is sending, then you would use the read function. An example of this is line 55 of my other example:
https://github.com/bolderflight/SBUS/blob/master/examples/SBUS_example/SBUS_example.ino#L55

Hope that helps!

Brian
 
I'm a little confused, I thought you were building an SBUS packet to send to servos?

I am kind of. Im going to input the SBUS stream to a RC transmitter to send the signal from ground to the aircraft.
I also want to light 8 LEDs dependent on the value of 3 channels of that SBUS stream I am generating.

These 3 channels are set by the position of 8 different 2-way switches, 6 of which are momentary.
Channel 5: 6 x on/(on) switches
Channel 7: 1 x on/on switch
Channel 8: 1 x on/on switch

Maybe im thinking about it the wrong way?

Here is my channel mapping for your info
//Channel Map
//CH1: Roll (pin 14 [A0])
//CH2: Pitch (pin 15 [A1])
//CH3: Throttle (pin 16 [A2])
//CH4: Yaw (pin 17 [A3])
//CH5: Mode selection switches momentary digital pins - 2 on Left Side, 4 on Right Side:
//pin 2 [RTL - Left Side]
//pin 7 [LAND - Left Side]
//pin 11 [STABILISED - Right Side]
//pin 12 [POSITION HOLD - Right Side]
//pin 24 [LOITER - Right Side]
//pin 26 [AUTO - Right Side]
//CH6: Camera pitch - Left Slider (pin 22 [A8])
//CH7: Arm [Motor Interlock] (pin 27)
//CH8: Brake (pin 28)
//CH9: Camera Shutter - Right 3-way Switch (pin 21 [A7])
//CH10: Left 2-way Switch (pin 29)
//CH11: Left 3-way Switch (pin 20 [A6])
//CH12: Right 2-way Switch (pin 30)
//CH13: Right Slider (pin 23 [A9])
//CH14: Left Twist (pin 18 [A4])
//CH15: Right Twist (pin 19 [A5])
//CH16:
 
I am kind of. Im going to input the SBUS stream to a RC transmitter to send the signal from ground to the aircraft.

Can you give some more detail, including the parts that you're planning on using for the RC transmitter and receiver? Also a wiring diagram, even a rough one, would be helpful.

The typical use case, that I'm aware of, for this library is below:
Screen Shot 2017-01-25 at 9.53.15 AM.png

In this case there is a standard RC transmitter (FrSky X9E) and receiver (FrSky X8R). The Teensy receives SBUS packets from the X8R. In my specific case, I'm using those SBUS packets for:
1. Switching between autonomous and manual flight modes based on the value of a channel
2. Adding stabilization to aircraft in addition to pilot commanding control surfaces
3. Changing mapping of pilot stick commands (i.e. instead of mapping to surface deflections, can map them to commanded aircraft pitch and roll angles)
4. Selecting, starting, and stopping experiments

I can then use the library to send SBUS commands to SBUS capable servos. This helps reduce wiring clutter by using a signal bus rather than needing to route each individual servo back to PWM outputs on Teensy.

I can think of ways that you could send SBUS packets from the ground to the aircraft without using standard RC transmitters and receivers, but specifics matter. Which is why it would be helpful to see your setup to make sure it will work.

I also want to light 8 LEDs dependent on the value of 3 channels of that SBUS stream I am generating.

These 3 channels are set by the position of 8 different 2-way switches, 6 of which are momentary.
Channel 5: 6 x on/(on) switches
Channel 7: 1 x on/on switch
Channel 8: 1 x on/on switch

In this case, you're setting the channel values with your switches so you know the value directly, no need to parse an SBUS packet for the LED's.

Hope that helps!
 
Here's a basic layout of my concept. The left antenna is for my RC, the other 2 are for Telemetry units (RFD900s)
Concept layout.jpg

The RC Module is a DTFUHF 1W 433MHz Receiver, used as a transmitter. There is firmware available for this already. I just need to plug in either a PPM or SBUS stream.
Im not limited to this module though, I think I could possibly use a HC-12 module if I want to use 2.4GHz

My flight controller is a pixhawk, which can take the SBUS transmission, but I can choose whatever I like with the DTFUHF equipment.
My hardware is about 95% built. My whole case is done, and gimbals/pots/switches are installed. Im just putting my 3rd revision schematic and PCB together now using EasyEDA.com

Here's a link to my Project

In this case, you're setting the channel values with your switches so you know the value directly, no need to parse an SBUS packet for the LED's.
The reason I prefer (and maybe im wrong) to set the LEDs based on the actual SBUS channel value is that the LEDs will tell me what the actual value is that's being sent, not just what I want it to be.
 
Last edited:
Here's a basic layout of my concept. The left antenna is for my RC, the other 2 are for Telemetry units (RFD900s)
View attachment 9500

The RC Module is a DTFUHF 1W 433MHz Receiver, used as a transmitter. There is firmware available for this already. I just need to plug in either a PPM or SBUS stream.
Im not limited to this module though, I think I could possibly use a HC-12 module if I want to use 2.4GHz

My flight controller is a pixhawk, which can take the SBUS transmission, but I can choose whatever I like with the DTFUHF equipment.
My hardware is about 95% built. My whole case is done, and gimbals/pots/switches are installed. Im just putting my 3rd revision schematic and PCB together now using EasyEDA.com

Here's a link to my Project


The reason I prefer (and maybe im wrong) to set the LEDs based on the actual SBUS channel value is that the LEDs will tell me what the actual value is that's being sent, not just what I want it to be.

That's very cool! Thanks so much for including and it helps me understand a lot. Should work well. Please let me know how everything ends up, it's very interesting.

The reason I prefer (and maybe im wrong) to set the LEDs based on the actual SBUS channel value is that the LEDs will tell me what the actual value is that's being sent, not just what I want it to be.

You can loop back the serial. In other words, if you declare the following to put SBUS on UART 1:
Code:
SBUS x8r(1);

"Y" a wire from TX, pin 1, and bring one end of that wire to your RC Module and the other end to RX, pin 0. Then you can use the following to parse the packet that you sent:
Code:
if(x8r.read(&channelsRX[0], &failSafe, &lostFrames)){
    // do stuff based on the value of channelsRX
}

The "if" statement would sit in your loop function. It only goes true on a good SBUS packet.
 
That's very cool! Thanks so much for including and it helps me understand a lot. Should work well. Please let me know how everything ends up, it's very interesting.
Thanks, One of the reasons im using the DTFUHF module is that it has a great chrome app for configuration.

"Y" a wire from TX, pin 1, and bring one end of that wire to your RC Module and the other end to RX, pin 0. Then you can use the following to parse the packet that you sent:
Awesome, I've changed my schematic now to suit. Im wiring from Tx3 (pin 8) into the "Y" then to the Rx3 (pin 7) and the SBUS out pin.
My code should be like this then?
Code:
SBUS x8r(3);
 //3 because the SBUS stream is being input onto Rx3 (pin 7)

Code:
if(x8r.read(&channelsRX[5], &failSafe, &lostFrames)){
    // do stuff based on the value of channel 5 of the SBUS stream.
}

Here's a photo of my prototype roughly put together. There's a few extra holes from upgrading certain parts from the original concept model, but the next prototype should look a lot better.
That's an 8" Windows tablet in there, so this thing is quite big, roughly 450mm wide from memory.
The gimbal sticks are the quanum gimbal upgrades for the Turnigy 9XR. They have hall sensors instead of pots, and are super smooth.
Prototype.jpg
 
Your code is close, you need to provide the starting index for the functions, so:

Code:
if(x8r.read(&channelsRX[0], &failSafe, &lostFrames)){
    // do stuff based on the value of channel 5 of the SBUS stream.
}

That if statement evaluates to true on receiving a good packet. You would then check the value of channelsRX[5] and do stuff based on that value within the if statement.
 
Status
Not open for further replies.
Back
Top