More Related Content Similar to JuniorDesignReport Similar to JuniorDesignReport (20) JuniorDesignReport2. Abstract:
The goal of this project was to create a robotic system that could mimic the
functions of the famous Minesweeper game. Teams of three or four were
assigned by the instructors, and comprised of both computer and electrical
engineering undergrad students at Binghamton University. Given the clear
and concise project layout, the success of the team was measured by that
of their final product in its demonstration.
To accomplish this task, we decided to use the Rover 5 Robot Chassis as
the base of our design. We were able to accomplish all necessary tasks
using only one microcontroller the Arduino Uno. Two ultrasonic distance
measuring sensors were implemented to perform the object avoidance
subtask, and a single Hbridge was used to drive the motors of our robot.
As for the metal detection we created two inductors around a ferrite core
due to its magnetic properties and designed a detection circuit that would
provide a voltage spike when the inductor would be in close proximity to
metal. We also successfully implemented an IR receiver, which was used
to wirelessly power on/off our robotic system.
The final product is an autonomous robot, which was able to maneuver a
6x6 foot course, avoid obstacles in its path, as well as detect metal
washers which were dispersed across the grid. For our team, this project
was a total success. Not only were we one of the few groups to detect all 4
mines, but we accomplished this in a systematic fashion, and did so in well
under the specified time allotted to us.
2
3. Table of Contents:
I Title Page………………………………….………………………………1
II Abstract…………………………………………………………………...2
III Table of Contents………………………………………………………...3
IV Project Overview………………………………………………………....4
V Block Diagram…………………………………………………………....6
VI Requirements…………………………………………………………….7
VII Verification of Requirements…………………………………………....8
VIII Technical Design Description………………………………………….10
IX Design Integration……………………………………………………...14
X Power Management…………………………………………………....15
XI Software………………………………………………………………....16
XII Appendices
i) Bill of Materials………………………………………………...19
ii) Robot Power Budget………………………………………….20
iii) Source Code…………………………………………………..21
3
4. Project Overview:
What was really unique about this project was not exactly what was done
(each team was trying to accomplish the same task), but it was how you
got there. Other than meeting certain criteria during your demonstration,
the rest of the project was left entirely up to individual team efforts.
Everything from which components to use, to how you wanted to approach
the puzzle, this project allowed ample freedom for design purposes.
The first thing our team did, which is essential in every project, was met
together and got a good understanding of each of our individual strengths
and weaknesses. This step is even more relevant in a project such as this
one, where there are multiple aspects pertaining to various topics, requiring
a wide range of skills and expertise across the team as a whole. After
getting to know our fellow peers, we broke the project down into a few parts
(which will be discussed in further detail later), making the somewhat
daunting task a little more approachable. We then assigned a member to
each of the created subtasks, and as a team agreed on a few technical
components which we wanted to pursue using going forward.
Once the parts had been received, and each team member had a better
fundamental grasp of their specific part assigned to them, we began the
design portion of the project. We attacked this process in a hierarchical
manner, whereas we only began collaborating with one another as our
assigned tasks became dependent on each others’. Another way to
describe this method would be like moving up a pyramid; as time went on
and our individual processes came to be, we would implement them
systematically, like building blocks. It wasn’t until the final week that all 4 of
us were in the lab working jointly as a team. While it was very important
that we remained in touch and on the same page throughout this time, if we
would have attempted to do everything together as unit, we never would
have finished in time.
4
9. Mine Detection
Our metal detector was designed to output a DC voltage when metal was
placed near it, as tested by lighting up an LED whenever metal was placed
near it, we had to design a way to count how many mines were detected.
To do this, we took the output of the metal detector and put it into the
analog pin of the Arduino, and used the “analogread” function within the
code. This allowed us to read the voltage output of the circuit, and from
there be able to send an output to a specified LED when the voltage read
was over a benchmark value determined by testing the detector with, and
without metal nearby.
Miscellaneous
1. As seen by our robot demo, everything works and we were a great
team!
2. We did take some source code from the internet for things such as
the IR sensor, as well as how to create an oscillator. However, they
were used more for inspiration; whereas we then manipulated them
to suite our needs for the project, making them our own
9
10. Technical Design Description:
Mine Detection
The metal detector design uses a 9v source for simplicity. We used Q2 and Q3 in
conjunction with capacitors C1 and C2 to create an oscillatory circuit to be passed
through the inductors. This works by causing Q2 and Q3 to become astable, meaning
that the transistors constantly switch on and off and never chose which one to leave on.
This happens because current flows through R2, and then R6 through Q2 and through
the diode into ground. While this happens, C1 becomes charged, and because it is
connected into the base of Q3, it causes Q3 to start conducting. This then in turn
causes C2 to charge, and switches the operation of transistors back and forth,
converting the DC signal into an AC signal. By placing metal near the inductors, this
oscillation can no longer occur and causes both the current and voltage to flow through
Q1, thus lighting up the LED. Without metal present, the voltage going through the LED
is ~1v, however once metal is placed near the inductors, it increases to ~2 volts,
depending on how close of a proximity the metal is. The sensitivity of the detector is
determined by how large of a resistance is placed on the emitter of Q3. By increasing
or decreasing the resistance, you determine how easily the circuit is allowed to oscillate.
The values needed for capacitors and resistors were derived from a similar design on
the internet, and manipulated to be able to be run off of a 9V source.
10
13. Obstacle Avoidance
To overcome this section of the project, we decided to use the HCSR04 ultrasonic
distance measuring sensors. Come to find out, this component has a very simple
process, and was just as easy to implement into Arduino. This sensor has 4 pins in
total, one of which connects to ground, and another which connects to a power source
(we used the 5v pin on the arduino uno). The remaining 2 pins are used for the
distance detection, one being an input and one being an output. When the trig pin is set
HIGH (digital 1) for at least 2 microseconds, the sensor begins to send out ultrasonic
sound waves, and continues to do so until it get set back to LOW (digital 0). On the
other hand, the echo pin goes HIGH when the sensor starts receiving back the waves.
One arduino function called “pusleln” is then called, and it determines how long the
echo pin remained HIGH for (or how long waves were being received). That number is
then divided by 2, to compensate for the distance traveled to and from the object, and
then divided again by a constant to get into a user friendly unit. For instance, we
divided the second time by 74, so our results would be displayed in inches.
Motor Control
The motors on our rover were controlled by the Arduino Uno, and driven by a single
HBridge. The HBridge takes in 4 signals from the arduino, and sends 4 signals
directly to the motors, acting as a middleman in the system. Two of the signals control
the left motor, and two control the right. Even more specifically, of the 2 pertaining to a
single motor, one drives the motor forward, and the other does the opposite direction.
These signals at all times are either set to HIGH or LOW (1 or 0), and determine the
current state of their motion. We were able to successfully complete this project using 4
different motor states, which we created as individual functions (found at the bottom of
our source code) and called within ‘main’ whenever we used them. They are as follows,
along with the corresponding signals necessary to perform the action:
following the format (left forward, left reverse, right forward, right reverse)
FORWARD (HIGH, LOW, HIGH, LOW)
TURN RIGHT (HIGH, LOW, LOW, HIGH)
TURN LEFT (LOW, HIGH, HIGH, LOW)
HALT (HIGH, HIGH, HIGH, HIGH)
We also used the supplied quadrature encoders by the rover, as a means of tracking
distance (we only relied on this for our hard coded 90 degree turns). As the motor
turns, the encoder values change rapidly from 03, in 2bit binary. We created a simple
counter (called ticks) which would increment every time the encoder value changed.
***A picture of our final product is included in the next section***
13
14. Design Integration:
The photos above are an accurate depiction of our final product, as taken
minutes after our demonstration. Our design used a total of three
breadboards, 2 for the object avoidance and one for the metal detector, all
connected via ground. The 2 on top were set up in a perpendicular fashion
so that there was ample room for all of our connections, and also so that
the sensors could be directly pushed into them (providing stability) and be
facing 90 degrees apart. The sensors were uniquely placed in the front
middle and back left, for reasons talked about in the software section. All
battery packs were taped down to the base of our design (simply a piece of
cardboard, allowing for more space than the rover itself gave us) to restrict
their movement as much as possible.
The breadboard for the metal detection system was resting on a piece of
plastic which we hot glued to the bottom of our robot. It was then further
supported by tape connecting the top of the robot, with the intentions of
keeping it level. The inspiration for this design came from the fact that we
wanted the best possible chance of detecting mines, which laid flat on the
ground, so we needed our inductor to be near the same level. Lastly, we
put an end of a water bottle around our inductor, as a protective measure
against the possibility of bashing into walls.
14
15. Power Management:
To power our robot we had to draw from a variety of sources. The motors
of the robot were powered by a 7.2v source, which they would quickly
drain. Because of this, it was imperative for testing purposes to always
keep fresh batteries on hand. As this source was drained, the speed of the
motors would change, and furthermore alter the desired amount of “ticks”
needed for our turns (as described by the quadrature encoders).
The Arduino was powered by a 9v battery, which in turn was used to power
the both the ultrasonic distance measuring sensors, as well as the IR
sensor. This was sufficient for our requirements, and was the
recommended source voltage from the Arduino manufacturer. The
ultrasonic sensors were connected to the 5v pin from the Arduino, with
each sensor pulling only 15mA of power from the Arduino, keeping us well
under the maximum current draw allowed by the system (15mA*2
sensors=30mA total draw). The infrared light sensor was connected to the
Arduino’s 3.3v pin, as recommended by the manufacturer.
The metal detection system was designed to be powered off of its own 9v
battery, with the intentions of not borrowing power from the other systems.
This was done as a precautionary measure; in case the robot would take
the entire three minutes of gameplay to find all of the mines, we wanted to
ensure the robot's ability to run for the entire time period.
15
16. Software:
We chose to use the Arduino language (C) to attack this project. The
reason for this was is because one of our members already had an arduino
uno, and we quickly realized that it was surprisingly easy to implement both
the ultrasonic and IR sensors, given the proper included libraries. Above is
a generalized FSM representing our robot’s movement around the course.
Although this wasn’t our first approach, we decided to head in this direction
once we realized we would be starting in the middle of a wall, rather than a
corner like we originally anticipated. This is actually a fairly simple design,
but systematic enough where we could almost guarantee it would traverse
the entire grid. Below is a more in depth description of each state.
As soon as we gave the start signal, our robot would travel forward until it
got within a specific distance of our front sensor (6 inches). NOTE: from
this point forward (in this section) we will refer to a sensor being HIGH
when it is detecting an object within that specified threshold, and LOW
when it is not. Once that distance was reached, we turned right 90
degrees, and then entered the 3rd state, where the decision making
process came into play.
16
17. After making the first right turn, we knew our robot would be in one of two
places, no matter how the course was set up. It would either be traveling
alongside the outer perimeter, or traveling next to an obstacle. However, in
both situations, we knew the left sensor would be HIGH, and we were able
to take advantage of this factor when deciding what action to take next. At
this point, we knew one of two possibilities could happen: (1) the left sensor
remains HIGH and the front sensor goes from LOW to HIGH or (2) the left
sensor goes from HIGH to LOW. Given the first scenario, we knew our
robot was blocked into a corner, whether it was the corner of the grid, or
simply the corner between the perimeter and an obstacle. No matter, at
this point we incremented an internal counter (called corners) by one, made
a 90 degree right turn, and then returned to this same state. If it was the
latter case, we knew that our robot had just passed an object, so we
wanted to make a 90 degree left turn, where we then incremented an
internal counter (called left) by one, and then once again returned to this
state.
Both of our internal counters are very important in our code, and had
boundaries associated with them, in order to verify the robot would take the
actions most logical. For instance, the way our code is designed, our robot
could get stuck in a loop traveling counterclockwise around an object in the
middle of the course. So to overcome that, we limited the number of
consecutive left turns to be 2. We also capped our corners counter at 10.
This number came from the fact that we knew the max number of “corners”
our robot could possibly detect in one lap around the track would be 8, and
that was only if both obstacles were placed along edges (which
coincidentally, they were!). Therefore, 10 corners allowed our robot to
traverse the perimeter more than once comfortably, however the number of
complete cycles would depend on the specific course setup. The reason
we made the perimeter a priority in our code was because we knew 2/4
mines would be located in corners, and we did not want to miss them.
17
18. Lastly, once our corners count reached 10, we decided to have our robot
enter a pseudo random function, or state 5 on the diagram. In this state,
the robot would travel straight until the front sensor went HIGH. At this
point, embedded in our code was a function that would pick a random
direction to turn, either left or right, and then a random number of “ticks” to
turn for (we shot for angles between 45 and 135 degrees). The robot
would remain in this state for the remainder of the testing time, with the
hopes that it would be able to randomly find the final 2 mines.
To incorporate our metal detector circuit and display a counter we needed
to include some code to read a digital voltage from an analog pin. To do so
we took the input from the analog pin and scaled it to be in volts. Once we
had a voltage reading we found a threshold that would indicate when metal
is being detected. We ended up using a value of about 1.3V as the
threshold. In order to have four LEDS display the count of mines detected,
we coded it so that when the threshold is crossed (rising edge) we
increment a counter that would correspond to the number of LEDS turned
on. We attempted to not double count the same mine, by not allowing for
the count to be incremented until the voltage level went below the threshold
again. We encountered some issues with this because when the metal
detector was jostled, it would sometimes spike the voltage level only for a
brief moment, thus causing our code to increment the counter without a
mine being detected. Although we were clearly able to display on a
separate LED when we detected mines, as the voltage spikes we not very
visible due to such short durations. From this we learned the importance of
hardware/software integration and how imperative it is to design software to
handle the limitations of hardware, and vice versa.
18
21. Source Code:
#include "IRremote.h"
int rFor = 11;
int rBack = A4;
int fecho = 2;
int ftrigger = 3;
int lecho = 7;
int ltrigger = 6;
int encoder1 = 8;
int encoder2 = 9;
int receiver = 10;
int lFor = 12;
int lBack = 13;
IRrecv irrecv(receiver);
decode_results results;
boolean flag = false;
int count = 0;
int ledcount = 0;
int prev1 = 0;
int prev2 = 0;
long fduration, fdistance, lduration, ldistance, l1distance, l1duration;
boolean start = false;
boolean state1 = true; //start in the forward state
boolean state2 = false; //turn right state
boolean state3 = false; //decision state (turn left when available)
boolean state4 = false; //turn left state
boolean state5 = false; //random turns state (will stay here until reset)
int lefts = 0; //number of consecutive left turns (max of 2 prevents circling objects)
int corners = 0; //number of “corners” detected (once 10 is reached, shift to state 5)
void setup() {
//sets console display and which pins will be used as input/output
Serial.begin(9600);
irrecv.enableIRIn();
pinMode(A3, OUTPUT);
pinMode(A2, OUTPUT);
pinMode(A1, OUTPUT);
pinMode(A0, OUTPUT);
pinMode(rFor, OUTPUT);
pinMode(rBack, OUTPUT);
pinMode(fecho,INPUT);
pinMode(ftrigger, OUTPUT);
pinMode(l1echo, INPUT);
pinMode(l1trigger, OUTPUT);
21
22. pinMode(lecho, INPUT);
pinMode(ltrigger, OUTPUT);
pinMode(encoder1, INPUT);
pinMode(encoder2, INPUT);
pinMode(receiver,INPUT);
pinMode(lFor, OUTPUT);
pinMode(lBack, OUTPUT);
start = false;
}
//main loop that will act as the “clock”, throughput of this code is limited by the amount of delays inside, typically a
//few milliseconds per loop cycle to get readings from our sensors. This did not hinder performance significantly.
void loop() {
//code for the led counter (number of mines detected)
int sensorValue = analogRead(A5);
// Convert the analog reading (which goes from 0 1023) to a voltage (0 5V):
float voltage = sensorValue * (5.0 / 1023.0);
// print out the value you read:
Serial.println(voltage);
if(voltage >= 1.30 && !flag)
{
ledcount++;
flag = true;
}else if(voltage < 1.30 && flag)
{
flag = false;
}
if(ledcount >= 1)
{
digitalWrite(A3, HIGH);
}
if(ledcount >= 2)
{
digitalWrite(A2, HIGH);
}
if(ledcount >= 3)
{
digitalWrite(A1, HIGH);
}
if(ledcount >= 4)
{
digitalWrite(A0, HIGH);
}
//code for gettting the IR signal
22
26. void forward()
{
digitalWrite(rFor, HIGH);
digitalWrite(rBack, LOW);
digitalWrite(lFor, HIGH);
digitalWrite(lBack, LOW);
}
//drives forward without checking sensors for certain amount of ticks (to allow left sensor to be in range of obstacle)
void forwardBlind(int ticks)
{
digitalWrite(rFor, HIGH);
digitalWrite(rBack, LOW);
digitalWrite(lFor, HIGH);
digitalWrite(lBack, LOW);
while(count <= ticks)
{
if(digitalRead(encoder1) != prev1)
{
count++;
prev1 = digitalRead(encoder1);
}
if(digitalRead(encoder2) != prev2)
{
count++;
prev2 = digitalRead(encoder2);
}
Serial.println(count);
}
count = 0;
halt();
}
void halt()
{
digitalWrite(rFor, HIGH);
digitalWrite(rBack, HIGH);
digitalWrite(lFor, HIGH);
digitalWrite(lBack, HIGH);
delay(500);
}
void turnR(int ticks)
{
digitalWrite(rFor, LOW);
digitalWrite(rBack, HIGH);
digitalWrite(lFor, HIGH);
digitalWrite(lBack, LOW);
while(count <= ticks)
{
26