Help with Arduino Tank controlled by i phone

Hello,

Everyone ! I have some problem with my project which I hope to get some help from forum.

I was trying to build a tank controlled by i phone.
It was after I saw this link.
http://www.projectallusion.com/1/post/2009/11/iphone-controlled-solar-powered-arduino-tank.html

However, I do not want to buy sparkfun motor controller board. So, I just used H bridge.
Here is my plan…

I used Touch OSC to send OSC messages from i phone to computer. They both have connected to the same wifi. I have processing sketch running on
my computer. So, depending on the OSC messages, the processing send signals to Arduino using X bee, where Arduino controls two motors using the H bridge.

The problem I am having is that the left sides and the right sides do not get the same result. For example, side A does exactly what I intend to do.
But, side B does not do what I want. When I try to turn the motor, it keeps turning on and off all the time.
But, it do it so fast that I cannot see the motor actually stop. But, it is definitely slower than the other one.
I know it because I used oscilloscope to check the voltage while I make the motor run.
The code I use is from the above website. I just modified it so that it can work with H bridge.

If anyone can give any suggestion to fix it, I would really more than appreciate it.

The following are my arduino code and processing code…

//-----------Start Arduino code ---------------


 
// To use, connect the Arduino to a computer and send commands using a serial terminal.
// eg AR40#   motor A forwards with a speed of 40
 
#define MotorAlogicone 10
#define MotorAlogictwo 11
#define MotorBlogicone 12
#define MotorBlogictwo 13
#define SerialSpeed 9600
#define BufferLength 16
#define LineEnd '#'
#define enablePin 9 // Pin for H bridge pin 1
#define enablePintwo 8  // Pin for H bridge pin 9 
 
char inputBuffer[BufferLength];
 
void setup()
{
  // motor pins must be outputs
  pinMode(MotorAlogicone, OUTPUT);
  pinMode(MotorAlogictwo, OUTPUT);
  pinMode(MotorBlogicone, OUTPUT);
  pinMode(MotorBlogictwo, OUTPUT);
 pinMode(enablePin, OUTPUT);
 pinMode(enablePintwo, OUTPUT);
 digitalWrite(enablePin, HIGH);
 digitalWrite(enablePintwo, HIGH);


  Serial.begin(SerialSpeed); 
}
 
//if you think about it, input here is the inputbuffer from void function
// process a command string
void HandleCommand(char* input, int length)
{
  Serial.println(input);

 





  int* command = (int*)input;
  // check commands
  // note that the two bytes are swapped, ie 'RA' means command AR
  switch(*command) {
    case 'FA':
      // motor A forwards
     digitalWrite (MotorAlogicone, LOW);
     digitalWrite(MotorAlogictwo, HIGH);
      break;

    case 'RA':
      // motor A reverse
     digitalWrite (MotorAlogicone, HIGH);
     digitalWrite(MotorAlogictwo, LOW);
      break;

    case 'FB':
      // motor B forwards
     digitalWrite (MotorBlogicone, LOW);
     digitalWrite(MotorBlogictwo, HIGH);
  break;

    case 'RB':
      // motor B reverse
     digitalWrite (MotorBlogicone, HIGH);
     digitalWrite(MotorBlogictwo, LOW);  
    break;

    case 'SA':       
      // Stop motor A
     digitalWrite (MotorAlogicone, LOW);
     digitalWrite(MotorAlogictwo, LOW);  
    case 'SB':
      // stop motor B
     digitalWrite (MotorBlogicone, LOW);
     digitalWrite(MotorBlogictwo, LOW);  


    default:
      break;
  }  
} 
 


void loop()
{ 
  // get a command string form the serial port
  int inputLength = 0;
  do {
    while (!Serial.available())
; // wait for input
   inputBuffer[inputLength] = Serial.read(); // read it in
  } while (inputBuffer[inputLength] != LineEnd && ++inputLength < BufferLength);
  inputBuffer[inputLength] = 0; //  add null terminator
  HandleCommand(inputBuffer, inputLength);
}

//----------- End Arduino code ---------------
//----------- Start Processing code ----------------

import oscP5.*;
import netP5.*;
import processing.serial.*;
Serial arduinoPort;
OscP5 oscP5;

float [] fader = new float [3];

void setup() {
  oscP5 = new OscP5(this,8000);
  arduinoPort = new Serial(this, "COM5", 9600);
}

void oscEvent(OscMessage theOscMessage) {

    String addr = theOscMessage.addrPattern();
    
       if(addr.indexOf("/1/fader") !=-1){ 
       String list[] = split(addr,'/');
     int  xfader = int(list[2].charAt(5) - 0x30);
     if(theOscMessage.get(0).floatValue() !=0){
     fader[xfader]  = theOscMessage.get(0).floatValue();
     }   
    }
}

