Introduction: Motion Following Robot

Hello instructables community!

After messing around with an Arduino for a couple months and avidly reading instructables, I decided that I would finally publish my own. I wanted to create something that moves by itself. I also wanted to create a system that reacts to the outside environment. After some thought I decided on a simple motion follower.

Potential Applications:

• Motion following camera
• Robots that will acknowledge their environments
• Motion following turret
• Educational projects
• Obstacle avoiding robots

Required Materials:

• Breadboard
• Ultrasonic Range Sensor x2 (I used the four pin version so if you are using the ping version you'll have to change the code a bit)
• Servo (I used a micro size)
• Arduino UNO or similar microcontroller
• Jumper Cables (female to male and male to male)
• Particle Board
• 9v Battery and connector
• Something to mount the servo on (I used some poster mounting putty)

Required Tools:

• Hot glue gun
• Xacto knife
• Computer with Arduino IDE
• Electrical tape or similar

Step 1: Build the Sensor Mount

First, we will need to build the sensor mount. For this I built a prototype out of cardboard and then built my final project in particle board. In the future I plan to 3d print a perfect mount for the sensor.

Cut a rectangle that is about the same height as one of the sensors and an 1/8th inch (about 3mm) longer than two of them together. Set the rectangle aside and cut out two identical isosceles triangles with the odd angle out being 120 degrees. I cut it at 120 degrees because the range sensors have a 15 degree cone that they measure, this allows for no blind spots while optimizing the area that is sensed.

Finally, place the sensors on the mount to determine where to cut the rectangular holes for them to fit in. Make the hole as small as possible because this snug fit makes up for not using any other adhesives or connectors. Now cut another small rectangular hole on the bottom triangle of the mount to allow for jumper cables to be passed through. Once the jumper cables are plugged in, the sensors should stay in place. If they don't, you will need to fasten them with some hot glue or pins.

When you are done with the mount, attach it to the servo.

Step 2: Wire Everything!

Now all you need to do is connect everything! I used Fritzing to create a circuit diagram. I have also provided some pictures of the final product.

The code provided uses digital pins 9 through 13. Pin 9 is the data pin for the servo. Pins 10 and 11 are the echo and trig pins, respectively, of the left sensor. Pins 12 and 13 are the echo and trig pins, respectively, of the right sensor. I connected the 5v and gnd pins from the Arduino to the breadboard and then used jumpers to connect the servo and sensors.

Step 3: Code

The code that I provided allows for the changing of the distance threshold. So in other words, how far the sensors can see. I will be uploading a new instructable soon to show how you can make the sensors even more accurate using a temperature sensor. Finally, my friend showed me a cool way of debugging really quick. All you do is use a boolean and some if statements. If the boolean is true, then serial communication will be on and communicating. If the boolean is false, then the program will run much faster but not communicate.

I will attach the .ino file, otherwise you can copy it from here:

/*************************************************************************************************
**************************************************************************************************

Motion Follow Created by Calvin Kielas-Jensen

Using an Arduino UNO, check Instructables.com for the circuit diagram.

This script allows two ultrasonic range sensors to follow movement while mounted on the top of a servo. The distance threshold can be changed but should not be set too far as the sensors will begin to fail.

Anyone is welcome to use and modify this code as long as I am given credit. Thank you for respecting the open source movement!

************************************************************************************************** *************************************************************************************************/

#include

Servo myservo;

const int Lin = 10, Rin = 12, Lout = 11, Rout = 13, serv = 9; //setting sensor pins and servo pin

// establish variables for duration // and the distance result in inches long Rduration, Lduration, Rinches, Linches;

int threshold = 10; //Sensor threshold in inches

int angle = 80; //Initial angle

boolean debug = false; //Serial communication for debuging. Set to true for serial communication.

void setup() { // initialize serial communication: if (debug) { Serial.begin(9600); } myservo.attach(9); //attach servo to pin 9 }

void loop() { //Most of the sensor code has been taken from David Mellis's PING sensor code //I modified it for a 4 pin sensor as oppsed to the 3 pin sensor // Give a short LOW pulse beforehand to ensure a clean HIGH pulse: pinMode(Rout, OUTPUT); digitalWrite(Rout, LOW); delayMicroseconds(2); digitalWrite(Rout, HIGH); delayMicroseconds(5); digitalWrite(Rout, LOW);

Rduration = pulseIn(Rin, HIGH); pinMode(Lout, OUTPUT); digitalWrite(Lout, LOW); delayMicroseconds(2); digitalWrite(Lout, HIGH); delayMicroseconds(5); digitalWrite(Lout, LOW);

Lduration = pulseIn(Lin, HIGH);

// convert the time into a distance Rinches = microsecondsToInches(Rduration); Linches = microsecondsToInches(Lduration); if (debug) { Serial.print("Left: "); Serial.print(Linches); Serial.println(" in"); Serial.print("Right: "); Serial.print(Rinches); Serial.println(" in"); } follow(); }

long microsecondsToInches(long microseconds) {

// According to Parallax's datasheet for the PING))), there are

// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per

// second). This gives the distance travelled by the ping, outbound

// and return, so we divide by 2 to get the distance of the obstacle.

// See: http://www.parallax.com/dl/docs/prod/acc/28015-PI...

return microseconds / 74 / 2; }

void follow() { if (Linches <= threshold || Rinches <= threshold) { if (Linches + 2 < Rinches) { angle = angle - 2; } if (Rinches + 2 < Linches) { angle = angle + 2; } } if (angle > 160) { angle = 160; } if (angle < 0) { angle = 0; } myservo.write(angle); }

Step 4: Conclusion

Once the code has been loaded, plug in the 9v battery and watch it start following anything that comes within the threshold range!

Troubleshooting:

  • If the sensors keep turning the wrong way, try switching the cables in pins 10 and 11 with the cables in pins 12 and 13.
  • If the sensors don't move at all, or just a little bit, check the wiring. It is really easy to accidentally move the jumper cables over one spot on the breadboard.
  • If the sensors are moving really slowly, go back to the code and make sure that the debug is false. The serial communications can really slow down the reaction time of the robot.
  • If you are still having issues, first make sure that the Arduino is on and that all jumper cables are in the correct spots. Switch the debug to true and check to see if the range sensors are working. You might also want to test the servo to make sure that it is also in working condition.

Some improvements I am planning on for the future:

  • Improving the accuracy of the sensors with the use of a temperature sensor
  • 3d printing the sensor mount and servo mount
  • Adding another servo and sensor to allow for vertical movement
  • Switching out the servos with stepper motors to allow for 360 degree following


I had a great time writing this instructable and hope to create many more! Please let me know how I did and how I can improve my future instructables.

Comments

author
BatL1 (author)2017-07-17

What is the range of it? and how small of things can it detect?

author
onaroll (author)2017-04-29

Hi there,

This was really fun to build and it works just great. Is there a way to add two blinking led's that activate when the servo turns?

Cheers

author
deepanker9 (author)2017-03-24

want to add wheels to this so it can follow the direction. Can you provide sketch and wire diagram please..

author
nigel.trewartha (author)2017-02-18

19.2.2017

May I suggest puting the source + construction info in GIT?

BD

author
kimosubby (author)2016-12-29

It is very easy to just copy and paste the code BUT doing that also copys spaces and unseen asci code as well. You need to go through the sketch and backspace any spaces and then re-introduce them with the space or tab key.
Also before that move all curly brackets to new lines using the return key and that way you can see the code packets and not delete tham in error.I know, been there and got the T shirt.

author
dasari12 (author)2016-12-27

hi i connected in a correct way....but not getting result....any one help me

author
MagicByCalvin (author)dasari122016-12-27

We need to see a picture of how you connected it. Could you tell us what the problem is? Is it not compiling, not uploading, not moving, moving erratically?

author
dasari12 (author)MagicByCalvin2016-12-28

the motor is not moving..

author
dasari12 (author)MagicByCalvin2016-12-27

i used the code which was attached to the article

author
MagicByCalvin (author)dasari122016-12-27

Ok, but what is wrong? What doesn't work? Your Arduino could be dead, you might not be uploading correctly, the motor may not be hooked up correctly, or a large number of other factors could be causing an issue. I need to know what your problems are and I need to see pictures of what you have hooked up in order to help you.

author
finlaye (author)2016-04-01

how could i change the threshhold so that i can add a camera

author
MagicByCalvin (author)finlaye2016-11-02

Were you hoping to have a camera mounted on the motion tracker or did you want to replace the ultrasonic sensors with a camera?

I would recommend replacing the sensors with a camera if you can send a live feed of the camera to a computer. You would then use computer vision in order to detect and track motion. A comment I left above regarding following a laser pointer might be helpful to you.

author
OlivD (author)2016-11-02

Hi, your project is really nice. I would like to get the same result but with sensor that follow a laser dot, so I can point where I want the sensor to "look". Do you know if it's a matter of programmation of the sensor or if i'll need to use other sensors.

author
MagicByCalvin (author)OlivD2016-11-02

Thank you!

You would need a sensor that can pick up the laser dot. In a very low light situation, you might be able to use photoresistors. But realistically, unless you were using a flashlight, a laser even in low light probably wouldn't work with a few discrete light sensors. I would recommend using OpenCV. OpenCV is a computer vision package that is built for both C++ and Python (as far as I know). You will need a computer to do the processing since an Arduino does not have sufficient power to process images. You will also need a camera. The camera doesn't need to be super fancy, in fact it could probably work with a cheap $20 webcam. The most important aspect of the camera would be its ability to differentiate the laser signal from the noise of the image. You would want to use OpenCV (or your own image processing algorithm of course, since this should be among the simpler tasks) to determine where in the image the laser dot was. Using that information, you could then drive the motor to, for example, always keep the laser dot in the middle of the image. For better results, you could pulse the laser at a specific frequency and use a filter to make sure that it is your laser and not a different laser or other sources of light that your algorithm picks up. Finally, I would recommend looking into control theory (if you have the time, desire, and ability) in order to better control the motor. A very basic, yet incredibly effective control system is a PID controller. I hope this helps!

author
HckmstrRahul (author)2015-08-12

can i try it with single Ultrasonic sensor? right now i have only one of them. if so, then suggest changes in the code that shd be done to achieve this. thanks fr the projct.

author

It would be possible with one ultrasonic sensor, but you would have to use a different approach to following whatever is in front of the sensor. The way I wrote the code looks at which sensor is closer to the object. If the object is closer to the right sensor, it moves right, if it is closer to the left, it moves left.
I am sure that there are other ways to do it, but I would have the sensor be wiggling left and right a couple degrees. If the sensor sees the object when it wiggles to the left, then it should turn further left, the same for the right. Let me know if that makes sense! If you are still interested I could write up a new Instructable sometime in the next two weeks.

author
Moo'L (author)MagicByCalvin2016-09-19

Really nice work! im in the same situation, i got one sensor and a servo, but im not good in coding at all. I try to implement your code in other (firmata) tying to use this behaviour with the max connection kit in ableton live.

author
beatniksailor (author)2016-08-25

I was working on something like this to get back at my cat for jumping on my head when I was sleeping(LOL). I H-glued the sensors on an old dvr that didn't burn right. The height of the servo left enough room to place a arduino Nano underneath. Good size to put on a $5 RC car.

author
shwami (author)2016-03-17

could you talk about why you chose to angle the sensors outwards away from each other? would angling them inwards (inside of a /\ instead of outside of the /\) make a difference? In stereo imagery, we angle the camera sensors inwards focusing on a point lying on an axis at equal distance from the sensors. Would that work better here as well?

author
MagicByCalvin (author)shwami2016-03-28

That is a great question. I did not apply any special analysis, I chose the angle based on the cone of sound produced by the sensors. I figured that angling the sensors so that the cones just touched would produce the best result. Upon reflecting on my design, I should have probably done some analysis and testing to produce the ideal angle. I am not familiar with the physics of stereo imagery but my thoughts are that I would not want to apply that for this design. I wanted the design to be able to pick up objects within the widest range in front of the sensors. My thoughts are that angling the sensors inwards would produce better detection of an object in front of them but would not detect objects as well that are further off center. I would love to hear your thoughts on it though!

author
afridave (author)MagicByCalvin2016-07-28

and...of course the more sensors you add the better it will detect...why not sensors all the way around?....just a thought.

author
shwami (author)MagicByCalvin2016-03-28

Indeed! now that I also had some more time to think about this, angling the sensors inwards would make the detection range focused right in the front, not exactly the requirement in this case. Having said that, I would go for a larger overlap of the cones to avoid interference with return sound waves. I am assuming that sounds picked up at the edges of the cone will lead to noisy readings as compared to the center of the cone. Sensitivity to the sounds at the edge of the cone may also get affected due to returning waves (after bouncing off nearby walls, perhaps?). By listening closer to the center of the cone, even with a tighter combined cone, you might get more accurate decisions.

author
niq_ro made it! (author)2016-04-22

I tested partial project, but is ok.. congratulations !

DVCI6398.JPGDVCI6399.JPGDVCI6406.JPG
author
BrentR10 (author)2016-03-28

Any chance anyone has done any tinkering with pneumatic motion tacking? Or even high torque DC Gear Motor motion tracking? I'm trying to get a pneumatic character to follow people as they draw near, but not sure how to efficiently do it. I was thinking position feedback cylinders, but a significantly cheaper alternative would be preferred. reversable DC Gear motors would also be a option


author
MagicByCalvin (author)BrentR102016-03-28

While I am not familiar with pneumatics, I do think you could create a simple feedback system with DC motors. All you would need it to use a gear on the motor shaft to turn a potentiometer. The potentiometer would then create a voltage divider and the voltage can be measured. That voltage can then be mapped to angular position (and velocity and acceleration too if you add one or two differentiators to the control system). Depending on the system you are building, you will want to look into some control theory if you haven't already. For heavier and more powerful systems, if you have an unstable system, you could destroy your project or even bring harm to yourself or others.

author
Botyard (author)2016-03-17

If anybody wants to 3D print the parts I added my design at Thingiverse: http://www.thingiverse.com/thing:1419631

author
chriscolon23 (author)2016-03-02

In the case of make this project but with a ultrasonic sensor of 3-pin, what I need to change in the code. I'm a beginner.

author

You'll have to look for the 3 pin code. I believe that I referred to it in my code. Essentially, instead of using two different pins, you use one pin as both of them by changing pins from output (make the ultrasonic sound) to input (receive the ultrasonic sound).

author

Ok! I didnt see the reference. Thanks!

author

You'll have to look for the 3 pin code. I believe that I referred to it in my code. Essentially, instead of using two different pins, you use one pin as both of them by changing pins from output (make the ultrasonic sound) to input (receive the ultrasonic sound).

author
AnirudhT1 (author)2016-01-29

Hi. I made the robot correctly and I wired everything correctly. But when I try to upload the code, I get this message:

exit status 1
a function-definition is not allowed here before '{' token

Any help?

author
MagicByCalvin (author)AnirudhT12016-01-29

Hey there!
Could you please post your code so that I can check it for the bug?

author
AnirudhT1 (author)MagicByCalvin2016-01-29

Hi. This is the code. I copied it from here and pasted it as it is. And I included the Servo library too.

#include <Servo.h>

Servo myservo;

const int Lin = 10, Rin = 12, Lout = 11, Rout = 13, serv = 9; //setting sensor pins and servo pin

// establish variables for duration // and the distance result in inches long Rduration, Lduration, Rinches, Linches;

int threshold = 10; //Sensor threshold in inches

int angle = 80; //Initial angle

boolean debug = false; //Serial communication for debuging. Set to true for serial communication.

void setup() { // initialize serial communication: if (debug) { Serial.begin(9600); } myservo.attach(9); //attach servo to pin 9 }

void loop() { //Most of the sensor code has been taken from David Mellis's PING sensor code //I modified it for a 4 pin sensor as oppsed to the 3 pin sensor // Give a short LOW pulse beforehand to ensure a clean HIGH pulse: pinMode(Rout, OUTPUT); digitalWrite(Rout, LOW); delayMicroseconds(2); digitalWrite(Rout, HIGH); delayMicroseconds(5); digitalWrite(Rout, LOW);

Rduration = pulseIn(Rin, HIGH); pinMode(Lout, OUTPUT); digitalWrite(Lout, LOW); delayMicroseconds(2); digitalWrite(Lout, HIGH); delayMicroseconds(5); digitalWrite(Lout, LOW);

Lduration = pulseIn(Lin, HIGH);

// convert the time into a distance Rinches = microsecondsToInches(Rduration); Linches = microsecondsToInches(Lduration); if (debug) { Serial.print("Left: "); Serial.print(Linches); Serial.println(" in"); Serial.print("Right: "); Serial.print(Rinches); Serial.println(" in"); } follow(); }

long microsecondsToInches(long microseconds) {

// According to Parallax's datasheet for the PING))), there are

// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per

// second). This gives the distance travelled by the ping, outbound

// and return, so we divide by 2 to get the distance of the obstacle.

// See: http://www.parallax.com/dl/docs/prod/acc/28015-PI...

return microseconds / 74 / 2; }

void follow() { if (Linches <= threshold || Rinches <= threshold) { if (Linches + 2 < Rinches) { angle = angle - 2; } if (Rinches + 2 < Linches) { angle = angle + 2; } } if (angle > 160) { angle = 160; } if (angle < 0) { angle = 0; } myservo.write(angle); }

author
AnirudhT1 (author)AnirudhT12016-01-29

And also, my ultrasonic sensor is a 4 pin one.

author
AnirudhT1 (author)AnirudhT12016-01-29

And in the code, some syntaxes are mixed in comments, so I removed the comment part from it, but still it is not working..

author
MagicByCalvin (author)AnirudhT12016-02-02

I took a look at it and it looks like certain things have been commented out that shouldn't be. For example, some of the curly braces, '{', '}', have been commented out. Make sure that there is no code in the comments. It might be helpful to download the code instead of copy and paste it if you haven't done so already.

author
dodosox (author)2016-01-19

hi thx for project but my servo will not move at all. can you help me with that?

author
MagicByCalvin (author)dodosox2016-01-19

How is your motor connected? Did you use the code I provided? Is the motor powered?

author
dodosox (author)MagicByCalvin2016-01-21

yes I am using your code how should I power the mototor. the arduino boad does not power.

author
MagicByCalvin (author)dodosox2016-01-21

Can you show me some pictures of how you have it set up?

author
dodosox (author)MagicByCalvin2016-01-22

here it is

IMG_3364.JPGIMG_3362.JPGIMG_3364.JPGIMG_3365.JPGIMG_3366.JPGIMG_3365.JPGIMG_3366.JPGIMG_3367.JPGIMG_3364.JPGIMG_3366.JPGIMG_3367.JPGIMG_3364.JPGIMG_3365.JPGIMG_3367.JPGIMG_3364.JPGIMG_3365.JPGIMG_3366.JPGIMG_3368.JPG
author
MagicByCalvin (author)dodosox2016-01-29

Your photos make it a little difficult to understand what is going on. But I believe that you are not connecting everything properly. It appears like your breadboard only has one rail on each side. The picture I posted of how to set it up uses a breadboard that has two rails per side. Look closely at the circuit diagram that I made and observe where connections are made. Once you are able to see exactly where each wire should connect to on the Arduino, connect them. If connected properly, it should work just fine for you!
Also just a tip, you might want to angle your ultrasonic range sensors out a little bit so that they aren't looking at the same thing.

author
MagicByCalvin (author)dodosox2016-01-29

Your photos make it a little difficult to understand what is going on. But I believe that you are not connecting everything properly. It appears like your breadboard only has one rail on each side. The picture I posted of how to set it up uses a breadboard that has two rails per side. Look closely at the circuit diagram that I made and observe where connections are made. Once you are able to see exactly where each wire should connect to on the Arduino, connect them. If connected properly, it should work just fine for you!
Also just a tip, you might want to angle your ultrasonic range sensors out a little bit so that they aren't looking at the same thing.

author
FadiJ (author)2015-11-01

Done it. Thanks

author
bukiadeniji made it! (author)2015-09-08

Thanks for sharing! The instructions were straightforward and easy to follow. I completed the setup without any issues at all!

IMG_9262.JPGIMG_9263.JPGIMG_9260.JPG
author
DrippDroppz made it! (author)2015-08-30

This is awesome! i just built one but am having some real trouble with coding...I am just a beginner with arduino. I have two, 4 pins ultrasound sensor. I KEEP GETTING ERRORS Could someone please help me get the finished code without adjusting it myself?

FullSizeRender.jpg
author

What seems to be your issue? Could you attach the code and the errors that you are getting? The code in my Instructable should work just fine for four pin sensors.

author

I have also tried downloading your .ino file and deleting all the text from arduino application on my Mac and placing yours in there. Still errors. Do I have to set anything up from your code?

author
DrippDroppz made it! (author)MagicByCalvin2015-08-31

Hey Calvin thanks for your help, I copied the setup code into setup section as well as the loop section. Here are the error codes as well as a picture.

The sketch name had to be modified. Sketch names can only consist

of ASCII characters and numbers (but cannot start with a number).

They should also be less than 64 characters long.

motion_follow.ino: In function 'void setup()':

motion_follow:3: error: 'debug' was not declared in this scope

motion_follow:7: error: 'myservo' was not declared in this scope

motion_follow.ino: In function 'void loop()':

motion_follow:15: error: 'Rout' was not declared in this scope

motion_follow:22: error: 'Rduration' was not declared in this scope

motion_follow:22: error: 'Rin' was not declared in this scope

motion_follow:24: error: 'Lout' was not declared in this scope

motion_follow:31: error: 'Lduration' was not declared in this scope

motion_follow:31: error: 'Lin' was not declared in this scope

motion_follow:34: error: 'Rinches' was not declared in this scope

motion_follow:35: error: 'Linches' was not declared in this scope

motion_follow:37: error: 'debug' was not declared in this scope

motion_follow.ino: In function 'void follow()':

motion_follow:62: error: 'Linches' was not declared in this scope

motion_follow:62: error: 'threshold' was not declared in this scope

motion_follow:62: error: 'Rinches' was not declared in this scope

motion_follow:66: error: 'angle' was not declared in this scope

motion_follow:70: error: 'angle' was not declared in this scope

motion_follow:73: error: 'angle' was not declared in this scope

motion_follow:77: error: 'angle' was not declared in this scope

motion_follow:81: error: 'myservo' was not declared in this scope

motion_follow:81: error: 'angle' was not declared in this scope

'debug' was not declared in this scope

Screen Shot 2015-08-31 at 7.17.30 PM.png
author

Try adding this at the very top of your code:

/*************************************************************************************************
**************************************************************************************************

Motion Follow Created by Calvin Kielas-Jensen

Using an Arduino UNO, check Instructables.com for the circuit diagram.

This script allows two ultrasonic range sensors to follow movement while mounted on the top of a servo. The distance threshold can be changed but should not be set too far as the sensors will begin to fail.

Anyone is welcome to use and modify this code as long as I am given credit. Thank you for respecting the open source movement!

************************************************************************************************** *************************************************************************************************/

#include Servo myservo;

const int Lin = 10, Rin = 12, Lout = 11, Rout = 13, serv = 9; //setting sensor pins and servo pin

// establish variables for duration // and the distance result in inches

long Rduration, Lduration, Rinches, Linches;

int threshold = 10; //Sensor threshold in inches

int angle = 80; //Initial angle

boolean debug = false; //Serial communication for debuging. Set to true for serial communication.

About This Instructable

65,200views

673favorites

License:

Bio: I am currently a student in South Dakota. All my life I have been interested in tinkering with electronic amd mechanical gizmos, however after working ... More »
More by MagicByCalvin:Improve Ultrasonic Range Sensor Accuracy Motion Following Robot
Add instructable to: