Introduction: My Sixth Project: Smart Tank Chassis With Ultrasonic Sensor

In the previous projects I tried different ways to control the smart tank manually. But how about if the tank makes its own decision and control itself? It should be quite interesting. Ultrasonic sensor can help to do so by sending sound wave in front of the sensor. It receives the wave once the wave meets obstacles and reflects to the sensor so as to determine the distance. So I've bought an ultrasonic sensor and start another project.

Step 1: Parts

HC-SR04 Ultrasonic Sensor with Servo and Rack

Smart Tank

Arduino Uno

Small Breadboard

Battery Box AA x 4

Battery Box 9-volt

I just add one more sensor on top of the third project actually.

Step 2: Wiring

I leave the servo unwired at this stage. For the sensor the wiring is as follow:

GND > Arduino GND

Echo > Pin 6

Trig > Pin 5

VCC > 5V

For the smart tank I listed the wiring again below. That is the same as the previous projects:

IB on the right side > pin 8

IA on the left side > pin 9

IA on the right side > pin 10

IB on the left side > pin 11

VCC on both side > + of the battery box

GND on both side > - of the battery box and Arduino GND

Step 3: Test the Sensor

I wanna test if the sensor works, so I google it and find anything can help. Google is our friend and this link can be one of the reference:

http://arthursrobotorial.blogspot.hk/2012_12_01_archive.html

#define trigPin 5

#define echoPin 6

void setup()

{

Serial.begin (9600);

pinMode(trigPin, OUTPUT);

pinMode(echoPin, INPUT);

}

int CheckDistance()

{

long duration, distance;

digitalWrite(trigPin, LOW); // Added this line

delayMicroseconds(2); // Added this line

digitalWrite(trigPin, HIGH);

// delayMicroseconds(1000); - Removed this line

delayMicroseconds(10); // Added this line

digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);

distance = (duration/2) / 29.1;

return distance;

}

void loop()

{

int testDistance = CheckDistance(); /// get object distance using ping

/// if object is more than 50 cm away it is out of range

if (testDistance >= 50 || testDistance <= 0) /// if object is more than 50 cm away it is out of range

{

Serial.println("Out of range");

}

else /// object is closer than 50cm, print distance

{

Serial.print(testDistance);

Serial.println(" cm");

delay(500); ///wait half a sec before next ping

}

In Arduino IDE, select Tools > Serial Monitor. It shows the distance if succeeds.

Step 4: Test the Sensor With the Tank

Then I combine the code in the first stage with the code in the third project and revise a little bit: If the distance between the sensor and the object is more than 30cm, it goes forward. Otherwise it turns right.


#define trigPin 5

#define echoPin 6

int motorPin = 8; //right side to IB - forwward

int motorPin2 = 9; //left side to IA - forwward

int motorPin3 = 10; //right side to IA - backward

int motorPin4 = 11; //left side to IB - backward

void setup()

{

Serial.begin (9600);

pinMode(motorPin, OUTPUT);

pinMode(motorPin2, OUTPUT);

pinMode(motorPin3, OUTPUT);

pinMode(motorPin4, OUTPUT);

pinMode(trigPin, OUTPUT);

pinMode(echoPin, INPUT);

}

void forward(){

digitalWrite(motorPin, HIGH);

digitalWrite(motorPin2, HIGH);

digitalWrite(motorPin3, LOW);

digitalWrite(motorPin4, LOW);

}

void backward() {

digitalWrite(motorPin, LOW);

digitalWrite(motorPin2, LOW);

digitalWrite(motorPin3, HIGH);

digitalWrite(motorPin4, HIGH);

}

void turnLeft() {

digitalWrite(motorPin, HIGH);

digitalWrite(motorPin2, LOW);

digitalWrite(motorPin3, LOW);

digitalWrite(motorPin4, HIGH);

}

void turnRight() {

digitalWrite(motorPin, LOW);

digitalWrite(motorPin2, HIGH);

digitalWrite(motorPin3, HIGH);

digitalWrite(motorPin4, LOW);

}

int CheckDistance()

{

long duration, distance;

digitalWrite(trigPin, LOW); // Added this line

delayMicroseconds(2); // Added this line

digitalWrite(trigPin, HIGH);

// delayMicroseconds(1000); - Removed this line

delayMicroseconds(10); // Added this line

digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);

distance = (duration/2) / 29.1;

return distance;

}

void loop()

{

int testDistance = CheckDistance(); /// get object distance using ping

if (testDistance >= 30 || testDistance <= 0) /// if object is more than 30 cm away it goes forward

{

forward();

}

else /// object is closer than 30cm, turns right

{

turnRight();

}

delay(500); ///wait half a sec before next ping

}

The result seems ok.

Step 5: Test the Whole Stuff

The servo included with this sensor can move 180 degree. Because I want the smart tank to avoid anything in the front, it would be too sensitive if it avoids obstacles in 180 degree. I want the servo moves in certain degree in front of the tank, not in the full degree of the servo. The servo has to be calibrate and make sure 90 degree is pointing to the front. You can turn the servo anticlockwise until it gets stuck. Then plug the sensor out and on again pointing at 9. After that turn the servo 90 degree clockwise until it points to the front.

For the wiring of the servo, brown one to Arduino GND, red to 5V and yellow to pin 7.

There is an example in Arduino library for our reference: Examples > Servo > sweep. As I said before, I don't want the servo keeps turning 180 degree, so I adjust the angle so as to fit the need. Here I use 0 to 100 degree. I have also adjust the servo to ensure it moves pointing to the front. I think the response of the servo is quite slow if keep using the example, so I delete the second part of the loop.

#include <Servo.h>

#define trigPin 5

#define echoPin 6

Servo myservo; // create servo object to control a servo

// a maximum of eight servo objects can be created

int pos = 0; // variable to store the servo position

int servoDirection = 100;

int servoDelay = 20;

int motorPin = 8; //right side to IB - forward

int motorPin2 = 9; //left side to IA - forward

int motorPin3 = 10; //right side to IA - backward

int motorPin4 = 11; //left side to IB - backward

void setup()

{

Serial.begin (9600);

myservo.attach(7); // attaches the servo on pin 7 to the servo object

myservo.write(pos);

pinMode(motorPin, OUTPUT);

pinMode(motorPin2, OUTPUT);

pinMode(motorPin3, OUTPUT);

pinMode(motorPin4, OUTPUT);

pinMode(trigPin, OUTPUT);

pinMode(echoPin, INPUT);

}

void forward(){

digitalWrite(motorPin, HIGH);

digitalWrite(motorPin2, HIGH);

digitalWrite(motorPin3, LOW);

digitalWrite(motorPin4, LOW);

}

void backward() {

digitalWrite(motorPin, LOW);

digitalWrite(motorPin2, LOW);

digitalWrite(motorPin3, HIGH);

digitalWrite(motorPin4, HIGH);

}

void turnLeft() {

digitalWrite(motorPin, HIGH);

digitalWrite(motorPin2, LOW);

digitalWrite(motorPin3, LOW);

digitalWrite(motorPin4, HIGH);

}

void turnRight() {

digitalWrite(motorPin, LOW);

digitalWrite(motorPin2, HIGH);

digitalWrite(motorPin3, HIGH);

digitalWrite(motorPin4, LOW);

}

int CheckDistance()

{

long duration, distance;

digitalWrite(trigPin, LOW);

delayMicroseconds(2);

digitalWrite(trigPin, HIGH);

delayMicroseconds(10);

digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);

distance = (duration/2) / 29.1;

return distance;

}

void sweepServo()

{

for(pos = 0; pos < 100; pos += 1) // goes from 0 degrees to 100 degrees

{ // in steps of 1 degree

myservo.write(pos); // tell servo to go to position in variable 'pos'

delay(10);

}

}

void loop()

{

sweepServo();

int testDistance = CheckDistance(); /// get object distance using ping

/// if object is more than 30 cm away it is out of range

if (testDistance >= 30 || testDistance <= 0) /// if object is more than 30 cm away it is out of range and goes forward

{

Serial.println("out of range");

forward();

}

else /// object is closer than 30cm, turn right and print distance

{

turnRight();

Serial.print(testDistance);

Serial.println("cm");

}

}

One problem arises: it has to run the loop completely before another loop starts. The sensor detect one time only when the servo move from 0 degree to 100 degree. I want the sensor detecting the distance without waiting the servo moves. In other word, I want the sensor detects several times in one servo rotation. How to do that?

Step 6: Troubleshooting

Google tells me I can use the function "millis" or "interrupt" to do so, but I still don't understand after reading several articles...... : ( The most common example is called Blink Without Delay. I still don't know how to use it in my situation...... So.... I try another way that is very cumbersome and the code is as follow:

#include <Servo.h>

#define trigPin 5

#define echoPin 6

Servo myservo; // create servo object to control a servo

int pos = 0; // variable to store the servo position

int servoDirection = 100;

int servoDelay = 20;

int motorPin = 8; //right side to IB - forward

int motorPin2 = 9; //left side to IA - forward

