Go Down

Topic: Sabertooth 2X60A with Arduino Uno (Read 2461 times) previous topic - next topic

Grace3211

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: http://forums.trossenrobotics.com/showthread.php?3636-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!! :)


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;
 }
}


Robin2

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
Two or three hours spent thinking and reading documentation solves most programming problems.

Grace3211

Hi!:)

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;
}

Robin2

Please take the trouble to post code properly using code tags
Code: [Select]
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
Two or three hours spent thinking and reading documentation solves most programming problems.

Grace3211

#4
Nov 03, 2014, 08:18 am Last Edit: Nov 03, 2014, 08:40 am by Grace3211
Hi, Robin, so sorry for the confusing parts.

Code: [Select]
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

Code: [Select]
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!:)

Robin2

Quote
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
Two or three hours spent thinking and reading documentation solves most programming problems.

Grace3211

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

Code: [Select]
#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;
}







Robin2

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
Two or three hours spent thinking and reading documentation solves most programming problems.

Grace3211

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)

Code: [Select]
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).

Robin2

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
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up