How to Make a Path Memorizing Robot using Arduino

Last updated on March 9th, 2024 at 05:51 pm

A simple path-memorizing robot car repeats the action or path that is stored in its memory. Making such a robot may seem complicated at first but believe me, it’s easier than you think. By the end of this article, you will be able to make:

(a) A wireless IR remote control Car using Arduino

(b) Turn it into a path-memorizing robot without using any extra components and

(c) How to use Arduino’s inbuilt EEPROM to store that path forever in its memory.

Step by Step Video tutorial:

How does a path memorizing robot work?

Before starting the tutorial let’s see the objective of the project and its working.

The car is operated manually by using the specified control buttons on IR remote. 2 moves it forward, 4 is for left, 6 is for right, 8 is for backward and 0 stops the car.

The path memorizing robot
The path memorizing robot

The first time you run the robot car after powering Arduino, it automatically stores the sequence in its memory. Now to repeat this stored sequence, I have assigned the Repeat button on IR remote. And in order to store a new sequence, you have to delete the current stored sequence first, by pressing a button.

And finally, to store the current sequence permanently to EEPROM, the function button is used. And to play it back the fast forward button is assigned.

Apart from all this, if at any point in time during operation, the robot runs into some error, you can easily reset Arduino by pressing the play button. Please note that you can change any button you like for any certain operation mentioned above in the CODE section.

Components:

To build this robot car you will need:

  1. One Arduino Uno
  2. An IR Remote and IR receiver
  3. Two geared DC Motors
  4. Motor driver module
  5. 9V Power supply. I am using 6 X 1.5v AA battery here
  6. Robot wheels
  7. Robot chassis
  8. Breadboard
  9. Wires

How to build the path memorizing robot?

Part 1: Assembling the chassis

Assembling the chassis
Assembling the chassis

First of all, you will need a Robot chassis, to which you can fit motors and tires. I am using 2 DC motors, 2 Rubber tires, and one Caster wheel. After finishing the robot assembly it’s time for the Electronics part.

Part 2: Brief introduction to the electronics

To control your robot car from the IR remote, you would need an IR receiver. This IR receiver will decode the received signal for the corresponding button pressed and send it to Arduino. Arduino acts as a controller for your Robot Car and the program written in it gives appropriate logic to control the Motors.

But we all know that Arduino cannot supply enough current to a DC Motor. And that’s why you also need a Motor driver here. You can use any motor driver you like. Like in this case, I am using L293D Motor Driver IC for this Robot car.

Part 3: IR receiver

Let’s talk about the IR remote we all use in our daily life. Yes, a TV remote. You must have observed a white LED in front of it. This white LED is actually an IR transmitter. It transmits Infrared waves of different frequencies depending on the button pressed.

This wave is then received and decoded by the IR receiver on the TV side, to find out which button you have pressed. We are going to use the same logic to build this project.

TV remote
TV remote

Now in order to distinguish between the buttons, each button is given a unique frequency. That means you must know what the frequency of each button is before using an IR remote. But the real question is how. Well, an Arduino can help us in this situation. So grab an Arduino and IR receiver.

Connect the left terminal of the sensor to digital pin 10 of Arduino. Middle terminal to GND and Right terminal to 5V pin of Arduino.

Now go to Arduino IDE software and download a library for IR remote.

IR remote library
IR remote library

Next, go to files, then example–>IR remote–>IRrecieve demo sketch.

IRreceive demo Sketch
IRreceive demo Sketch

Upload this code to your board. Now open the serial monitor and press any button on the IR remote. As you can see here, the corresponding Hex code for the button is printed on the Serial Monitor. Note down the Hexadecimal Code for all the buttons. And now you can program Arduino to perform a certain function when it receives a certain hex code.

Hex codes
Hex codes

Part 4: Circuit diagram

Circuit diagram
Circuit diagram

Tinkercad file link: https://www.tinkercad.com/things/73bMPNPUEKh

Connect the motor driver IC to your Arduino board and DC motors. I am using L293D IC and the above picture is the schematic for the same. If you are using L293D, then connect it, as shown in the Circuit diagram. And now that we have finished the circuit connections, it is time to move on to the Arduino Code:

Part 5: Arduino program A— Normal IR remote control car

This is a simple IR remote control car program without any memorizing functionality. The end goal is to control the car using an IR remote. First of all download and include the IRremote library from the library manager. Next, write some macros so that you can easily change the Arduino pins directly from here:

/*
***********************IR Remote Control Car**************************
* 
* Created on: May 27, 2021
* Author: Ankit Negi 
* 
* Youtube: www.youtube.com/theelectronicguy
* Website: www.eTechnophiles.com
*/

#include <IRremote.h>

/*
   Left Motor
*/
// IN 1
#define LM_IN1    2
// IN 2
#define LM_IN2    4
/*
   Right Motor
*/
// IN 3
#define RM_IN3    5
// IN 4
#define RM_IN4    7


// IR receiver
# define RECV_PIN 10

IRrecv irrecv(RECV_PIN);

decode_results results;

//HEX codes for buttons
#define FWD       0xFD8877 // go forward
#define LFT       0xFD28D7 // go left
#define RGT       0xFD6897 // go right
#define BWD       0xFD9867 // go backward
#define STOP      0xFD30CF // stop
#define RESET     0xFD00FF // Resets the Arduino Board(RED)

unsigned long int value=0;

/*
 ************Arduino Reset Pin**************
 */
#define RESET_PIN A0

void setup() {
  
  // set mode of the pins as output
  for (int i = 2; i <= 7; i++) {
    pinMode(i, OUTPUT);
  }


  // start serial communication
  Serial.begin(9600);
  // In case the interrupt driver crashes on setup, give a clue
  // to the user what's going on.
  Serial.println("Enabling IRin");
  irrecv.enableIRIn(); // Start the receiver
  Serial.println("Enabled IRin");

}

void loop() {
  if (irrecv.decode(&results)) {
    value = results.value;
    Serial.println(value, HEX);
    irrecv.resume(); // Receive the next value
    delay(200);
  }

  delay(100);
  check_Inst(value);
  value=0;
}

void check_Inst(long int value) {

  switch (value) {
    case FWD:
      go_Forward();
      break;
    case LFT:
      go_Left();
      break;
    case RGT:
      go_Right();
      break;
    case BWD:
      go_Backward();
      break;
    case STOP:
      go_Stop();
      break;
    case RESET:
      pinMode(RESET_PIN,OUTPUT);
      digitalWrite(RESET_PIN,HIGH);   
      break;  

    default:
      value = 0;
  }
}

void go_Forward() {
 
  movement_Inst_Fwd();
  delay(10);
}

void go_Left() {
   
  movement_Inst_Lft();
  delay(10);
}

void go_Right() {
  
  movement_Inst_Rgt();
  delay(10);
}

void go_Backward(){

  movement_Inst_Bwd();
  delay(10);
}  

void go_Stop(){
  
  movement_Inst_Stp();
  delay(10);
}  

/*
 * These movement instruction are repeated several times in the code
 */
void movement_Inst_Fwd(void){
  Serial.println("Going_Forward");
  
  // forward movement instructions
  digitalWrite(LM_IN1,HIGH);
  digitalWrite(LM_IN2,LOW);
  digitalWrite(RM_IN3,HIGH);
  digitalWrite(RM_IN4,LOW);   
  } 
  
void movement_Inst_Lft(void){
  Serial.println("Going_Left");
  
  // Left movement instructions
  digitalWrite(LM_IN1,LOW);
  digitalWrite(LM_IN2,LOW);
  digitalWrite(RM_IN3,HIGH);
  digitalWrite(RM_IN4,LOW);  
  delay(500);
  digitalWrite(LM_IN1,LOW);
  digitalWrite(LM_IN2,LOW);
  digitalWrite(RM_IN3,LOW);
  digitalWrite(RM_IN4,LOW);    
  delay(500);
  }
  
void movement_Inst_Rgt(void){
  Serial.println("Going_Right");  
  
  // Rgt movement instructions
  digitalWrite(LM_IN1,HIGH);
  digitalWrite(LM_IN2,LOW);
  digitalWrite(RM_IN3,LOW);
  digitalWrite(RM_IN4,LOW); 
  delay(500);
  digitalWrite(LM_IN1,LOW);
  digitalWrite(LM_IN2,LOW);
  digitalWrite(RM_IN3,LOW);
  digitalWrite(RM_IN4,LOW); 
  delay(500);
    
  }
  
void movement_Inst_Bwd(void){
  Serial.println("Going_Backward"); 
    
  // Bwd movement instructions
  digitalWrite(LM_IN1,LOW);
  digitalWrite(LM_IN2,HIGH);
  digitalWrite(RM_IN3,LOW);
  digitalWrite(RM_IN4,HIGH);   
  }
  
void movement_Inst_Stp(void){  
  Serial.println("Stopping");    
  
  // Stp movement instructions
  digitalWrite(LM_IN1,LOW);
  digitalWrite(LM_IN2,LOW);
  digitalWrite(RM_IN3,LOW);
  digitalWrite(RM_IN4,LOW);  
  }

Part 6: Arduino Program B— Path memorizing robot (temporary)

/*
*********************Path Memorizing Robot(temp)************************
* 
* Created on: May 27, 2021
* Author: Ankit Negi 
* 
* Youtube: www.youtube.com/theelectronicguy
* Website: www.eTechnophiles.com
*/

#include <IRremote.h>

/*
   Left Motor
*/
// IN 1
#define LM_IN1    2
// IN 2
#define LM_IN2    4
/*
   Right Motor
*/
// IN 3
#define RM_IN3    5
// IN 4
#define RM_IN4    7


// IR receiver
# define RECV_PIN 10

IRrecv irrecv(RECV_PIN);

decode_results results;

//HEX codes for buttons
#define FWD       0xFD8877 // go forward
#define LFT       0xFD28D7 // go left
#define RGT       0xFD6897 // go right
#define BWD       0xFD9867 // go backward
#define STOP      0xFD30CF // stop
#define RPEAT     0xFD708F // repeat the stored sequence of movement from the temporary memory(automatically stores)
#define DEL       0xFDB04F // delete the stored sequence of movement from temporary memory(EQ)
#define RESET     0xFD00FF // Resets the Arduino Board(RED)


unsigned long int value = 0; // stores the incoming hex value
byte seq = 0; //stores the current number of executed sequences
byte seq_Array[50];// array to store the movement sequence in terms of integers(1 for FWD, 2 for LEFT and so on..)

//counter for counting the number of times program pass through a movement function(fwd, lft etc.)
int fwd_Counter = -1;
int lft_Counter = -1;
int rgt_Counter = -1;
int bwd_Counter = -1;
int stp_Counter = -1;

//global "current time" variables for different movement functions(fwd, lft etc.)
unsigned long int current_Time0 = 0;// for FWD movement
unsigned long int current_Time1 = 0;// for LEFT movement
unsigned long int current_Time2 = 0;// for RIGHT movement
unsigned long int current_Time3 = 0;// for BWD movement
unsigned long int current_Time4 = 0;// for STOP

//total time spend by the pgm in executing the movement(fwd, lft etc.) for a particular movement counter
unsigned long int total_Fwd_Time[10];
unsigned long int total_Lft_Time[10];
unsigned long int total_Rgt_Time[10];
unsigned long int total_Bwd_Time[10];
unsigned long int total_Stp_Time[10];

/*
 ************Arduino Reset Pin**************
 */
#define RESET_PIN A0

void setup() {

  // set mode of the pins as output
  for (int i = 2; i <= 7; i++) {
    pinMode(i, OUTPUT);
  }


  // start serial communication
  Serial.begin(9600);
  // In case the interrupt driver crashes on setup, give a clue
  // to the user what's going on.
  Serial.println("Enabling IRin");
  irrecv.enableIRIn(); // Start the receiver
  Serial.println("Enabled IRin");

}

void loop() {
  if (irrecv.decode(&results)) {
    value = results.value;
    Serial.println(value, HEX);
    irrecv.resume(); // Receive the next value
    delay(200);
  }

  delay(100);
  check_Inst(value);
  value=0;
}

void check_Inst(long int value) {

  switch (value) {
    case FWD:
      go_Forward();
      delay(10);
      break;
    case LFT:
      go_Left();
      delay(10);
      break;
    case RGT:
      go_Right();
      delay(10);
      break;
    case BWD:
      go_Backward();
      delay(10);
      break;
    case STOP:
      go_Stop();
      delay(10);
      break;
    case RPEAT:
      go_In_Seq();
      delay(10);
      break;
    case DEL:
      del_From_Local_Mem();
      delay(10);
      break;
    case RESET:
      pinMode(RESET_PIN,OUTPUT);
      digitalWrite(RESET_PIN,HIGH);   
      break;  
      
    default:
      value = 0;
  }
}

void go_Forward() {
  
  movement_Inst_Fwd();

  current_Time0 = millis();
  int i = seq_Array[(seq - 1)];
  switch (i) {
    case 2:
      total_Lft_Time[lft_Counter + 1] = (current_Time0 - current_Time1);
      lft_Counter++;
      break;

    case 3:
      total_Rgt_Time[rgt_Counter + 1] = (current_Time0 - current_Time2);
      rgt_Counter++;
      break;

    case 4:
      total_Bwd_Time[bwd_Counter + 1] = (current_Time0 - current_Time3);
      bwd_Counter++;
      break;

    case 5:
      total_Stp_Time[stp_Counter + 1] = (current_Time0 - current_Time4);
      stp_Counter++;
      break;
  }

  seq_Array[seq] = 1;
  seq++;
}

void go_Left() {

  movement_Inst_Lft();

  current_Time1 = millis();
  int i = seq_Array[(seq - 1)];
  switch (i) {
    case 1:
      total_Fwd_Time[fwd_Counter + 1] = (current_Time1 - current_Time0);
      fwd_Counter++;
      break;

    case 3:
      total_Rgt_Time[rgt_Counter + 1] = (current_Time1 - current_Time2);
      rgt_Counter++;
      break;

    case 4:
      total_Bwd_Time[bwd_Counter + 1] = (current_Time1 - current_Time3);
      bwd_Counter++;
      break;

    case 5:
      total_Stp_Time[stp_Counter + 1] = (current_Time1 - current_Time4);
      stp_Counter++;
      break;
  }

  seq_Array[seq] = 2;
  seq++;
}

void go_Right() {

  movement_Inst_Rgt();

  current_Time2 = millis();
  int i = seq_Array[(seq - 1)];
  switch (i) {
    case 1:
      total_Fwd_Time[fwd_Counter + 1] = (current_Time2 - current_Time0);
      fwd_Counter++;
      break;

    case 2:
      total_Lft_Time[lft_Counter + 1] = (current_Time2 - current_Time1);
      lft_Counter++;
      break;

    case 4:
      total_Bwd_Time[bwd_Counter + 1] = (current_Time2 - current_Time3);
      bwd_Counter++;
      break;

    case 5:
      total_Stp_Time[stp_Counter + 1] = (current_Time2 - current_Time4);
      stp_Counter++;
      break;
  }

  seq_Array[seq] = 3;
  seq++;
}

void go_Backward() {
  
  movement_Inst_Bwd();

  current_Time3 = millis();
  int i = seq_Array[(seq - 1)];
  switch (i) {
    case 1:
      total_Fwd_Time[fwd_Counter + 1] = (current_Time3 - current_Time0);
      fwd_Counter++;
      break;

    case 2:
      total_Lft_Time[lft_Counter + 1] = (current_Time3 - current_Time1);
      lft_Counter++;
      break;

    case 3:
      total_Rgt_Time[rgt_Counter + 1] = (current_Time3 - current_Time2);
      rgt_Counter++;
      break;

    case 5:
      total_Stp_Time[stp_Counter + 1] = (current_Time3 - current_Time4);
      stp_Counter++;
      break;
  }

  seq_Array[seq] = 4;
  seq++;
}

void go_Stop() {

  movement_Inst_Stp();

  current_Time4 = millis();
  int i = seq_Array[(seq - 1)];
  switch (i) {
    case 1:
      total_Fwd_Time[fwd_Counter + 1] = (current_Time4 - current_Time0);
      fwd_Counter++;
      break;

    case 2:
      total_Lft_Time[lft_Counter + 1] = (current_Time4 - current_Time1);
      lft_Counter++;
      break;

    case 3:
      total_Rgt_Time[rgt_Counter + 1] = (current_Time4 - current_Time2);
      rgt_Counter++;
      break;

    case 4:
      total_Bwd_Time[bwd_Counter + 1] = (current_Time4 - current_Time3);
      bwd_Counter++;
      break;
  }

  seq_Array[seq] = 5;
  seq++;
}

void go_In_Seq(void) {
  value = 0;
  for (int i = 0; i < (seq + 1); i++) {
    int value1 = 0;
    value1 = seq_Array[i];
    switch (value1) {
      case 1:
        static int j = 0;
        go_Forward_Seq(j);
        j++;
        break;
      case 2:
        static int k = 0;
        go_Left_Seq(k);
        k++;
        break;
      case 3:
        static int l = 0;
        go_Right_Seq(l);
        l++;
        break;
      case 4:
        static int m = 0;
        go_Backward_Seq(m);
        m++;
        break;
      case 5:
        static int n = 0;
        go_Stop_Seq(n);
        n++;
        break;
      default:
        j = 0; k = 0; l = 0; m = 0; n = 0;
    }
  }
}

void del_From_Local_Mem() {
  //set the movement counters to their default values
  fwd_Counter = -1;
  lft_Counter = -1;
  rgt_Counter = -1;
  bwd_Counter = - 1;
  stp_Counter = - 1;

  //set the total movement time to its default value
  for (int i = 0; i < 10; i++) {
    total_Fwd_Time[i] = 0;
    total_Lft_Time[i] = 0;
    total_Rgt_Time[i] = 0;
    total_Bwd_Time[i] = 0;
    total_Stp_Time[i] = 0;
  }

  // Reset the sequence array(stored movement instructions)
  for (int i = 0; i < 50; i++) {
    seq_Array[i] = 0;
  }

  seq = 0;
  value = 0;
}

 
/**********************************************************************************************************
     These function moves the car in a direction for the time specified/stored in the total_x_time array
************************************************************************************************************/
void go_Forward_Seq(int j) {
  //go in forward direction sequence
  movement_Inst_Fwd();//
  delay(total_Fwd_Time[j]);
}

void go_Left_Seq(int k) {
  //go in Left direction sequence
  movement_Inst_Lft();
  delay(total_Lft_Time[k]);
}

void go_Right_Seq(int l) {
  //go in right direction sequence
  movement_Inst_Rgt();
  delay(total_Rgt_Time[l]);
}

void go_Backward_Seq(int m) {
  //go in backward direction sequence
  movement_Inst_Bwd();
  delay(total_Bwd_Time[m]);
}

void go_Stop_Seq(int n) {
  //go in Stop sequence
  movement_Inst_Stp();
  delay(total_Stp_Time[n]);
}

/*********************************************************************************************
          These movement instruction are repeated(required) several times in the code
**********************************************************************************************/
void movement_Inst_Fwd(void) {
  Serial.println("Going_Forward");
  // forward movement instructions
  digitalWrite(LM_IN1, HIGH);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, HIGH);
  digitalWrite(RM_IN4, LOW);
}

void movement_Inst_Lft(void) {
  Serial.println("Going_Left");
  // Left movement instructions
  digitalWrite(LM_IN1, LOW);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, HIGH);
  digitalWrite(RM_IN4, LOW);
  delay(500);
  digitalWrite(LM_IN1, LOW);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, LOW);
  digitalWrite(RM_IN4, LOW);
  delay(500);
}

void movement_Inst_Rgt(void) {
  Serial.println("Going_Right");
  // Rgt movement instructions
  digitalWrite(LM_IN1, HIGH);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, LOW);
  digitalWrite(RM_IN4, LOW);
  delay(500);
  digitalWrite(LM_IN1, LOW);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, LOW);
  digitalWrite(RM_IN4, LOW);
  delay(500);

}

void movement_Inst_Bwd(void) {
  Serial.println("Going_Backward");
  // Bwd movement instructions
  digitalWrite(LM_IN1, LOW);
  digitalWrite(LM_IN2, HIGH);
  digitalWrite(RM_IN3, LOW);
  digitalWrite(RM_IN4, HIGH);
}

void movement_Inst_Stp(void) {
  Serial.println("Stopping");
  // Stp movement instructions
  digitalWrite(LM_IN1, LOW);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, LOW);
  digitalWrite(RM_IN4, LOW);
}

Part 7: Arduino code C— EEPROM path memorizing robot (permanent)

/*
************************Path Memorizing Robot****************************
* 
* Created on: May 27, 2021
* Author: Ankit Negi 
* 
* Youtube: www.youtube.com/theelectronicguy
* Website: www.eTechnophiles.com
*/

#include <IRremote.h>// IR remote library
#include <EEPROM.h>// EEPROM pre-installed library


/*
   ***********Left Motor***********
*/

// IN 1
#define LM_IN1    2
// IN 2
#define LM_IN2    4
/*
   ************Right Motor************
*/
// IN 3
#define RM_IN3    5
// IN 4
#define RM_IN4    7


/*
   ********************IR Receiver**********************
*/
# define RECV_PIN 10// Pin to which IR reciever is connected

IRrecv irrecv(RECV_PIN);// Pass the pin number to the function

decode_results results;// variable results stores the decoded hex values

/*
 ************HEX code of all the buttons used in the project**************
 */
#define FWD       0xFD8877 // go forward(2)
#define LFT       0xFD28D7 // go left(4)
#define RGT       0xFD6897 // go right(6)
#define BWD       0xFD9867 // go backward(8)
#define STOP      0xFD30CF // stop(0)
#define RPEAT     0xFD708F // repeat the stored sequence of movement from the temporary memory(automatically stores) (REPT)
#define DEL       0xFDB04F // delete the stored sequence of movement from temporary memory(EQ)
#define PERST     0xFD40BF // copy the sequence from temp. memory to the peramanent memory(EEPROM)
#define PLAYEPROM 0xFD609F // repeat the sequence stored in EEPROM(FASTFWD)
#define RESET     0xFD00FF // Resets the Arduino Board(RED)
                  


/*
 ************Global Variables and Arrays**************
 */
 
unsigned long int value = 0; // stores the incoming hex value
byte seq = 0; //stores the current number of executed sequences
byte seq_Array[50];// array to store the movement sequence in terms of integers(1 for FWD, 2 for LEFT and so on..)

//counter for counting the number of times program pass through a movement function(fwd, lft etc.)
int fwd_Counter = -1;
int lft_Counter = -1;
int rgt_Counter = -1;
int bwd_Counter = -1;
int stp_Counter = -1;

//global "current time" variables for different movement functions(fwd, lft etc.)
unsigned long int current_Time0 = 0;// for FWD movement
unsigned long int current_Time1 = 0;// for LEFT movement
unsigned long int current_Time2 = 0;// for RIGHT movement
unsigned long int current_Time3 = 0;// for BWD movement
unsigned long int current_Time4 = 0;// for STOP

//total time spend by the pgm in executing the movement(fwd, lft etc.) for a particular movement counter
unsigned long int total_Fwd_Time[10];
unsigned long int total_Lft_Time[10];
unsigned long int total_Rgt_Time[10];
unsigned long int total_Bwd_Time[10];
unsigned long int total_Stp_Time[10];

/*
 ************Arduino Reset Pin**************
 */
#define RESET_PIN A0

 
void setup() {

  // set mode of the pins as output
  for (int i = 2; i <= 7; i++) {
    pinMode(i, OUTPUT);
  }


  // start serial communication
  Serial.begin(9600);
  // In case the interrupt driver crashes on setup, give a clue
  // to the user what's going on.
  Serial.println("Enabling IRin");
  irrecv.enableIRIn(); // Start the receiver
  Serial.println("Enabled IRin");

}

void loop() {
  if (irrecv.decode(&results)) {
    value = results.value;
    Serial.println(value, HEX);
    irrecv.resume(); // Receive the next value
    delay(200);
  }

  delay(100);
  check_Inst(value);
  value=0;

}

void check_Inst(long int value) {

  switch (value) {
    case FWD:
      go_Forward();
      delay(10);
      break;
    case LFT:
      go_Left();
      delay(10);
      break;
    case RGT:
      go_Right();
      delay(10);
      break;
    case BWD:
      go_Backward();
      delay(10);
      break;
    case STOP:
      go_Stop();
      delay(10);
      break;
    case RPEAT:
      go_In_Seq();
      delay(10);
      break;
    case DEL:
      del_From_Local_Mem();
      delay(10);
      break;
    case PERST:
      write_To_Permt_Mem();
      delay(10);
      break;  
    case PLAYEPROM:
      Read_Permt_Mem();
      delay(10);
      break;   
    case RESET:
      pinMode(RESET_PIN, OUTPUT);
      digitalWrite(RESET_PIN,HIGH);   
      break;
                
     default:
      value = 0;
  }
}

void go_Forward() {
  movement_Inst_Fwd();

  current_Time0 = millis();
  int i = seq_Array[(seq - 1)];
  switch (i) {
    case 2:
      // total time elaspsed since Left button is pressed including rest time 
      total_Lft_Time[lft_Counter + 1] = (current_Time0 - current_Time1);
      lft_Counter++;
      break;

    case 3:
      // total time elaspsed since Right button is pressed including rest time 
      total_Rgt_Time[rgt_Counter + 1] = (current_Time0 - current_Time2);
      rgt_Counter++;
      break;

    case 4:
      total_Bwd_Time[bwd_Counter + 1] = (current_Time0 - current_Time3);
      bwd_Counter++;
      break;

    case 5:
      total_Stp_Time[stp_Counter + 1] = (current_Time0 - current_Time4);
      stp_Counter++;
      break;
  }

  seq_Array[seq] = 1;
  seq++;
}

void go_Left() {
  movement_Inst_Lft();

  current_Time1 = millis();
  int i = seq_Array[(seq - 1)];
  switch (i) {
    case 1:
      total_Fwd_Time[fwd_Counter + 1] = (current_Time1 - current_Time0);
      fwd_Counter++;
      break;

    case 3:
      total_Rgt_Time[rgt_Counter + 1] = (current_Time1 - current_Time2);
      rgt_Counter++;
      break;

    case 4:
      total_Bwd_Time[bwd_Counter + 1] = (current_Time1 - current_Time3);
      bwd_Counter++;
      break;

    case 5:
      total_Stp_Time[stp_Counter + 1] = (current_Time1 - current_Time4);
      stp_Counter++;
      break;
  }

  seq_Array[seq] = 2;
  seq++;
}

void go_Right() {
  movement_Inst_Rgt();

  current_Time2 = millis();
  int i = seq_Array[(seq - 1)];
  switch (i) {
    case 1:
      total_Fwd_Time[fwd_Counter + 1] = (current_Time2 - current_Time0);
      fwd_Counter++;
      break;

    case 2:
      total_Lft_Time[lft_Counter + 1] = (current_Time2 - current_Time1);
      lft_Counter++;
      break;

    case 4:
      total_Bwd_Time[bwd_Counter + 1] = (current_Time2 - current_Time3);
      bwd_Counter++;
      break;

    case 5:
      total_Stp_Time[stp_Counter + 1] = (current_Time2 - current_Time4);
      stp_Counter++;
      break;
  }

  seq_Array[seq] = 3;
  seq++;
}

void go_Backward() {
  movement_Inst_Bwd();

  current_Time3 = millis();
  int i = seq_Array[(seq - 1)];
  switch (i) {
    case 1:
      total_Fwd_Time[fwd_Counter + 1] = (current_Time3 - current_Time0);
      fwd_Counter++;
      break;

    case 2:
      total_Lft_Time[lft_Counter + 1] = (current_Time3 - current_Time1);
      lft_Counter++;
      break;

    case 3:
      total_Rgt_Time[rgt_Counter + 1] = (current_Time3 - current_Time2);
      rgt_Counter++;
      break;

    case 5:
      total_Stp_Time[stp_Counter + 1] = (current_Time3 - current_Time4);
      stp_Counter++;
      break;
  }

  seq_Array[seq] = 4;
  seq++;
}

void go_Stop() {
  movement_Inst_Stp();

  current_Time4 = millis();
  int i = seq_Array[(seq - 1)];
  switch (i) {
    case 1:
      total_Fwd_Time[fwd_Counter + 1] = (current_Time4 - current_Time0);
      fwd_Counter++;
      break;

    case 2:
      total_Lft_Time[lft_Counter + 1] = (current_Time4 - current_Time1);
      lft_Counter++;
      break;

    case 3:
      total_Rgt_Time[rgt_Counter + 1] = (current_Time4 - current_Time2);
      rgt_Counter++;
      break;

    case 4:
      total_Bwd_Time[bwd_Counter + 1] = (current_Time4 - current_Time3);
      bwd_Counter++;
      break;
  }

  seq_Array[seq] = 5;
  seq++;
}

void go_In_Seq(void) {
  value = 0;
  for (int i = 0; i < (seq + 1); i++) {
    int value1 = 0;
    value1 = seq_Array[i];
    switch (value1) {
      case 1:
        static int j = 0;
        go_Forward_Seq(j);
        j++;
        break;
      case 2:
        static int k = 0;
        go_Left_Seq(k);
        k++;
        break;
      case 3:
        static int l = 0;
        go_Right_Seq(l);
        l++;
        break;
      case 4:
        static int m = 0;
        go_Backward_Seq(m);
        m++;
        break;
      case 5:
        static int n = 0;
        go_Stop_Seq(n);
        n++;
        break;
      default:
        j = 0; k = 0; l = 0; m = 0; n = 0;
    }
  }
}

void del_From_Local_Mem() {
  //set the movement counters to their default values
  fwd_Counter = -1;
  lft_Counter = -1;
  rgt_Counter = -1;
  bwd_Counter = - 1;
  stp_Counter = - 1;

  //set the total movement time to its default value
  for (int i = 0; i < 10; i++) {
    total_Fwd_Time[i] = 0;
    total_Lft_Time[i] = 0;
    total_Rgt_Time[i] = 0;
    total_Bwd_Time[i] = 0;
    total_Stp_Time[i] = 0;
  }

  // Reset the sequence array(stored movement instructions)
  for (int i = 0; i < 50; i++) {
    seq_Array[i] = 0;
  }

  seq = 0;
  
}


/**********************************************************************************************************
     This function copy the data from the arrays to the EEPROM(permanent memory)
************************************************************************************************************/

void write_To_Permt_Mem(){
  // total number of movement is stored in a random address i.e, 100
  EEPROM.write(100,seq);
    
  //writing the movement sequence
  for(int i=0; i<seq; i++){ 
  EEPROM.write(2*i,seq_Array[i]);
  }

  //storing the time bw two successive movements
  for(int i=1; i<seq+1; i++){           
  if(seq_Array[i-1]==1){
    static byte a=0;
    EEPROM.write(2*i-1,(total_Fwd_Time[a])/1000);// Note: One location can store maximum value of 255, hence the time is divided by 1000 here. And then multiplied by 1000 while retreiving the data from EEPROM location
    a++;
    }
  else if(seq_Array[i-1]==2){
    static byte b=0;
    EEPROM.write(2*i-1,(total_Lft_Time[b])/1000);
    b++;
    }
  else if(seq_Array[i-1]==3){
    static byte c=0;
    EEPROM.write(2*i-1,(total_Rgt_Time[c])/1000);
    c++;
    }
  else if(seq_Array[i-1]==4){
    static byte d=0;
    EEPROM.write(2*i-1,(total_Bwd_Time[d])/1000);  
    d++;
    }
  else if(seq_Array[i-1]==5){
    static byte e=0;
    EEPROM.write(2*i-1,(total_Stp_Time[e])/1000);  
    e++;
    }             
  }
 } 

 
/**********************************************************************************************************
     This function reads the stored sequence from the EEPROM(permanent memory)
************************************************************************************************************/

void Read_Permt_Mem(){
  // Read from permanent memory
   byte x = EEPROM.read(100);
   for(int i=0; i<x+1; i++){
    byte r = EEPROM.read(2*i);
    switch(r){
      case 1:
        movement_Inst_Fwd();
        break;
      case 2:
        movement_Inst_Lft();
        break;
      case 3:
        movement_Inst_Rgt();
        break;
      case 4:
        movement_Inst_Bwd();
        break; 
      case 5:
        movement_Inst_Stp();
        break;                          
      }
     delay((EEPROM.read(i+1))*1000);    // multiplied by thousand because the original time was divided by 1000 while storing in EEPROM.
    }
  }
 
/**********************************************************************************************************
     These function moves the car in a direction for the time specified/stored in the total_x_time array
************************************************************************************************************/
void go_Forward_Seq(int j) {
  //go in forward direction sequence
  movement_Inst_Fwd();
  delay(total_Fwd_Time[j]);
}

void go_Left_Seq(int k) {
  //go in Left direction sequence
  movement_Inst_Lft();
  delay(total_Lft_Time[k]);
}

void go_Right_Seq(int l) {
  //go in right direction sequence
  movement_Inst_Rgt();
  delay(total_Rgt_Time[l]);
}

void go_Backward_Seq(int m) {
  //go in backward direction sequence
  movement_Inst_Bwd();
  delay(total_Bwd_Time[m]);
}

void go_Stop_Seq(int n) {
  //go in Stop sequence
  movement_Inst_Stp();
  delay(total_Stp_Time[n]);
}

/*********************************************************************************************
          These movement instruction are repeated(required) several times in the code
**********************************************************************************************/
void movement_Inst_Fwd(void) {
  // forward movement instructions
  Serial.println("Going_Forward");
  digitalWrite(LM_IN1, HIGH);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, HIGH);
  digitalWrite(RM_IN4, LOW);
}

void movement_Inst_Lft(void) {
  // Left movement instructions
  Serial.println("Going_Left");
  digitalWrite(LM_IN1, LOW);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, HIGH);
  digitalWrite(RM_IN4, LOW);
  delay(500);// default delay for smooth rotation.
  digitalWrite(LM_IN1, LOW);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, LOW);
  digitalWrite(RM_IN4, LOW);
  delay(500);
  // NOTE: The minimum delay for RIGHT/LEFT movement is 1S(inluding .5s ON time & .5s OFF time). Hence subtract 1s before repeating this movement
}

void movement_Inst_Rgt(void) {
  // Rgt movement instructions
  Serial.println("Going_Right"); 
  digitalWrite(LM_IN1, HIGH);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, LOW);
  digitalWrite(RM_IN4, LOW);
  delay(500);// default delay for smooth rotation.
  digitalWrite(LM_IN1, LOW);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, LOW);
  digitalWrite(RM_IN4, LOW);
  delay(500);
  // NOTE: The minimum delay for RIGHT/LEFT movement is 1S(inluding .5s ON time & .5s OFF time). Hence subtract 1s before repeating this movement 

}

void movement_Inst_Bwd(void) {
  // Bwd movement instructions
  Serial.println("Going_Backward"); 
  digitalWrite(LM_IN1, LOW);
  digitalWrite(LM_IN2, HIGH);
  digitalWrite(RM_IN3, LOW);
  digitalWrite(RM_IN4, HIGH);
}

void movement_Inst_Stp(void) {
  // Stp movement instructions
  Serial.println("Stopping");
  digitalWrite(LM_IN1, LOW);
  digitalWrite(LM_IN2, LOW);
  digitalWrite(RM_IN3, LOW);
  digitalWrite(RM_IN4, LOW);
}

Interested in buying this project?


Photo of author

Ankit Negi

I am an electrical engineer by profession who loves to tinker with electronic devices and gadgets and have been doing so for over six years now. During this period, I have made many projects and helped thousands of students through my blog and YouTube videos. I am active on Linkedin.

1 thought on “How to Make a Path Memorizing Robot using Arduino”

Leave a Comment