If This Then That - Duck Animatronic
by Oxyhadron in Circuits > Arduino
351 Views, 11 Favorites, 0 Comments
If This Then That - Duck Animatronic
ive always had a facination with animatronics so this is my attempt at a simple duck head animatronic.
The animatronic moves forwards backwards and side to side, opens and closes its mouths and makes a quack noises based on joystick inputs.
Supplies
Supplies
- Arduino Uno + cable
- 3 servos (sg90 or mg90s)
- small speaker (8ohm 0.2W worked fine for me)
- thumbstick
- enough wood to make a box (or if you have already have a project box that will also work)
- metal wire (1mm thick)
- conductive wire
- rubber mat the size of the arduino
- 4.5mm rod (i used brass but it doesnt matter what material)
- solder
- electrical tape (or heat shrink tubing)
- 10mm rod ~ 7cm long
- 14 small screws
- a bunch of zipties
Tools used
- 3D printer
- Drillpress
- Bandsaw
- Hammer
- Soldering iron
- needle nose pliers
- wire cutters
- Screwdriver
- Knife
Designing the Animatronic
the idea was to design an animatronic, at first i wanted it to move the head front to back side to side and rotate horizontaly
but about halfway though designing it i decided to have a moving mouth as it would make it more lifelike.
my first design was way smaller and more fragile, i also made a huge oversight when modeling, that being that the arm where the servos connect must connect 90 degrees at the same radius above the pivot point otherwise it would lock up when moving in a circle.
looking back on the design process i learned how valuable plannig things out from the start can be, instead of improvising all the way through, as is my usual method.
This project also made me brush up on my arduino programming skills
i now know how to use the servo and pcm libraries
aswell as making memore familiar with fusion360.
3D Print All the Parts
Printed in cura with a 0.8 mm nozzle
settings used in cura
- 0.32 mm line width
- 3 walls
- 20% infill
- printed with supports
- 20% support infill
total print time (with these settings) if everything prints fine in one go ~ 5 hours and 48 minutes.
83 grams of fillament
cleanup
- some parts of the 3d print might have the right tolerances, you can use a knife to clean up and shave away some materiak
- if you have the wrong servos wires dont route properly so you might have to cut out a few slots, using a lighter and a cheap knife you dont care about you can melt away part of the plastic, this is easier than cutting
Downloads
Make Wooden Enclosure
instructions for making the enclosure
there are multiple ways to make a box but this is how i did it:
- cut the wood to the approximate dimensions of the drawing
- for the part where the joystick goes its important to clear away wood where the pins are gonna go
- hammer in temporary nails
- testfit everything so you know everything fits
- pull apart wood so the nails are possible to place back
- put glue on the places where it has to stick
- hammer back down all the temporary nails (this acts as allignent and clamping force
- clamp down the work piece for extra pressure
- remove clamps
- sand down imperfections and finish with a neutral oil or a clear varnish
Program the Arduino
install FlagPCM library (this is an edited version of the PCM library that avoids conflicts between internal timers) FlagPCM: https://github.com/codemee/FlagPCM
how to install library
- download FlagPCM
- in Arduino IDE Sketch>Include library>Add .zip library
- select FlagPCM
copy the code and upload it to your arduino
#include <FlagPCM.h>
#include <Servo.h>
float sm; // float for smoothing servo 1
float sm2; // float for smoothing servo 2
const int Y_pin = A0; // analog pin connected to Y output
const int X_pin = A1; // analog pin connected to Y output
int val;
int val2;
int angle = 2; // initial angle for servo (beteen 1 and 179)
int angleStep = 30; // servo step size
const int minAngle = 0; //min angle
const int maxAngle = 31; //max angle
const int type = 2; // either 1 or 2 changes servo direction on button click
int buttonPushed = 0; // int for button push logic
Servo myservo; // create servo object to control a servo
Servo myservo2; // create servo object to control a servo
Servo myservo3; // create servo object to control a servo
#define servoPin 6 // attaches servo 3 on pin6
#define pushButtonPin 2 // attaches button on pin 2
// programs sound file as array
const unsigned char sample[] PROGMEM = {
129, 128, 128, 127, 128, 128, 128, 128, 128, 128, 127, 127, 126, 126, 126, 126, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 127, 127, 127, 128, 128, 128, 127, 126, 127, 128, 128, 127, 127, 127, 126, 127, 128, 128, 128, 127, 127, 128, 128, 127, 127, 127, 128, 129, 129, 128, 126, 126, 127, 129, 129, 127, 126, 127, 127, 127, 127, 127, 126, 127, 128, 128, 128, 127, 128, 129, 129, 128, 127, 127, 127, 127, 127, 128, 129, 129, 130, 129, 128, 127, 126, 127, 127, 127, 128, 128, 128, 128, 127, 127, 127, 127, 126, 126, 126, 127, 128, 127, 127, 125, 124, 126, 126, 124, 121, 120, 123, 126, 128, 128, 127, 127, 129, 132, 134, 136, 137, 139, 141, 139, 130, 119, 110, 106, 108, 112, 116, 118, 116, 115, 109, 102, 99, 97, 99, 108, 116, 123, 130, 134, 132, 128, 123, 121, 121, 126, 134, 141, 146, 148, 147, 142, 135, 129, 127, 129, 133, 143, 154, 163, 170, 170, 164, 148, 116, 91, 88, 100, 124, 146, 160, 164, 153, 127, 97, 81, 84, 101, 123, 140, 150, 150, 138, 121, 108, 99, 101, 111, 119, 122, 118, 109, 101, 96, 100, 105, 109, 111, 107, 104, 101, 102, 108, 116, 126, 135, 144, 151, 151, 149, 144, 146, 156, 171, 192, 208, 220, 206, 148, 81, 50, 75, 135, 182, 196, 183, 151, 97, 46, 33, 61, 118, 169, 179, 164, 143, 123, 115, 119, 134, 156, 164, 150, 127, 113, 117, 129, 135, 134, 123, 97, 68, 50, 51, 76, 100, 112, 109, 91, 76, 76, 90, 115, 135, 142, 144, 141, 139, 145, 156, 174, 203, 229, 245, 228, 145, 50, 26, 83, 176, 226, 199, 144, 95, 60, 51, 68, 113, 156, 151, 118, 102, 119, 153, 177, 175, 156, 132, 113, 112, 135, 168, 184, 166, 123, 90, 77, 76, 84, 91, 87, 79, 68, 67, 76, 83, 89, 91, 94, 98, 102, 115, 136, 158, 169, 175, 185, 194, 223, 245, 196, 95, 36, 68, 154, 212, 192, 135, 103, 80, 61, 72, 99, 113, 100, 83, 105, 157, 181, 170, 141, 111, 111, 131, 155, 178, 175, 155, 139, 139, 142, 128, 104, 84, 76, 75, 77, 84, 86, 86, 83, 81, 87, 91, 102, 119, 129, 130, 141, 160, 189, 223, 238, 240, 180, 56, 33, 137, 229, 233, 151, 89, 106, 130, 128, 108, 65, 39, 55, 104, 171, 186, 134, 101, 115, 142, 156, 149, 138, 131, 134, 158, 186, 172, 119, 86, 98, 117, 109, 84, 68, 75, 90, 100, 91, 75, 87, 114, 130, 129, 124, 139, 177, 214, 238, 239, 157, 37, 59, 195, 255, 182, 78, 96, 170, 168, 136, 80, 19, 29, 88, 159, 171, 103, 67, 119, 170, 156, 116, 97, 119, 154, 173, 179, 145, 90, 94, 146, 158, 114, 76, 77, 100, 107, 96, 92, 79, 79, 114, 134, 128, 124, 146, 205, 239, 228, 200, 111, 38, 125, 239, 234, 136, 63, 139, 215, 154, 82, 40, 38, 103, 153, 149, 99, 67, 124, 180, 148, 100, 104, 145, 168, 149, 136, 137, 131, 144, 150, 120, 83, 81, 112, 120, 101, 89, 95, 106, 109, 118, 123, 115, 142, 192, 214, 235, 209, 88, 51, 165, 239, 197, 103, 92, 187, 196, 109, 58, 58, 106, 147, 116, 77, 66, 110, 181, 149, 75, 90, 144, 167, 142, 111, 119, 136, 156, 168, 126, 74, 91, 140, 126, 74, 61, 90, 123, 122, 100, 107, 130, 146, 188, 221, 210, 139, 35, 98, 234, 190, 100, 78, 145, 235, 154, 56, 69, 80, 121, 148, 95, 55, 83, 156, 171, 85, 46, 116, 157, 134, 113, 109, 123, 141, 147, 138, 113, 101, 109, 117, 101, 87, 96, 105, 114, 115, 126, 145, 151, 175, 208, 208, 114, 31, 144, 246, 164, 86, 103, 178, 212, 140, 71, 73, 107, 147, 143, 88, 75, 134, 171, 124, 59, 86, 152, 144, 105, 105, 136, 148, 136, 128, 121, 116, 120, 126, 110, 93, 111, 123, 101, 92, 117, 136, 147, 166, 187, 209, 147, 37, 96, 224, 193, 94, 90, 179, 218, 141, 77, 76, 99, 145, 134, 72, 77, 139, 183, 136, 55, 87, 158, 147, 97, 78, 117, 154, 144, 124, 114, 116, 121, 119, 104, 89, 102, 124, 116, 102, 117, 132, 155, 170, 168, 186, 114, 29, 137, 229, 141, 65, 101, 183, 190, 108, 69, 91, 118, 141, 107, 61, 112, 171, 161, 114, 74, 118, 166, 128, 94, 101, 134, 164, 146, 123, 122, 126, 126, 121, 121, 106, 97, 126, 139, 137, 140, 136, 160, 182, 189, 173, 75, 78, 208, 190, 100, 95, 131, 190, 164, 80, 83, 114, 137, 137, 78, 82, 159, 165, 115, 86, 100, 144, 135, 94, 96, 122, 142, 139, 121, 115, 121, 129, 119, 112, 112, 108, 124, 133, 136, 148, 157, 173, 179, 182, 137, 65, 134, 212, 138, 88, 124, 161, 165, 120, 89, 100, 116, 128, 116, 83, 102, 158, 151, 98, 82, 120, 148, 112, 82, 108, 131, 125, 118, 117, 117, 115, 112, 110, 113, 105, 104, 113, 115, 133, 140, 148, 171, 174, 190, 122, 48, 171, 215, 108, 100, 134, 163, 170, 111, 93, 109, 118, 133, 110, 83, 123, 165, 133, 91, 99, 139, 154, 103, 81, 130, 144, 124, 124, 126, 128, 131, 115, 107, 113, 110, 121, 128, 122, 130, 143, 161, 177, 183, 131, 68, 153, 224, 132, 89, 137, 167, 164, 131, 107, 116, 127, 121, 110, 103, 117, 151, 143, 109, 106, 126, 138, 114, 95, 124, 141, 120, 123, 146, 137, 121, 114, 104, 119, 127, 113, 110, 126, 143, 146, 148, 158, 178, 142, 55, 116, 216, 139, 86, 140, 164, 159, 130, 107, 121, 135, 125, 108, 109, 125, 152, 149, 114, 113, 133, 135, 117, 96, 114, 134, 125, 126, 139, 140, 125, 114, 115, 125, 124, 109, 114, 136, 146, 141, 137, 156, 187, 149, 58, 104, 210, 152, 92, 137, 159, 157, 139, 110, 116, 132, 127, 111, 112, 127, 142, 146, 126, 118, 131, 137, 125, 108, 115, 134, 133, 126, 130, 134, 128, 114, 112, 128, 125, 110, 118, 136, 152, 144, 129, 159, 193, 123, 49, 144, 211, 122, 95, 147, 169, 157, 119, 107, 124, 135, 126, 102, 113, 140, 144, 133, 114, 117, 137, 133, 110, 104, 124, 134, 118, 115, 128, 127, 124, 124, 111, 109, 123, 121, 105, 114, 140, 131, 124, 143, 150, 163, 126, 76, 148, 173, 97, 117, 151, 142, 152, 129, 111, 125, 123, 119, 112, 109, 131, 141, 124, 117, 122, 127, 130, 112, 103, 121, 127, 117, 115, 124, 129, 119, 103, 113, 128, 114, 104, 119, 132, 130, 122, 131, 165, 171, 98, 65, 160, 174, 74, 80, 144, 149, 127, 110, 112, 121, 122, 108, 100, 118, 128, 131, 131, 118, 121, 132, 130, 116, 112, 130, 133, 122, 124, 129, 133, 128, 113, 120, 130, 108, 106, 125, 119, 116, 122, 128, 138, 129, 140, 174, 133, 70, 121, 179, 123, 87, 130, 164, 156, 121, 109, 120, 129, 132, 109, 109, 138, 139, 127, 117, 117, 133, 134, 115, 111, 128, 136, 126, 119, 128, 143, 134, 116, 122, 123, 107, 120, 129, 100, 114, 143, 123, 120, 127, 133, 150, 148, 155, 125, 94, 166, 169, 92, 123, 169, 152, 130, 117, 127, 135, 123, 121, 118, 119, 131, 130, 119, 119, 127, 130, 126, 119, 122, 137, 134, 123, 130, 137, 131, 123, 116, 120, 132, 121, 100, 105, 126, 129, 105, 102, 129, 132, 123, 117, 119, 147, 157, 150, 132, 101, 147, 184, 118, 111, 160, 155, 137,
};
void setup() {
myservo.attach(7);
myservo2.attach(8);
myservo3.attach(servoPin); // attaches the servo on pin 3 to the servo object
Serial.begin(9600); // setup serial
pinMode(pushButtonPin, INPUT_PULLUP);
myservo3.write(angle);//initial position
}
void loop() {
if (digitalRead(pushButtonPin) == LOW) // if button pressed change buttonpushed to 1 {
buttonPushed = 1;
}
if ( buttonPushed ) {
// change the angle for next time through the loop:
angle = angle + angleStep;
// reverse the direction of the moving at the ends of the angle:
if (angle >= maxAngle) {
angleStep = -angleStep; //makes servo move back
if (type == 1)
{
buttonPushed = 0;
}
}
if (angle <= minAngle) {
playback(sample, sizeof(sample)); //plays back sound at the moment the mouth reaches the bottom
angleStep = -angleStep;
if (type == 2)
{
buttonPushed = 0;
}
}
myservo3.write(angle); // move the servo to desired angle
delay(100); // waits for the servo to get there
}
val = analogRead(Y_pin); //reads analog value ypin
val = map(val, 0, 1023, 170, 0); //converts joystick data to servo angle
sm = (val * 0.05) + (sm * 0.95); // smoothes servo angle value
val2 = analogRead(X_pin); //reads analog value pin
val2 = map(val2, 0, 1023, 0, 170); //converts joystick data to servo angle
sm2 = (val2 * 0.05) + (sm2 * 0.95);// smoothes servo angle value
myservo.write(sm); //writes smoothed value to servo
myservo2.write(sm2); // writes smoothed value to servo 2
delay(5); ads delay to servo
}
Assemble Parts
universal joint
- cut the swivel rod for universal joint ~ 12mm and 17mm
- push the 12mm part through the middle and top part to the end. then you can route the 17mm part through the hole of the middle and bottom parts of the universal joint
- glue down one side of the 17mm rod to the side of the bottom part of the universal joint
connection to box
- route the 10mm diameter rod through the 3d printed parts
- glue the bottom of the universal joint and the base together onto the 10mm rod
- screw down the base onto the box
connect servos to 3d printed parts
- screw down the servos using the standard servo mounting points
- if the screws wont go in you can heat up the screw using a lighter so that it will melt the pla around the screw
- the top servo is just a pressfit, you can screw it down but its not necessary, at the step you can attach the bottom part of the mouth which is also pressfit.
connect servo to the top part of the unversal joint using steel wire
- using needle nose pliers you can bend a cirular shape in the steel wire that you route through the designated holes in the top part
- measuring where the top part of the universal joint would sit flat you bend the bottom of the steel wire 90 degrees you can the push the steel wire though the holes in the servo arm (if the steel wire is too big you can use a lighter to melt the hole bigger) then you can bend the arm another 90 degrees upwards so its snug
- trim excess of the wire
mount the joystick
- it might be wise to do this after wiring as you likely cant wire it when its firmly in place
- push the 3d printed plate through the hole cut in the front of the enclosure
- screw in screws at the back of the joystick
- push the 3d printed joystick knob onto the joystick component
mount the arduino to the bottom of the enclosure
- not strictly necessary but its wise to use some sort of squishy non conductive material on the bottom of the arduino not to damage it when screwing in the arduino.
- screw in the arduino
mount speaker
- glue down the speaker ontop of the speaker holes
Wire the Electronics
wire the electronics according to the diagram ( if unclear ):
- the bottom servos are connected to digital pin 7 and 8, ground, and 5v
- the top servo is connected to digital pin 6, ground, and 5v
- the button is connected to digital pin 6 and ground
- the speaker is connected to digital pin 11 and ground
use zipties to tidy up the wires
- you can use zipties to tidy up bundles of wires
- if you solder wires together, dont forget to put electrical tape around it to prevent short circuits
(optional) push the wires of the top servo through a maluable rubber tube so it looks neater
- put zipties on both ends of the tube. one underneath the enclosure so it doesnt come out
The Ducks Appearance
my lovely mother knitted the duck out of wool for me,so i cant give instructions on how she did it because i dont know how to knit.
alternatively you can glue apropriately colored fabric onto the 3D printed parts.
Done!
duck animatronic demo: