Arduino Duemilanove and Sabertooth 25A dual motor

Hi everyone,

Please help me with the Sabertooth 25A dual motors controller board. I'am trying to hook up with the Arduino Duemilanvoe microcontroller board powered by ATmega328. Problem is:
what port should the Sabertooth signal line go on to Arduibo board. I tried with PWM ports and Analog ports but neither of them worked
I'll appreaciated with your help

Austin

I tried to hook on port PWM of the Arduino with 10K ohms resister filter and used the following command code:

#define SABER_TX_PIN = 13
#define SABER_BAUDRATE 9600
void setup()
{
pinMode ( SABER_TX_PIN, OUTPUT );
}
void loop()
{
analogWrite(SABER_TX_PIN, 40);
delay (2000);
}

I just tried to test but tt failed. Please give an advice.

Per the below you should easily be able to operate it as a servo or in other modes.

ok thanks. i'll try to filter it.

I tried with the filter(resister + .1uf cap.) with the following codes, but know works

void setup()
{
pinMode (10,OUTPUT );
Serial.begin(9600);
}
void loop() {
analogWrite (10,100);
delay (2000);
}
Can some expert give me advises? I'm really headache. spent alot of $$ on this project

NOOO It Didn't work

but i don't know what other method :frowning:

thanks Richard for your consulting

I actually worked with this motor controller but with an msp430 based system. I used the packeted serial mode which can be accomplished like so:

switches:
1 off
2 off
3 on
4 on
5 on
6 on
(this sets the address of the motor controller to 128)

void setup() {
Serial.begin(9600);
Serial.print('x'); //auto bauding character must be sent before anything else
}

now to issue commands to control the motor something like this can be used:
send_packet(char address, char command, char data) {
Serial.print(address);
Serial.print(command);
Serial.print(data);
Serial.print( (address + command + data) & 127 );
}

the commands are listed in this pdf under the packeted serial section: http://www.dimensionengineering.com/datasheets/Sabertooth2x25.pdf

One extra thing when I was using this controller there was a very particular way to power it up. This consisted of first powering the msp430(arduino in this case) then powering the motor controller. The program then had to either wait for a button press or have a set delay before sending the bauding character. I don't know if this applies on the arduino but during power up the pin state would randomly fluctuate causing a bauding error to occur.

Connect the motor controller board to the arduino just like one would do for a servo (refer to the previously posted quick start link). Load the below code into the arduino (note that it uses the WString.h library). Then using the arduino serial monitor, send the desired timing values to the arduino, which will set the proper pulse rate to send to the motor controller.

//zoomkat 7-30-10 serial servo test
//type servo position 0 to 180 in serial monitor
//for writeMicroseconds, use a value like 1500

#include <WString.h> //provides easy string handling
String readString = String(100);
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
      Serial.begin(9600);
        myservo.attach(9);
        }

void loop() {

        while (Serial.available()) {
        delay(10);  
          if (Serial.available() >0) {
        char c = Serial.read();  //gets one byte from serial buffer
        readString.append(c); } //makes the string readString
        }
        
      if (readString.length() >0) {
      Serial.println(readString);
      int n;
      n = atoi(readString); //convert string to number
      myservo.writeMicroseconds(n);
      //myservo.write(n);
      readString="";
      } 
   }

Wow, The first time i see the codes of Packetized Serial control method. It is complicated for me, i don't know where to command for speed.
as with mdmetzle code: what are data, command mean even i compared with the Sabertooth datasheet and modified the numbers as:
void setup() {
Serial.begin(9600);
Serial.print('13'); //pin 13 as an input port
}

void loop()
{send_packet();
delay();}

void send_packet(char address, char command, char data) {
Serial.print(130);
Serial.print(0);
Serial.print(100);
Serial.print( (130 + 0 + 100) & 0b01111111 );
}
RESULT--->In function 'void loop()':
error: too few arguments to function 'void send_packet(char, char, char)'

As with zoomkat direction
RESULT ---->
53: error: WString.h: No such file or directory In function 'void loop()':
Bad error line: -3

In the past, i have a year experience in Analog controlling method. simply, i just used to command move(motor1,+/-speed). it worked. I am fine with controlling small volt motors, but high Amps motor (big) needs motor controller and that is my current problem.

Thanks for sharing your codes

As with zoomkat direction
RESULT ---->
53: error: WString.h: No such file or directory In function 'void loop()':
Bad error line: -3

The WString.h library is found below, along with some "how to" info.

http://www.arduino.cc/en/Tutorial/TextString

Where can i set the speed though

Where can i set the speed though

Well, if you use the sketch I provided, you put a value between 1000 and 2000 in the serial monitor box and click send or hit the enter key. That timing value will be used to control the motor controller. The below is from page 13 of the pdf owner's manual, which you should look at for appropriate dip switch settings.

If switch 6 is set in the DOWN position, then Microcontroller mode is enabled. This disables the Timeout Failsafe and auto-calibration. This means that the Sabertooth will continue to drive the motor according to the last command until another command is given. If the control link is possible unreliable – like a radio - then this can be dangerous due to the robot not stopping. However, it is extremely convenient if you are controlling the Sabertooth from a microcontroller.

In this case, commanding the controller can be done with as little as three lines of code.
Output_High(Pin connected to S1)
Delay(1000us to 2000us)
Output_Low(Pin connected to S1)

I'll try to see if it work. thanks

Hey Austin,

Try this, it should work real fine:

Connection:

pulsing arduino digital pin 9 to S1 and GND ( arduino) to 0V = to control motor 1
pulsing arduino digital pin 10 to S2 and GND ( arduino) to 0V = to control motor 2

My code for motor 1 to go forward:

#include

Servo myservo;

void setup()
{
myservo.attach(9);
myservo.write(180); // with 0 being full-speed in one direction, 180 being full speed in the other, and a value near 90 being no movement
}

void loop() {}

This would be the easiest way to control your motor via sabertooth through the Arduino

Please feedback of your results.. so I can help :slight_smile:

Regards!

I'm working on this as well. I have an arduino Mega and a 2x10, but essentially the same thing.

I first tried the PWM, I built the RC filter and all and I just got stutters. Frustrated, but I expected it. They recommend a PWM of 1000Hz or higher and the arduino's PWM is only 490 Hz.

I was glad to read about the serial interface, that would work just fine for me but I'm having difficulty getting it to run, and I saw here how simple the servo control was. My system is not working, I have pins 1, 4, and 6 down

This is my snippet:

#include <HMC.h>
#include <Servo.h>
Servo myservo;
int LeftSpeed=0;
void setup()
{
  myservo.attach(7);
  Serial.begin(9600);
  delay(5000); // The HMC5843 needs 5ms, motor controller needs 2000, play it safe and wait for 5000.
  HMC.init();
}
 
void loop()
{
  int x,y,z;
  delay(100); // There will be new values every 100ms
  HMC.getValues(&x,&y,&z);
  if ((x<-100||x>100)&&y<200){
    LeftSpeed=180;
  }else {
    LeftSpeed=90;
  }
  Serial.print("x:");
  Serial.print(x);
  Serial.print(" y:");
  Serial.print(y);
  Serial.print(" z:");
  Serial.println(z);
  Serial.print("Left Motor Speed:");
  Serial.println(LeftSpeed);
  myservo.write(LeftSpeed);
}

HMC is a magnetometer. This is just a feature demonstration I'm trying to create by friday. I want the bot to basically turn to north, and if we pick it up and turn it, it will turn back to north. Don't worry about the magnetometer code, using the serial output and moving the compass by hand I have verified that it works like a charm.

Am I missing something with the servo spoofing for this setup? My motors just run. Continuously. The moment the battery switch gets thrown, boom it starts moving and nothing seems to faze it.

I plan on adding the right motor in eventually too, but that's simple once I figure out why the left motor isn't working as expected.

and while moving the magnetometer around monitoring the serial output I see that the value of LeftSpeed does in fact change appropriately, but it does not seem to affect the actual motor...

I assume that you are using simplified serial mode on the saber?

Try this code: edit it to fit your need; in the void loop function:

#include <SoftwareSerial.h>

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

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

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

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

// 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 initSabertooth( void )
{
// Init software UART to communicate
// with the Sabertooth 2x5
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 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, BYTE );

return;
}

