Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 23 of 23

Thread: Teensy 3 UART settings

  1. #1
    Junior Member daniel-arg's Avatar
    Join Date
    Jul 2013
    Location
    Paris
    Posts
    8

    Teensy 3 UART settings

    Hello!

    I'm working on a project where I need to set the serial data format to 100000 Bauds, 8 bits, Even Parity, 2 stop bits, and the signal is inverted.

    I found the way to set all the parameters but the number of stop bits.

    I read many times the K20 Reference Manual and I can't find anything to set 2 stop bits.

    May someone help me?

    Thank you very much in advance!

  2. #2
    Junior Member
    Join Date
    May 2014
    Posts
    3
    Hi!

    I have a similar problem...

    Did you succeed in reading out a protocol with 2 stop bits?

  3. #3
    Junior Member daniel-arg's Avatar
    Join Date
    Jul 2013
    Location
    Paris
    Posts
    8
    Quote Originally Posted by powermik View Post
    Hi!

    I have a similar problem...

    Did you succeed in reading out a protocol with 2 stop bits?
    Quote Originally Posted by powermik View Post
    Hi!

    I have a similar problem...

    Did you succeed in reading out a protocol with 2 stop bits?
    Yes, I did.
    But I had to modify the standard Hardwareserial/Serial source files on Arduino.
    I think the best is to make a copy of those libraries and make a new one, otherwise, my modifications are overwritten each time a new version of teensy is released.

    My need was to have a 8E2 protocol (12 bits if you consider the start bit).
    what I did is to use 9 bits protocol (actually, 8 bits+address mark bit+parity+1 stop: 12 bits), and change address mark bit in order to match a 8E2 protocol.
    See page 1125, section 45.4.5.2 of the cpu reference manual (https://www.pjrc.com/teensy/K20P64M50SF0RM.pdf)

    I'm not sure it is clear, maybe 1 or 2 examples can help:

    Example1:
    In 8 bits, if the data to send is 0xA3 (b10100011), the data frame is
    1 10100011 1 11
    I do the calculations to send it in 8E1 format with address mark set.
    1 10100011 1 1 1

    Example2:
    In 8 bits, if the data to send is 0xA2 (b10100010), the data frame is
    1 10100010 0 11
    I do the calculations to send it in 8E1 format with address mark clear.
    1 10100010 0 1 1

    The idea is to set or clear the address mark bit, in order to make the parity bit be always 1, and thus it is interpreted as a stop bit by the receiver

    Cheers, Daniel

  4. #4
    Junior Member
    Join Date
    May 2014
    Posts
    3
    Sounds like you only need to send data - i need to receive them

    Greetings, Michael

  5. #5
    Junior Member daniel-arg's Avatar
    Join Date
    Jul 2013
    Location
    Paris
    Posts
    8
    It works both ways...
    You just have to ignore the address mark bit

  6. #6
    Junior Member
    Join Date
    May 2014
    Posts
    3
    just tried and it works thx 4 the hint.

    just noticed that you probably wanted to receive/send sbus - what have you built?

    i would like to build a light/sound controller for some of my r/c cars

    Michael

  7. #7
    Junior Member daniel-arg's Avatar
    Join Date
    Jul 2013
    Location
    Paris
    Posts
    8
    I made a SBUS2 device
    Look here:
    https://sites.google.com/site/wbtelemetry/

    Happy to hear It worked for you.

    Cheers, Daniel

  8. #8
    Hey Daniel

    Do you talk about the S-BUS to control servos sent by a Receiver? I use a X8R Receiver from FrSky and this one can send the Servo-Information with S-BUS protocol. I want do handle it in a teensy...

  9. #9
    Junior Member
    Join Date
    Sep 2014
    Posts
    1
    Hi Daniel,
    could you please provide some source code for your modifications?
    Thanks, Tobias
    Last edited by tosi84; 09-04-2014 at 10:17 AM.

  10. #10
    Junior Member
    Join Date
    Jan 2015
    Posts
    5
    Hi All,

    I seem to have the same problem. I want to make the teensy talk to sBus servos. So i need some sort of implementation of 8E2 serial communication. Is there an elegant way to achieve this? I followed to way of Daniel above and i understand how this makes it possible to get the 2 stopbits (or at least make the receiver think that) but isn't the parity bit always set the opposite this way? Because the receiver expects for 0xA2 (for instance to use the same example):

    start data parity stop stop
    1 10100010 1 1 1

    So issn't the receiver checking the parity??? Did someone try this with "standard" sbus devices?
    I didn't check it myself so far because to be honest i was a tiny bit lost when i looked at the source files for the teensy serial.
    If someone could point me to an as explicit as possible solution i would be incredible thankful for it :-)

    @Daniel or powermik: Where did you insert your changes? Directly in the serial*.c i guess? Would you be so kind to share your modifications?

    Thanx a lot. Any help is much appreciated.

  11. #11
    Junior Member
    Join Date
    Jan 2015
    Posts
    5
    Hi tosi84,

    did you get this working by now? What did you do???

    Thanx a lot. Any help is much appreciated.

  12. #12
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,599
    Quote Originally Posted by alx View Post
    So i need some sort of implementation of 8E2 serial communication.
    The closest Teensy 3.1 supports is 8E1.

    For receiving data that's sent by another device in 8E2 format, you can simply use 8E1.

    Really, this will work fine. Nothing bad will come of using 8E1 to receive 8E2, because the "stop bits" are merely idle time between the data bits. 2 stops simply means there's a minimum 2 bit time with the line high before the next start bit can go low. Using 8E1 will simply cause Teensy to start waiting for the next start bit earlier, which is perfectly fine.

    For transmitting data to another device that's expecting 8E2, using 8E1 could be troublesome. The problem is that other device is expecting the line to remain high for 2 bit times (or longer) before the next start bit can begin.

    First, I'd try simply sending 8E1 and see what happens. Odds are good the UART in that other device probably only requires 1 stop bit. Pretty much all modern UARTs are designed to allow receiving with as little as 0.5 stop bit time, regardless of what they're configuration actually is. The hardware is almost always designed this way, because the other side might have its clock running slightly faster. UARTs that don't receive properly with 1/2 stop bit time aren't able to deal with such clock mismatch. Virtually all modern UARTs are well designed.

    But if you really want to transmit true 8E2, the only viable workaround on Teensy 3.1 is to delay before sending each byte. For example, if you're using 100000 baud, each bit is exactly 10 us. 8E2 is 1 start, 8 data, 1 parity and 2 stops, for a total of 12 bit times. That's 120 us. Teensy 3.1 will complete transmitting in 110 us. To make sure you always have at least 2 stop bits, just wait 120 us (or longer) until you write the next byte. The code won't be pretty, but it will slow the rate of transmission by increasing the idle time. To the other end, that will look the same as 8E2.
    Last edited by PaulStoffregen; 01-28-2015 at 10:20 AM.

  13. #13
    Junior Member
    Join Date
    Jan 2015
    Posts
    5
    Quote Originally Posted by PaulStoffregen View Post
    The closest Teensy 3.1 supports is 8E1.

    For receiving data that's sent by another device in 8E2 format, you can simply use 8E1.

    Really, this will work fine. Nothing bad will come of using 8E1 to receive 8E2, because the "stop bits" are merely idle time between the data bits. 2 stops simply means there's a minimum 2 bit time with the line high before the next start bit can go low. Using 8E1 will simply cause Teensy to start waiting for the next start bit earlier, which is perfectly fine.

    For transmitting data to another device that's expecting 8E2, using 8E1 could be troublesome. The problem is that other device is expecting the line to remain high for 2 bit times (or longer) before the next start bit can begin.

    First, I'd try simply sending 8E1 and see what happens. Odds are good the UART in that other device probably only requires 1 stop bit. Pretty much all modern UARTs are designed to allow receiving with as little as 0.5 stop bit time, regardless of what they're configuration actually is. The hardware is almost always designed this way, because the other side might have its clock running slightly faster. UARTs that don't receive properly with 1/2 stop bit time aren't able to deal with such clock mismatch. Virtually all modern UARTs are well designed.

    But if you really want to transmit true 8E2, the only viable workaround on Teensy 3.1 is to delay before sending each byte. For example, if you're using 100000 baud, each bit is exactly 10 us. 8E2 is 1 start, 8 data, 1 parity and 2 stops, for a total of 12 bit times. That's 120 us. Teensy 3.1 will complete transmitting in 110 us. To make sure you always have at least 2 stop bits, just wait 120 us (or longer) until you write the next byte. The code won't be pretty, but it will slow the rate of transmission by increasing the idle time. To the other end, that will look the same as 8E2.

    Thanx for the super fast reply. I will go for your last suggestion and delay the bytes a bit when sending. Receiving is fine with 8E1 as you had guessed already. Sending with 8E1 doesn't seem to work just out of the box. But i just checked with one Futaba s-Bus servo so there might be more tolerant devices out there.

  14. #14
    Hey alx or Paul

    Can you tell me how to delay? I have the same problem with FrSky-Servos...

    See also here: https://forum.pjrc.com/threads/25265...ll=1#post59534

  15. #15
    Junior Member
    Join Date
    Jan 2015
    Posts
    5
    Quote Originally Posted by nique View Post
    Hey alx or Paul

    Can you tell me how to delay? I have the same problem with FrSky-Servos...

    See also here: https://forum.pjrc.com/threads/25265...ll=1#post59534
    i simply worked with elapsedMicros to delay the next Serial.write(data). Loop through outputbuffer (with the 25 bytes for the Sbus) byte by byte and wait till 120us are passed for every byte....
    something like this

    elapsedMicros byteDelay=0;
    int sendIndex=0;
    while (sendIndex<25)
    {
    // Sending one byte of data takes 11bit in 8E1 and 110us at 100000baud but we need one stopbit longer so we start the next sending after 120us not 110
    if (byteDelay >= 120)
    {
    byteDelay = 0;
    sbusPort.write(sBusDataOut[sendIndex]); // sBusDataOut has the Output-bytes
    sendIndex++;
    }
    }

    i know this is not really cool because the controller just hangs in the while loop and doesn't do anything else but i did this so far just to check really quick if it works. And it does.

  16. #16
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    Can Teensy 3.x support 8 data bits + parity = 9 bits, plus 1.5 stop bits? That's the ISO7816 standard (smart cards). Also required is single-wire mode: TX,RX in half-duplex on one wire, usually the UART TX pin.

    Many/most chip and software specs leave it ambiguous if parity is or is not included in the bits per character definition; some assume that you the reader "know" that 8 bits even parity is 7 data bits and 1 parity bit -which is incompatible with the ISO standard above. This includes most serial terminal software I've found. I do have 8 + parity bits w/1.5 stop bits working on a different microprocessor, but it lacks FIFOs.

    Ideally, all specs would say "n Bits per character including or excluding the parity bit".
    Last edited by stevech; 02-09-2015 at 04:22 PM.

  17. #17
    Junior Member
    Join Date
    Jan 2015
    Posts
    5
    Quote Originally Posted by stevech View Post
    Can Teensy 3.x support 8 data bits + parity = 9 bits, plus 1.5 stop bits? That's the ISO7816 standard (smart cards). Also required is single-wire mode: TX,RX in half-duplex on one wire, usually the UART TX pin.

    Many/most chip and software specs leave it ambiguous if parity is or is not included in the bits per character definition; some assume that you the reader "know" that 8 bits even parity is 7 data bits and 1 parity bit -which is incompatible with the ISO standard above. This includes most serial terminal software I've found. I do have 8 + parity bits w/1.5 stop bits working on a different microprocessor, but it lacks FIFOs.

    Ideally, all specs would say "n Bits per character including or excluding the parity bit".
    Yes it can. Check out https://www.pjrc.com/teensy/td_uart.html there is a complete list of supported serial modes. Or https://www.pjrc.com/teensy/K20P64M50SF0RM.pdf.

    There the 8bit data modes really mean 8bit of data. So "8 data bits + parity" means here 8E1 or 8O1. And it supports it even with TX or RX inverted in every flavour which is cool as well because you don't need to invert the signals externally if you need to.

  18. #18
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    Thanks.
    Many software or hardware products say 8E1 or 8O1 but do not send /receive 9 bits.
    That's why it should be that one says "including" or "excluding" the parity bit so it's unambiguous.

    ISO7816-3 specifies inverted polarity and reversed most-significant-bit as first-sent, as an option. Few or no one uses this mode for ISL7816, but rather, "direct" is the norm.

    Some chips support 9 bits no parity. So the "chars" sent/received are uint16_t. Not sure where that's popular.
    Last edited by stevech; 02-09-2015 at 09:12 PM.

  19. #19
    Quote Originally Posted by alx View Post
    i simply worked with elapsedMicros to delay the next Serial.write(data). Loop through outputbuffer (with the 25 bytes for the Sbus) byte by byte and wait till 120us are passed for every byte....
    something like this

    elapsedMicros byteDelay=0;
    int sendIndex=0;
    while (sendIndex<25)
    {
    // Sending one byte of data takes 11bit in 8E1 and 110us at 100000baud but we need one stopbit longer so we start the next sending after 120us not 110
    if (byteDelay >= 120)
    {
    byteDelay = 0;
    sbusPort.write(sBusDataOut[sendIndex]); // sBusDataOut has the Output-bytes
    sendIndex++;
    }
    }

    i know this is not really cool because the controller just hangs in the while loop and doesn't do anything else but i did this so far just to check really quick if it works. And it does.
    Thanks, that helps!

    Would it also work, if you replace the while with an if? So the code can continue its job? I have the problem, that I need to read 3 other inbound s-bus-connections.... Ok, that may be to vague, I have first to check my used send-routine.

    I use this: https://github.com/mikeshub/FUTABA_SBUS

    If I'm right, it must be in the FUTABA_SBUS.cpp file in the FUTABA_SBUS::FeedLine routine - right? alx, have you an idea where? I'm not a developer...
    Last edited by nique; 02-10-2015 at 08:46 AM.

  20. #20
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,599
    Quote Originally Posted by nique View Post
    Would it also work, if you replace the while with an if? So the code can continue its job?
    Yes. The one change you'd probably need to make is moving "elapsedMicros byteDelay=0;" outside of loop(). If it remains inside loop, it'll be set back to zero. Obviously you want it to keep counting up to the 120 us delay. Likewise, sendIndex and other stuff that keeps track of where you are in the data would need to become variables that retain state.

    I have the problem, that I need to read 3 other inbound s-bus-connections....
    Shouldn't be a problem. Obviously you'd need 3 of those elapsedMicros variables and 3 index integers. Teensy has plenty of memory and the processor is very fast, relative to waiting 120 us, so this shouldn't be a problem.

  21. #21
    Thanks

    Hmm, it seams that I have not really understood. The idea yes, but not how to implement. Below what my code is.

    In row 144 of the lib, you can find what I have done. I changed the logic to alx: I do first send data out and wait then to complete the 120us. This makes more sense to me, because the other way around, he first waits and then do something...

    Where I'm wrong? And how can I debug? Its bad, I cant run teens with RX and one servo on the USB - not enough power... I have a digital oscilloscope - but don't really know how to setup to see anything. PWM works, but I never have seen the SBUS-Signal to check something...

    Thanks for hints.

    Code:
    #include <Teensy_SBUS.h>
    
    Teensy_SBUS sBusPIC;          // Pilot in Command
    Teensy_SBUS sBusSIC;          // Second in Command
    Teensy_SBUS sBusTIC;          // Teacher in Command
    
    
    void setup(){
      sBusPIC.begin(1);
      sBusSIC.begin(2);
      sBusTIC.begin(3);
      sBusPIC.PassthroughSet(true);
      sBusSIC.PassthroughSet(true);
      sBusTIC.PassthroughSet(true);
      
      Serial.begin(115200);
    }  
    
    
    void loop(){
      sBusPIC.FeedLine();
      if (sBusPIC.toChannels == 1){
        sBusPIC.UpdateServos();
        sBusPIC.UpdateChannels();
        sBusPIC.toChannels = 0;
      }
      sBusSIC.FeedLine();
      if (sBusSIC.toChannels == 1){
        sBusSIC.UpdateServos();
        sBusSIC.UpdateChannels();
        sBusSIC.toChannels = 0;
      }
      sBusTIC.FeedLine();
      if (sBusTIC.toChannels == 1){
        sBusTIC.UpdateServos();
        sBusTIC.UpdateChannels();
        sBusTIC.toChannels = 0;
      }
    
    
    
    //  printAllsBusStatus();  
    //  delay(15);
    }  
    
    
    
    void printAllsBusStatus() {
      uint8_t i;
      Serial.println("PIC  | SIC");
        for (i=0; i<25; i++) {
          Serial.print(sBusPIC.sbusData[i]);
          Serial.print("   |   ");
          Serial.println(sBusSIC.sbusData[i]);
        }
      Serial.println("");
    }
    My "DecisionMaker.ino"

    Code:
    #include "Teensy_SBUS.h"
    
    void Teensy_SBUS::begin(uint8_t port_nr){
        port = port_nr;
    	uint8_t loc_sbusData[25] = {
    	  0x0f,0x01,0x04,0x20,0x00,0xff,0x07,0x40,0x00,0x02,0x10,0x80,0x2c,0x64,0x21,0x0b,0x59,0x08,0x40,0x00,0x02,0x10,0x80,0x00,0x00};
    	int16_t loc_channels[18]  = {
    	  		1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,0,0};
    	int16_t loc_servos[18]    = {
      			1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,0,0};
      	switch (port) {
    	  case 1:
    	    port1.begin(BAUDRATE,SERIAL_8E1_RXINV_TXINV);
    		break;
    	  case 2:
    	    port2.begin(BAUDRATE,SERIAL_8E1_RXINV_TXINV);
    		break;
    	  case 3:
    	    port3.begin(BAUDRATE,SERIAL_8E1_RXINV_TXINV);
    		break;
    	  }
    
    	memcpy(sbusData,loc_sbusData,25);
    	memcpy(channels,loc_channels,18);
    	memcpy(servos,loc_servos,18);
    	failsafe_status = SBUS_SIGNAL_OK;
    	sbus_passthrough = 1;
    	toChannels = 0;
    	bufferIndex=0;
    	feedState = 0;
    }
    
    int16_t Teensy_SBUS::Channel(uint8_t ch) {
      // Read channel data
      if ((ch>0)&&(ch<=16)){
        return channels[ch-1];
      }
      else{
        return 1023;
      }
    }
    uint8_t Teensy_SBUS::DigiChannel(uint8_t ch) {
      // Read digital channel data
      if ((ch>0) && (ch<=2)) {
        return channels[15+ch];
      }
      else{
        return 0;
      }
    }
    void Teensy_SBUS::Servo(uint8_t ch, int16_t position) {
      // Set servo position
      if ((ch>0)&&(ch<=16)) {
        if (position>2048) {
          position=2048;
        }
        servos[ch-1] = position;
      }
    }
    void Teensy_SBUS::DigiServo(uint8_t ch, uint8_t position) {
      // Set digital servo position
      if ((ch>0) && (ch<=2)) {
        if (position>1) {
          position=1;
        }
        servos[15+ch] = position;
      }
    }
    uint8_t Teensy_SBUS::Failsafe(void) {
      return failsafe_status;
    }
    
    void Teensy_SBUS::PassthroughSet(int mode) {
      // Set passtrough mode, if true, received channel data is send to servos
      sbus_passthrough = mode;
    }
    
    int Teensy_SBUS::PassthroughRet(void) {
      // Return current passthrough mode
      return sbus_passthrough;
    }
    void Teensy_SBUS::UpdateServos(void) {
      // Send data to servos
      // Passtrough mode = false >> send own servo data
      // Passtrough mode = true >> send received channel data
      uint8_t i;
      if (sbus_passthrough==0) {
        // clear received channel data
        for (i=1; i<24; i++) {
          sbusData[i] = 0;
        }
    
        // reset counters
        ch = 0;
        bit_in_servo = 0;
        byte_in_sbus = 1;
        bit_in_sbus = 0;
    
        // store servo data
        for (i=0; i<176; i++) {
          if (servos[ch] & (1<<bit_in_servo)) {
            sbusData[byte_in_sbus] |= (1<<bit_in_sbus);
          }
          bit_in_sbus++;
          bit_in_servo++;
    
          if (bit_in_sbus == 8) {
            bit_in_sbus =0;
            byte_in_sbus++;
          }
          if (bit_in_servo == 11) {
            bit_in_servo =0;
            ch++;
          }
        }
    
        // DigiChannel 1
        if (channels[16] == 1) {
          sbusData[23] |= (1<<0);
        }
        // DigiChannel 2
        if (channels[17] == 1) {
          sbusData[23] |= (1<<1);
        }
    
        // Failsafe
        if (failsafe_status == SBUS_SIGNAL_LOST) {
          sbusData[23] |= (1<<2);
        }
    
        if (failsafe_status == SBUS_SIGNAL_FAILSAFE) {
          sbusData[23] |= (1<<2);
          sbusData[23] |= (1<<3);
        }
      }
      // send data out
      //serialPort.write(sbusData,25);
        elapsedMicros byteDelay1=0;
        elapsedMicros byteDelay2=0;
        elapsedMicros byteDelay3=0;
      	switch (port) {
    	  case 1:
    		  for (i=0;i<25;i++) {
    			byteDelay1 = 0;
    			port1.write(sbusData[i]);
    			while (byteDelay1 <120) {delay(1);}
    			// Sending one byte of data takes 11bit in 8E1 and 110us at 100000baud 
    			// but we need one stopbit longer so we start the next sending after 120us not 110
    		  }
    		break;
    	  case 2:
    		  for (i=0;i<25;i++) {
    			port2.write(sbusData[i]);
    		  }
    		break;
    	  case 3:
    		  for (i=0;i<25;i++) {
    			port3.write(sbusData[i]);
    		  }
    		break;
    	  }
    
    }
    void Teensy_SBUS::UpdateChannels(void) {
      //uint8_t i;
      //uint8_t sbus_pointer = 0;
      // clear channels[]
      /*for (i=0; i<16; i++) {
        channels[i] = 0;
      }
    
      // reset counters
      byte_in_sbus = 1;
      bit_in_sbus = 0;
      ch = 0;
      bit_in_channel = 0;
      //this method is much slower than the other method
      // process actual sbus data
      for (i=0; i<176; i++) {
        if (sbusData[byte_in_sbus] & (1<<bit_in_sbus)) {
          channels[ch] |= (1<<bit_in_channel);
        }
        bit_in_sbus++;
        bit_in_channel++;
    
        if (bit_in_sbus == 8) {
          bit_in_sbus =0;
          byte_in_sbus++;
        }
        if (bit_in_channel == 11) {
          bit_in_channel =0;
          ch++;
        }
      }*/
    
      channels[0]  = ((sbusData[1]|sbusData[2]<< 8) & 0x07FF);
      channels[1]  = ((sbusData[2]>>3|sbusData[3]<<5) & 0x07FF);
      channels[2]  = ((sbusData[3]>>6|sbusData[4]<<2|sbusData[5]<<10) & 0x07FF);
      channels[3]  = ((sbusData[5]>>1|sbusData[6]<<7) & 0x07FF);
      channels[4]  = ((sbusData[6]>>4|sbusData[7]<<4) & 0x07FF);
      channels[5]  = ((sbusData[7]>>7|sbusData[8]<<1|sbusData[9]<<9) & 0x07FF);
      channels[6]  = ((sbusData[9]>>2|sbusData[10]<<6) & 0x07FF);
      channels[7]  = ((sbusData[10]>>5|sbusData[11]<<3) & 0x07FF); // & the other 8 + 2 channels if you need them
      #ifdef ALL_CHANNELS
      channels[8]  = ((sbusData[12]|sbusData[13]<< 8) & 0x07FF);
      channels[9]  = ((sbusData[13]>>3|sbusData[14]<<5) & 0x07FF);
      channels[10] = ((sbusData[14]>>6|sbusData[15]<<2|sbusData[16]<<10) & 0x07FF);
      channels[11] = ((sbusData[16]>>1|sbusData[17]<<7) & 0x07FF);
      channels[12] = ((sbusData[17]>>4|sbusData[18]<<4) & 0x07FF);
      channels[13] = ((sbusData[18]>>7|sbusData[19]<<1|sbusData[20]<<9) & 0x07FF);
      channels[14] = ((sbusData[20]>>2|sbusData[21]<<6) & 0x07FF);
        channels[15] = ((sbusData[21]>>5|sbusData[22]<<3) & 0x07FF);
      #endif
      // DigiChannel 1
      /*if (sbusData[23] & (1<<0)) {
        channels[16] = 1;
      }
      else{
        channels[16] = 0;
      }
      // DigiChannel 2
      if (sbusData[23] & (1<<1)) {
        channels[17] = 1;
      }
      else{
        channels[17] = 0;
      }*/
      // Failsafe
      failsafe_status = SBUS_SIGNAL_OK;
      if (sbusData[23] & (1<<2)) {
        failsafe_status = SBUS_SIGNAL_LOST;
      }
      if (sbusData[23] & (1<<3)) {
        failsafe_status = SBUS_SIGNAL_FAILSAFE;
      }
    
    }
    void Teensy_SBUS::FeedLine(void){
      	switch (port) {
    	  case 1:
    		  if (port1.available() > 24){
    			while(port1.available() > 0){
    			  inData = port1.read();
    			  switch (feedState){
    			  case 0:
    				if (inData != 0x0f){
    				  while(port1.available() > 0){//read the contents of in buffer this should resync the transmission
    					inData = port1.read();
    				  }
    				  return;
    				}
    				else{
    				  bufferIndex = 0;
    				  inBuffer[bufferIndex] = inData;
    				  inBuffer[24] = 0xff;
    				  feedState = 1;
    				}
    				break;
    			  case 1:
    				bufferIndex ++;
    				inBuffer[bufferIndex] = inData;
    				if (bufferIndex < 24 && port1.available() == 0){
    				  feedState = 0;
    				}
    				if (bufferIndex == 24){
    				  feedState = 0;
    				  if (inBuffer[0]==0x0f && inBuffer[24] == 0x00){
    					memcpy(sbusData,inBuffer,25);
    					toChannels = 1;
    				  }
    				}
    				break;
    			  }
    			}
    		  }
    		break;
    	  case 2:
    		  if (port2.available() > 24){
    			while(port2.available() > 0){
    			  inData = port2.read();
    			  switch (feedState){
    			  case 0:
    				if (inData != 0x0f){
    				  while(port2.available() > 0){//read the contents of in buffer this should resync the transmission
    					inData = port2.read();
    				  }
    				  return;
    				}
    				else{
    				  bufferIndex = 0;
    				  inBuffer[bufferIndex] = inData;
    				  inBuffer[24] = 0xff;
    				  feedState = 1;
    				}
    				break;
    			  case 1:
    				bufferIndex ++;
    				inBuffer[bufferIndex] = inData;
    				if (bufferIndex < 24 && port2.available() == 0){
    				  feedState = 0;
    				}
    				if (bufferIndex == 24){
    				  feedState = 0;
    				  if (inBuffer[0]==0x0f && inBuffer[24] == 0x00){
    					memcpy(sbusData,inBuffer,25);
    					toChannels = 1;
    				  }
    				}
    				break;
    			  }
    			}
    		  }
    		break;
    	  case 3:
    		  if (port3.available() > 24){
    			while(port3.available() > 0){
    			  inData = port3.read();
    			  switch (feedState){
    			  case 0:
    				if (inData != 0x0f){
    				  while(port3.available() > 0){//read the contents of in buffer this should resync the transmission
    					inData = port3.read();
    				  }
    				  return;
    				}
    				else{
    				  bufferIndex = 0;
    				  inBuffer[bufferIndex] = inData;
    				  inBuffer[24] = 0xff;
    				  feedState = 1;
    				}
    				break;
    			  case 1:
    				bufferIndex ++;
    				inBuffer[bufferIndex] = inData;
    				if (bufferIndex < 24 && port3.available() == 0){
    				  feedState = 0;
    				}
    				if (bufferIndex == 24){
    				  feedState = 0;
    				  if (inBuffer[0]==0x0f && inBuffer[24] == 0x00){
    					memcpy(sbusData,inBuffer,25);
    					toChannels = 1;
    				  }
    				}
    				break;
    			  }
    			}
    		  }
    		break;
    	  }
    
    
    }
    Teensy_SBUS.cpp

    Code:
    
    #ifndef Teensy_SBUS_h
    #define Teensy_SBUS_h
    
    #include <Arduino.h>
    
    
    #define SBUS_SIGNAL_OK          0x00
    #define SBUS_SIGNAL_LOST        0x01
    #define SBUS_SIGNAL_FAILSAFE    0x03
    #define BAUDRATE 100000
    #define port1 Serial1
    #define port2 Serial2
    #define port3 Serial3
    //#define ALL_CHANNELS
    
    
    class Teensy_SBUS
    {
    	public:
    		uint8_t sbusData[25];
    		int16_t channels[18];
    		int16_t servos[18];
    		uint8_t  failsafe_status;
    		int sbus_passthrough;
    		int toChannels;
    		void begin(uint8_t port_nr);
    		int16_t Channel(uint8_t ch);
    		uint8_t DigiChannel(uint8_t ch);
    		void Servo(uint8_t ch, int16_t position);
    		void DigiServo(uint8_t ch, uint8_t position);
    		uint8_t Failsafe(void);
    		void PassthroughSet(int mode);
    		int PassthroughRet(void);
    		void UpdateServos(void);
    		void UpdateChannels(void);
    		void FeedLine(void);
    	private:
    	    uint8_t port;
    		uint8_t byte_in_sbus;
    		uint8_t bit_in_sbus;
    		uint8_t ch;
    		uint8_t bit_in_channel;
    		uint8_t bit_in_servo;
    		uint8_t inBuffer[25];
    		int bufferIndex;
    		uint8_t inData;
    		int feedState;
    
    };
    
    #endif
    Teensy_SBUS.h

  22. #22
    Ok, I'm on

    I started with the same code as @alx

    I played with the "if (byteDelay >= 120) " value. And at 113, I had a servo move. But only of an analog servo after the FrSky S-BUS-to-PWM Converter. The FrSky S-BUS Servo did once move a bit at 118... But anyway, also the analog servo does not work reliable. As I move the stick very slow (as almost in the air), the servo moves right. But as I move the stick fast from, the servo does not follow right. I can see the problems also at the LED of the converter. Normaly the four LED stays. But at hard move, they start to flicker. After a some tenth of a second, its all stable again.

    To me, this solution seams not to work.

    @PaulStoffregen is there an other way to deal? Is there an external part that can translate?

  23. #23
    Hi,

    thanks for the many hints in this thread. I had the same problems with transmitting data to an SBUS servo as described above. I tried
    the delay method and it worked already quite well. The wasted processor time looked unacceptable for my project and I tried a different
    approach with an IntervalTimer for the required delay. So far it behaves quite well and it looks like it frees a good amount of processor time.

    I am not an experienced programmer of a Teensy. It would be great if someone with experience of interrupt handling would have a look
    at the code and give me a feedback about my interrupt handling. It's all in the attached .ino ..

    The code generates SBUS packets and sends them to the servo - sort of a servotester.
    Attached Files Attached Files

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •