Sabertooth 2X60A with Arduino Uno

Hi,

I have a Sabertooth 2x60A to drive 2 DC motors using simplified serial mode with 38400 baud rate.

My project is similar to this link, so I adopt the code: Arduino and Sabertooth 2x5 ?

For the trial, I only send the command stop 0, but turned out that the motor1 is rotating. Anyone know what's wrong? HELP!! :slight_smile:

this is my code for trying the 0 command

#include <SoftwareSerial.h>

// Labels for use with the Sabertooth 2x5 motor controller

// Digital pin 13 is the serial transmit pin to the
// Sabertooth 2x60
#define SABER_TX_PIN 13

// NOT USED (but still init'd)
// Digital pin 12 is the serial receive pin from the
// Sabertooth 2x60
#define SABER_RX_PIN 12

// Set to 38400 through Sabertooth dip switches
#define SABER_BAUDRATE 38400

// Simplified serial Limits for each motor
#define SABER_MOTOR1_FULL_FORWARD 127
#define SABER_MOTOR1_FULL_REVERSE 1
#define SABER_MOTOR1_FULL_STOP 64

#define SABER_MOTOR2_FULL_FORWARD 255
#define SABER_MOTOR2_FULL_REVERSE 128
#define SABER_MOTOR2_FULL_STOP 192

// Motor level to send when issuing the full stop command
#define SABER_ALL_STOP 0

SoftwareSerial SaberSerial = SoftwareSerial( SABER_RX_PIN, SABER_TX_PIN );

void setup()
{
// Init software UART to communicate
// with the Sabertooth 2x60
pinMode( SABER_TX_PIN, OUTPUT );

SaberSerial.begin( SABER_BAUDRATE );

// 2 second time delay for the Sabertooth to init
delay( 2000 );
// Send full stop command
setEngineSpeed( SABER_ALL_STOP );
}

void loop ()
{
}

void setEngineSpeed( signed char cNewMotorSpeed )
{
unsigned char cSpeedVal_Motor1 = 0;

unsigned char cSpeedVal_Motor2 = 0;

// Check for full stop command
if( cNewMotorSpeed == 0 )
{
// Send full stop command for both motors
SaberSerial.print(0);

return;
}
}

You have not provided a link to the datasheet for the Sabertooth so that we can see the commands it expects.

The values in your #defines are byte values (0-255) but the variable in setEngineSpeed() is a char (-128 to + 127).

...R

Hi!:slight_smile:

For the sabertooth, it can be controlled by sending a character (1-127 is motor1 and 128-255 motor2, where 1 is full reverse and 127 is full forward).

I have modified the code and now it works well now. However, when I add a receiver code, then it cant work as before, do you know what's wrong?

My code that works is:

#include <SoftwareSerial.h>

#define SABER_TX_PIN 1

// NOT USED (but still init'd)
#define SABER_RX_PIN 12

// Set to 38400 through Sabertooth dip switches
#define SABER_BAUDRATE 38400

// Simplified serial Limits for each motor
#define SABER_MOTOR1_FULL_FORWARD 127
#define SABER_MOTOR1_FULL_REVERSE 1
#define SABER_MOTOR1_FULL_STOP 64

#define SABER_MOTOR2_FULL_FORWARD 255
#define SABER_MOTOR2_FULL_REVERSE 128
#define SABER_MOTOR2_FULL_STOP 192

// Motor level to send when issuing the full stop command
#define SABER_ALL_STOP 0

SoftwareSerial SaberSerial = SoftwareSerial( SABER_RX_PIN, SABER_TX_PIN );

void setup()
{

pinMode( SABER_TX_PIN, OUTPUT );

SaberSerial.begin( SABER_BAUDRATE );

// 2 second time delay for the Sabertooth to init
delay( 2000 );
}

void loop ()
{
setEngineSpeed(550);
}