int motorPin3 = 10; //right side to IA - backward

int motorPin4 = 11; //left side to IB - backward

void setup()

{

Serial.begin (9600);

myservo.attach(7); // attaches the servo on pin 7 to the servo object

myservo.write(pos);

pinMode(motorPin, OUTPUT);

pinMode(motorPin2, OUTPUT);

pinMode(motorPin3, OUTPUT);

pinMode(motorPin4, OUTPUT);

pinMode(trigPin, OUTPUT);

pinMode(echoPin, INPUT);

}

void forward(){

digitalWrite(motorPin, HIGH);

digitalWrite(motorPin2, HIGH);

digitalWrite(motorPin3, LOW);

digitalWrite(motorPin4, LOW);

}

void backward() {

digitalWrite(motorPin, LOW);

digitalWrite(motorPin2, LOW);

digitalWrite(motorPin3, HIGH);

digitalWrite(motorPin4, HIGH);

}

void turnLeft() {

digitalWrite(motorPin, HIGH);

digitalWrite(motorPin2, LOW);

digitalWrite(motorPin3, LOW);

digitalWrite(motorPin4, HIGH);

}

void turnRight() {

digitalWrite(motorPin, LOW);

digitalWrite(motorPin2, HIGH);

digitalWrite(motorPin3, HIGH);

digitalWrite(motorPin4, LOW);

}

int CheckDistance()

{

long duration, distance;

digitalWrite(trigPin, LOW); // Added this line

delayMicroseconds(2); // Added this line

digitalWrite(trigPin, HIGH);

delayMicroseconds(10); // Added this line

digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);

distance = (duration/2) / 29.1;

return distance;

}

void sweepServo1(){

for(pos = 10; pos < 40; pos += 1) // goes from 0 degrees to 100 degrees

{ // in steps of 1 degree

myservo.write(pos); // tell servo to go to position in variable 'pos'

delay(10);

}

int testDistance = CheckDistance(); /// get object distance using ping

/// if object is more than 30 cm away it is out of range

if (testDistance >= 30 || testDistance <= 0) /// if object is more than 30 cm away it is out of range

{

forward();

}

else /// object is closer than 30cm, prit distance

{

turnRight();

Serial.print(testDistance);

Serial.println("cm");

}

}

void sweepServo2(){

for(pos = 40; pos < 80; pos += 1) // goes from 0 degrees to 100 degrees

{ // in steps of 1 degree

myservo.write(pos); // tell servo to go to position in variable 'pos'

delay(10);

}

int testDistance = CheckDistance(); // get object distance using ping

if (testDistance >= 30 || testDistance <= 0) // if object is more than 30 cm away it is out of range

{

forward();

}

else // object is closer than 30cm, prit distance

{

turnRight();

Serial.print(testDistance);

Serial.println("cm");

}

}

void sweepServo3(){

for(pos = 80; pos < 120; pos += 1) // goes from 0 degrees to 100 degrees

{ // in steps of 1 degree

myservo.write(pos); // tell servo to go to position in variable 'pos'

delay(10);

}

int testDistance = CheckDistance(); // get object distance using ping

if (testDistance >= 30 || testDistance <= 0) // if object is more than 30 cm away it is out of range

{

forward();

}

else // object is closer than 30cm, prit distance

{

turnRight();

Serial.print(testDistance);

Serial.println("cm");

}

}

void loop()

{

sweepServo1();

sweepServo2();

sweepServo3();

}

I separate the servo sweep into three parts (sweepServo1 to 3). Each part controls different angles and all parts are looped together in orders.

Step 7: Result

It works! After trial and error, I think 30 cm is appropriate and the tank has enough time to respond. But the final code can be made much more simple. Please tell me how to revise if anyone knows how to add the function "millis" or "interrupt". Next time I will try a very different stuff. Thanks for your watching. See you!

Comments

author
masud Molla made it! (author)2016-09-01

where r from motor driver. ..
Why can use motor drive ...

temp_1679498848.jpg
author
venkiakshay made it! (author)2015-04-30

Any Suggestions?

author
venkiakshay made it! (author)2015-04-29

author
venkiakshay made it! (author)2015-04-29

author
muiinfathul94 made it! (author)2015-03-22

how to change motor speed to 255..??? please my motor very slow and can't support my base... im use 12v batries...

author
muiinfathul94 made it! (author)2015-03-22

how can I set 255speed motor...???

author
muiinfathul94 made it! (author)2015-03-22

how to change a speed for the motor from code..????

author
mohamed4data made it! (author)2014-07-28

dear sir
I used 360 degree servo motor instead of yours but the servo rotates as a dc motor

author
thereyno made it! (author)thereyno2014-07-28

its better to use 180 servo so you can set the angle of the servo.

author
mohamed4data made it! (author)mohamed4data2014-07-29

Thanks but how can I set or which degree would be used 0 to 100 or ???

author
Rookie P made it! (author)Rookie P2014-07-29

I use the code as follow:

#include <Servo.h>

Servo myservo;

int pos = 0; // variable to store the servo position

int servoDirection = 100;

int servoDelay = 20;

void setup()

{


Serial.begin (9600);


myservo.attach(7); // attaches
the servo on pin 7 to the servo object

myservo.write(pos);

}

void loop()

{

for(pos = 0; pos < 100; pos += 1) // goes from 0 degrees to 100 degrees

{
// in steps of 1 degree

myservo.write(pos); // tell servo to go to position in variable 'pos'

delay(10);

}

}

You can change the angle within the range 0 - 180. Hope this can help.

author
AlB1 made it! (author)2014-07-27

Great job. Thanks for sharing! We built a similar project. However,
for budget reasons, we used IR sensors instead of the ultrasonic. Also,
using TouchOSC, we were able to control it with an iPad as shown below
so you might want to try that instead of the PS3 controller. Cheers!

author
Rookie P made it! (author)Rookie P2014-07-27

It's cool! I love the cam (phone) so much! It can follow the ball and avoid obstacles simultaneously! Are you using 2 IR sensor for obstacles avoidance and 2 for ball detection? It seems that the car is activated after the app is opened. How did you make this? Sorry for so many questions but your project is really awesome!

author
AlB1 made it! (author)AlB12014-07-27

Actually, the IR sensors are only used to avoid obstacles. To track the ball, I use an API called OpenCV in conjunction with the camera on the smartphone. Your observation is correct, the car is activated after the app is opened.

author
ivver made it! (author)2014-07-25

Love it :-) Nice project, have you ever thought about putting 3 or 2 sonars on thank? Maybe with 3 sonars you'll get quicker response, one moving part less and your battery will last longer

author
pucksurfer made it! (author)2014-07-25

This is really cool

author
BLR_RAVI made it! (author)2014-07-25

very very impressive project by you..i loved it..nice..and hope to see more from you

author
David97 made it! (author)2014-07-25

Looks good. A tamiya plate platform and dual gearbox works not bad. However the motors out of the box are not particularly good. Here is one I built a few months ago as my 1st robot. It uses a arduino pro mini, hs-sro4, tamiya gearbox, universial plates, and a hk-6ch controller. The next project will be incorporating a line following module and a 2560 arduino on a custom pcb. As my 1st smd robot. However I still need to build a oven.

DSC03550_zpse32d0a63.jpg
author
Rookie P made it! (author)Rookie P2014-07-25

It's awesome doing on a custom pcb! Please share your project after finish. : )

author
egrasso made it! (author)2014-07-24

Exactly what I thought with changing modes. I quickly tried to add the code to switch modes but it didn't work. Circuitsathome.com I believe is where I got the library and parts of code. I took me a little while to get the code right but basically the left and right stick are watched for what value they have. Stick all the way forward gives a 0 value and down gives a 255 value. So if the value is less than 128, between 128 and 0 is mapped between 0 and 255. Then i know the stick is forward and using a motor shield turn one pin LOW the other pin for that motor HIGH and send the mapped value to the third pin for the motor shield. Any more questions let me know maybe I will make the instructable for it.

author
Rookie P made it! (author)Rookie P2014-07-25

This is a good reference. Thanks for sharing more idea about controlling. I think I have to buy a USB host and start another project. : )

author
egrasso made it! (author)2014-07-24

I used an arduino mega adk which has a USB host on board. I think it can be done with a USB host shield. I used a USB dongle then which happened to connect with the ps3 controller.

author
egrasso made it! (author)2014-07-23

Great instructable. I built a tank track with a ps3 controller and a sonar. I haven't programmed the sonar into it yet but want to be able to control autonomous and manual mode with the ps3 controller. I noticed that the sonar seems to scan and will have to use that!

author
Rookie P made it! (author)Rookie P2014-07-24

It's great! I also wanna know how to control it with a PS3 controller. Are they also connected with bluetooth? It will be a cool stuff if adding a sonar and be able to switch between different modes! : )

About This Instructable

30,889views

359favorites

License:

More by Rookie P:My Ninth Project: Robot Arm with Joystick ShieldMy Eighth Project: Robot Arm with Smart Tank Chassis and BluetoothMy Seventh Project: Robot Arm Set
Add instructable to: