Programmable 4wd robot with start button

Hello everyone!:slight_smile: I'm curious if it is possible to make 4wd programmed arduino robot with additional buttons. In other words, there's 4wd robot and there are 4 direction buttons(right,left,forward,backward) and start button. I want to make it like if someone pushes combinations like right-right-left-forward, it should go 2 steps to right, 1step to left and to forward. After setting this combos, start button should be pressed so robot could move in the direction that has been set before. Dear all, tell me pls, is this possible in arduino? I've searched many resources, unfortunately I haven't found anything similar to my case. Thanks.

So what you want to do is receive commands and just remember them. Then when another (start) command arrives you read back what you remembered and apply the commands. I can't see anything very difficult about that.

I'd start by just getting a robot that runs using all the commands normally in real-time. There are many examples of those around. Then when you have that working adding the extra "Remember commands to apply later" mode should be straightforward.

Which part of it seems difficult to you?

Steve

Sure it is.

slipstick:
So what you want to do is receive commands and just remember them. Then when another (start) command arrives you read back what you remembered and apply the commands. I can't see anything very difficult about that.

I'd start by just getting a robot that runs using all the commands normally in real-time. There are many examples of those around. Then when you have that working adding the extra "Remember commands to apply later" mode should be straightforward.

Which part of it seems difficult to you?

Steve

Thx for reply, Steve) The difficult part to me is "remembering" things... I can easily program moving whatever the route is, even if it is an obstacle avoiding robot... But as I mentioned before, I have no idea how to "remember" direction commands and after execute start command. If it is just only direction commands, I could easily write it in loop. But when it comes to start command - I stuck... Could you please provide a similar case? thank you:)

During the input phase, store the direction and distance commands in an array, until the start button is pushed or the array is filled completely.

Then, a separate part of the program gets commands out of the array and executes them.

If you will post details about what you already have, forum members can add suggestions.

Alright, here’s my source code(I use a matrix keypad for this called YL-102):

#include <Keypad.h>

//L298N
const int LeftMotorForward = 5;
const int LeftMotorBackward = 4;
const int RightMotorForward = 3;
const int RightMotorBackward = 2;

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns

char keys[ROWS][COLS] = {
  {'a','b','c','d'},
  {'e','f','g','h'},
  {'i','j','k','l'},
  {'m','n','o','p'}
  };
  
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {10, 11, 12, 13}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

boolean goesForward = false;

void setup(){
  pinMode(LeftMotorForward, OUTPUT);
  pinMode(LeftMotorBackward, OUTPUT);
  pinMode(RightMotorForward, OUTPUT);
  pinMode(RightMotorBackward, OUTPUT);
  Serial.begin(9600);
}

void loop(){
  char key = keypad.getKey();

  if (key != NO_KEY){
  Serial.println(key);
  
  if (key == 'a'){
    moveForward();  
    }
  if (key == 'b'){
    moveStop();
  }
  if (key == 'c'){
    moveBackward();
  }
  }
  }
  
void moveStop(){
  
  digitalWrite(RightMotorForward, LOW);
  digitalWrite(LeftMotorForward, LOW);
  digitalWrite(RightMotorBackward, LOW);
  digitalWrite(LeftMotorBackward, LOW);
}

void moveForward(){

  if(!goesForward){

    goesForward=true;
    
    digitalWrite(LeftMotorForward, HIGH);
    digitalWrite(RightMotorForward, HIGH);
  
    digitalWrite(LeftMotorBackward, LOW);
    digitalWrite(RightMotorBackward, LOW); 
  }
}

void moveBackward(){

  goesForward=false;

  digitalWrite(LeftMotorBackward, HIGH);
  digitalWrite(RightMotorBackward, HIGH);
  
  digitalWrite(LeftMotorForward, LOW);
  digitalWrite(RightMotorForward, LOW);
  
}

void turnRight(){

  digitalWrite(LeftMotorForward, HIGH);
  digitalWrite(RightMotorBackward, HIGH);
  
  digitalWrite(LeftMotorBackward, LOW);
  digitalWrite(RightMotorForward, LOW);
  
  delay(500);
  
  digitalWrite(LeftMotorForward, HIGH);
  digitalWrite(RightMotorForward, HIGH);
  
  digitalWrite(LeftMotorBackward, LOW);
  digitalWrite(RightMotorBackward, LOW);
 
  
  
}

void turnLeft(){

  digitalWrite(LeftMotorBackward, HIGH);
  digitalWrite(RightMotorForward, HIGH);
  
  digitalWrite(LeftMotorForward, LOW);
  digitalWrite(RightMotorBackward, LOW);

  delay(500);
  
  digitalWrite(LeftMotorForward, HIGH);
  digitalWrite(RightMotorForward, HIGH);
  
  digitalWrite(LeftMotorBackward, LOW);
  digitalWrite(RightMotorBackward, LOW);
}

The thing is it is needed to be like this project which uses sequences to playback LEDs in given order after pushing buttons: How to Record a Push Button Sequence with Arduino - Learn Robotics
The source code of the project in the link above(in case it’s unavailable):

/*
 * Record & Play Button Presses Template
 * "records" button presses and plays them back sequentially using LEDs.
 * Requires 6X buttons and 6X LED's 4X 
 * Full tutorial available on
 * on www.learnrobotics.org/blog
 * 
 * February 20, 2019
 * Liz Miller
 *
 */

int arr[10];
boolean previous = LOW;
unsigned long time1 = 0;
int debounce = 200;
int index_state = 0;
boolean empty = false;

int button[4] = {2,4,6,8};
int leds[4] = {3,5,7,9};

int play_led = 13;
int play_button=12;

int record_led = 11;
int record_button=10;
int record_count = 0;
int state = HIGH;

bool full = false;

void setup()
{
   for(int i = 0;i<5 ;i++){
    pinMode(button[i],INPUT);
    pinMode(leds[i],OUTPUT);
    }
   for(int n=0;n<10;n++) arr[n] = 7;//initialization
   pinMode(record_led, OUTPUT);
   pinMode(play_led, OUTPUT);
   digitalWrite(play_led,HIGH);
   empty=true;
   Serial.begin(9600);
}

void blink_record(int repeat){
  for(int i=0; i<repeat; i++){
    digitalWrite(record_led, HIGH);
    delay(100);
    digitalWrite(record_led,LOW);
    delay(100);
  }
}

/*
 * Shuts off 4 LED's
 * Sequence array is NOT empty
 */
void all_off(){
  for(int i=0;i<5;i++){
    digitalWrite(leds[i],LOW);
  }
  empty=false;
}

/*
 * Prints out the sequence array to Serial
 */
void show_array(){
   for (int i = 0; i<10; i++){
    Serial.print(arr[i]);
  }
  Serial.println();
}

/*
 * Erases the sequence array by filling with arbitrary number we'll never use
 * Sequence array is empty
 */
void erase_stored(){
  for(int n=0;n<10;n++) arr[n] = 7; //random number we'll never use
  empty=true;
}

/*
 * Plays back the sequence routine when triggered
 * Erases the sequence array upon completion
 */
void playback(){
  digitalWrite(play_led,HIGH);
  digitalWrite(record_led,LOW);
  
    for(int i = 0; i<10; i++){
      if (arr[i]!=7){
        digitalWrite(leds[arr[i]],HIGH);
        delay(250);
        digitalWrite(leds[arr[i]],LOW);
        delay(250);
    }
  }
  digitalWrite(play_led,LOW);
  erase_stored(); //erases array for the next time
  delay(1000);
  digitalWrite(play_led,HIGH);
  show_array();
  index_state=-1;
}

/*
 * Records and plays back a sequence using button presses
 * Record button must be triggered to record a sequence
 * Play button triggers the playback
 */
void play_record(){
  boolean mode = digitalRead(button[0]) || digitalRead(button[1]) || digitalRead(button[2]) || digitalRead(button[3]) || digitalRead(record_button) || digitalRead(play_button);
  
  //wait here till one of the pushbutton goes high;
  while(mode == LOW && record_count <= 1){
    
    mode = digitalRead(button[0]) || digitalRead(button[1]) || digitalRead(button[2]) || digitalRead(button[3]) || digitalRead(record_button) || digitalRead(play_button);
    if( mode == HIGH && previous == LOW && millis() - time1 > debounce){

  //find out which one is high and store that value in array;

  /*
   * EXAMPLE CASE for single button.
   * Add additional readings to check additional buttons
   */
    if(digitalRead(button[0]) && record_count ==1) {
      arr[index_state] = 0; //set the button 0 to the current index
      digitalWrite(leds[0],HIGH); //turn on the respective LED
      delay(50); //briefly turn on LED to show which button was pressed
      all_off(); //make sure all LEDs are OFF
    }
    
    //**** add your button conditions here ****
    
    
    else;
    
    //print the value and the index;
    Serial.print(arr[index_state]);
    Serial.print(" Stored in index: ");
    Serial.println(index_state);

    /*
     * once we reach an index of 9 we need to reset the 
     * index so that we don't overflow the sequence array
     */
    if(index_state < 9){
      index_state = (index_state + 1);
    }
    
    else{ //wait for PLAY PRESS?
      all_off();
      blink_record(5); //optionally blink the record LED
      index_state = 0; //reset
    }
      
    state = !state;
    //update value of time1 for button debouncing
    time1 =  millis();
    }
  }
}


void loop(){
  play_record();  
}

To be honest, I have no idea how to attach function like moveForward() into for(). In the LED project it’s like digitalWrite(leds[0],HIGH)… But I don’t know how to handle this issue for my project… Please, help me:(

If you would like someone to write code for you, post on the Gigs and Collaborations section. You may be asked to pay for the help.

Otherwise, to learn this stuff, take your time and do it step by step.

  1. Learn how to store keypresses or characters in an array. Study the example you posted.

  2. Learn how to play back those characters, for example, just using serial.print().

  3. When those parts both work, modify the playback function to execute robot commands as in your first program. The playback code might look like this:

   for (int i=0; i<number_of_commands; i++) {
   if (array[i] == 'b'){
    moveStop();
    }
    if (array[i] == 'c') {
    moveBackward();
   }
  } // end for i

The way you describe it you want a "Record" mode in which you just push the buttons but the robot does not move. And then you want to switch into a "Play" mode in which it takes the entries you've recorded and executes them. Is that right? And you talk about moving for 2 steps which suggests that a 'step' is a fixed time motor run. O.k.?

Your current program sees a button then does the move immediately and not for a fixed time or distance. And of course you don't yet have anything other than forward, back and stop. So you need some more keys and move routines or it's not going to do anything very interesting.

But in 'record mode' you can just store the keys a,b,c,d etc in an array.

Then in 'play mode' it should read them back from the array and treat them just like your current program treats directly entered keys (you can basically use the same set of if statements once you've extended them for all the moves).

That LED program looks seriously over-complicated to me. I don't think you need anything quite that complex.

Steve

jremington:
If you would like someone to write code for you, post on the Gigs and Collaborations section. You may be asked to pay for the help.

Otherwise, to learn this stuff, take your time and do it step by step.

  1. Learn how to store keypresses or characters in an array. Study the example you posted.

  2. Learn how to play back those characters, for example, just using serial.print().

  3. When those parts both work, modify the playback function to execute robot commands as in your first program. The playback code might look like this:

   for (int i=0; i<number_of_commands; i++) {

if (array[i] == ‚Äėb‚Äô){
    moveStop();
    }
¬† ¬† if (array[i] == ‚Äėc‚Äô) {
    moveBackward();
  }
  } // end for i

Thanks for the advises, jremington:) I’ll post later my experiments.

slipstick:
The way you describe it you want a "Record" mode in which you just push the buttons but the robot does not move. And then you want to switch into a "Play" mode in which it takes the entries you've recorded and executes them. Is that right? And you talk about moving for 2 steps which suggests that a 'step' is a fixed time motor run. O.k.?

Your current program sees a button then does the move immediately and not for a fixed time or distance. And of course you don't yet have anything other than forward, back and stop. So you need some more keys and move routines or it's not going to do anything very interesting.

But in 'record mode' you can just store the keys a,b,c,d etc in an array.

Then in 'play mode' it should read them back from the array and treat them just like your current program treats directly entered keys (you can basically use the same set of if statements once you've extended them for all the moves).

That LED program looks seriously over-complicated to me. I don't think you need anything quite that complex.

Steve

Thanks for reply, Steve:) The 1st source code is just for example:) The main idea is for teaching purposes for kids. So, you said that I can just store the keys a,b,c,d etc in an array. But how can I call them back in a source code so they can be played in given sequences? I mean, they are not just digits, they are functions like moveForward() and etc... For example, in the source code of the LED project above is given chunk of code that digitalWrite(leds[0],HIGH) will be played:

if(digitalRead(button[0]) && record_count ==1) {
      arr[index_state] = 0; //set the button 0 to the current index
      digitalWrite(leds[0],HIGH); //turn on the respective LED
      delay(50); //briefly turn on LED to show which button was pressed
      all_off(); //make sure all LEDs are OFF
    }

To get the most out of this forum, we suggest that you actually read the responses to your posts, rather than just quoting them.

But how can I call them back in a source code so they can be played in given sequences?

Example given in reply #6, part 3. Take a moment to actually read it.

jremington:
To get the most out of this forum, we suggest that you actually read the responses to your posts, rather than just quoting them.
Example given in reply #6, part 3. Take a moment to actually read it.

Sorry... Shame on me... However, it's literally 48th hour in a row of searching answers for questions(and I have really bad headache)... In the second example are given only single type buttons, not matrix keypad... So I have one question: how can I store values from matrix keypad in an array? Thx.

Get some sleep and then do more research. This has been done MANY times.