void setEngineSpeed( signed int a )
{
int motorspeed1;
int motorspeed2;
//char cSpeedVal_Motor1 = char(a);

motorspeed1 = map(a, 1023, 0, 127, 1);
motorspeed2 = map(a, 1023, 0, 255, 128);

//convert the int to char which later is sent to the motor driver
char cSpeedVal_Motor1 = char(motorspeed1);
char cSpeedVal_Motor2 = char(motorspeed2);

SaberSerial.print(cSpeedVal_Motor1);
SaberSerial.print(cSpeedVal_Motor2);

return;
}

and this one, can't work

#include <VirtualWire.h>
#include <SoftwareSerial.h>

#define saber_Tx_Pin 1
#define saber_Rx_Pin 12
#define saber_Baudrate 38400

//definition of the motor

#define saber_Motor1_FullForward 96
#define saber_Motor1_Stop 64
#define saber_Motor1_FullReverse 32
#define saber_Motor2_FullForward 223
#define saber_Motor2_Stop 192
#define saber_Motor2_FullReverse 159

#define saber_Stop 0

//definition of receiver
int ledPin = 13;
char Ychar[5]; //y-coordinate for sabertooth input
char Xchar[5]; //x-coordinate for sabertooth input
char XYchar[10];

String xx, yy;

SoftwareSerial SaberSerial = SoftwareSerial (saber_Rx_Pin, saber_Tx_Pin);

void initSabertooth()
{
char stop1 = 64;
char stop2 = 192;

pinMode(saber_Tx_Pin, OUTPUT);
SaberSerial.begin (saber_Baudrate);
SaberSerial.print (stop1);
SaberSerial.print (stop2);
delay (2000);
}

void setup ()
{
initSabertooth();

vw_setup(2000);
vw_set_rx_pin(7);
vw_rx_start();
}

void loop ()
{
//receiver code
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

if(vw_get_message(buf, &buflen))
{
int i;
digitalWrite(ledPin, HIGH);

for(i = 0; i < buflen; i++)
{
XYchar = char(buf*);*
* XYchar[buflen] = '\0';*
* String xy = String(XYchar);*
* if(xy.indexOf(",")>=0)*
* {*
* xx = xy.substring(0,(xy.indexOf(",")));*
* yy = xy.substring(xy.indexOf(",")+1);*
* xx.toCharArray(Xchar, xx.length()+1);*
* yy.toCharArray(Ychar, yy.length()+1);*
* }*
* }*
* }*

* int x = atoi(Xchar);*
* int y = atoi(Ychar);*
* delay(200);*
* //motor coding, x and y are the joystick coordinates*
* if (x == 499 && y == 499)*
* {*
* char stop1 = 64;*
* char stop2 = 192;*
* SaberSerial.print (stop1);*
* SaberSerial.print (stop2);*

* }*
* else if (x == 499 && y != 499)*
* {*
* motorStraight (y);*
* }*

* digitalWrite(ledPin, LOW);*
* delay (100); *
}
void motorStraight (signed int a)
{
* int motorspeed1;*
* int motorspeed2;*
* motorspeed1 = map(a, 1023, 0, 127, 1);*
* motorspeed2 = map(a, 1023, 0, 255, 128);*

//convert the int to char which later is sent to the motor driver
* char cSpeedVal_Motor1 = char(motorspeed1);
char cSpeedVal_Motor2 = char(motorspeed2);*

* SaberSerial.print(cSpeedVal_Motor1);
SaberSerial.print(cSpeedVal_Motor2);
_
return;_
_
}*_

Please take the trouble to post code properly using code tags so it looks like this

Yours is the second time today that I have discovered that the code is really two completely separate programs.

Please modify your post to make it easier to read.

I am much too lazy to try to look for differences between them. You tell me what changes you made and what results you get with the revised program and I will have another look at it.

...R

Hi, Robin, so sorry for the confusing parts.

void loop ()
{   
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  if(vw_get_message(buf, &buflen))
  {
    int i;
    digitalWrite(ledPin, HIGH);
    
    for(i = 0; i < buflen; i++)
    {
      XYchar[i] = char(buf[i]);
      XYchar[buflen] = '\0';
      String xy = String(XYchar);
      if(xy.indexOf(",")>=0)
      {
        xx = xy.substring(0,(xy.indexOf(",")));
        yy = xy.substring(xy.indexOf(",")+1);
        xx.toCharArray(Xchar, xx.length()+1);
        yy.toCharArray(Ychar, yy.length()+1);
      }
    }
  }
  
  int xtemp=atoi(Xchar);
  int ytemp=atoi(Ychar);
  int x=constrain(xtemp, 1, 1023);
  int y=constrain(ytemp, 1, 1023);
  

   if(y==1)
{ 
    setEngineSpeed(550);
}
    
    delay(100);
}[code]

[/code]

what happened is that the motor is always running when my condition is this

if(y==1)
{ 
    setEngineSpeed(550);
}

meaning that the y stays 1 forever, regardless I move the joystick. However, when I check the value of y and x using serial.print command, the values changed according to the joystick. do you know what's wrong? How to keep updating the value of x and y? Thanks!:slight_smile:

However, when I check the value of y and x using serial.print command, the values changed according to the joystick

Post the code with those print statements in it. Also, post a complete compilable program.

...R

Hi, Robin,

I have developed a bit further, that now I know it is not because x and y is not updated, but i think it is due to the inconsistent loop timing (i.e. i have the ledpin13 on at the beginning of the loop, and ledpin13 off at the and of the loop. I assumed it should blink consistently with regular time spacing. But, turned out, it seems to blink randomly without pattern). Sometimes it stops for 3-4 sec, then starts blinking again. Help... Thank you..

here is my full compilable code

#include <SoftwareSerial.h>
#include <VirtualWire.h>

int ledPin = 13;
char Ychar[5];  //y-coordinate for sabertooth input
char Xchar[5];  //x-coordinate for sabertooth input
char XYchar[10];

String xx, yy;

// Labels for use with the Sabertooth 2x5 motor controller

// Digital pin 13 is the serial transmit pin to the 
// Sabertooth 2x60
#define SABER_TX_PIN 1

#define SABER_RX_PIN 12

// Set to 38400 through Sabertooth dip switches
#define SABER_BAUDRATE 38400

SoftwareSerial SaberSerial = SoftwareSerial( SABER_RX_PIN, SABER_TX_PIN );

void setup()
{
  pinMode( SABER_TX_PIN, OUTPUT );

  SaberSerial.begin( SABER_BAUDRATE ); 

 // 2 second time delay for the Sabertooth to init
  delay( 2000 );
 
  //Serial.begin(38400);
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);

  vw_setup(2000);
  vw_set_rx_pin(7);
  vw_rx_start();
}


void loop ()
{   
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  if(vw_get_message(buf, &buflen))
  {
    int i;
    digitalWrite(ledPin, HIGH);
    
    for(i = 0; i < buflen; i++)
    {
      XYchar[i] = char(buf[i]);
      XYchar[buflen] = '\0';
      String xy = String(XYchar);
      if(xy.indexOf(",")>=0)
      {
        xx = xy.substring(0,(xy.indexOf(",")));
        yy = xy.substring(xy.indexOf(",")+1);
        xx.toCharArray(Xchar, xx.length()+1);
        yy.toCharArray(Ychar, yy.length()+1);
      }
    }
  }
  
  int xtemp=atoi(Xchar);
  int ytemp=atoi(Ychar);
  int x=constrain(xtemp, 448, 550);
  int y=constrain(ytemp, 448, 550);
  
    
  char stop1=64;
  char stop2=192;
  
  if (y>496 && y<501 && x>496 && x<501)//STOP y 497-500 x 497-500//
  {
    SaberSerial.print(stop1);
    SaberSerial.print(stop2);
    delay(100);
  }
  else if(y<497 && x>496 && x<501)//REVERSE y 496-0//
  {
    straight(y);
  }
  else if(y>500 && x>496 && x<501)//FORWARD y501-1023//
  {
    straight(y);
  }
  else if(x<497 && y>496 && y<501)//RIGHT x 496-0//
  { 
    right(x);
  }
  else if(x>500 && y>496 && y<501)//RIGHT x 501-1023//
  { 
    left(x);
  }
  else
  {
    combine(x,y);
  }
  
  digitalWrite(ledPin, LOW);
  delay(100);
}


void straight( signed int a )
{
  int motorspeed1;
  int motorspeed2;

  motorspeed1 = map(a, 1023, 1, 127, 1);
  motorspeed2 = map(a, 1023, 1, 255, 128);
 
  char cSpeedVal_Motor1 = char(motorspeed1);
  char cSpeedVal_Motor2 = char(motorspeed2);
   
  SaberSerial.print(cSpeedVal_Motor1);
  SaberSerial.print(cSpeedVal_Motor2);
   
  delay(100);
  return;
}

void right( signed int a )
{
  int motorspeed1;

  motorspeed1 = map(a, 499, 1, 64, 127);
  
  char cSpeedVal_Motor1 = char(motorspeed1);
   
  SaberSerial.print(cSpeedVal_Motor1);
   
  delay(100);
  return;
}

void left( signed int a )
{
  int motorspeed2;

  motorspeed2 = map(a, 499, 1023, 192, 255);
    
  char cSpeedVal_Motor2 = char(motorspeed2);
   
  SaberSerial.print(cSpeedVal_Motor2);
   
  delay(100);
  return;
}


void combine( signed int dir, signed int spee )
{
  int motorint1;
  int motorint2;
  char final1;
  char final2;
  
  //forward
  if (spee>500)
  {
    if(dir>500)//left --> 1 less than 2
    {
      motorint1 = map(dir, 499, 1023, 64, 110);
      motorint2 = map(spee, 499, 1023, 192, 255);
      final1 = char(motorint1);
      final2 = char(motorint2);
    }
    else if(dir<497)//right --> 2 less than 1
    {
      motorint1 = map(spee, 499, 1023, 64, 127);
      motorint2 = map(dir, 499, 1, 192, 238);
      final1 = char(motorint1);
      final2 = char(motorint2);
    }
  }
  //reverse
  else if (spee<497)
  {
    if(dir>501)//left --> 1 less than 2
    {
      motorint1 = map(dir, 499, 1023, 64, 18);
      motorint2 = map(spee, 499, 1, 192, 128);
      final1 = char(motorint1);
      final2 = char(motorint2);
    }
    else if(dir<497)//right --> 2 less than 1
    {
      motorint1 = map(spee, 499, 1, 64, 1);
      motorint2 = map(dir, 499, 1, 192, 146);
      final1 = char(motorint1);
      final2 = char(motorint2);
    }
  }
  
  SaberSerial.print(final1);
  SaberSerial.print(final2);
  
  delay(100);
  return;
}

The previous code had a function setEngineSpeed() which seems to have disappeared and I am lost.

You need to write a plain language explanation of how the code is supposed to work as I am too lazy to try to reverse-engineer it.

...R

Hi,

the setEngineSpeed() function is replaced by these straight(y), right(y), left(y), at each conditional statement like this (they are the same function)

if (y>496 && y<501 && x>496 && x<501)//STOP y 497-500 x 497-500//
  {
    SaberSerial.print(stop1);
    SaberSerial.print(stop2);
    delay(100);
  }
  else if(y<497 && x>496 && x<501)//REVERSE y 496-0//
  {
    straight(y);
  }
  else if(y>500 && x>496 && x<501)//FORWARD y501-1023//
  {
    straight(y);
  }
  else if(x<497 && y>496 && y<501)//RIGHT x 496-0//
  { 
    right(x);
  }
  else if(x>500 && y>496 && y<501)//RIGHT x 501-1023//
  { 
    left(x);
  }
  else
  {
    combine(x,y);
  }

so, for the looping parts, the receiver will get x and y value. then, we will check the x and y using that if condition, which then determine how the motor move. then, it will get the x y value again, and so on. the problem is, the x y value data taking from the receiver is not consistent (not responsive).

Grace3211:
the setEngineSpeed() function is replaced by these straight(y), right(y), left(y), at each conditional statement like this (they are the same function)

I don't think you could reasonably have expected me to figure that out ? ? ?

You know how the code is supposed to work and I don't.

You need to write a little essay that describes in plain language what all the different parts of the program are supposed to do.

...R