Introduction: Arduino Animatronic Eyes

About: My name is Lance. I absolutely love tinkering and making things. There is something absolutely satisfying when making something from nothing.

After reviewing and scouring the internet like most hackers I decided what I wanted wasn't documented well. So I set out to not only do the project for myself but to also try and get some sort of documentation.



For this project you will need:

Electronics side:
1 - Arduino board
1 - Breadboard (anysize)
2 - Servo's I used Futaba S3003

Hardware side:
1 - Set of eyes (ebay, I specifically looked for realistic acrylic doll eyes that had the cornea bump in them). 
1 - Set of RC Car half shafts
8 - EZ connectors*
4 - Servo horns (All of mine came with my servos)
Connecting rod (various sizes and thicknesses)
1 - Sheet of Plexiglass/Acryilic Sheet (I used this as my base. Only because I had it on hand.)
1 - 12" length of Aluminum Angle Bracket 


Assorted Extras:
Aluminium Shims fabricated on the spot from bar aluminum
Screws
Cotter pins
Threaded Rod (or a bolt with head cut off)
Nuts
2 Part Epoxy

Tools:
Drill
Hack Saw
Propane Torch
Pliers
File
Dremel

*NOTE: The EZ connector hole sizes are determined by the thickness of your connecting rod. I was lucky enough to have an RC Hobby store down the road so I purchased what was on clearance  If you buy the wrong size you could always attempt to drill a bigger hole in the EZ connector but it may be more of a pain.

Step 1: Hardware Setup

Unfortunately these eyes were a Halloween rush so I didn't document the build well. I will do my best to explain how I did everything.

For the first step start with a well drawn out plan. Keep it simple.  Servo 1 is for the X-Axis.  Servo 2 is for the Y-Axis (see picture).

"Keep it simple servo" - Christen Gundersen 

Next you will want to start marking out on the plexiglass, or piece of wood, etc where the servos will be and where the eye brackets will be.

Everything starts with a good plan!

My first cheap test using ping pong balls.





Step 2: Cutting and Mounting Eye Brackets

When I made my eye brackets I did all freehand with little planning but I learned quite a few things doing it that I will pass on to you.

NOTE: I did drill three holes to allow for expansion for eyelids.

When finding out where you want to drill your holes for the eyeball rod (see pic). You must take into account to leave room for your nut on the inside of the bracket. If you drill the hole two low you won't be able to install the nut. 

You don't have to cut notches in your brackets on the right side. (I am not sure why I did actually.....) You do need to have notches on the left side of the eyeballs for the control rods to pass by without rubbing. 

To mount the brackets I drilled a small hole through both the aluminum and the plexi, then I used some spare screws to mount them. 

CAUTION: You have to pre-drill plexiglass before you screw into it otherwise you WILL crack it.

Last thing is ensure your eyes are far enough apart that you can fit the servo's behind comfortably. 


Step 3: Mounting Servos/horns.

Cut your base to receive the servos. I didn't have much in the way of cutting tools for plexiglass so I used a drill on the four corners and then used a dremel cutting bit to cut the rectangles. You don't want the plexi to melt so take your time and move pretty quickly.

When mounting the servos, servo #2 needs to be shimmed higher. This is for two reasons 1) to keep the servo horn in line with the top of the eyeball and 2) to keep it from interfering with the servo # 1 control rods.

Next you will want to attach the secondary horns to act as dummies to move the second eye. Placement is critical so you don't get a "lazy eye". I mounted them using shims or washers to raise the horn to the servo's level. (see pic) Also the washer that is touching the horn is a nylon(plastic) washer to ease friction.

Step 4: Prepping and Mounting Eyeballs

When you receive the eyes they are for dolls so we have to prep them. 

This is a four step process:

1) Take the back half of the eyeball and cut off a half inch ring of the widest part. (see pic two)
2) Glue the ring to the eye using two part epoxy. DO NOT get glue on the front of the eyeball or you will ruin the realistic touch. Use the glue sparingly.
3) Don't touch them until the glue dries.*
4) Drill a hole in the top and left side of eyeball #1 and on the top and left side of eyeball #2. This hole is to receive the cotter pin in step five.

