Robot to turn left and move straight

Hi! I am new to Arduino programming and would like to ask for some help regarding my project. How do I let my robot turn left and the continue moving straight? As of now, I know the angle of the robot. When I move straight in one of the direction, the angle is around 180 to 200+ degrees. When my robot turn left, the angle will become more than 270 degrees. However, in Arduino loop function, I added in the codes when the angle is 180 to 245 degrees, my robot will be moving straight. When the angle if more than 270 degrees, my robot will turn left. However, my robot keeps turning left as the first turning angle returned is 270, the following angles returned are also 270+ which causes my robot to keep turning left. Is there any way I can get my robot to just turn left once and continue moving straight? Thank You!

The codes below are the a portion of codes I have written for the movement of the robot:

void forward(){
SoftPWMSetPercent(in2, 100);
SoftPWMSetPercent(in4, 100);
SoftPWMSetPercent(in9, 100);
SoftPWMSetPercent(in11, 100);
}

void turn_Left(){
SoftPWMSetPercent(in4, 100);
SoftPWMSetPercent(in11, 100);
SoftPWMSetPercent(in3, 100);
SoftPWMSetPercent(in10, 100);
}

if(angle >= 180 && angle <= 245)
{
   forward();
   if(angle > 270)
   {
       turn_Left();
   }
}

Hi,

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html

Please post your entire code.

  • What model Arduino are you using?
  • What steppers are you using?
  • What stepper controllers are you using?
  • What are you using to measure angle?
  • How are you powering the Arduino and steppers?

Can you post a picture of your robot?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom.. :slight_smile:

Is the angle relative to the starting position, or is it derived from a compass? The latter would be resistant to outside movements. The logic might be simpler if you go north, west, south or east rather than left or right.

ChrisTenone:
Is the angle relative to the starting position, or is it derived from a compass? The latter would be resistant to outside movements. The logic might be simpler if you go north, west, south or east rather than left or right.

The angle is derived from a compass. How do I follow the logic of using north, south, east or west rather than left or right? Thanks for the suggestion! I think it is really a better idea by using north, south, east or west compared to left or right.

Please follow the directions in reply #1.

The Arduino Model I am using is Arduino Mega 2560. I am using atan2 formula to find the angle between 2 latitude and longitude points. The photo below is the robot that I am currently using for my project.

Please follow the directions in reply #1.

Code snippet is useless and doesn't make much sense anyway (why go straight when it's going to such a wide range of directions, turn if it's way out of that range, do nothing at all other directions). Robot looks nice.

For it to go a certain direction, you code should be like "if current angle > target angle turn left, if current angle < target angle turn right, otherwise go straight".

Well, two issues there: it's never equal so that should be "> target angle + a bit", and there's the 360 degree = 0 degree point you have to deal with - you don't want to make a near full turn to go from a 358 degree to a 2 degree heading.

Hi again ngjy, I see the biggest bene of using compass points, is that it matches your input data, and is protected against an unexpected disorientation.

However folks here can't help you much without more information. For understanding the operation of your device, a circuit is needed, as well as the actual code. You needn't worry about that though. Folks here are respectful of your ownership of the code, but they need to see it to help. Because the problems most often are exactly where the project maker thinks they aren't.

Thankyou everyone for the reply! I only post a snippet of the codes because I was still editing some parts of it as the previous person working on this project added some codes that were not used in the program but I really thanked all of you for willing to guide me with my project. The codes below are the full coding:

#include <SoftPWM.h>

const byte numChars = 100;
char receivedChars[numChars];	// an array to store the received data

const int numbers = 5;
int fiveNumber[numbers];

boolean newData = false;
int i=0;

int count;

// save data sent in by bluetooth through android phone
int dataNumber = 0;
char distance[100] = {
  0}; 
char angle[100] = {
  0};

// declare variables
double x;
double angleDouble;

double delayTime;

/* declare motor pins
 =================
 M1 |in2,3      in4,5| M2
 |                |
 M3 |in9,10   in11,12| M4
 =================
 SMART CART [PINS] 
 */

