Teensy 3.2 SBUS

Status
Not open for further replies.

Garug

Well-known member
I have been using Teensy 3. for sending SBUS and it has worked fine with 8E1 inverted 100000 baud, though the specification says 8E2.

However now I have found HW that does not accept the 8E1, and have not found any way sending 8E2.

So thinking, I could but the data to be send, 25 bytes with end bits etc, to an array of bits and send that bit by bit waiting 10 us in between every bit, but that would take 6 ms, 50 times per second, so not good.

Is there some bit banging library that would accept the array of bits and send them on the background without loading the processor too much?

Kind of like RAW serial out, a serial port that does not add any start/stop bits or parity, just sends the RAW binary data with given rate.

So I would provide an array of 300 bits to be send with rate 10 us between the bits, a new array would be provided 50 times per second. It would be good that it would notify when the array has been sent.

Best actually would be if this could be done by relatively simple register manipulation, not needing to use any huge libraries.

Just asking if someone has done something like this and willing to share or any good pointers where to start looking how to do this.
 
Last edited:
UART serial is by definition self-clocking (the A in UART). Hence, start and stop bits are needed. The UARTs always support the 8E1 you reference, though not often. By 8E1 I assume you mean 8 data bits and a 9th bit as parity. That's in most all UARTs to support protocols like ISO7816. Rarely used in hobby stuff so it may not be in the library call but can be done by adding that, or doing I/O directly to the UART's configuration registers. I use ISO7816 9 bit (1 is parity) on a project for ISO7816 (not on Teensy).

USARTs are on most ARMs, and can do synchronous protocols such as ye ole X.25 and HDLC. These use a separate clock signal.
Using USARTs with separate clocking needs a well defined frame synch method, as the above-named and other synchronous protocols do.

Blasting out a bit stream without a preamble and so on won't work for the receiving end.

The SPI and I2C ports are for such things. Frame sync is within those protocols.
 
My idea is to generate the complete bit steam, including start/stop bits parity etc. It is 25 bytes each with additional bits 12 bits. so should be 300 bits. Just would need a way to send that bitsteam each bit 10 us separated.
 
Are you doing this only because you haven't been able to use 9 bit mode (8 data, 1 parity)?

The hard part of what you propose to do is the receiving end. Is that end under your control?
 
https://www.pjrc.com/teensy/K20P64M72SF1RM.pdf

47.3.3 UART Control Register 1 (UART_C1)

PE
Parity Enable
Enables the parity function. When parity is enabled, parity function inserts a parity bit in the bit position
immediately preceding the stop bit. This field must be set when C7816[ISO_7816E] is set/enabled.
0 Parity function disabled.
1 Parity function enabled.
0
PT
Parity Type
Determines whether the UART generates and checks for even parity or odd parity. With even parity, an
even number of 1s clears the parity bit and an odd number of 1s sets the parity bit. With odd parity, an odd
number of 1s clears the parity bit and an even number of 1s sets the parity bit. This field must be cleared
when C7816[ISO_7816E] is set/enabled.
0 Even parity.
1 Odd parity.

don't know if it is settable on a "official" way, but perhaps it can be done with some simple edits to serial1.c

edit: oops, sorry, you're looking for E2.. hm... perhaps it is somewhere, too..
 
Last edited:
The S-BUS protocol

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)

[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

The problem is I have not found any way to set Teensy 3.2 serial to One Byte = 1 startbit + 8 databit + 1 paritybit + 2 stopbit (8E2) Some systems work with 8E1 Inverted that Teensy 3.2 supports, but not all.

So I could generate the above 300 bits (with start/stop/parity bits for each byte) to a array, if there would be a way to send that bit array accurately timed without loading the processor more than HW serial does.

I was thinking if there would be a way to send bits, not bytes, or a way to configure Teensy 3.2 HW serial so that it does not add any stop/start/parity bits (but still would need to use the other 2 serial ports normally) maybe using SPI (but I need normal SPI too)

I really love Teensy 3.2 but this is a big problem, I hope that there is other solution than using different processor.

Here is the Teensy supported https://www.pjrc.com/teensy/td_uart.html, I use currently SERIAL_8E1_RXINV_TXINV, but it does not work with all SBUS devices. (receiving data seems to be ok, but not sending)

I have tried adding 10 us delay after each byte (to simulate the additional stop byte), but that did not help. I guess it is send via a FIFO buffer, so the 10 us delay is just delaying providing the data to the buffer... Now thinking, I am sending 20 ms intervals, the protocol says 14 or 7 ms. must test that.
 
Last edited:
SBUS protocol... unfamiliar to me.

Does SBUS allow 8 bit bytes rather than two 8 bit bytes per 11 bit datum?

With a UART, you cannot create a frame (long byte) with a start bit, 11 data bits, and a parity bit. You're talking to an SBUS device which, from your description, has 11 bits of data for each channel and one cannot split that up into one 8 bit byte followed by another 8 bit byte with just 3 data bits used.

Stop byte / endbyte is an SBUS thing.

So you can build data in byte arrays in memory, but UARTS and USARTs won't create the serial stream needed for SBUS compliance, as I read this.
Nor SPI or I2C.
Seems you'd need an SBUS interface device, or spend a lot of time trying to use a simple external shift register and software to generate the compliant formats. Bit-banging a GPIO bit (at 100Kbps) is doable but the systick and other interrupts will occasionally disrupt the timing.
 
SBUS is just serial data send as 1 startbit + 8 databit + 1 paritybit + 2 stopbit (8E2), baudrate = 100'000 bit/s 25 bytes (it is inverted levels). the SBUS data wrapping is build inside those bytes (8 databit) and not important for this discussion, it is just the payload send as normal 8E2_INV serial data.

so it is 12 bits per byte and 25 bytes, repeated every 14 ms or a correctly formatted 300 bit array send every 14 ms.

Looking for solution to send serial 8E2 100'000 bit/s (inverted levels) or to send 300 bit array bits separated 10 us, no bits added, just sending the bit array as it is.
 
I have sent and received sBus packets with an Atmega 2560 on a few projects by initializing the UART with 'Serial.begin(100000, SERIAL_8E2);' and connecting to the device via a hex inverting Schmitt trigger. I have read sBus using the Teensy with 'Serial.begin(100000, SERIAL_8E1_RXINV);' no external inverter required.

I would like to think you could configure Teensy's UART to do exactly what you need. 47.3.3 from the technical reference manual at https://cache.freescale.com/files/32bit/doc/ref_manual/K20P64M72SF1RM.pdf would be a good place to start.
 
2 stop bits only matters for transmitting. The 2nd stop bit prevents the next byte from transmitting as soon.

For reception, 8E1 and 8E2 are the same. The receiver ignores everything after the last data bit.
 
Yes, for receiving 8E1 is working, for some devices 8E1 is working also on sending, but not all. Is there any way to set the Teensy 3.2 to send 8E2? On the above linked 47.3.3 I do not directly find 2 stop bits but maybe using 9E1 and setting LSB to stop bit? I would need to have only one post configured to 8E2 (rather inverted so that a separate inverter does not need to be used), the other Serial outs should work normally.
 
Last edited:
2 stop bits only matters for transmitting. The 2nd stop bit prevents the next byte from transmitting as soon.

For reception, 8E1 and 8E2 are the same. The receiver ignores everything after the last data bit.
In some use cases, using 2 stop bits allows more time for the receiving end to process data. But really, a proper protocol for flow control is the right answer.
 
Hi all, i'm new to this forum,

i need to read SBUS (from FrSky X8R receiver) and write it down as output, having possibility to change values etc with teensy
Can anyone post some code to do that?

thanks!
 
Hi Garug

have a look at this thread.

https://forum.pjrc.com/threads/23956-Teensy-3-UART-settings

I did not like the delay method because it used to much processor time. Instead I tried a solution with an IntervalTimer. Works
so far fine with a FrSky servo and an Futaba servo.

In the ino you find at the end of the thread the delay method and the delay method are implemented for comparison. Both work on my T3.2.

regards andi
 
Status
Not open for further replies.
Back
Top