Overview
Have you ever wanted to build a robot, but don't know where to start? Or... are you looking for a project that you can cut-your-teeth on?
This servo-controlled animatronic robot head uses two servos for movement, two speakers for eyes and an LED mouth for a friendly remote-controlled robot.
This an advanced project, for people who already know how to control servos and LEDs. This tutorial will focus on the 3D printing and assembly of the 'bot head!
Page last edited March 08, 2024
Text editor powered by tinymce.
Tools / Materials
Tools
- 220 grit sand paper
- screw driver
- hot-glue gun
- hand torch
- soldering iron
- variable speed drill
- hand saw (for cutting the dowel)
Some of the parts might have tight tolerances... I plan on using a M3 tap to reduce the risk of splitting the plastic.
Materials
- cute desktop speakers for the eyes
- 3D printed parts
- 2X analog feedback servo
- electret microphone
- 5X 3mm LEDS
- 3X 330ohm Resistors
- 4X 8mm M3 screws
- 10X 10mm M3 screws
- 2X M3 nuts
- 5X short wood screws
- 1X 20mm X 120mm dowel (usually sold in meter lengths)
- super glue
- 5-minute epoxy
Grab your speakers and let's go!
Page last edited March 08, 2024
Text editor powered by tinymce.
Design
I thought to myself, "I wonder what earlier versions of WALL-E and Johnny 5 were like."
A few sketches later, I had a rough-cut on the head ready to go. It's a simple design, a U-joint and two armatures connected to two servos.
Page last edited March 08, 2024
Text editor powered by tinymce.
Assembly: U-Joint
Page last edited March 08, 2024
Text editor powered by tinymce.
Assembly: Mounts
Page last edited March 08, 2024
Text editor powered by tinymce.
Assembly: Servo Plate
Page last edited March 08, 2024
Text editor powered by tinymce.
Assembly: Rod Ends
Page last edited March 08, 2024
Text editor powered by tinymce.
Assembly: Armature
- rods should be roughly the same length (+/- 2mm)
- rod-ends should be aligned
Page last edited March 08, 2024
Text editor powered by tinymce.
Assembly: Mouth
Page last edited March 08, 2024
Text editor powered by tinymce.
Assembly: Eyes
5-minute epoxy is pretty good... but I'd wait more like 30 minutes just to be safe.
Voila!
Page last edited March 08, 2024
Text editor powered by tinymce.
Mission Control
This approach means you will be driving the servos dynamically.
Page last edited March 08, 2024
Text editor powered by tinymce.
Source Code
- yellow wire to pin 9: drives the LEDs on the far right and left
- blue wire to pin 10: drives the LEDs between the center and outside
- purple wire to pin 11: drives the LED in the center of the mouth
- green wire to ground
And this is the sketch that drives the LEDs based on the sound levels captured by the microphone.
There are some settings in there like HI_CUT, LO_CUT, and DC_OFFSET that you might have to adjust depending on what kind of audio you intend to drive the microphone with and how you've hooked it up.
As-is, this sketch works pretty well with the mic attached to your shirt just below the mouth.
// Connect LED positive to pins 9, 10, 11 with common ground.
#define MIC_PIN A0 // connected to the out pin on the mic
#define DC_OFFSET 3.3 // mic is plugged into 3.3v
const byte HI_CUT = 255; // upper brightness limit
const byte LO_CUT = 40; // lower iimit turns LEDs off
// sample window width in mS (50 mS = 20Hz)
const int sampleWindow = 50;
unsigned int sample;
int LED_CENTER = 11; // LED at center of the mouth
int LED_MIDDLE = 10; // LEDs between the center and outside
int LED_OUTSDE = 9; // LEDs on the outside of the mouth
void setup() {
// Serial.begin(9600); // remove comment for debugging
pinMode( LED_CENTER, OUTPUT );
pinMode( LED_MIDDLE, OUTPUT );
pinMode( LED_OUTSDE, OUTPUT );
}
void loop() {
unsigned long startMillis= millis(); // start of sample window
unsigned int peakToPeak = 0; // peak-to-peak level
unsigned int signalMax = 0;
unsigned int signalMin = 1024;
double lvl = 0;
// collect data for 50 mS within a reasonable range
while (millis() - startMillis < sampleWindow) {
sample = analogRead(MIC_PIN);
if (sample < 1024) {
if (sample > signalMax) {
signalMax = sample;
}
else if (sample < signalMin) {
signalMin = sample;
}
}
}
lvl = signalMax - signalMin; // max - min = peak-peak amplitude
lvl = ( lvl * DC_OFFSET ); // reduce operational range
lvl = ( lvl < LO_CUT ? 0 : lvl ); // low cut filter for noise
lvl = ( lvl > HI_CUT ? HI_CUT : lvl ); // high cut filter for clipping
analogWrite( LED_CENTER, lvl ); // 100% brightness
analogWrite( LED_MIDDLE, lvl * .8 ); // 80% brightness of center
analogWrite( LED_OUTSDE, lvl * .3 ); // 30% brightness of center
// Serial.println(lvl); // remove comment for debugging
}
Have fun with your new robotic friend!
Page last edited March 08, 2024
Text editor powered by tinymce.