Robotics, need help with Bolder sbus code

I have a good amount of a tank/arm/cannon system I am making

EDIT I have Bolder sbus.h library on the Arduino Mega and it is working, giving me values.. now.. to learn how to send commands per channel to output pins.

DBH-12 H-bridge, 2 x 125rpm 37D motors, Arduino MEGA, with an articulating arm powered off NEMA 17 steppers through planetary gear 5:18:1 through 20:100 GT2 timing pulleys driven by 2 x TB6600, and double shaft servos on forearm.. that's as far as I've gotten.

Why did you start a topic in the Uncategorised category of the forum when its description explicitly tells you not to ?

Your topic has been moved to a relevant category. Please be careful in future when deciding where to start new topics

You are not new to the forum. I know that because the forum highlights new members. So you can't use "I'm new here" as an excuse for ignoring the forum guide, not including your code, links to the specs of your components, your schematics, or posting in an inappropriate forum section...

I'll move your topic for you. You need to fix those other things now.

EDIT: @UKHeliBob beat me to it.

I never said I was "new" just didn't know there we're such rules...seems like a "general question" to me.. @Delta_G it was in my rumbled reading last night... I believe it was in a library, person said the UNO can read 100k (which I got to interpret SBUS) but MEGA cannot (which I cannot get recognize SBUS) so it made sense.. in the serial monitor it's just non sense coming back from the MEGA

@Delta_G , MEGA should interpret SBUS just the same as the UNO does?

#define MAX_GROUP_TIME 24138
// if SBUS frames are received faster than this

uint8_t frame[24]; // SBUS received bytes. 1st byte of 25-byte frame is always 0x0F, and is not stored
uint16_t dTimes[6]; // times (in half-microsecond units) for the edges of the first 6 PWM channels, to be output on Port D (pins D2-D7)
uint16_t bTimes[6]; // similarly for the next 6 PWM channels, output on Port B (pins D8-D13) 
uint16_t cTimes[6]; // and for the last 6 PWM channels, output on Port C (pins A0-A5) 
uint16_t maxTime = 18000; // greatest of { dTimes[5], bTimes[5], cTimes[5] } after this time the pulse output loop can be terminated; 

void setup() {
  Serial.begin(100000, SERIAL_8E2); // SBUS runs at 100kBaud 8E2: 25-byte frames, without gaps, take 3000us
  PORTD = 0b00000000; //  1st 6 PWM channel outputs on D2-D7
  DDRD  = 0b11111100;
  PORTB = 0b00000000; // next 6 PWM channel outputs on D8-D13 
  DDRB  = 0b00111111;
  PORTC = 0b00000000; // last 6 PWM channel outputs on A0-A5
  DDRC  = 0b00111111;

  // using 16-bit Timer1 to time simple intervals in half-microseconds for outputting the servo pulses
  TCCR1A = 0x00;
  TCCR1B = 0x02;
}

void loop() {
  while(Serial.available()) {
    // try to receive a 25-byte frame that begins with 0x0F and ends with 0x00
    // scan until an 0x0F byte is received, or the receive buffer is empty
    int b = Serial.read();
    if (b != 0x0F) {
      continue;
    }
    frame[23] = 0xFF; // a good received frame overwrites this with 0x00
    // now attempt to receive 24 bytes
    int i = 0;
    while (i < 24) {
      i += Serial.readBytes(frame + i, min(Serial.available(), 24 - i));
    }
    if (i == 24 && frame[23] == 0x000) { // complete frame received, so output pulses
      uint16_t edgeTime = 0;
      for (uint8_t ch = 0; ch < 6; ch++) {
        edgeTime += channel(ch) + 1976; // conversion from 11-bit SBUS value, 0 to 2047, to half-microsecond pulse width 1976 to 4023
        dTimes[ch] = edgeTime;
      }
      edgeTime = 0;
      for (uint8_t ch = 6; ch < 12; ch++) {
        edgeTime += channel(ch) + 1976; // conversion from 11-bit SBUS value, 0 to 2047, to half-microsecond pulse width 1976 to 4023
        bTimes[ch - 6] = edgeTime;
      }
      edgeTime = 0;
      for (uint8_t ch = 12; ch < 16; ch++) {
        edgeTime += channel(ch) + 1976; // conversion from 11-bit SBUS value, 0 to 2047, to half-microsecond pulse width 1976 to 4023
        cTimes[ch - 12] = edgeTime;
      }
      edgeTime += frame[22] & 0x01 ? 4023 : 1976; // digital channel 17
      cTimes[4] = edgeTime;
      edgeTime += frame[22] & 0x02 ? 4023 : 1976; // digital channel 18
      cTimes[5] = edgeTime;
      
      uint8_t dIndex = 0; // counts 0 to 5 for which of first group of 6 PWM channels is being output
      uint8_t dMask = 0b00000100; // mask for outputting first group of 6 PWM channels on D2-D7
      uint16_t dTime = dTimes[dIndex];
      uint8_t bIndex = 0; // counts 0 to 5 for which of the second group of 6 PWM channels is being output
      uint8_t bMask = 0b00000001; // mask for outputting second group of 6 PWM channels on D8-D13
      uint16_t bTime = bTimes[bIndex];
      uint8_t cIndex = 0; // counts 0 to 5 for which of the second group of 6 PWM channels is being output
      uint8_t cMask = 0b00000001; // mask for outputting third group of 6 PWM channels on A0-A5
      uint16_t cTime = cTimes[cIndex];
      
      uint16_t currentTimer = 0;
      PORTD = dMask;
      PORTB = bMask;
      PORTC = cMask;
      TCNT1 = 0;
      while (currentTimer < MAX_GROUP_TIME) {
        if (dIndex < 6 && currentTimer > dTime) {
          dMask <<= 1;
          PORTD = dMask;
          dIndex++;
          dTime = dTimes[dIndex];
        }
        if (bIndex < 6 && currentTimer > bTime) {
          bMask <<= 1;
          PORTB = bMask;
          bIndex++;
          bTime = bTimes[bIndex];
        }
        if (cIndex < 6 && currentTimer > cTime) {
          cMask <<= 1;
          PORTC = cMask;
          cIndex++;
          cTime = cTimes[cIndex];
        }
        currentTimer = TCNT1;
      }
      PORTD = PORTB = PORTC = 0b00000000;
      // outputting pulses takes 12.07ms with an extra 0.1ms calculation time.
      // If SBUS frames arrive faster then that the next one will already have started now.
      // empty the serial receive buffer so that the output pulses are synced with the SBUS frames.
      // for example, if the SBUS frames arrive at 11ms intervals, then every other received frame will be discarded, and the PWM frequency will be 22ms
      while (Serial.available()) {
         Serial.read();
      }
      break;
    }
  }
}

