Arduino, Data logging, and PS2

Hi All,

I've read through other posts and have researched elsewhere but do not seem to be able to resolve an approach to the project I have... which is this:

I have built a omni-directional robot using four mecanum wheels. I would like to:

  • control the robot remotely ( through RC, PS2 controller, or bluetooth )
  • record the actions
  • be able to edit the actions slightly as necessary ( such as slowing things down or adjusting movements )
  • playback these edited actions as a program.

I have the robot working in a very basic way. It currently uses an arduino which is sending our serial to two sabertooth drivers ( 2x25 ).

I have tried connecting a PS2 controller using Bill Porter's library ( thanks Bill ). I've had it working with other projects I may with my kids but it seems to run into problems with this one. ( likely because of the serial going to the sabertooth. )

My research into data logging onto an SD Card seems to point toward recording of the serial print in the form of txt. I'd be interested in recording the actions that can easily be edited to written back into a program of actions.

QUESTIONS:

Does anyone have suggestions on how to wirelessly/RC control, record, edit and playback?
What would be a suggested combinations of hardware and software?
Would RC be better? Maybe XBee?
Is an Arduino suitable for this?
Is what I am looking to do feasible?

I appreciate the feedback.

Is what I am looking to do feasible?

YES

Is an Arduino suitable for this?

YES

What would be a suggested combinations of hardware and software?
Would RC be better? Maybe XBee?

everything would work, you need to think more in terms of communication speed needs. BT can be fine.

Does anyone have suggestions on how to wirelessly/RC control, record, edit and playback?

I would probably start with a Processing program on a computer to remote collect the information and a simple process to send back commands to the robot. if you opt for a simple human readable text format, the editing can be done "manually" in a text editor and be sent back to be parsed and executed by the robot.

you would need to write a command language that is not too verbose like

S = stop
R = turn Right
L = turn Left
F = forward
B = Backward

and possibly passing timing, angle, or other metrics like
F10R30S would mean forward 10 seconds or 10 whatever you want, Turn Right 30 degrees or during 30 seconds etc and Stop... you decide the language to meet your needs; keep it compact so that it does not clutter too much of your arduino's memory

if you want ideas for moving something around, You could look at the basic commands of the LOGO language (an interpreter is here) which is probably way too much for what you have in mind but a cool idea :slight_smile:

Thanks JML, this is helpful.

Maybe I could have the action commands themselves also sent as serial print lines ( including necessary syntax). This could be copied back into a new program without much editing.

One issue I am running into before I can get to recording actions is communicating with the robot itself. I currently have it set to use TLL serial to run the sabertooth drivers ( through packet serial ).

When trying to use a PS2 wireless controller I run into all sort of issues. ( I’ve had the PS2 working fine on other projects ). Any suggestions on what might cause that interference ( I assume the serial ) and how I might resolve it?

I could go with RC directly to the sabertooth but ideally I’d like to work through the arduino as that is what would run the robot afterwards.

I’ve attached the current PS2 / Mecanum serial code I have. Both work fine independently. Things get messy when combining the two.

// Shared Line Sample for Packet Serial
// Copyright (c) 2012 Dimension Engineering LLC
// See license.txt for license details.

#include <Sabertooth.h>  // Up to 8 Sabertooth/SyRen motor drivers can share the same S1 line.
#include <PS2X_lib.h>  //for v1.6 // this brings up library which works in background

Sabertooth ST1(128); // Sabertooth with address 128
Sabertooth ST2(129); // Sabertooth with address 129
PS2X ps2x; // create PS2 Controller Class

//right now, the library does NOT support hot pluggable controllers, meaning 
//you must always either restart your Arduino after you conect the controller, 
//or call config_gamepad(pins) again after connecting the controller.

byte vibrate = 0;


void setup()
{

 SabertoothTXPinSerial.begin(9600);
 // Sabertooth::autobaud(SabertoothTXPinSerial); // Autobaud is for the whole serial line -- you don't need to do
                                               // it for each individual motor driver. This is the version of
                                                // the autobaud command that is not tied to a particular
                                               // Sabertooth object.
                                               // See the examples in 1.Basics for information on whether you
                                               // need this line at all.
 
 pinMode(12, OUTPUT); // Vcc source to PS2 reciever
 pinMode(13, OUTPUT); // GND source to PS2 reciever
 
 digitalWrite(12, HIGH); // Vcc
 digitalWrite(13, LOW); // GND
 
 ps2x.config_gamepad(11,9,10,8, true, true);   //setup pins and settings:  GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error

}

