xl97's Iron Man motorized face plate tutorial

I know this may be a little out dated but I have been reading over this post trying to build my sons future Halloween costume. The information here is top notch and I really appreciate someone taking the time to do this. I'm a total noob to electronics and programming so any help would be appreciated.

First, my helmet is 3D printed with all the hinges already attached. I currently have it hooked up to a breadboard and Arduino UNO with two push buttons. I'm using a single Servo design which works perfectly.

Second, I have tried to use the schematic at the beginning of this post with the supplied code but I have had no luck.

Below is the layout I am using on my board and I've tried to mimic the schematic as best as possible. I'm also using the latest code on this thread. I know it has 2 servos on it and I only have one. I'm assuming that's not an issue. My main goal is to get this working first before I move onto adding the LED strips I'll be using. I just want to make sure my code and schematic is right first.
Smooth Sango (2).png


What I'm using:
MG 995 Servo
Operating Speed : 0.17sec / 60 degrees (4.8V no load) & 0.13sec / 60 degrees (6.0V no load)
Stall Torque : 13 kg-cm at 4.8V & 15kg-cm at 6V
Operation Voltage : 4.8 - 7.2Volts
Gear Type: All Metal Gears
Color: Black
Item size: 40 * 19 * 43mm

LM7805 VRegulator
2 - 10uf non-polarized capacitors
2 - NPN Transistors
220k ohm Resistors
2 - White 3.0V -3.2V LED's

I did notice one thing though. The schematic is using a "Internal Pull-up" button. Not sure what that is. I'm using the standard buttons out of my electronics kit.
IMG_5294.JPG
IMG_5295.JPG
 
Hi-

1.) That is NOT an internal pull-up button...

its a regular button/switch.. with the CODE set for that button to use an internal pull up (so it not floating.... meaning it is set to either hi or lo.. and not 'floating' in the middle... in this case.. it is set 'hi' with the interal pull-up resistor (no external resistor/part needed).. and the button is 'pulled low' when pressed (and connects to the GND rail)...which has no resistance/resistor on it... and the code check for when the butotn is 'lo'.)


2.) What is it doing? nothing?

From your wiring diagram.. I dont see any GND wires connecting the Arduino to the rest of the circuit?
 
Last edited:
When I had everything hooked up and code loaded, I would press the button and nothing would happen. Your are correct I did not have the UNO grounded to the breadboard.

Since I have been messing around with it I decided to make it as simple as possible and redid my breadboard and eliminated the VR, capacitors, and transistors. My goal is to just get something to work. This is what I did.

Brilliant Elzing.png



I did realize on your schematic that it did not have any power going to the push button. I went back on some tutorials I did for Arduino and set the button up as shown. I grounded the board to the breadboard and rest of the circuits.

Now when I press the button the lights slowly glow to bright and I can here the Servo buzzing. I press the buzzer again and the lights slowly fade and the buzzing stops. Progress!

IMG_5297.JPG
IMG_5298.JPG


Here's your code I'm using

// IronMan Helmet: eye blink sequence_v1.0
// created by: xl97
// Movie Props, Costumes and Scale Models | the RPF thread:
// http://www.therpf.com/f24/iron-man-m...ml#post2647126

//import servo lib
#include <Servo.h>

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

const int buttonPin = 2; // the pin that the pushbutton is attached to
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
int pos = 0; // variable to store the servo positions
int pos1 = 180;

// led control pins (need to be PWM enabled pins for fading)
const int leftEye = 6; // the number of the left eye/pcb LEDs
const int rightEye = 3; // the number of the right eye/pcb LEDs

unsigned long delaytime = 1;
unsigned long blinkspeed = 100;
unsigned long currentPWM = 0;
boolean isOpen = true;

#define S_IDLE 1
#define S_LEDON 2
#define S_WAITON 3
#define S_LEDOFF 4
#define S_WAITOFF 5
#define S_INITON 6
#define S_INITWAIT 7
#define S_BLINKON 8
#define S_SERVOUP 9
#define S_SERVODOWN 0