uint16_t channel(uint8_t ch) { // extract 11-bit channel[ch] value from frame. ch 0-15
  uint8_t k = ch > 7 ? 11 : 0; // offset into frame array: 0 for channels 0-7, 11 for channels 8-15
  switch (ch % 8) { // pattern repeats (except for k-offset) after 8 channels
    case 0:
      return (uint16_t)frame[0+k] | ((((uint16_t)frame[1+k]) & 0x07) << 8);
    case 1:
      return ((uint16_t)(frame[1+k] & 0xF8) >> 3) | ((((uint16_t)frame[2+k]) & 0x3F) << 5);
    case 2:
      return ((uint16_t)(frame[2+k] & 0xC0) >> 6) | ((((uint16_t)frame[3+k])) << 2) | ((((uint16_t)frame[4+k]) & 0x01) << 10);
    case 3:
      return ((uint16_t)(frame[4+k] & 0xFE) >> 1) | ((((uint16_t)frame[5+k]) & 0x0F) << 7);
    case 4:
      return ((uint16_t)(frame[5+k] & 0xF0) >> 4) | ((((uint16_t)frame[6+k]) & 0x7F) << 4);
    case 5:
      return ((uint16_t)(frame[6+k] & 0x80) >> 7) | ((((uint16_t)frame[7+k])) << 1) | ((((uint16_t)frame[8+k]) & 0x03) << 9);
    case 6:
      return ((uint16_t)(frame[8+k] & 0xFC) >> 2) | ((((uint16_t)frame[9+k]) & 0x1F) << 6);
    case 7:
      return ((uint16_t)(frame[9+k] & 0xE0) >> 5) | (((uint16_t)frame[10+k]) << 3);
  }
  return 0xFFFF; // execution never reaches here, but this supresses a compliler warning

Please be more clear - it is not a Mega that can't receive a SBUS on 100K. To be honest - it's your code not able to receive the SBUS on Mega

@Delta_G thanks for replying, I'll tinker with it some more.. it would be nice to get everything working as is and test.. before invest in a custom 3 or 4 joystick controller.. this is getting a lil complicated for me at least.. trying to tell which channel goes where.. at what it needs to do.. as 2 of the channels are steppers.. which if it was automated.. I've done.. but to control position off input.. with an if statement I think? Another reason I am eager to just start a whole system i.e. XRF to easily tell what carrier does from the host.

@b707 can you please explain.. I'd like to understand how this code works better..

There's nothing to explain here. You should never attribute errors to controller problems; in 99% of cases the problem is in your code.

I am only conveying what I have found online..

I am currently using <SBUS.h> which is for futaba it appears i have everything linked to the MEGA.. tbs reciever set to SBUS, using a Taranis Q-7 i think.. it appears I can run 16 channels through this as is.. and use a switch mixer.. although a controller is in the future build.. as of right now I can get back like this.. THANK YOU so much for correcting the negligent certainty that I was going to have to scrub the whole idea of SBUS.. the Futabu library appears easy to code.. i.e. run Serial command to CH(x) I think... hopefully that is it... I will need PWM which I believe i can do in IDE.. the value via serial monitor is returning -84-84 values which I can scale with a reduced accuracy :/..

It is my understanding the BolderSBUS library is not suited for my application, am I correct? It appears that is for dev board... i.e. teensy 4.1 and such..

I'm pretty excited I am seeing SOMETHING tho, any advice, suggestions, anything? Which library do you think is better for my application? Which would be a little more forgiving in the command code?

I also lost channel one, it doesn't show in the serial monitor, is that due to the library? I am using the example code for SBUS.h

#include <SBUS.h>
SBUS sbus(Serial1);

void setup()
{
  sbus.begin();
  Serial.begin(115200);
  Serial.println("SBUS Status");
}

// this is timer2, which triggers ever 1ms and processes the incoming SBUS datastream
ISR(TIMER2_COMPA_vect)
{
  sbus.process();
}

void loop()
{
  delay(300);
  printSBUSStatus();
}

void printSBUSStatus()
{
  Serial.print("Ch1  ");
  Serial.println(sbus.getNormalizedChannel(1));
  Serial.print("Ch2  ");
  Serial.println(sbus.getNormalizedChannel(2));
  Serial.print("Ch3  ");
  Serial.println(sbus.getNormalizedChannel(3));
  Serial.print("Ch4  ");
  Serial.println(sbus.getNormalizedChannel(4));
  Serial.print("Ch5  ");
  Serial.println(sbus.getNormalizedChannel(5));
  Serial.print("Ch6  ");
  Serial.println(sbus.getNormalizedChannel(6));
  Serial.print("Ch7  ");
  Serial.println(sbus.getNormalizedChannel(7));
  Serial.print("Ch8  ");
  Serial.println(sbus.getNormalizedChannel(8));
  Serial.print("Ch9  ");
  Serial.println(sbus.getNormalizedChannel(9));
  Serial.print("Ch10 ");
  Serial.println(sbus.getNormalizedChannel(10));
  Serial.print("Ch11 ");
  Serial.println(sbus.getNormalizedChannel(11));
  Serial.print("Ch12 ");
  Serial.println(sbus.getNormalizedChannel(12));
  Serial.print("Ch13 ");
  Serial.println(sbus.getNormalizedChannel(13));
  Serial.print("Ch14 ");
  Serial.println(sbus.getNormalizedChannel(14));
  Serial.print("Ch15 ");
  Serial.println(sbus.getNormalizedChannel(15));
  Serial.print("Ch16 ");
  Serial.println(sbus.getNormalizedChannel(16));
  Serial.println();
  Serial.print("Failsafe: ");
  if (sbus.getFailsafeStatus() == SBUS_FAILSAFE_ACTIVE) {
    Serial.println("Active");
  }
  if (sbus.getFailsafeStatus() == SBUS_FAILSAFE_INACTIVE) {
    Serial.println("Not Active");
  }

  Serial.print("Data loss on connection: ");
  Serial.print(sbus.getFrameLoss());
  Serial.println("%");

  Serial.print("Frames: ");
  Serial.print(sbus.getGoodFrames());
  Serial.print(" / ");
  Serial.print(sbus.getLostFrames());
  Serial.print(" / ");
  Serial.println(sbus.getDecoderErrorFrames());

  Serial.print("Time diff: ");

}

Sadly, this looks like an instructables / cut & paste newbie problem.

Extreme lack of fundamental understanding and no knowledge of the code and hardware they’re trying to implement,

System design isn’t much like LEGO, you need to understand, plan and think while executing. People will help if you understand what they’re talking about.

Sorry, harsh truth.

1 Like

that's why I'm here, not for every person to tell me how I don't follow a guide line, so far the only one helpful in any way was Delta, I am clearly not a master coder, and yes, I copy past from instructible to get me started.. that came directly from the web, not what I have Infront of me now.. I do want to understand it better, put downs is not teaching me any of my mistakes..

Do you have a drivers licence ?
The consequences are greater.

that exactly is my meaning by "advice" I feel I am learning how to write with 3 different "SBUS" libraries and I'm not sure which is best for my application.. i.e. I'm messing with this code that says it's for "Futaba" SBUS but it works... I want to try the Boulder.SBUS library but I'm not sure how to indicate the separate channel write functions.. I have read the "readme" on so many libraries at this point that I get things twisted when I am trying to write.. I'll use a function from one library not in the other. and it's just messy. The code below is what I have as of now... I get the tracks to move.. very slowly.. I believe it has something to do with serial monitor is reading values from -86 to 86 and should give me values from 900's-1800's.. not really sure why, how to fix, or if it's just how Futaba uses Sbus that's messing with it... I am sending the receiver through a amplifying inverter.. 10k resistor on the Sbus TX 5k resistor on the 5v power pin to the 4444 transistor...

yes I have a license, I'm a junior in college for Aerospace Engineering.. hope your day gets better buddy...

#include <SBUS.h>
SBUS sbus(Serial1);
#define motorLeft_IN1 4
#define motorLeft_IN2 5
#define motorRight_IN1 6
#define motorRight_IN2 7
int ch2, ch3, ch6, ch8 = 0;

int motorSpeed, steeringValue, leftMotorSpeed, rightMotorSpeed = 0;

void setup()
{
  sbus.begin();
  Serial.begin(115200);
  Serial.println("SBUS Status");

  // DC motors control - set them stationary

  // Left track
  digitalWrite(motorLeft_IN1, LOW);   // PWM value
  digitalWrite(motorLeft_IN2, LOW); // Forward

  // Right track
  digitalWrite(motorRight_IN1, LOW);   // PWM value
  digitalWrite(motorRight_IN2, LOW); // Forward


}

// this is timer2, which triggers ever 1ms and processes the incoming SBUS datastream
ISR(TIMER2_COMPA_vect)
{
  sbus.process();
}

void loop()
{

    ch2 = sbus.getChannel(2); // ch0 - left and right;
  ch3 = sbus.getChannel(3); // ch1 - forward and backward;


  // convert the incoming date into suitable PWM value
  steeringValue = map(ch2, 1000, 2000, -185, 185); // 0 to 185 range because then I add +70 in order to avoid low PWM values as to motors won't start if so
  motorSpeed = map(ch3, 500, 1500, -100, 100);
  motorSpeed = abs(motorSpeed);

  leftMotorSpeed = 70 + motorSpeed + steeringValue; // 70 + (0-185) + (0 - 185 ) =  70 - 255 so this range from 70 to 255 is used as PWM value
  rightMotorSpeed = 70 + motorSpeed - steeringValue;

  leftMotorSpeed = constrain(leftMotorSpeed, 0, 255); // constrain the PWM value from 0 to 255
  rightMotorSpeed = constrain(rightMotorSpeed, 0, 255);

  // if PWM is lower than -10, set PWM value to 0

  if (leftMotorSpeed < -10) {
    leftMotorSpeed = 0;
  }
  if (rightMotorSpeed < 10) {
    rightMotorSpeed = 0;
  }
  
  // if right joystick up > forward
  
  if (ch3 > 10 && ch3 < 90) {
    analogWrite(motorLeft_IN1, leftMotorSpeed);  // PWM input
    digitalWrite(motorLeft_IN2, LOW); // Direction - Forward

    analogWrite(motorRight_IN1, rightMotorSpeed);  // PWM input
    digitalWrite(motorRight_IN2, LOW); // Direction - Forward
  }

  // if right joystick down > backward
  if (ch3 > -90 && ch3 < -10) {
    digitalWrite(motorLeft_IN1, LOW);  // Direction - Backward
    analogWrite(motorLeft_IN2, leftMotorSpeed); // PWM input

    digitalWrite(motorRight_IN1, LOW);  // Direction - Backward
    analogWrite(motorRight_IN2, rightMotorSpeed); // PWM input
  }
  // if right joystick middle, don't move
  if (ch3 > -10 && ch3 < 10) {
    if (leftMotorSpeed < 75 && rightMotorSpeed < 75) {
      digitalWrite(motorLeft_IN1, LOW);
      digitalWrite(motorLeft_IN2, LOW);

      digitalWrite(motorRight_IN1, LOW);
      digitalWrite(motorRight_IN2, LOW);
    }
    // if right joystick move just left or right, without going up or down, move the tank left or right (only 1 motor move)
    else {
      analogWrite(motorLeft_IN1, leftMotorSpeed);  // PWM input
      digitalWrite(motorLeft_IN2, LOW); // Direction - Forward

      analogWrite(motorRight_IN1, rightMotorSpeed);  // PWM input
      digitalWrite(motorRight_IN2, LOW); // Direction - Forward
    }
  }
  delay(500);
  printSBUSStatus();
}

void printSBUSStatus()
{
  Serial.print("Ch1  ");
  Serial.println(sbus.getNormalizedChannel(1));
  Serial.print("Ch2  ");
  Serial.println(sbus.getNormalizedChannel(2));
  Serial.print("Ch3  ");
  Serial.println(sbus.getNormalizedChannel(3));
  Serial.print("Ch4  ");
  Serial.println(sbus.getNormalizedChannel(4));
  Serial.print("Ch5  ");
  Serial.println(sbus.getNormalizedChannel(5));
  Serial.print("Ch6  ");
  Serial.println(sbus.getNormalizedChannel(6));
  Serial.print("Ch7  ");
  Serial.println(sbus.getNormalizedChannel(7));
  Serial.print("Ch8  ");
  Serial.println(sbus.getNormalizedChannel(8));
  Serial.print("Ch9  ");
  Serial.println(sbus.getNormalizedChannel(9));
  Serial.print("Ch10 ");
  Serial.println(sbus.getNormalizedChannel(10));
  Serial.print("Ch11 ");
  Serial.println(sbus.getNormalizedChannel(11));
  Serial.print("Ch12 ");
  Serial.println(sbus.getNormalizedChannel(12));
  Serial.print("Ch13 ");
  Serial.println(sbus.getNormalizedChannel(13));
  Serial.print("Ch14 ");
  Serial.println(sbus.getNormalizedChannel(14));
  Serial.print("Ch15 ");
  Serial.println(sbus.getNormalizedChannel(15));
  Serial.print("Ch16 ");
  Serial.println(sbus.getNormalizedChannel(16));
  Serial.println();
  Serial.print("Failsafe: ");
  if (sbus.getFailsafeStatus() == SBUS_FAILSAFE_ACTIVE) {
    Serial.println("Active");
  }
  if (sbus.getFailsafeStatus() == SBUS_FAILSAFE_INACTIVE) {
    Serial.println("Not Active");
  }

  Serial.print("Data loss on connection: ");
  Serial.print(sbus.getFrameLoss());
  Serial.println("%");

  Serial.print("Frames: ");
  Serial.print(sbus.getGoodFrames());
  Serial.print(" / ");
  Serial.print(sbus.getLostFrames());
  Serial.print(" / ");
  Serial.println(sbus.getDecoderErrorFrames());

  Serial.print("Time diff: ");

}

horrible metaphor.. cause.. yes you can do that.. but I know what you are thinking you are saying.. I get it.. so many libraries.. and they'll all "work" and none knows all.. I hoped maybe someone would be knowledgably enough and kind enough to steer me in a certain direction.. I get that so many "creators" find their way on this forum for "projects" and dealing with people who do not help themselves can be frustrating.. Last semester I built an autonomous tank with a vacuum arm controlling z axis with a stepper motor through a TMC2208 driver to move materials. I have spend weeks on this project trying to code what I have built and am just now arriving here asking for help. That is all I'm after.. if I have something "insulting" in some way i apologize. I know this isn't "general knowledge" if it was.. I'd know it..

NOW.. I have loaded bolder.SBUS on the mega and the values are much better.. values I'm use to seeing with RC transmitter. I'm reading here from the literature that this library send the information across in a 25byte bit.. (I think I said that right) and each individual byte is a channel. Now I am learning how to convert what I have so far into this code.. an example would be awesome if anyone knows where one might be

Explain your request in plain English.

originally I was trying to figure out how to pilot this machine when SBUS didn't work for me.. someone set me straight and said SBUS does work with a MEGA and now I am getting values via bolder library.. now I am learning how to code channels in this library..

so maybe an example?

What machine?

Is this a boat or a plane?

A protocol? Use another.

An example of what?