// Calculate the speed value for motor 1
if( cNewMotorSpeed >= 100 )
{
cSpeedVal_Motor1 = SABER_MOTOR1_FULL_FORWARD;

cSpeedVal_Motor2 = SABER_MOTOR2_FULL_FORWARD;
}
else if( cNewMotorSpeed <= -100 )
{
cSpeedVal_Motor1 = SABER_MOTOR1_FULL_REVERSE;

cSpeedVal_Motor2 = SABER_MOTOR2_FULL_REVERSE;
}
else
{
// Calc motor 1 speed (Final value ranges from 1 to 127)
cSpeedVal_Motor1 = map( cNewMotorSpeed,
-100,
100,
SABER_MOTOR1_FULL_REVERSE,
SABER_MOTOR1_FULL_FORWARD );

// Calc motor 2 speed (Final value ranges from 128 to 255)
cSpeedVal_Motor2 = map( cNewMotorSpeed,
-100,
100,
SABER_MOTOR2_FULL_REVERSE,
SABER_MOTOR2_FULL_FORWARD );
}

// Fire the values off to the Sabertooth motor controller
SaberSerial.print( cSpeedVal_Motor1, BYTE );
SaberSerial.print( cSpeedVal_Motor2, BYTE );
}

void setup( )
{
initSabertooth( );
}

//void control( )
//{
// // Full stop
// setEngineSpeed( 0 );
//
// // Half reverse
// setEngineSpeed( -50 );
//
// // Full reverse
// setEngineSpeed( -100 );
//
// // Half forward
// setEngineSpeed( 50 );
//
// // Full forward
// setEngineSpeed( 100 );
//}

void setEngineSpeedDir( signed char cNewMotorSpeedDir )
{
unsigned char cSpeedValDir_Motor1 = 0;

unsigned char cSpeedValDir_Motor2 = 0;

if( cNewMotorSpeedDir >= 100 )
{
cSpeedValDir_Motor1 = SABER_MOTOR1_FULL_FORWARD; // GO RIGHT

cSpeedValDir_Motor2 = SABER_MOTOR2_FULL_STOP;
}
else if( cNewMotorSpeedDir <= -100 )
{
cSpeedValDir_Motor1 = SABER_MOTOR1_FULL_STOP; // GO LEFT

cSpeedValDir_Motor2 = SABER_MOTOR2_FULL_FORWARD;
}
else
{
// Calc motor 1 speed (Final value ranges from 64 to 127)
cSpeedValDir_Motor1 = map( cNewMotorSpeedDir,
-100,
100,
SABER_MOTOR1_FULL_STOP,
SABER_MOTOR1_FULL_FORWARD );

// Calc motor 2 speed (Final value ranges from 192 to 255)
cSpeedValDir_Motor2 = map( cNewMotorSpeedDir,
-100,
100,
SABER_MOTOR2_FULL_FORWARD,
SABER_MOTOR2_FULL_STOP);
}

// Fire the values off to the Sabertooth motor controller
SaberSerial.print( cSpeedValDir_Motor1, BYTE );

SaberSerial.print( cSpeedValDir_Motor2, BYTE );
}

//void turn ( )
//{
// // Turn left
// setEngineSpeedDir( -100 );
//
// // Turn right
// setEngineSpeedDir( 100 );
//}

void loop()
{
setEngineSpeedDir( -100 );
delay( 5000 );
setEngineSpeed( 0 );
delay( 5000 );
setEngineSpeed( 50 );
delay( 5000 );
setEngineSpeed( 100 );
delay( 5000 );

// signed char traverse;
// signed char negotiate;
//
// if(Serial.available()>0)
// {
// int data = Serial.read();
//
//// digitalWrite(buttonPin,LOW);
//
// switch(data)
// {
// case'w':traverse = 100;break; //full forward
// case's':traverse = -50;break; // half reverse
// case'q':traverse = 0;break; // Stop
// case'a':negotiate = -100;break; // left
// case'd':negotiate = 100;break; // right
// }
//
// setEngineSpeed( traverse );
// setEngineSpeedDir( negotiate );
// }
}

I'm confused, do I really need a software serial library? the mega has 4 serial pins, but I couldn't get the serial communication to work at all. it seems like the servo control is a lot simpler, but that isn't exactly working either so who knows what's easier.

The strange thing is as I move the compass once it changes to an appropriate "north" reading and the serial output confirms that a speed change is supposed to take place the motor itself hiccups quickly but then it continues as if unchanged.

from the capabilities of the serial communication it looks like it might not work for me, my robot cannot stop and make turns, it has to keep going and make turns on the fly (i.e. just lowering the speed of one motor to make long sweeping turns). It moves at about 5 ft/s and will carry a load of about 100 lbs.