*While the eyeballs cure you will want to get onto the eyeball mounting rod/pivot point.

So I was trying to figure out how I would get the pivot point done during brainstorming and I came across the half shafts at the RC store. What I had to do was cut them down to a more manageable size and find a mounting rod.

The mounting rod is just a bolt I had laying around that I "screwed" into the half shaft and then bolted to the bracket. This was such a tight connection I didn't even have to glue it!

Once your half shaft is on the rod you can epoxy it to the eyeball stub with the two part epoxy. Ensure you let the epoxy fully cure so as not to weaken it.

Lastly, mount the eyeball mounting rod onto the bracket. Take time to ensure the eyeballs are the same distance from the bracket and don't adjust them anymore.

Step 5: Installing Connecting Rods

For my setup, I used some connecting rod/push rod they had at the RC store. Do note these rods come in varying lengths and diameters so be sure you get your EZ connectors to match. 

The great thing about the connecting rods and EZ connectors is that you can adjust it to any length indefinitely because the rod just slips through the EZ connector and the screw on top clamps the rod in place.

Cut your rods to length either using heavy duty pliers or even the hack saw. The important thing is to ensure you have no burrs on the end so it will slip into the EZ connector.

On the end that is going to the eyeball, you will need to devise some sort of hook. For this task, I employed the use of a cotter pin because it was readily available in my garage and because it already had a nice "hook" feature to it. What you need to do is cut one leg of the cotter pin short and solder the longer leg to your connector rod. Once you have it soldered on (and cooled) you can hook it into the holes you drilled in the eyeballs and close it using pliers.

For the last part you need to insert it into the EZ Connector on the horns but do not tighten them down yet. (they should be able to slide on the rods for now)

Step 6: Wire Up the Servos

Using my breadboard, so I could drive both servos from the Arduino's on board 5VDC, I set up the board as follows:

1) 5VDC(ORANGE WIRE) to breadboard power strip
2) GND(BLUE WIRE) to breadboard power strip (I try to use the same ground on both servos)
3) Digital PIN 8(YELLOW WIRE BOTTOM) to horizontal servos (X-Axis)
4) Digital PIN 9(YELLOW WIRE TOP) to vertical servos (Y-Axis)

That's it! Now on to the software side.

Step 7: Programming

This may be the single most confusing part of the project so I tried to write as much code as I could to ideally minimize the issues you may have.

All files are in the sketchbook.zip.

First here is the code to get your servos centered. The problem you face is getting the servo position correct. Keep in mind these servos go from 0 to 180 degrees.

So in summary we want to set the servos to 90 and 90 so its in the center of the servos "range of motion". Then we can set the Horizontal (X-Axis) and Vertical (Y-Axis) limits. For that you can use the eyes_servo_single_test changing horServo.write(); and vertServo.write();

[eyes_servo_single_test CODE]

#include <Servo.h>

Servo horServo;
Servo vertServo;

void setup(){
  horServo.attach(8);
  vertServo.attach(9);
}

void loop(){
  horServo.write(80);
  vertServo.write(40);
}

[END CODE]

Next I would use eyes_full_servo_test again plugging in your high and low values for the servos that way you can see if you have any binding. I built in a blinking key so you can visualize what step your on. You can always stop it midway by pulling the USB cord.

[eyes_full_servo_test CODE]

//==================
//This is a quick servo position test I did for my Eye Project
//The servos move from the set postions for the X and Y axis
//Test one sets the LED HIGH 20 seconds, long blink.
//Test two sets the servos at position 40,0 for 6.5 seconds, two blinks.
//Test three sets the servos at position 80,0 for 7.5 seconds, three blinks.
//Test four sets the servos at position 0,70 for 8.5 seconds, four blinks.
//Test five sets the servos at position 0,110 for 9.5 seconds, five blinks.

//NEED TO PRESS RESET ONCE TEST IS COMPLETE

#include <Servo.h> //servo library

Servo horServo; //x-axis servo
Servo vertServo; //y-asxis servo
int led = 13;

void setup(){
  horServo.attach(8); //x-axis servo pin 8
  vertServo.attach(9); //y-axis servo pin 9
  pinMode(led, OUTPUT);
}

void loop(){
  //==================TEST ONE=============//

  //Servos in resting or center position. 
  horServo.write(80);
  vertServo.write(40);

  //blink once
  digitalWrite(led, HIGH);
  delay(20000);
  digitalWrite(led, LOW);

  //============Test Two=================//

  //test two blinks twice

  horServo.write(20); //x left limit
  vertServo.write(40);

  //blink twice
  digitalWrite(led, HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led,HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(5000);

  //=================Test Three==================//

  //test three blinks three times

  horServo.write(80); //x right limit
  vertServo.write(40);

  //blink three times
  digitalWrite(led, HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led,HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led,HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(5000);


  //==================Test four==================//

  //Test four blinks four times

  horServo.write(80);
  vertServo.write(0); //y top limit

  //blink four times
  digitalWrite(led, HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led,HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led,HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led,HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(5000);

  //=================Test Five===================//

  //Test Five blinks five times

  horServo.write(80);
  vertServo.write(110); //y bottom limit

  //blinks five times
  digitalWrite(led, HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led,HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led,HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led,HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
  digitalWrite(led,HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(5000);

  //=====================END======================//

  //Servos back to resting or center. Testing ended hit RESET or wait FOREVER

  horServo.write(80);
  vertServo.write(40);  
  digitalWrite(led, HIGH);
  while(1){}


}

[END CODE]


The code uses PI to move the eyes in a radius. You need to ensure you have your servos on pin 8 and 9 or change it in the code. Once you are confident you have everything set properly you can set the EZ connectors in place.

[eyes_sketch CODE]

#include <math.h>

#define pi    3.14159265358979323846
#define twopi (2*pi)
float circleradius = 50; //50 each side - make no more any of your max limit values
float stepnumber = 360;
float stepangle;


#include <Servo.h> //include servo library for servo control

Servo horServo; //servo for left/right movement
Servo vertServo; //servo for up/down movement

byte randomhor; //define random horizontal position variable
byte randomvert; //define random vertical position variable
int randomdelay; //define random delay variable

#define HLEFTLIMIT 40 //define left limit on horizontal (left/right) servo
#define HRIGHTLIMIT 80 //define right limit on horizontal (left/right) servo

#define VTOPLIMIT 70//define top limit on vertical (up/down) servo
#define VBOTLIMIT 110 //define bottom limit on horizontal (up/down) servo


void setup()
{
  horServo.attach(8); //horizontal servo on pin 8
  vertServo.attach(9); //vertical servo on pin 9
  randomSeed(analogRead(0)); //Create some random values using an unconnected analog pin

  stepangle = twopi/stepnumber;
  for(int i = 0; i<stepnumber; i++){
    float angle = i*stepangle;
    float x = sin(angle)*circleradius;
    float y = cos(angle)*circleradius;

    x = map(x, 1-circleradius, circleradius, 0, 2*circleradius);
    y = map(y, 1-circleradius, circleradius, 0, 2*circleradius);

    horServo.write(x); //write to the horizontal servo
    vertServo.write(y); //write to the horizontal servo

    delay(10);
  }
}


void loop()
{
  randomhor = random(HLEFTLIMIT, HRIGHTLIMIT); //set limits
  randomvert = random(VTOPLIMIT, VBOTLIMIT); //set limits
  randomdelay = random(1000, 4000); //moves every 1 to 4 seconds

  horServo.write(randomhor); //write to the horizontal servo
  vertServo.write(randomvert); //write to the vertical servo
  delay(randomdelay); //delay a random amount of time (within values set above)
}

[END CODE]

Step 8: Finishing Touches

I chose to also learn how to make a mask AND learn to fiberglass. I won't be going into those steps here but you can find out on other instructables (I did!)

I did a simple fiberglass mask and riveted in some angle brackets to hold the eye in place.

Good Luck everyone! Be sure to leave feedback for version 2.0!

Kit Contest

First Prize in the
Kit Contest

Arduino Contest

Finalist in the
Arduino Contest

Epilog Challenge V

Participated in the
Epilog Challenge V