Predicting the time for robot car project using millis()

Hi, I am building and coding a robot car for a school project. The objective is to accurately predict the time the robot takes to get from point A to point B. I've used speed encoder disks with IR sensors to sense how the robot is moving and currently the robot only does 4 movements: turn right, turn left, move forward, and move back.

I've decided that each of these movements including the delay after should take 4 seconds (the robot moves at most 50 cm at a time and 4 seconds is plenty of time). I'm not too familiar with using the millis() function, but I'm trying to use it to stop the robot for 4-(however many seconds it takes to do the movement) so I can just count up the functions and multiply by 4 to get the approximate time.

In the code below, I have made it move forward and right which should get a reading of 8000 milliseconds on the serial monitor, but I'm getting way over (8813, 8634, 8645, 8632, 8669 etc.) Is there a problem with the code?

Materias:
DC motors
L298N motor driver
arduino uno
IR sensors with encoder disks
6 AA batteries

const int MOTOR_A=2;
const int MOTOR_B=3;


const float slotcount=20.00; // 20 Slots in encoder disk


volatile int counter_A=0;
volatile int counter_B=0;


// MOTOR_A


int enA=10;
int in1=9;
int in2=8;


//MOTOR_B


int enB=5;
int in3=7;
int in4=6;


const long runTime= 4000;
unsigned long previousTime=0;
unsigned long currentTime=millis();


//MOTOR_A pulse count ISR


void ISR_countA(){
counter_A++;
}


//MOTOR_B pulse count ISR


void ISR_countB(){
counter_B++;
}


//Function to convert from centimeters to slots
int CMtoSlots(float cm) {
float circumference = 21.5;
float cm_slot = circumference/ slotcount; // CM per Slot


float result=cm/cm_slot;
return result;


}


//0<=mspeed<=255


// Function to Move Forward


void moveForward(int slots, int mspeed){
previousTime=currentTime;


int Counter_A=0;
int Counter_B=0;


digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);

while (slots>= counter_A && slots>= counter_B){


if (slots>= counter_A){
 analogWrite(enA, mspeed);
} else {
 analogWrite(enA, 0); 
}
if (slots>= counter_B){
 analogWrite(enB, mspeed);
} else {
 analogWrite(enB, 0);
}
}

counter_A=0;
counter_B=0;
analogWrite(enA, 0);
analogWrite(enB,0);

if(currentTime-previousTime <= runTime){
delay(runTime-(currentTime-previousTime));
}

}

// Function to Move Backward


void moveBackward(int slots, int mspeed){
previousTime=currentTime;

counter_A=0;
counter_B=0;


digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);


while (slots>= counter_A && slots>= counter_B){

if (slots>= counter_A){
 analogWrite(enA, mspeed);
} else {
 analogWrite(enA, 0);
}
if (slots>= counter_B){
 analogWrite(enB, mspeed);
} else {
  analogWrite(enB, 0);
}
}

counter_A=0;
counter_B=0;
analogWrite(enA, 0);
analogWrite(enB,0);

if(currentTime-previousTime <= runTime){
delay(runTime-(currentTime-previousTime));
}

}


// Function to Move Left


void turnLeft(int slots, int mspeed){
previousTime=currentTime;

counter_A=0;
counter_B=0;


digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);


while (slots>= counter_A && slots>= counter_B){


if (slots>= counter_A){
 analogWrite(enA, mspeed);
} else{
analogWrite(enA, 0);
}
if (slots>= counter_B){
 analogWrite(enB, mspeed);
} else{
analogWrite(enB, 0);
} 
}

counter_A=0;
counter_B=0;
analogWrite(enA, 0);
analogWrite(enB,0);

if(currentTime-previousTime <= runTime){
delay(runTime-(currentTime-previousTime));
}


}

// Function to Move Right


void turnRight(int slots, int mspeed){
previousTime=currentTime;

counter_A=0;
counter_B=0;


digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);


while (slots>= counter_A && slots>= counter_B){


if (slots>= counter_A){
 analogWrite(enA, mspeed);
} else{
 analogWrite(enA, 0); 
}
if (slots>= counter_B){
 analogWrite(enB, mspeed);
} else{
analogWrite(enB, 0);
}
}

counter_A=0;
counter_B=0;
analogWrite(enA, 0);
analogWrite(enB,0);

if(currentTime-previousTime <= runTime){
delay(runTime-(currentTime-previousTime));
}
}

void setup() {
Serial.begin(9600);


attachInterrupt(digitalPinToInterrupt(MOTOR_A), ISR_countA, RISING);
attachInterrupt(digitalPinToInterrupt(MOTOR_B), ISR_countB, RISING);


moveForward(CMtoSlots(10),100);
turnRight(10,100);



int TotalTime= millis();


Serial.println(TotalTime);
}




void loop() {




}


Nope...lost me in your description.

So you want to "accurately predict"or is it "measure" time taken.

accurately predict, i'm trying to get each movement including the delay after to be 4 seconds for example in the code I did moveFoward(10) and then moveleft(10) which should show up as 8000 milliseconds on the serial monitor right?

But the delay in the very end shouldn't really matter because in the real competition, the car going to do a lot more than move forward and right once if that makes sense.

I am lost too but I notice in your sketch that you have 2 different variables named counter_A, each with a different scope

volatile int counter_A = 0;

and

    int Counter_A = 0;

Could that be causing a problem ?

thanks, I changed it, but its not changing the problem with the time...

Please can we have a more detailed explanation of what you are trying to measure and how you are doing it ?

For instance, when you say

Where does the figure of 8000 coming from ?

I'm trying to measure each movement(forward, right, left, backward), and then delay so that the total time is 4000 milliseconds.

And to do that I'm trying to use the millis() function to measure the time it takes to do each of those(forward, back, right, left) and then delaying it for 4-(the time it takes to do each of those).

For example, say I want it to go forward for 10 cm:
the total time would be (time it takes to go forward 10cm)+delay(4000-time it takes to go forward 10cm)=4000milliseconds

if that makes sense, sorry for the confusion!

The time that each movement takes depends on how long you program the movement to run for. Where in your sketch do you set the time that each movement function should run for ?

Are you trying to determine the time that it takes for the encoder on a wheel to generate a certain number of pulses on its output ?

In the last couple of lines of each movement function:

if(currentTime-previousTime <= runTime){
delay(runTime-(currentTime-previousTime));

the previousTime is set equal to the currentTime in the beginning of each function, so by calculating the difference between the two after the while loop arn't I determining the time it takes for the encoder to generate the necessary pulses?

In order to determine how long a function takes to run you should save the value of millis() at the start of the function and at the point where the function finishes execution of the code that you are trying to monitor.

Give them sensible names such as startTime and endTime. The time taken to execute the commands in the function with then be endTime - startTime. Bear in mind that millis() itself takes time to return a value as will calculation of the elapsed time

You have still not explained where the figure of 8000 comes from and why you need to multiply something by 4

It's working now!! thank you!

I changed it here (I got a little impatient lol) but in the code below there are 11 "movement functions" and I set the run time as 2000milliseconds=2 seconds so the total time the code should run for is
(11)(2000milliseconds)(because each movement function runs for 2 seconds)=
(11)(2seconds)=
22000 milliseconds=
22 seconds.

and 22002 is what is showing up on the serial monitor.

turnRight(9,150);
moveForward(CMtoSlots(50-6.2),150);
turnLeft(7,150);
moveForward(CMtoSlots(50-6.2),150);
moveForward(CMtoSlots(50-6.2),150);
turnLeft(7,150);
moveForward(CMtoSlots(50-6.2),150);
turnRight(9,150);
moveForward(CMtoSlots(50-6.2),150);
turnRight(9,150);
moveForward(CMtoSlots(50-6.2),150);

Please post the whole of your revised sketch

const int MOTOR_A=2;
const int MOTOR_B=3;


const float slotcount=20.00; // 20 Slots in encoder disk


volatile int counter_A=0;
volatile int counter_B=0;


// MOTOR_A


int enA=10;
int in1=9;
int in2=8;


//MOTOR_B


int enB=5;
int in3=7;
int in4=6;


const long runTime= 2000;
unsigned long previousTime=0;
unsigned long currentTime=millis();


//MOTOR_A pulse count ISR


void ISR_countA(){
counter_A++;
}


//MOTOR_B pulse count ISR


void ISR_countB(){
counter_B++;
}


//Function to convert from centimeters to slots
int CMtoSlots(float cm) {
float circumference = 21.5;
float cm_slot = circumference/ slotcount; // CM per Slot


float result=cm/cm_slot;
return result;


}


//0<=mspeed<=255


// Function to Move Forward


void moveForward(int slots, int mspeed){
unsigned long startTimeF=millis();


counter_A=0;
counter_B=0;


digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);

while (slots>= counter_A){


if (slots>= counter_A){
 analogWrite(enA, 120);
} else {
 analogWrite(enA, 0); 
}
if (slots>= counter_A){
 analogWrite(enB, mspeed);
} else {
 analogWrite(enB, 0);
}
}
unsigned long endTimeF=millis();

counter_A=0;
counter_B=0;
analogWrite(enA, 0);
analogWrite(enB,0);

delay(runTime-(endTimeF-startTimeF));

}

// Function to Move Backward


void moveBackward(int slots, int mspeed){
unsigned long startTimeB=millis();

counter_A=0;
counter_B=0;


digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);


while (slots>= counter_A){

if (slots>= counter_A){
 analogWrite(enA, 120);
} else {
 analogWrite(enA, 0);
}
if (slots>= counter_A){
 analogWrite(enB, mspeed);
} else {
  analogWrite(enB, 0);
}
}
unsigned long endTimeB=millis();

counter_A=0;
counter_B=0;
analogWrite(enA, 0);
analogWrite(enB,0);

delay(runTime-(endTimeB-startTimeB));


}


// Function to Move Left


void turnLeft(int slots, int mspeed){
unsigned long startTimeL=millis();

counter_A=0;
counter_B=0;


digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);


while (slots>= counter_A){


if (slots>= counter_A){
 analogWrite(enA, 120);
} else{
analogWrite(enA, 0);
}
if (slots>= counter_A){
 analogWrite(enB, mspeed);
} else{
analogWrite(enB, 0);
} 
}

unsigned long endTimeL=millis();

counter_A=0;
counter_B=0;
analogWrite(enA, 0);
analogWrite(enB,0);

delay(runTime-(endTimeL-startTimeL));



}

// Function to Move Right


void turnRight(int slots, int mspeed){
unsigned long startTimeR=millis();

counter_A=0;
counter_B=0;


digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);


while (slots>= counter_A){


if (slots>= counter_A){
 analogWrite(enA, 120);
} else{
 analogWrite(enA, 0); 
}
if (slots>= counter_A){
 analogWrite(enB, mspeed);
} else{
analogWrite(enB, 0);
}
}

unsigned long endTimeR=millis();

counter_A=0;
counter_B=0;
analogWrite(enA, 0);
analogWrite(enB,0);


delay(runTime-(endTimeR-startTimeR));

}

void setup() {
Serial.begin(9600);


attachInterrupt(digitalPinToInterrupt(MOTOR_A), ISR_countA, RISING);
attachInterrupt(digitalPinToInterrupt(MOTOR_B), ISR_countB, RISING);



turnRight(8,150);
moveForward(CMtoSlots(50-6.2),150);
turnLeft(6,150);
moveForward(CMtoSlots(50-6.2),150);
moveForward(CMtoSlots(50-6.2),150);
turnLeft(6,150);
moveForward(CMtoSlots(50-6.2),150);
turnRight(8,150);
moveForward(CMtoSlots(50-6.2),150);
turnRight(8,150);
moveForward(CMtoSlots(50-6.2),150);




int TotalTime= millis();


Serial.println(TotalTime);
}




void loop() {




}

and this is the path that it should take from A to B:

I am glad to have been of help

See how much easier it is when you use sensible names for variables ? As far as possible I like my code to read like a sentence in English

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.