void draw() {
//---------------------------------Motor A
 if(fader[1] > 0.65){
    arduinoPort.write("AF#");
  }
   if(fader[1] < 0.35){
    arduinoPort.write("AR#");
  }
  //--------------------------------Motor B
   if(fader[2] > 0.65){
    arduinoPort.write("BF#");
  }
   if(fader[2] < 0.35){
    arduinoPort.write("BR#");
  }
  //----------------------------stop commands
     if(fader[1] < 0.65 && fader[1] > 0.35 ){
    arduinoPort.write("AS#");                            //stop motor A
  }
       if(fader[2] < 0.65 && fader[2] > 0.35 ){
    arduinoPort.write("BS#");     //stop motor B
  }
  
}

Moderator edit: I’m really getting bored with this game now.

You've been a registered user here for nearly a year. In that time, you must have noticed that other people post code in code boxes. Do you think that you could do the same, please?

I am sorry. Even though I registered it a year ago, I never used it. And, it is my first time posting something. Thank you for suggestion . Please look at it.

//-----------Start Arduino code ---------------

// Test program for SparkFun Ardumoto board
// Copyright (c) 2009 mechomaniac.com
 
// To use, connect the Arduino to a computer and send commands using a serial terminal.
// eg AR40#   motor A forwards with a speed of 40
 
#define MotorAlogicone 10
#define MotorAlogictwo 11
#define MotorBlogicone 12
#define MotorBlogictwo 13
#define SerialSpeed 9600
#define BufferLength 16
#define LineEnd '#'
#define enablePin 9 // Pin for H bridge pin 1
#define enablePintwo 8  // Pin for H bridge pin 9 
 
char inputBuffer[BufferLength];
 
void setup()
{
  // motor pins must be outputs
  pinMode(MotorAlogicone, OUTPUT);
  pinMode(MotorAlogictwo, OUTPUT);
  pinMode(MotorBlogicone, OUTPUT);
  pinMode(MotorBlogictwo, OUTPUT);
 pinMode(enablePin, OUTPUT);
 pinMode(enablePintwo, OUTPUT);
 digitalWrite(enablePin, HIGH);
 digitalWrite(enablePintwo, HIGH);


  Serial.begin(SerialSpeed); 
}
 
//if you think about it, input here is the inputbuffer from void function
// process a command string
void HandleCommand(char* input, int length)
{
  Serial.println(input);

 





  int* command = (int*)input;
  // check commands
  // note that the two bytes are swapped, ie 'RA' means command AR
  switch(*command) {
    case 'FA':
      // motor A forwards
     digitalWrite (MotorAlogicone, LOW);
     digitalWrite(MotorAlogictwo, HIGH);
      break;

    case 'RA':
      // motor A reverse
     digitalWrite (MotorAlogicone, HIGH);
     digitalWrite(MotorAlogictwo, LOW);
      break;

    case 'FB':
      // motor B forwards
     digitalWrite (MotorBlogicone, LOW);
     digitalWrite(MotorBlogictwo, HIGH);
  break;

    case 'RB':
      // motor B reverse
     digitalWrite (MotorBlogicone, HIGH);
     digitalWrite(MotorBlogictwo, LOW);  
    break;

    case 'SA':       
      // Stop motor A
     digitalWrite (MotorAlogicone, LOW);
     digitalWrite(MotorAlogictwo, LOW);  
    case 'SB':
      // stop motor B
     digitalWrite (MotorBlogicone, LOW);
     digitalWrite(MotorBlogictwo, LOW);  


    default:
      break;
  }  
} 
 


void loop()
{ 
  // get a command string form the serial port
  int inputLength = 0;
  do {
    while (!Serial.available())
; // wait for input
   inputBuffer[inputLength] = Serial.read(); // read it in
  } while (inputBuffer[inputLength] != LineEnd && ++inputLength < BufferLength);
  inputBuffer[inputLength] = 0; //  add null terminator
  HandleCommand(inputBuffer, inputLength);
}

//----------- End Arduino code ---------------

processing Code

//----------- Start Processing code ----------------

import oscP5.*;
import netP5.*;
import processing.serial.*;
Serial arduinoPort;
OscP5 oscP5;

float [] fader = new float [3];

void setup() {
  oscP5 = new OscP5(this,8000);
  arduinoPort = new Serial(this, "COM5", 9600);
}

void oscEvent(OscMessage theOscMessage) {

    String addr = theOscMessage.addrPattern();
    
       if(addr.indexOf("/1/fader") !=-1){ 
       String list[] = split(addr,'/');
     int  xfader = int(list[2].charAt(5) - 0x30);
     if(theOscMessage.get(0).floatValue() !=0){
     fader[xfader]  = theOscMessage.get(0).floatValue();
     }   
    }
}

void draw() {
//---------------------------------Motor A
 if(fader[1] > 0.65){
    arduinoPort.write("AF#");
  }
   if(fader[1] < 0.35){
    arduinoPort.write("AR#");
  }
  //--------------------------------Motor B
   if(fader[2] > 0.65){
    arduinoPort.write("BF#");
  }
   if(fader[2] < 0.35){
    arduinoPort.write("BR#");
  }
  //----------------------------stop commands
     if(fader[1] < 0.65 && fader[1] > 0.35 ){
    arduinoPort.write("AS#");                            //stop motor A
  }
       if(fader[2] < 0.65 && fader[2] > 0.35 ){
    arduinoPort.write("BS#");     //stop motor B
  }
  
}

With dual motion systems like this it is hard to get both sides to run at the same speed. Small differences in motor speed, gearing efficiency ect can make a machine go in circles when it is supposed to go straight.

There are 2 ways to fix it: Set the faster side to run at a slower speed using PWM until you get your bot in a straight line.

The other way to set a master and slave side. You essentially set the master side to the speed you want, and through a feedback system, the slave side follows suit.

I am sorry. I should have elaborated a little more. I suspected it might be the problem wireless communication. therefore, I just use cable to connect Arduino with my computer. I send command using Serial monitor such as this.

//----------------------Arduino code-------------------------

#define MotorAlogicone 10
#define MotorAlogictwo 11
#define MotorBlogicone 12
#define MotorBlogictwo 13

#define enablePin 9 // Pin for H bridge pin 1
#define enablePintwo 8  // Pin for H bridge pin 9 
int message=0;
void setup() {  
  Serial.begin(9600);  //set serial to 9600 baud rate
    // motor pins must be outputs
  pinMode(MotorAlogicone, OUTPUT);
  pinMode(MotorAlogictwo, OUTPUT);
  pinMode(MotorBlogicone, OUTPUT);
  pinMode(MotorBlogictwo, OUTPUT);
 pinMode(enablePin, OUTPUT);
 pinMode(enablePintwo, OUTPUT);
 digitalWrite(enablePin, HIGH);
 digitalWrite(enablePintwo, HIGH);

}

void loop(){
    if (Serial.available() > 0) { //  Check if there is a new message
      message = Serial.read();    //  Put the serial input into the message

   if (message == 'a'){  //  If a capitol R is received...
    digitalWrite (MotorAlogicone, LOW);
     digitalWrite(MotorAlogictwo, HIGH);       //  Set redLED to 255 (on)
   }
   if (message == 'b'){  //  If a lowercase r is received...
    digitalWrite (MotorAlogicone, HIGH);
     digitalWrite(MotorAlogictwo, LOW);         //  Set redLED to 0 (off)
   }
 if (message == 'c'){  //  If a lowercase r is received...
    digitalWrite (MotorBlogicone, LOW);
     digitalWrite(MotorBlogictwo, HIGH);         //  Set redLED to 0 (off)
   }
   if (message == 'd'){  //  If a lowercase r is received...
    digitalWrite (MotorBlogicone, HIGH);
     digitalWrite(MotorBlogictwo, LOW);         //  Set redLED to 0 (off)
   }
   
    if (message == 'e'){  //  If a lowercase r is received...
    digitalWrite (MotorAlogicone, LOW);
     digitalWrite(MotorAlogictwo, LOW);         //  Set redLED to 0 (off)
   }
   
    if (message == 'f'){  //  If a lowercase r is received...
    digitalWrite (MotorBlogicone, LOW);
     digitalWrite(MotorBlogictwo, LOW);         //  Set redLED to 0 (off)
   }
   
   
   
   
   
   
   
   
   
 }   

}

//----------------------------end Arduino code--------------------------------

When I do that, these two motors run at the same speed. And, the oscilloscope shows the same voltage for both sides. Any idea ? Thanks in advance...................

I suggest you separate out the code to parse the input command, from the code that drives the motors.

In the parsing code, work out which command you have and then call the corresponding function to turn the motors on or off. I don't know what those output values will do or what the six commands you implemented are intended to do to the two motors. Hopefully if you separate this out then you can make that clear at the same time.

While you're doing that, have another look at the code to parse your commands. I'm not sure what this is meant to do, but it seems to be declaring a character literal containing two characters. Does that even compile?

case 'FA':

case 'FA': Yes, it does compiles. Since you pointed it out, I will assign difference cases as single letters such as a, b ,c , d , e ,f . I have not tested it yet. But, do you think it will fix the problem.

I'm not sure what this is meant to do, but it seems to be declaring a character literal containing two characters. Does that even compile?

Perfectly legal, though not very portable, and may cause alignment exceptions on some architectures.

AWOL:

I'm not sure what this is meant to do, but it seems to be declaring a character literal containing two characters. Does that even compile?

Perfectly legal, though not very portable, and may cause alignment exceptions on some architectures.

I've never seen that syntax used before. What data type does it declare, and what value?

What data type does it declare, and what value?

They are called multi-byte characters. The data type is char, but it is a 2 byte char. Common for non-English language character sets.

Thank you for explaining. But, do you have any idea on what might have been wrong so that one side keeps turning on and off ?

But, do you have any idea on what might have been wrong so that one side keeps turning on and off ?

Bad wiring, supply incapable of sufficient current?