//FSM init vars
static int state = S_IDLE; // initial state is 1, the "idle" state.
static unsigned long lastTime; // To store the "current" time in for delays.


void setup() {
// Set up serial port
Serial.begin(9600);
//start it off
//state = S_BLINKON;
Serial.print("INTIT STATE: ");
Serial.println(state);

myservo.attach(9); // attaches the servo on pin 9 to the servo object
myservo1.attach(10); // attaches the servo on pin 10 to the servo object

pinMode(buttonPin, INPUT); // initialize the button pin as a input
digitalWrite(buttonPin, HIGH); //use interal pull up resistors
}

void loop() {
switch(state)
{
case S_IDLE:
// We don't need to do anything here, waiting for a forced state change...like button press.
//check mian button state
buttonState = digitalRead(buttonPin);

// compare buttonState to previous state
if (buttonState != lastButtonState) {
//if button pressed/down
if (buttonState == LOW){
//ie: pressed
if(isOpen == true){
Serial.print("CLOSING FACE PLATE: ");
Serial.println(isOpen, DEC);
state = S_SERVODOWN;
}
else{
Serial.print("OPENING FACE PLATE: ");
Serial.println(isOpen, DEC);
//state = S_SERVOUP;
state = S_LEDOFF;
}
isOpen = !isOpen;

}
else{
//went from ON/HIGH to LOW/OFF..ie: released
//Serial.print("RELEASE: ");
//Serial.println(isOpen, DEC);
}

}
// save the current state for next loop
lastButtonState = buttonState;
break;

case S_BLINKON:
Serial.println("init blink.........");
//do blink routine here
analogWrite(leftEye, 155);
analogWrite(rightEye, 155);
delay(blinkspeed);
analogWrite(leftEye, 0);
analogWrite(rightEye, 0);
delay(10);
/*
analogWrite(leftEye, 155);
analogWrite(rightEye, 155);
delay(blinkspeed);
analogWrite(leftEye, 0);
analogWrite(rightEye, 0);
delay(10);
*/
currentPWM = 0;
state = S_LEDON;
break;

case S_LEDON:
Serial.println("increase........");
lastTime = millis(); // Remember the current time
analogWrite(leftEye, currentPWM);
analogWrite(rightEye, currentPWM);
state = S_WAITON; // Move to the next state
break;

case S_WAITON:
// If one second has passed, then move on to the next state.
if(millis() > lastTime + delaytime)
{
if(currentPWM < 255){
currentPWM += 5;
state = S_LEDON;
}
else{
Serial.println("@ 255 done........");
state = S_IDLE;
//state = S_LEDOFF; //no auto turn off.. set to idle state
}
}
break;

case S_LEDOFF:
Serial.println("........decrease");
lastTime = millis(); // Remember the current time
analogWrite(leftEye, currentPWM);
analogWrite(rightEye, currentPWM);
state = S_WAITOFF;
break;

case S_WAITOFF:
// If one second has passed, then move on to the next state.
if(millis() > lastTime + delaytime)
{
if(currentPWM > 0){
currentPWM -= 5;
state = S_LEDOFF;
}
else{
Serial.println("@ 0 done........");
state = S_SERVOUP; //leds off..raise faceplate
}
}
break;

case S_SERVOUP:
myservo.write(100);
myservo1.write(100);
//delay(20); //wait to trigger the led flicker.. will remove delay() use in next revision
state = S_IDLE;
Serial.println("servo up.........");
break;

case S_SERVODOWN:
myservo.write(0);
myservo1.write(0);
delay(20); //wait to trigger the led flicker.. will remove delay() use in next revision
state = S_BLINKON;
Serial.println("servo down.........");
break;

default:
state = S_IDLE;
break;
}
}
 
Update:

I realized in the code you had the values for the servo set to 100 for up and 0 for down. I had to change it to 180 for up and 100 for down. That is how my servo is setup in the helmet. After this change I can get the lights to fad off and the helmet to go up however when I press the button again, the servo starts to hum(buzz) and the lights come back on. It won't go down. Do you think that is another grounding issue or possibly power? I checked with a volt meter and I'm getting 5.35V from the battery pack. I feel if it has enough power to go up it should go down. This is where I am stuck now.

case S_SERVOUP:
myservo.write(100);
myservo1.write(100);
//delay(20); //wait to trigger the led flicker.. will remove delay() use in next revision
state = S_IDLE;
Serial.println("servo up.........");
break;

case S_SERVODOWN:
myservo.write(0);
myservo1.write(0);
delay(20); //wait to trigger the led flicker.. will remove delay() use in next revision
state = S_BLINKON;
Serial.println("servo down.........");
break;
 
I would start with smaller values... and then work your way to your servos limits.


while these hobby servos state they are 0-180 degrees.. that is often not the real case..

most likely about 15-160 or so...

start with a very SMALL range/window.. and then increase until you get the 'hum/buzz' (no movement) and them back off a little bit)

All GND lines must be connected.. so make sure the battery GND and the SERVO GND and the Arduino GND all connect somewhere..
 
Update:

I realized in the code you had the values for the servo set to 100 for up and 0 for down. I had to change it to 180 for up and 100 for down. That is how my servo is setup in the helmet. After this change I can get the lights to fad off and the helmet to go up however when I press the button again, the servo starts to hum(buzz) and the lights come back on. It won't go down. Do you think that is another grounding issue or possibly power? I checked with a volt meter and I'm getting 5.35V from the battery pack. I feel if it has enough power to go up it should go down. This is where I am stuck now.

case S_SERVOUP:
myservo.write(100);
myservo1.write(100);

//delay(20); //wait to trigger the led flicker.. will remove delay() use in next revision
state = S_IDLE;
Serial.println("servo up.........");
break;

case S_SERVODOWN:
myservo.write(0);
myservo1.write(0);

delay(20); //wait to trigger the led flicker.. will remove delay() use in next revision
state = S_BLINKON;
Serial.println("servo down.........");
break;

What you say is different than the code you've shown. I suspect your problem is that you're not running the code you think you're running.
 
Hey there x197, thanks for everything youve done to help make an easy tutorial on how to motarize an ironman helmet. Being said I dont have a lick of experience in coding arduinos and programming or any of this lmao. I just finished bondoing and painting my helmet yesterday and was planning on going to a electronics store to pick up things I need to tackle the next step for motorzing it. I read through the thread but was hoping maybe you could text me a list of things I would need to buy, so that I could show it to the clerk to help me pick things out when i get there. Thanks for the help!
 
Depends on how you plan on putting it all together?

custom PCB?

breadboard?

direct (deadbug) solder?

Outside of the regulator/capacitors.. the rest is up to you.

Whatever Arduino you decide to work with..

Not sure how many or what type of leds you will use.

an NPN transistor that can work with the amount of current the leds you decide to work need.
 
I figured out my issue. I'm guessing since the servo I'm using, MG995, takes a lot of power. The specs say 4.8V to 7.2V I attached an additional 4 pack of AA's and this is driving the servo nicely. I also went back and added the Voltage regulator. I will be adding back in the NPN transitors next to see if the lights will continue to work. Below is the current setup. Also, the video I made of it finally working.



Brilliant Elzing (1).png
 
Im mostly going off of the schematic you have at the start of this thread and 7sinzz's thread, so far i think ill pick up a breadoard, some wires+resistors, 8 leds, 2 servos, 7v battery, a button and an arduino uno. Im not sure what the npn tansistor is or the other two symbols and the regulator are in the diagram but hopefully i should be good with grabbing those for now? ill try and post a pic of what i end up with after i mess around with it a little later td haha
 
regulator is labeled: LM7805 I believe

capacitors are also labeled.. .33uF and 0.1uF capacitors..
** (look at the LM7805 datasheet, it will show you want caps are to be used)

the NPN transistor needs to be able to supply/control enough current for the leds you are using.

Are you using many? just 1? If 1.. then you wont need the transistors..

An Arduino board (individual pin) can only supply (roughly) up to 40mA of current to the connected led.. that like 2-3 leds tops!..

if you need more.. then you will need to have the Arduino pin control the transistor (allowing for more current to pass to the leds)
 
xl97 or any other knowledgeable person, how would one use the third sketch on the first post ( fade blinking eyes open and close faceplate) and replace the push button with an ir remote control. I have downloaded and run ir remote demo and copied and converted the hexadecimal codes per each button on my ir remote, just don't know how to add to, or modify the sketch to have the remote activate the faceplate opening or closing. I'm fairly new as this is my first electronics project. Any help will be greatly appreciated
 
Post your IR module.. so we can know what you are using.. and the specs/example code..etc..etc
Is there a sketch I can run that would identify my ir receiver? I actually took apart a Wal-Mart led strip and removed the ir receiver diode and hooked it up to my arduino. I ran the IRrecDemo in order to get the hex codes. I'm sorry I'm super new to all of this.
 
Last edited:
Is there a sketch I can run that would identify my ir receiver? I actually took apart a Wal-Mart led strip and removed the ir receiver diode and hooked it up to my arduino. I ran the IRrecDemo in order to get the hex codes. I'm sorry I'm super new to all of this.
As I'm going thru some of the ir sketches I ran the IRrecvDump and see that the receiving diode is receiving a nec signal at 32 bits.
 
Link to.... something?

Where are you looking at these sketches?

Help us... help you! LOL
Sorry I'm using the arduino ide and I have downloaded the ir Remote library would you like me to copy and paste the sketches or results and also what would be the best practice of doing that to be best viewed here on the forum
 
Yes please.....


I am at work.. and do not have the Arduino IDE installed anywhere to load any sketches to view them


Please use code tags..

or at the very least post a link to the actual library you are using? (there are many)


if you are getting a value returned...... then it shouldnt -too- hard to implement in some fashion.
 
Yes please.....


I am at work.. and do not have the Arduino IDE installed anywhere to load any sketches to view them


Please use code tags..

or at the very least post a link to the actual library you are using? (there are many)


if you are getting a value returned...... then it shouldnt -too- hard to implement in some fashion.
Ok I how I did this right as far as copying the code.

This is the code for the helmet which I originally downloaded here

Code:
#include <Servo.h>
//servo 1
Servo myservo;

int val; // variable for reading the pin status
int val2; // variable for reading the delayed/debounced status
int buttonState;
int pos = 20;
int servostatus = 0;
int switchPin =4; // Switch connected to digital pin 2
int ledPin = 6;


void setup() // run once, when the sketch starts
{
//servo 1

myservo.attach(5);
pinMode(switchPin, INPUT);
pinMode(ledPin, OUTPUT);
buttonState = digitalRead(switchPin);
myservo.write(0);

}

void loop() // run over and over again

//servo 1
{
val = digitalRead(switchPin); // read input value and store it in val
delay(10); // 10 milliseconds is a good amount of time
val2 = digitalRead(switchPin); // read the input again to check for bounces
if (val == val2) { // make sure we got 2 consistant readings!
if (val != buttonState) { // the button state has changed!
if (val == LOW) { // check if the button is pressed
if (servostatus == 0) { // is the light off?
servostatus = 1; // turn light on!

myservo.write(120);

delay(1000);
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(ledPin, LOW);
delay(00);
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(ledPin, LOW);
delay(00);


// fading
for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
// sets the value (range from 0 to 255):
analogWrite(ledPin, fadeValue);
delay(30);


}

} else {
servostatus = 0; // turn light off!


digitalWrite(ledPin, LOW);
delay(15);
myservo.write(25);







}
}
}
buttonState = val; // save the new state in our variable
}
}