void loop()
{
    int power;

    
     ps2x.read_gamepad(false, vibrate);          //read controller and set large motor to spin at 'vibrate' speed
    if(ps2x.Button(PSB_START))                   //will be TRUE as long as button is pressed      
    if(ps2x.Button(PSB_SELECT))
        
    if(ps2x.Button(PSB_PAD_UP)) {         //will be TRUE as long as button is pressed
               ST2.drive(20);
               ST1.turn(0);
               ST2.drive(20);
               ST2.turn(0);
         }
         
    if(ps2x.Button(PSB_PAD_RIGHT)){
               ST1.drive(-20);
               ST2.turn(0);
               ST2.drive(-20);
               ST2.turn(0);
         }
         
   if(ps2x.Button(PSB_PAD_LEFT)){
      
         for (power = -45; power <= 45; power ++){
              ST1.motor(1, power);
              ST1.motor(2, power);
              ST2.motor(1, power);
              ST2.motor(2, power);
              delay(20);
          }// end of for
      } // end of if
      
   if(ps2x.Button(PSB_PAD_DOWN)){
    
         for (power = -25; power <= 0; power ++){
              ST1.motor(1, power);
              ST1.motor(2, power);
              ST2.motor(1, power);
              ST2.motor(2, power);
              delay(120);
           }// end of for
      }  //end of if

  if(ps2x.ButtonPressed(PSB_RED)) {    //will be TRUE if button was JUST pressed     
              ST1.motor(1, 0);
              ST1.motor(2, 0);
              ST2.motor(1, 0);
              ST2.motor(2, 0);
      } // end of if
  
} // end of loop

how are things wired and powered?

There is a 12v battery that powers the sabertooth drivers.

The ardunio is then powered by the sabertooth’s 5vdc and GND out.

The PS2 receiver has a board with six pins and are set in the following order:

DATA = Pin 19
CMD = Pin 18
ATT = Pin 17
CLK = Pin 16
5V = Pin 15
GND = Pin 14

Sabertooth is run through serial ( S1 )… address 128 and address 129

I’ve simplified the code to test things out. The PS2 controller works fine until I include the motor commands such as – ST1.motor(1, 40); – then things get a little crazy. I’ve attached the simplified code. If I commend out the motor commands everything works fine.

// Shared Line Sample for Packet Serial
// Copyright (c) 2012 Dimension Engineering LLC
// See license.txt for license details.

#include <Sabertooth.h>  // Up to 8 Sabertooth/SyRen motor drivers can share the same S1 line.
Sabertooth ST1(128); // Sabertooth with address 128
Sabertooth ST2(129); // Sabertooth with address 129

#include <PS2X_lib.h>  //for v1.6 // this brings up library which works in background
PS2X ps2x; // create PS2 Controller Class

//right now, the library does NOT support hot pluggable controllers, meaning 
//you must always either restart your Arduino after you conect the controller, 
//or call config_gamepad(pins) again after connecting the controller.

byte vibrate = 0;


void setup()
{
 Serial.begin(57600);
 SabertoothTXPinSerial.begin(57600);
 Sabertooth::autobaud(SabertoothTXPinSerial); // Autobaud is for the whole serial line -- you don't need to do
                                               // it for each individual motor driver. This is the version of
                                                // the autobaud command that is not tied to a particular
                                               // Sabertooth object.
                                               // See the examples in 1.Basics for information on whether you
                                               // need this line at all.
 
 pinMode(15, OUTPUT); // Vcc source to PS2 reciever
 pinMode(14, OUTPUT); // GND source to PS2 reciever
 
 digitalWrite(15, HIGH); // Vcc
 digitalWrite(14, LOW); // GND

  
 ps2x.config_gamepad(16,18,17,19, true, true);   //setup pins and settings:  GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error
 
}
void loop()
{
  
    ps2x.read_gamepad(false, vibrate);          //read controller and set large motor to spin at 'vibrate' speed
    
    if(ps2x.Button(PSB_START))                   //will be TRUE as long as button is pressed
         Serial.println("Start is being held");
    if(ps2x.Button(PSB_SELECT))
         Serial.println("Select is being held");
            
   if(ps2x.Button(PSB_L2)) {
        Serial.println("SHAFE LEFT2"); 
              ST1.motor(1, 40);
              ST1.motor(2, 40);
              ST2.motor(1, 40);
              ST2.motor(2, 40);
        }else{
              ST1.motor(1, 00);
              ST1.motor(2, 00);
              ST2.motor(1, 00);
              ST2.motor(2, 00);
        }
}

Where is Serial connected? The transmit line from the arduino needs to be connected to S1

And your dip set for simplified serial, right? (DIP switches 1 is ON and 2 is OFF)

Try 9600 baud (DIP switch 4 OFF and 5 should be ON) and modify SabertoothTXPinSerial.begin(57600); accordingly

--> ON OFF ON OFF ON OFF for your DIP switches (switch 3 assuming your are not using lithium )

Sabertooth controls two motors with one 8 byte character, when operating in Simplified Serial mode, each motor has 7 bits of resolution. Sending a character between 1 and 127 will control motor 1. 1 is full reverse, 64 is stop and 127 is full forward. Sending a character between 128 and 255 will control motor 2. 128 is full reverse, 192 is stop and 255 is full forward. Character 0 (hex 0x00) is a special case. Sending this character will shut down both motors.

I would verify this works first before doing anything else

The arduino is communicating with the two sabertooth controllers from pin1 / TX to S1 on each of the two sabertooth controller ( both 2x25 ). It is communicating in packet serial. The address are 128 and 129. And the DIP have been set correctly... OFF/OFF/ON/ON/ON/ON for 128 and OFF/OFF/ON/OFF/ON/ON for 129.

I have send direct commands [ such as ST1.motor(1, 127); or ST1.drive(30); ] and things work. Things are wired correctly. The issue come when introducing the PS2 programming into the mix.

Both the PS2 and Sabertooth programs will work independently. I believe there is a problem with competing serial information when combining the two but I don't know where that conflict is.

The problems shows up in the serial monitor ( random character and noise ) and while the robot will make movements it reflects what looks like serial noise.

I could switch to RC control to take the PS2 issue out but I do want to record the actions through an SD shield to edit and playback later. I would need an arduino in the mix somewhere and would prefer to stick with the PS2 controller. I think the PS3 controller can work on bluetooth. I'm not sure if these would make a different.

If none of these work I would also switch to an analog output to the Sabertooth but this isn't ideal.

So you have 2 wires going out of pin 1 to 2 different sabertooth controller?

You don’t have PS2X_COM_DEBUG or PS2X_DEBUG defined in your PS2 library set? (that is sending printing to the Serial line)

the library defines which port to use with this:

#if defined(USBCON)
#define SabertoothTXPinSerial Serial1 // Arduino Leonardo has TX->1 on Serial1, not Serial.
#else
#define SabertoothTXPinSerial Serial
#endif
#define SyRenTXPinSerial SabertoothTXPinSerial

Do you have an Arduino Mega (looks like it)? I would be tempted to move SabertoothTXPinSerial to Serial3 for example → pin 14 (TX) just to see if there is any conflict with standard serial

#if defined(USBCON)
#define SabertoothTXPinSerial Serial1 // Arduino Leonardo has TX->1 on Serial1, not Serial.
#else
#define SabertoothTXPinSerial Serial3 // CHANGED FOR TESTING
#endif
#define SyRenTXPinSerial SabertoothTXPinSerial

Thanks for this.

I have things are connected to an UNO. It's one wire going to the two Sabertooth Controllers. TX to Sabertooth1 S1 and Sabertooth1 S1 to Sabertooth2 S1. Their addressed different ( 128 and 129 ) and it sends out Packet Serial. When not using the PS2 controller there is no issue in communication between the UNO and two Sabertooth. I know that the Packet Serial works and that things are wired correctly.

As far as the PS2, I have this configured correctly as I've tested it with other things on the same Arduino be make sure ( such as turning LEDs on/off etc. )

I believe everything is wired and configured properly because they do work when isolated. It is really only when combining the two sets of code that issues arise.

I have gone into the PS2 library to remove the commented out DEBUG. It doesn't make a difference.

Maybe I should try a PS3 controller using bluetooth instead of the wireless of the PS2??