Arduino 2WD Lafvin Robot

I started a Robotics Club recently at the Institute I’m currently working at in which I’ve been slowly getting my beginner students to become acquianted with Arduino-based robots and Arduino coding.

We purchased a set of Lafvin 2WD Robot Kits (see image above) from Little Bird Electronics and step-by-step I’ve been getting my students to learn how to control each piece of hardware attached to the robot. We’re working towards getting the robot to move around a room without bumping into anything it might encounter along the way.

In this post I thought I’d share some code I’ve written for this club that uses an ultrasonic sensor mounted on a servo motor to detect the distance of obstacles from the robot.

The code gets the rotor to sweep 180 degrees in one direction and then back again. It stops, however, every 45 degrees to use the ultrasonic sensor to detect if there is an object within 30cm (1 foot) of the machine. If there is, a message is printed on the Serial Monitor.

Key equipment used is as follows:

  • Arduino Uno R3
  • Arduino Sensor Expansion Shield V5.0 (attached to Uno)
  • SG90 Micro Servo motor
  • Ultrasonic Sensor (HC-SR04)

This video shows how we have put together the pieces and connections. The relevant connection diagrams are as follows:

The code below is well-commented so there’s no need for me to explain any more. But please note that you will need to install the “Servo” library before running this code.

If you have any questions, post them below and I’ll get back to you as soon as I can.

/* 
  This code uses an Ultrasonic (US) sensor mounted on a servo motor to detect obstacles
  for a moving robot. The rotor sweeps 180 degrees from left to right and then
  back again. It takes readings every 45 degrees (and 200 milliseconds). If there is 
  an object within 30cm, it prints a message to the Serial monitor. 
  Once the obstacle is cleared, the rotor will start sweeping again.

  My code works for an Arduino Uno R3 board and a Sensor ExapansionShield v5.0. 
  The rotor and sensor are connected to pins A0-A2 of the Power Shield.

  I have also put in skeleton code (via "sweep" variable) to indicate where one might 
  write code to manoeuvre a robot if an obstacle is encountered.
*/

#include <Servo.h> // Servo library
#include "SR04.h" // Ultrasonic (US) sensor library
#define TRIG_PIN A1 // UltraSonic I/O 
#define ECHO_PIN A0 // UltraSonic I/O

// Create Ultrasonic object
SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);
int obj_distance; // variable to store distance returned by US sensor
int distance_threshold = 30; // how close to get to an object before deciding to act

// Create a servo object
Servo myServo;

int sweep_directions[] = {0, 45, 90, 135, 180}; // possible rotor positions (degrees)
int direction_index = 0; // current index of rotor position
int direction = 1; // Direction of rotor: 1 for forward (sweep right), -1 for backward (sweep left)

// Time tracking variables to only move the rotor between certain elapsed time intervals
unsigned long previousMillis = 0;
const unsigned int interval = 200; // interval in milliseconds between US readings

// this boolean is not used in this code but I left it here to give you an idea of how 
// you could build an obstacle avoiding robot in the future
bool sweep = true; 

void setup() {
  // Start the serial monitor
  Serial.begin(9600);

  // Connect servo motor to shield
  myServo.attach(A2);
}

void loop() {
  // Get the current time
  unsigned long currentMillis = millis();

  // Check if the interval has passed from last reading
  if (currentMillis - previousMillis >= interval) {
    obj_distance = sr04.Distance(); // get obstacle distance
    
    if(obj_distance <= distance_threshold) {
      // obstacle detected within distance threshold
      Serial.print("STOP! Obstacle distance: ");
      Serial.println(obj_distance);
      /* 
        You would write code here to stop the robot from moving,
        set sweep to false to give the robot time to work out 
        which direction to turn and then to manoeuvre.

        Once, we're good to go again, set sweep to true.
      */
      
    }
    else if(sweep) {
      // If we're in "sweep" state, we change rotor direction and
      // wait another 200 milliseconds from the last reading
      myServo.write(sweep_directions[direction_index]);
      Serial.print("Sweep direction:");
      Serial.println(sweep_directions[direction_index]);

      // Check if the end or beginning of the array is reached
      if (direction_index == 4) {
        direction = -1; // Reverse direction of sweeping at the end
      } else if (direction_index == 0) {
        direction = 1; // Reverse direction at the beginning
      }
      direction_index += direction; // increment or decrement index accordingly
    }
    previousMillis = currentMillis;
  }
}

To be informed when new content like this is posted, subscribe to the mailing list:


(Note: If this post is found on a site other than zbigatron.com, a bot has stolen it – it’s been happening a lot lately)

Leave a Reply

Your email address will not be published. Required fields are marked *