This is the sketch I used to get the hex numbers forthe remote

Code:
/*
 * IRremote: IRrecvDump - dump details of IR codes with IRrecv
 * An IR detector/demodulator must be connected to the input RECV_PIN.
 * Version 0.1 July, 2009
 * Copyright 2009 Ken Shirriff
 * http://arcfn.com
 * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
 * LG added by Darryl Smith (based on the JVC protocol)
 */

#include <IRremote.h>

/* 
*  Default is Arduino pin D11. 
*  You can change this to another available Arduino Pin.
*  Your IR receiver should be connected to the pin defined here
*/
int RECV_PIN = 9;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}


void dump(decode_results *results) {
  // Dumps out the decode_results structure.
  // Call this after IRrecv::decode()
  int count = results->rawlen;
  if (results->decode_type == UNKNOWN) {
    Serial.print("Unknown encoding: ");
  }
  else if (results->decode_type == NEC) {
    Serial.print("Decoded NEC: ");

  }
  else if (results->decode_type == SONY) {
    Serial.print("Decoded SONY: ");
  }
  else if (results->decode_type == RC5) {
    Serial.print("Decoded RC5: ");
  }
  else if (results->decode_type == RC6) {
    Serial.print("Decoded RC6: ");
  }
  else if (results->decode_type == PANASONIC) {
    Serial.print("Decoded PANASONIC - Address: ");
    Serial.print(results->address, HEX);
    Serial.print(" Value: ");
  }
  else if (results->decode_type == LG) {
    Serial.print("Decoded LG: ");
  }
  else if (results->decode_type == JVC) {
    Serial.print("Decoded JVC: ");
  }
  else if (results->decode_type == AIWA_RC_T501) {
    Serial.print("Decoded AIWA RC T501: ");
  }
  else if (results->decode_type == WHYNTER) {
    Serial.print("Decoded Whynter: ");
  }
  Serial.print(results->value, HEX);
  Serial.print(" (");
  Serial.print(results->bits, DEC);
  Serial.println(" bits)");
  Serial.print("Raw (");
  Serial.print(count, DEC);
  Serial.print("): ");

  for (int i = 1; i < count; i++) {
    if (i & 1) {
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    }
    else {
      Serial.write('-');
      Serial.print((unsigned long) results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println();
}

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
}

And here is a result from a button pushed on the remote using the previous sketch

F7807F
Decoded NEC: F7807F (32 bits)
Raw (68): 9200 -4500 600 -500 600 -550 650 -500 600 -500 650 -500 650 -500 600 -550 600 -500 650 -1600 650 -1600 650 -1600 600 -1650 600 -550 600 -1600 650 -1650 600 -1600 600 -1650 600 -550 600 -500 650 -500 650 -500 600 -500 650 -500 600 -550 600 -550 600 -1650 600 -1600 650 -1600 650 -1600 600 -1650 600 -1650 600 -1600 650
 
Ok I how I did this right as far as copying the code.

This is the code for the helmet which I originally downloaded here

Code:
#include <Servo.h>
//servo 1
Servo myservo;

int val; // variable for reading the pin status
int val2; // variable for reading the delayed/debounced status
int buttonState;
int pos = 20;
int servostatus = 0;
int switchPin =4; // Switch connected to digital pin 2
int ledPin = 6;


void setup() // run once, when the sketch starts
{
//servo 1

myservo.attach(5);
pinMode(switchPin, INPUT);
pinMode(ledPin, OUTPUT);
buttonState = digitalRead(switchPin);
myservo.write(0);

}

void loop() // run over and over again

//servo 1
{
val = digitalRead(switchPin); // read input value and store it in val
delay(10); // 10 milliseconds is a good amount of time
val2 = digitalRead(switchPin); // read the input again to check for bounces
if (val == val2) { // make sure we got 2 consistant readings!
if (val != buttonState) { // the button state has changed!
if (val == LOW) { // check if the button is pressed
if (servostatus == 0) { // is the light off?
servostatus = 1; // turn light on!

myservo.write(120);

delay(1000);
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(ledPin, LOW);
delay(00);
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(ledPin, LOW);
delay(00);


// fading
for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
// sets the value (range from 0 to 255):
analogWrite(ledPin, fadeValue);
delay(30);


}

} else {
servostatus = 0; // turn light off!


digitalWrite(ledPin, LOW);
delay(15);
myservo.write(25);







}
}
}
buttonState = val; // save the new state in our variable
}
}


This is the sketch I used to get the hex numbers forthe remote

Code:
/*
* IRremote: IRrecvDump - dump details of IR codes with IRrecv
* An IR detector/demodulator must be connected to the input RECV_PIN.
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
* JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
* LG added by Darryl Smith (based on the JVC protocol)
*/

#include <IRremote.h>

/*
*  Default is Arduino pin D11.
*  You can change this to another available Arduino Pin.
*  Your IR receiver should be connected to the pin defined here
*/
int RECV_PIN = 9;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}


void dump(decode_results *results) {
  // Dumps out the decode_results structure.
  // Call this after IRrecv::decode()
  int count = results->rawlen;
  if (results->decode_type == UNKNOWN) {
    Serial.print("Unknown encoding: ");
  }
  else if (results->decode_type == NEC) {
    Serial.print("Decoded NEC: ");

  }
  else if (results->decode_type == SONY) {
    Serial.print("Decoded SONY: ");
  }
  else if (results->decode_type == RC5) {
    Serial.print("Decoded RC5: ");
  }
  else if (results->decode_type == RC6) {
    Serial.print("Decoded RC6: ");
  }
  else if (results->decode_type == PANASONIC) {
    Serial.print("Decoded PANASONIC - Address: ");
    Serial.print(results->address, HEX);
    Serial.print(" Value: ");
  }
  else if (results->decode_type == LG) {
    Serial.print("Decoded LG: ");
  }
  else if (results->decode_type == JVC) {
    Serial.print("Decoded JVC: ");
  }
  else if (results->decode_type == AIWA_RC_T501) {
    Serial.print("Decoded AIWA RC T501: ");
  }
  else if (results->decode_type == WHYNTER) {
    Serial.print("Decoded Whynter: ");
  }
  Serial.print(results->value, HEX);
  Serial.print(" (");
  Serial.print(results->bits, DEC);
  Serial.println(" bits)");
  Serial.print("Raw (");
  Serial.print(count, DEC);
  Serial.print("): ");

  for (int i = 1; i < count; i++) {
    if (i & 1) {
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    }
    else {
      Serial.write('-');
      Serial.print((unsigned long) results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println();
}

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
}

And here is a result from a button pushed on the remote using the previous sketch

F7807F
Decoded NEC: F7807F (32 bits)
Raw (68): 9200 -4500 600 -500 600 -550 650 -500 600 -500 650 -500 650 -500 600 -550 600 -500 650 -1600 650 -1600 650 -1600 600 -1650 600 -550 600 -1600 650 -1650 600 -1600 600 -1650 600 -550 600 -500 650 -500 650 -500 600 -500 650 -500 600 -550 600 -550 600 -1650 600 -1600 650 -1600 650 -1600 600 -1650 600 -1650 600 -1600 650
Oh yeah and for clarification the ir receiver is hooked up to another arduino for testing purposes but will be installed on the arduino in the helmet replacing the hard wired toggle switch.
 

Your message may be considered spam for the following reasons:

If you wish to reply despite these issues, check the box below before replying.
Be aware that malicious compliance may result in more severe penalties.
Back
Top