Futaba SBUS reverse engineered to work with Arduino


hi guys,

http://www.futaba-rc.com/sbus/index.html

i needed use both regular servos , sbus servos project have going on right now. sbus interesting thing. uses 100000 baud inverted uart 25 byte transmission. each channel transmitted using 11 bits of data. there start end byte. use 2 stop bits , parity. fun comes in. signal transmitted big endian, each of individual bytes little endian. had figured stuff out when stumbled upon gem:

http://mbed.org/users/digixx/notebook/futaba-s-bus-controlled-by-mbed/

not did have confirm reverse engineering suspicions, had made great algorithm bit bang transmission correct format. due user fat16lib excellent serial library allows things changing parity , stop bits. modified code guys on @ mbed had done , used hex inverter , results perfect. wrote none of code , did allow free redistribution go nuts. imo ability use sbus pretty big arduino. if feel motivated i'll turn proper library. is. if can read code, way thing works pretty self explanatory:

http://www.youtube.com/watch?v=_qelbebtsdw

code: [select]
#include <serialport.h>

#define sbus_signal_ok          0x00
#define sbus_signal_lost        0x01
#define sbus_signal_failsafe    0x03

serialport<0,25,25> port0;

uint8_t sbus_data[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 channels[18]  = {
  1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,0,0};
int16_t servos[18]    = {
  1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,0,0};
uint8_t  failsafe_status = sbus_signal_failsafe;
int sbus_passthrough = 1;
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=0;
uint8_t indata;
int tochannels = 0;
uint32_t baud = 100000;
void setup(){
  //serial.begin(100000);
  port0.begin(baud,  sp_2_stop_bit | sp_even_parity | sp_8_bit_char);

}

void loop(){
  feedline();
  if(tochannels==1){
    update_channels();
    update_servos();
    tochannels=0;
  } 
  //update_servos();
}





int16_t channel(uint8_t ch) {
  // read channel data
  if ((ch>0)&&(ch<=16)){
    return channels[ch-1];
  }
  else{
    return 1023;
  }
}
uint8_t digichannel(uint8_t ch) {
  // read digital channel data
  if ((ch>0) && (ch<=2)) {
    return channels[15+ch];
  }
  else{
    return 0;
  }
}
void 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 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 failsafe(void) {
  return failsafe_status;
}

void passthroughset(int mode) {
  // set passtrough mode, if true, received channel data send servos
  sbus_passthrough = mode;
}

int passthroughret(void) {
  // return current passthrough mode
  return sbus_passthrough;
}
void update_servos(void) {
  // send data 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
    (i=1; i<24; i++) {
      sbus_data[i] = 0;
    }

    // reset counters
    ch = 0;
    bit_in_servo = 0;
    byte_in_sbus = 1;
    bit_in_sbus = 0;

    // store servo data
    (i=0; i<176; i++) {
      if (servos[ch] & (1<<bit_in_servo)) {
        sbus_data[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) {
      sbus_data[23] |= (1<<0);
    }
    // digichannel 2
    if (channels[17] == 1) {
      sbus_data[23] |= (1<<1);
    }

    // failsafe
    if (failsafe_status == sbus_signal_lost) {
      sbus_data[23] |= (1<<2);
    }

    if (failsafe_status == sbus_signal_failsafe) {
      sbus_data[23] |= (1<<2);
      sbus_data[23] |= (1<<3);
    }
  }
  // send data out
  //serialport.write(sbus_data,25);
(i=0;i<25;i++) {
    port0.write(sbus_data[i]);
  }
}
void update_channels(void) {
  uint8_t i;
  uint8_t sbus_pointer = 0;
  // clear channels[]
  (i=0; i<16; i++) {
    channels[i] = 0;
  }

  // reset counters
  byte_in_sbus = 1;
  bit_in_sbus = 0;
  ch = 0;
  bit_in_channel = 0;

  // process actual sbus data
  (i=0; i<176; i++) {
    if (sbus_data[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++;
    }
  }
  // digichannel 1
  if (sbus_data[23] & (1<<0)) {
    channels[16] = 1;
  }
  else{
    channels[16] = 0;
  }
  // digichannel 2
  if (sbus_data[23] & (1<<1)) {
    channels[17] = 1;
  }
  else{
    channels[17] = 0;
  }
  // failsafe
  failsafe_status = sbus_signal_ok;
  if (sbus_data[23] & (1<<2)) {
    failsafe_status = sbus_signal_lost;
  }
  if (sbus_data[23] & (1<<3)) {
    failsafe_status = sbus_signal_failsafe;
  }

}
void feedline(){
  while(port0.available()){
    indata = port0.read();
    if (indata == 0x0f){
      bufferindex = 0;
      inbuffer[bufferindex] = indata;
      inbuffer[24] = 0xff;
    }
    else{
      bufferindex ++;
      inbuffer[bufferindex] = indata;
    }
    if(inbuffer[0]==0x0f & inbuffer[24] == 0x00){

      memcpy(sbus_data,inbuffer,25);
      tochannels = 1;
      return;
    }
  }
}

it took me while find fat16lib serialport library you've used (probably because i'm new @ this), here's link:

http://arduino.cc/forum/index.php/topic,85207.0.html


Arduino Forum > Community > Exhibition / Gallery > Futaba SBUS reverse engineered to work with Arduino


arduino

Comments

Popular posts from this blog

Thread: PKI Client 5.00 install (for eToken Pro)

ATmega2560-Arduino Pin Mapping

Crossfader Arduino Tutorial