// motor 1
int in2 = 2; 
int in3 = 3;
// motor 2
int in4 = 4; 
int in5 = 5;
// motor 3
int in9 = 9; 
int in10 = 10;
// motor 4
int in11 = 11; 
int in12 = 12;


void setup() {
  // arduino default serial
  Serial.begin(9600);  

  // enable softPWM
  SoftPWMBegin();
  SoftPWMSet(2,0); 
  SoftPWMSet(3,0);
  SoftPWMSet(4,0); 
  SoftPWMSet(5,0);
  SoftPWMSet(9,0); 
  SoftPWMSet(10,0);
  SoftPWMSet(11,0); 
  SoftPWMSet(12,0);

  // change bluetooth serial port to 115200 
  Serial1.begin(115200);
  Serial1.print("$");
  Serial1.print("$");
  Serial1.print("$");
  delay(100);

  Serial1.begin(19200); // 19200 for bluetooth RN42
  Serial.println("<Arduino is ready>");
}

void loop() {
  recvWithEndMarker();
  showData();
}

void recvWithEndMarker() {
  static byte ndx = 0;   //local variable to store up to 8 digit numbers from 0 to 255
  char endMarker = '\n'; //break line
  char rc;

  if (Serial1.available() > 0) {  //Bluetooth connected
    rc = Serial1.read();  //storing value for connected Bluetooth

    if (rc != endMarker) {    //connected Bluetooth is not equals to break line
      receivedChars[ndx] = rc; //store the connected Bluetoothh values into an array
      ndx++; //increment

      if (ndx >= numChars) {   //if index is more than or equals to 100
        ndx = numChars - 1; //index = 100 - 1
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0; //index = 0
      newData = true;  //there is newData
    }
  }
}

void showData() {
  if (newData == true) { //if there is newData
    dataNumber = 0;	// new for this version
    dataNumber = atoi(receivedChars); // new for this version , atoi(receivedchars) is to convert all Bluetooth data stored in array to int

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(receivedChars,","); // get the first part - the string , split the values by ,
    strcpy(distance, strtokIndx); // copy value to distance
    Serial.print("Distance: ");

    x = atof(distance); // in meters , convert string to float/double
    Serial.println(x);

    // get angle
    strtokIndx = strtok(NULL,","); // continue  , split the values by ,
    strcpy(angle, strtokIndx); // copy value to angle
    angleDouble = atof(angle); //convert string to float/double

    
    Serial.print("Angle: ");
    Serial.println(angleDouble);
   
    count = 0;    
    if (count < 5){
      fiveNumber[count] = angleDouble; //storing angle into array
      count++; //increment
      Serial.println(fiveNumber[count]); 
    }
    else{
      count = 0;
    }

    if (x > 0){ //if distance is more than 0
      double delayTime = x * 10;  //distance * 10
      if(i > 1){
        // 1 second * distance // move for amount of seconds 10ms // delay time 10 = 1s
        
      }
    }
    else {
      clearAll();
    }    
    clearAll();
    newData = false;
  }
  i++;
}

// start of motor wheel movements
void forward(){
  SoftPWMSetPercent(in2, 200);  //motor 1
  SoftPWMSetPercent(in4, 200);  //motor 2
  SoftPWMSetPercent(in9, 199);  //motor 3
  SoftPWMSetPercent(in11, 199);  //motor 4
  delay(1000);
}

void backward(int speed) {
  SoftPWMSetPercent(in3, speed);  //motor 1
  SoftPWMSetPercent(in5, speed);  //motor 2
  SoftPWMSetPercent(in10, speed);  //motor 3
  SoftPWMSetPercent(in12, speed);  //motor 4
  delay(1000);
}

void turnLeft(int speed){
  SoftPWMSetPercent(in4, speed);  //motor 2 forward
  SoftPWMSetPercent(in11, speed); //motor 4 forward
  SoftPWMSetPercent(in3, speed);  //motor 1 backward
  SoftPWMSetPercent(in10, speed); //motor 3 backward
  delay(1000);
}

void turnRight(int speed){
  SoftPWMSetPercent(in2, speed);  //motor 1 forward
  SoftPWMSetPercent(in9, speed);  //motor 3 forward
  SoftPWMSetPercent(in5, speed);  //motor 2 backward
  SoftPWMSetPercent(in12, speed); //motor 4 backward
  delay(1000);
}

int clear = 0; //set clear to 0
void clearAll(){  //set all speed of the motors to 0
  SoftPWMSetPercent(in2, clear);
  SoftPWMSetPercent(in3, clear);
  SoftPWMSetPercent(in4, clear);
  SoftPWMSetPercent(in5, clear);

  SoftPWMSetPercent(in9, clear);
  SoftPWMSetPercent(in10, clear);
  SoftPWMSetPercent(in11, clear);
  SoftPWMSetPercent(in12, clear);
}
// end of motor wheel movements

Several things about that code.

  1. use byte instead of int for pin numbers. You're wasting memory.
  2. what motor driver do you use? I'm used to seeing the in1 and in2 for direction and an enable pin for the PWM signal. You need just one PWM signal per motor.
  3. why using softPWM while the Mega has 15 hardware PWM pins available?
  4. AVR processors don't do double precision. It's an alias of float.
  5. in setup() you set Serial1 to 115200 bps, a few lines later to 19200. Why?

These bits stand out in your code:

    dataNumber = 0;	// new for this version
    dataNumber = atoi(receivedChars); // new for this version , atoi(receivedchars) is to convert all Bluetooth data stored in array to int
[/code
The first line isn't doing anything.

[code]
      if(i > 1){
        // 1 second * distance // move for amount of seconds 10ms // delay time 10 = 1s
       
      }

Something seems to be missing here.

    else {
      clearAll();
    }   
    clearAll();

The else block is redundant.

  SoftPWMSetPercent(in2, 200);  //motor 1

200%, seriously? Also I notice that in the other blocks you use a variable speed, not a fixed number. And there's a delay(1000) in there, meaning your robot is not responsive to any sensor input for a full second, while it's moving! So no obstacle detection and avoidance during that time...

Hi,
What motor driver are you using?

This makes the pins more self explanatory;

// motor 1
int M1Pin2 = 2; 
int M1Pin3 = 3;
// motor 2
int M2Pin4 = 4; 
int M2Pin5 = 5;
// motor 3
int M3Pin9 = 9; 
int M3Pin10 = 10;
// motor 4
int M4Pin11 = 11; 
int M4Pin12 = 12;

Tom.... :slight_smile:

Hi! Thanks for all the replies! The motor driver that my robot is using is L298N Motor Controller. :slight_smile:

That one indeed is normally controlled by three pins per motor.

Two (in1 and in2) for left/right/brake; one (en) enable pin which you can use a PWM signal on. Just use one of the PWM pins for that (they're marked on the Mega's PCB), and analogWrite(pin, value) to set the duty cycle. No softPWM or so.

Also there are much better motor controllers to be had rather than this one. The L298N is notorious for dropping so much voltage in the controller that the motors don't have enough left to run properly...

Thank You for the information! I will take that into consideration for my project! Thanks for all the help!

One more question. How do I compare the values of the angles retrieved using if else statement?
I intend to write if else statement for the turning of the robot such that if the robot's angle is smaller than the current angle - 90 it will turn left. However the way I code it using if else statement does not seem to work. Do I need to store the current angle and create another variable to copy these two values? The codes below are the if else statements that I have tried out.
angleDouble is the return angle of the robot.

if (angleDouble <= angleDouble - 90)
{
  Serial.println("Turn Right");
}
else if (angleDouble >= angleDouble + 90)
{
  Serial.println("Turn Left");
}
if (angleDouble <= angleDouble - 90)

Of course this will never work. Something is never smaller than itself -90. You have to compare to some other variable.

Thanks for the reply!