Joseph Taylor

Obstacle Avoiding Arduino Robot


This is a group project. We have discussed the requirements of this project and how we plan to meet the requirements. We have also discussed other things that we could work on to boost our marks.

The assignment requires the robot to drive down a corridor, avoiding obstacles using at least two ultrasonic sensor and it has to display data on an LCD display. We decided that the following would be displayed on the LCD:

  • Temperature/Humidity
  • Light level
  • Ultrasonic sensor distances
  • Movement status/direction
  • The data is to be displayed on a 20×4 I2C LCD Display.

The brains of the robot will be an Arduino Uno. Two ultrasonic sensors will be used for obstacle avoidance, and we’ll probably power the robot using a Poundland Power Bank.

We have been given two stepper motors to drive the robot, and we were told to use another wheel to balance the robot. This got me thinking. How cool would it be if the robot was self balancing, utilising an Arduino compatible gyroscope module. I know we don’t need to do this, but it would be pretty cool if the robot balanced all by itself, would it not?

We’ve been given some of the parts to start testing the robot. We’ve been given:

  • Laser cut base frame
  • Laser cut wheels
  • 3D printed motor mounts

The things we’ll need are:

  • DHT11 Temperature/Humidity sensor (from my personal collection)
  • Light dependant resistor (we have been given a couple by the lab technician)

First things first is to get the basics working, like the motors working together and at least 2 ultrasonic sensors working together. We’ll get these working separately and then work on combining the two systems together once we have them functioning separately.

Assembly and motor control

We started to assemble the robot. Here are some pictures:

I started working on getting the two motors working together. I stripped down the code from the Stepper Motor Project, and added the functionality of running a second motor. I chose to operate the motors using Full Step Drive as this provides more torque than Wave Drive, but doesn’t reduce the speed like Half Step Drive does.

Here is the code to get the two motors working together:




/* Stepper Motor Project for EO122
 * Joseph Taylor
 *
 * Designed to drive two unipolar stepper motors (5-wire)
 *
 * ----- Left Motor -----
 * Blue (1) - Pin 8
 * Pink (2) - Pin 9
 * Yellow (3) - Pin 10
 * Orange (4) - Pin 11
 * Red (5) - 5V
 *
 * ----- Right Motor -----
 * Blue (1) - Pin 4
 * Pink (2) - Pin 5
 * Yellow (3) - Pin 6
 * Orange (4) - Pin 7
 * Red (5) - 5V
 *
 */
 
// Assign each motor pin to an Arduino pin
int motorLPin1 = 8;
int motorLPin2 = 9;
int motorLPin3 = 10;
int motorLPin4 = 11;
 
int motorRPin1 = 4;
int motorRPin2 = 5;
int motorRPin3 = 6;
int motorRPin4 = 7;
 
// Set other variables
int delayTime = 0;
int robotDirection = 0;
 
void setup() {
 
 // Initiate all the motor pins
 pinMode(motorLPin1, OUTPUT);
 pinMode(motorLPin2, OUTPUT);
 pinMode(motorLPin3, OUTPUT);
 pinMode(motorLPin4, OUTPUT);
 pinMode(motorRPin1, OUTPUT);
 pinMode(motorRPin2, OUTPUT);
 pinMode(motorRPin3, OUTPUT);
 pinMode(motorRPin4, OUTPUT);
 
}
 
void loop() {
 
 // Run the forward function
 forward();
 
 // Set the delay time between motor pulses (I found 2ms to be the best)
 delayTime = 2;
}
 
 
// The forward function
void forward() {
 if (robotDirection == 0) {
 digitalWrite(motorLPin1, HIGH);
 digitalWrite(motorLPin2, LOW);
 digitalWrite(motorLPin3, LOW);
 digitalWrite(motorLPin4, HIGH);
 
 digitalWrite(motorRPin1, LOW);
 digitalWrite(motorRPin2, LOW);
 digitalWrite(motorRPin3, HIGH);
 digitalWrite(motorRPin4, HIGH);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, HIGH);
 digitalWrite(motorLPin2, HIGH);
 digitalWrite(motorLPin3, LOW);
 digitalWrite(motorLPin4, LOW);
 
 digitalWrite(motorRPin1, LOW);
 digitalWrite(motorRPin2, HIGH);
 digitalWrite(motorRPin3, HIGH);
 digitalWrite(motorRPin4, LOW);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, LOW);
 digitalWrite(motorLPin2, HIGH);
 digitalWrite(motorLPin3, HIGH);
 digitalWrite(motorLPin4, LOW);
 
 digitalWrite(motorRPin1, HIGH);
 digitalWrite(motorRPin2, HIGH);
 digitalWrite(motorRPin3, LOW);
 digitalWrite(motorRPin4, LOW);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, LOW);
 digitalWrite(motorLPin2, LOW);
 digitalWrite(motorLPin3, HIGH);
 digitalWrite(motorLPin4, HIGH);
 
 digitalWrite(motorRPin1, HIGH);
 digitalWrite(motorRPin2, LOW);
 digitalWrite(motorRPin3, LOW);
 digitalWrite(motorRPin4, HIGH);
 
 delay(delayTime);
 
 }
}
 
// The reverse function
void reverse() {
 if (robotDirection == 1) {
 digitalWrite(motorLPin1, LOW);
 digitalWrite(motorLPin2, LOW);
 digitalWrite(motorLPin3, HIGH);
 digitalWrite(motorLPin4, HIGH);
 
 digitalWrite(motorRPin1, HIGH);
 digitalWrite(motorRPin2, LOW);
 digitalWrite(motorRPin3, LOW);
 digitalWrite(motorRPin4, HIGH);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, LOW);
 digitalWrite(motorLPin2, HIGH);
 digitalWrite(motorLPin3, HIGH);
 digitalWrite(motorLPin4, LOW);
 
 digitalWrite(motorRPin1, HIGH);
 digitalWrite(motorRPin2, HIGH);
 digitalWrite(motorRPin3, LOW);
 digitalWrite(motorRPin4, LOW);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, HIGH);
 digitalWrite(motorLPin2, HIGH);
 digitalWrite(motorLPin3, LOW);
 digitalWrite(motorLPin4, LOW);
 
 digitalWrite(motorRPin1, LOW);
 digitalWrite(motorRPin2, HIGH);
 digitalWrite(motorRPin3, HIGH);
 digitalWrite(motorRPin4, LOW);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, HIGH);
 digitalWrite(motorLPin2, LOW);
 digitalWrite(motorLPin3, LOW);
 digitalWrite(motorLPin4, HIGH);
 
 digitalWrite(motorRPin1, LOW);
 digitalWrite(motorRPin2, LOW);
 digitalWrite(motorRPin3, HIGH);
 digitalWrite(motorRPin4, HIGH);
 
 delay(delayTime);
 }
}
 
// The clockwise function
void clockwise() {
 if (robotDirection == 2) {
 digitalWrite(motorLPin1, HIGH);
 digitalWrite(motorLPin2, LOW);
 digitalWrite(motorLPin3, LOW);
 digitalWrite(motorLPin4, HIGH);
 
 digitalWrite(motorRPin1, HIGH);
 digitalWrite(motorRPin2, LOW);
 digitalWrite(motorRPin3, LOW);
 digitalWrite(motorRPin4, HIGH);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, HIGH);
 digitalWrite(motorLPin2, HIGH);
 digitalWrite(motorLPin3, LOW);
 digitalWrite(motorLPin4, LOW);
 
 digitalWrite(motorRPin1, HIGH);
 digitalWrite(motorRPin2, HIGH);
 digitalWrite(motorRPin3, LOW);
 digitalWrite(motorRPin4, LOW);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, LOW);
 digitalWrite(motorLPin2, HIGH);
 digitalWrite(motorLPin3, HIGH);
 digitalWrite(motorLPin4, LOW);
 
 digitalWrite(motorRPin1, LOW);
 digitalWrite(motorRPin2, HIGH);
 digitalWrite(motorRPin3, HIGH);
 digitalWrite(motorRPin4, LOW);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, LOW);
 digitalWrite(motorLPin2, LOW);
 digitalWrite(motorLPin3, HIGH);
 digitalWrite(motorLPin4, HIGH);
 
 digitalWrite(motorRPin1, LOW);
 digitalWrite(motorRPin2, LOW);
 digitalWrite(motorRPin3, HIGH);
 digitalWrite(motorRPin4, HIGH);
 
 delay(delayTime);
 
 }
}
 
// The anticlockwise function
void anticlockwise() {
 if (robotDirection == 3) {
 digitalWrite(motorLPin1, LOW);
 digitalWrite(motorLPin2, LOW);
 digitalWrite(motorLPin3, HIGH);
 digitalWrite(motorLPin4, HIGH);
 
 digitalWrite(motorRPin1, LOW);
 digitalWrite(motorRPin2, LOW);
 digitalWrite(motorRPin3, HIGH);
 digitalWrite(motorRPin4, HIGH);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, LOW);
 digitalWrite(motorLPin2, HIGH);
 digitalWrite(motorLPin3, HIGH);
 digitalWrite(motorLPin4, LOW);
 
 digitalWrite(motorRPin1, LOW);
 digitalWrite(motorRPin2, HIGH);
 digitalWrite(motorRPin3, HIGH);
 digitalWrite(motorRPin4, LOW);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, HIGH);
 digitalWrite(motorLPin2, HIGH);
 digitalWrite(motorLPin3, LOW);
 digitalWrite(motorLPin4, LOW);
 
 digitalWrite(motorRPin1, HIGH);
 digitalWrite(motorRPin2, HIGH);
 digitalWrite(motorRPin3, LOW);
 digitalWrite(motorRPin4, LOW);
 
 delay(delayTime);
 
 digitalWrite(motorLPin1, HIGH);
 digitalWrite(motorLPin2, LOW);
 digitalWrite(motorLPin3, LOW);
 digitalWrite(motorLPin4, HIGH);
 
 digitalWrite(motorRPin1, HIGH);
 digitalWrite(motorRPin2, LOW);
 digitalWrite(motorRPin3, LOW);
 digitalWrite(motorRPin4, HIGH);
 
 delay(delayTime);
 
 }
}
						

The code above is working with the breadboard Blu-Tacked onto the base.

Because the orientation of one of the motors is the opposite to the other, I had to modify the code so that the second motor ran anti-clockwise. I put all of this in it’s own function called ‘forward()’. The next step will be to create a ‘reverse()’ function and the ability for the robot to turn.

Here is a video of the robot moving forward. I’ve powered the Arduino using my portable USB charger (sorry about the vertical video, but I think it kind of works for this video):


PCB Design

So far we have been using breadboards to test the individual components. We were introduced to Proteus 8.5. This is the piece of software that we’re expected to design our PCBs for this project with. We have to make a shield that sits on top of the Arduino to enable connectivity with all of the components.

I have designed the shield PCB and it has been printed. A couple of weeks ago when I first started this project I was told that I could design the PCB to be double sided “if I was feeling brave”. I felt brave and designed the PCB to be double sided. As it turns out, the uni doesn’t have the capability to print double sided PCBs. This was slightly irritating, but luckily I’d only put the bare minimum on the second side, meaning there would only be a few bodge wires.

Here is a screenshot of my PBC in Proteus 8:

Here is a picture of the PCB (ignore the “51”, that is just a number to help the technician identify everyone’s PCBs):

It turns out I made a mistake while designing my PCB, I ended up connecting the 5V and GND rails together. Other than that, the motor drive side of things all works as expected! The pictures below show the fully soldered PCB:

This video shows the robot moving around with it’s shiny new PCB shield (again, sorry about the vertical video, but I think it kind of works for this video):


Power Supply

I have used a Poundland battery bank to power it, as it supplies a pretty stable 5V line and it is rechargeable. Much better than the 3x AA battery pack we were provided, which we were expected to connect to the 5V line, even though 3x AA batteries provide an unregulated nominal voltage of 4.5V. This can cause inconsistencies when using the analogue input as the 5V rail is used as a reference for the analogue to digital converter.

LCD Display

The next thing to get working was the LCD display. Having the LCD working would make it easier to get the sensors working, as we would have a way of seeing the sensor outputs. This was done simply by using the LiquidCrystal_I2C Arduino library.




#include <Wire.h>;
#include <LiquidCrystal_I2C.h>;
 
// Set the LCD address to 0x27 for a 16 chars and 4 line display
LiquidCrystal_I2C lcd(0x27, 20, 4);
 
void setup()
{
 // initialize the LCD
 lcd.begin();
 
 // Turn on the blacklight and print a message.
 lcd.backlight();
 lcd.setCursor(0, 0);
 lcd.print("Line 1");
 lcd.setCursor(0, 1);
 lcd.print("Line 2");
 lcd.setCursor(0, 2);
 lcd.print("Line 3");
 lcd.setCursor(0, 3);
 lcd.print("Line 4");
}
 
void loop()
{
 // Do nothing here...
}
				

To be continued...


If you have any questions about this project, or any others on my site get in touch!