ironman proj. trying to understand using things in sequence w. state machine.

first off thank you for any support and positive comments. i just bought an arduino mega 2560 to use as the heart of my project. i am currently building a movie replica of iron mans suit from avengers movie that came out semi recently. i will be using the arduino for many things in the suit but currently im having difficulty drawing up a sketch to use my servos by switch.

essentially what i would like to do is turn a switch on and the servos movement acts like a gate swinging open 90 degrees and then swing it upwards like a toll booth bar vertically 90 degrees. i will be using one servo to swing it on the x axis and then another servo to swing it up on the axis. once i hit the switch a second time i would like it to back track as if it swings down and then closes the gate.

im using 6 servos to duplicate the effect you see when tony stark gets kicked out of his building by loki and his suit flies out the window and when you see the helmet attach to his head you can see that the jawbone is split in half and comes down and then they swing inwards and attach in the middle followed shortly after by the face plate closing down ontop of the jaw to complete the helmet suit up.

so im replicating this so that one press of the button opens the whole front to expose my face/take the helmet off and a 2nd click of the button closes up the whole helmet as if i were suiting up.

sorry for being so lengthy i just figured the more details the easier it would be to understand what im trying to accomplish. thanks again for any help!

Servo button toggle test code.

//zoomkat servo button toggle test 4-28-2012

#include <Servo.h>
int button = 5; //button pin, connect to ground to move servo
int press = 0;
Servo servo;
Servo servo1;
boolean toggle = true;

void setup()
{
  pinMode(button, INPUT); //arduino monitor pin state
  servo.attach(7); //pin for servo control signal
  servo1.attach(8); //pin for servo control signal
  digitalWrite(5, HIGH); //enable pullups to make pin high
}

void loop()
{
  press = digitalRead(button);
  if (press == LOW)
  {
    if(toggle)
    {
      servo.write(160);
      servo1.write(20);
      toggle = !toggle;
    }
    else
    {
      servo.write(20);
      servo1.write(160);
      toggle = !toggle;
    }
  }
  delay(500);  //delay for debounce
}

so i sent that sketch to my arduino and i think i have my servos hooked up wrong. i have 2 servos both the ground wires to the arduino grounds, both servo powers spliced to one end of the push button switch, the other end of the switch to 5 , and then each of the digital servo leads one on 7 and the other on 8.

do i have to run power from the 5v to test it? they are regular 4.8 volt servos 180 degree. i thank you for your patience as im fresh out of the box newbie :frowning:

You must use an external power supply for the servos with a common GND to the Arduino.
The voltage regulator on the Arduino cannot supply enough current to drive standard servos. At best you will get unpredictable results and at worst the voltage regulator will be damaged.

is it possible to use a 9v battery? as the only power supply i can use has to be batteries because this will be a mobile project considering its for a suit. i know they are 4.8v for each servo but i mainly want to test what i want to do in the helmet and most importantly i want to understand so i can continue developing the code further/my electronics skills.

if i can use a 9v how exactly would i hook it up? thanks again the support i know such noobish questions make people grind their teeth with discomfort lol.

You can use a 9v battery but you should put a voltage regulator then to get the 5v for servos. You can also use 3 of those 1.5v (AA) batteries to get 4.5v for you servos. Although, servos can draw a lot of current, so I don't how would multiple batteries react to that.

You can use a 9v battery

True, but don't bother with the wimpy PP3s as they will go flat in no time.

Presumably when this project is running for real it will not be drawing its current via the USB port so you need to think ahead. You can use the same power supply for the Arduino and the servos, just don't take the servo 5V from the 5V pin on the Arduino, take it directly from the battery. 4 AA (or larger) batteries would last a while.

both servo powers spliced to one end of the push button switch, the other end of the switch to 5 , and then each of the digital servo leads one on 7 and the other on 8.

No, the switch should be wired as described in the comments in the code I posted (between the arduino pin 5 and the arduino ground. I suggest you try a rechargeable 9v battery to power the arduino via the external power connector, and maybe 5 or 6 rechargeable AA batteries (each battery typically outputs 1.2v) to power the servos. Below is a basic servo wiring diagram.

tysm i made an external power supply using a old car adapter port head and a 9v lead i had. then made 2 3 AA battery packs one for each servo and hooked it up like you said and thanks to the debounce it has super minimal jitter on the servos. now all i have to do is figure out how to code it so that when i push the button the first servo goes from 0 to 90 while the second servo has a slight delay before it too goes from 0 to 90 and then when i press the button a second time it reverses the second servo first followed by the first servo last.

shouldnt be too hard but thanks again for all the help so far. this is exciting. off to work bbl for more testing.

The StateChangeDetection example sketch shows how to detect when a button has been pressed.

If you only want your sketch to move these two servos and nothing else, you could just write a piece of code that moves the first servo, waits for a moment and then moves the second servo. You can use a global variable to keep track of whether the faceplate is 'open' or 'closed' and carry out the appropriate servo movement sequence when the button press occurs. (In effect, this would be a state machine with two states.)

If you want your sketch to be able to do other things independently of controlling the faceplate then a non-blocking approach would be better, but the code for that is slightly harder to understand so I suggest you do the simple blocking version first anyway.

PeterH:
The StateChangeDetection example sketch shows how to detect when a button has been pressed.

If you only want your sketch to move these two servos and nothing else, you could just write a piece of code that moves the first servo, waits for a moment and then moves the second servo. You can use a global variable to keep track of whether the faceplate is 'open' or 'closed' and carry out the appropriate servo movement sequence when the button press occurs. (In effect, this would be a state machine with two states.)

If you want your sketch to be able to do other things independently of controlling the faceplate then a non-blocking approach would be better, but the code for that is slightly harder to understand so I suggest you do the simple blocking version first anyway.

well i will be using my arduino to control the rest of my suit. the suit will have multiple leds to control (the eyes, uni beam, hand repulsors), i also will be adding a way to play a few various songs like his theme song etc (i bought an sd shield). i will have a speaker in each ear producing sfx\music outwards, a small speaker in each of the hand repulsors, a speaker in the unibeam, and a voice changer installed in the helmet so it gives it that kind of metalic echo sound. multiple other servos opening and closing certain fake weaponry. possibly a few more gimmicks.

  1. the way to control all of this has to be in one unified sketch correct?
  2. does the arduino have a limit as far as how many servos it can control, leds, speakers, etc? i bought it because it has 54 inputs\outputs i believe figuring itd be plenty.

right now im mainly trying to finish the helmet of which i want to get the servos up and running first so i can install them and bondo\paint the helmet. as you can see i have much ahead of me with this project so im sure ill be using this forum plenty.thanks again for all the input guys i truly do appreciate it.

Correct, each Arduino runs a single sketch. Written correctly, that sketch can control multiple features independently. Sound output and voice changing would require additional hardware, but the general task of controlling lots of lights and servos etc based on multiple switch inputs is the sort of thing the Arduino is good at. The mega 2560 has lots of pins and timers and so on and is a good platform for this sort of thing.

update

so ive been screwing around still trying to learn how to write code. been reading my arduino book, watching tutorials, using this site to research scripts and their uses, etc. i still havent been able to rewrite the code properly to what i hope to do. so im going to restate what im looking to accomplish.

-------------------to open the helmet----------------------------------

  1. user presses the touch button , (normally open switch).
  2. servo.2 tilts down/counter clockwise 15 degrees. (entire jaw tilts down -15 degrees)
  3. delay for 250ms
  4. servo.2 tilts up/clockwise 15 degrees. (the jaw splits,the users left side tilts up while the right side tilts down 15 degrees)
  5. delay for 250ms
  6. servo.3 rotates left/clockwise 30 degrees. (the left side positions itself out beyond the plane of the users head which allows the needed clearance for step 8 )
  7. delay for 250ms
  8. servo.1 rotates counter clockwise 45 degrees. (the front face of the chin aligns with the rest of the jawbone to avoid getting caught in the next step)
  9. delay for 250ms
  10. servo.2 tilts up/clockwise 125 degrees. (the left side tilts up along side the head)
  11. all servos stay in their current positions until the button is pressed a second time. (at this point each jaw bone half will be on the sides of the helmet)

---------------------- to close the helmet-----------------
at this point i want to be able to press the button a second time and then pretty much do everything above accept in reverse to close the helmet.

  1. user presses button. (consider the helmet fully opened before this is pressed)
  2. servo.2 tilts down 125 degrees. (jaw tilts down from the side of the face)
  3. delay 250ms
  4. servo.1 rotates in/clockwise 45degrees. (front face of chin goes back to its original position)
  5. delay 250ms
  6. servo.3 rotates in/clockwise 30degrees. (the jaw rotates inward to be in front of the users face)
  7. delay 250ms
  8. servo.2 tilts down/counter clockwise 15 degrees. (the jaw connects with the right side half)
  9. delay 250ms
  10. servo.2 tilts up/clockwise 15 degrees. (the jaw now being connected as one piece tilts up to lock in place)
  11. all servos stay in this closed state until the button is pressed again. (helmet is considered closed at this point)
    ----————————————————

after doing some research i think i may have to use a combination of , boolean , if , if else , break , delay and a few others but im not quite sure how to write it properly as all my experiments with trying so havent accomplished anything =(

each side of the jaw will be done in a similar way so if i can figure out how to code the left side then ill be able to understand how to code the right side myself with its few changes. the reason i have a 250 ms delay is because i want each servos command to happen shortly after each other so it properly looks like its suiting up and is slow enough to enjoy. all variables can be altered as far as degrees and delay between each servo action as i know ill have to tinker with that part.

here are some video examples of what im trying to accomplish.....fast forward to 9mins 48s of the video and it lasts to 9min 56s
this part you can see the suit up of his helmet and how im currently working on just the chin so far.

in this part of the video is the actual mark suit im working on but also shows how im making the jaw come from around the side of my head. fast forward to 1min 15s to see it and lasts to 1min 20s.

What you want to do sounds perfectly feasible using an Arduino but some points to consider.

Use an external power supply for the servos. Do not take power for them from the 5V pin on the Arduino as it cannot supply enough current. Make sure the the GND connections of both the Arduino and servo power supplies are connected together.

Enable the internal pullup resistors on your switch inputs or use external pull up or down resistors although this is less convenient. This ensures that inputs are always in a known state (HIGH or LOW) and not floating at an uncertain voltage.

Do not use the delay() function if you want the Arduino to do anything except control the servos, as whilst executing the delay() it cannot do anything else such as respond to switch/button inputs. Embrace the use of millis() for timing as used in the BlinkWithoutDelay example and described more fully here Gammon Forum : Electronics : Microprocessors : How to do multiple things at once ... like cook bacon and eggs

To manage the multiple sequential servo movements consider the use of a state machine. This may sound daunting when you read up about it but is easier in practice. Your servo system can only be in one state at any one time so, combined with millis() timing, it can execute the appropriate commands for that state until the time comes to change state.

so im guessing these are the two scripts\commands i need to combine somehow. you were right to talk about how confusing state machine and FSM are. most other scripts ive learned kinda how to decypher but this however utterly makes no sense :disappointed_relieved: ...i had already created 3 - 3 AA battery packs one for each servo. the arduino is also on its own 9v battery pack. the thing i havent done yet i dont think is enabling a pull up or pull down resistor. ill research that as it probally is easy to find.i used the example script from your blinkwithoutdelay link so anywhere you see LED still in the script asume i mean servo

how do i stitch these sketches together to be able to accomplish my bellow series of servo actions. thank you again for all your support. im learning slowly but surely. once im finished with my project im going to make sure i put together a list of people who deserve credit where credit is due. it might help everyone involved to get a little more reputation hopefully. if you do not wish to be known for your help in my project just say so in the end of your posts.

-------------------to open the helmet----------------------------------

  1. user presses the touch button , (normally open switch).
  2. servo.2 tilts down/counter clockwise 15 degrees. (entire jaw tilts down -15 degrees)
  3. delay for 250ms
  4. servo.2 tilts up/clockwise 15 degrees. (the jaw splits,the users left side tilts up while the right side tilts down 15 degrees)
  5. delay for 250ms
  6. servo.3 rotates left/clockwise 30 degrees. (the left side positions itself out beyond the plane of the users head which allows the needed clearance for step 8 )
  7. delay for 250ms
  8. servo.1 rotates counter clockwise 45 degrees. (the front face of the chin aligns with the rest of the jawbone to avoid getting caught in the next step)
  9. delay for 250ms
  10. servo.2 tilts up/clockwise 125 degrees. (the left side tilts up along side the head)
  11. all servos stay in their current positions until the button is pressed a second time. (at this point each jaw bone half will be on the sides of the helmet)

---------------------- to close the helmet-----------------
at this point i want to be able to press the button a second time and then pretty much do everything above accept in reverse to close the helmet.

  1. user presses button. (consider the helmet fully opened before this is pressed)
  2. servo.2 tilts down 125 degrees. (jaw tilts down from the side of the face)
  3. delay 250ms
  4. servo.1 rotates in/clockwise 45degrees. (front face of chin goes back to its original position)
  5. delay 250ms
  6. servo.3 rotates in/clockwise 30degrees. (the jaw rotates inward to be in front of the users face)
  7. delay 250ms
  8. servo.2 tilts down/counter clockwise 15 degrees. (the jaw connects with the right side half)
  9. delay 250ms
  10. servo.2 tilts up/clockwise 15 degrees. (the jaw now being connected as one piece tilts up to lock in place)
  11. all servos stay in this closed state until the button is pressed again. (helmet is considered closed at this point)
    ----————————————————

// Which pins are connected to which LED
const byte servo.1 = 7;
const byte servo.2 = 8;
const byte servo.3 = 9;

// Time periods of blinks in milliseconds (1000 to a second).
const unsigned long servo.1interval = 500;
const unsigned long servo.2interval = 1000;
const unsigned long servo.3interval = 1500;

// Variable holding the timer value so far. One for each "Timer"
unsigned long servo.1timer;
unsigned long servo.2timer;
unsigned long servo.3timer;

void setup ()
{
pinMode (servo.1, OUTPUT);
pinMode (servo.2, OUTPUT);
pinMode (servo.3, OUTPUT);
servo.1timer = millis ();
servo.2timer = millis ();
servo.3timer = millis ();
} // end of setup

void toggleservo.1 ()
{
if (digitalRead (servo.1) == LOW)
digitalWrite (servo.1, HIGH);
else
digitalWrite (servo.1, LOW);

// remember when we toggled it
servo.1timer = millis ();
} // end of toggleservo.1

void toggleservo.2 ()
{
if (digitalRead (servo.2) == LOW)
digitalWrite (servo.2, HIGH);
else
digitalWrite (servo.2, LOW);

// remember when we toggled it
servo.2timer = millis ();
} // end of toggleservo.2

void loop ()
{

// Handling servo.1.
if ( (millis () - servo.1timer) >= servo.1interval)
toggleservo.1 ();

// Handling servo.2
if ( (millis () - servo.2timer) >= servo.2interval)
toggleservo.2 ();

// Handling servo.3
if ( (millis () - servo.3timer) >= servo.3interval)
toggleservo.3 ();

/* Other code that needs to execute goes here.
It will be called many thousand times per second because the above code
does not wait for the servo interval to finish. */

} // end of loop
-――――――—―—―—―
void loop(){
if (button.uniquePress()){
//increment buttonPresses and constrain it to [ 0, 1, 2, 3 ]
buttonPresses = ++buttonPresses % NUMBER_OF_STATES;
switch (buttonPresses){
case 0: ledStateMachine.transitionTo(On); break;
case 1: ledStateMachine.transitionTo(Off); break;
case 2: ledStateMachine.transitionTo(FadeIn); break;
case 3: ledStateMachine.transitionTo(FadeOut); break;
}

As it happens the numbers in your lists serve to illustrate the use of states quite well. The statements relating to each number are the actions to be taken when the system is in that state. When the action is complete update the state number in a variable and the system will move on.

This is probably easiest to do using switch/case where the switch variable is the state and the case is the state number. Some pseudo-code

switch (state)
  case 1
    when button input detected
    set case to 2
    break
  
  case 2
    command servo 2 counter clockwise 15 degrees
    set case to 3
    break
    
  case 3
    wait 250ms (using millis() timing)
    set case to 4
    break
    
  case 4
    command servo 2 clockwise 15 degrees
    set case to 5
    break
    
   case 5
    wait 250ms (using millis() timing)
    set case to 6
    break
    
    etc, etc

Using millis() timing means that the program can continue to execute the loop() function so that other actions can be responded to whilst the servo movements and waits take place.

Incidentally, I think that it would be better to use variables to save the state of output pins rather than to read their state like this

if (digitalRead (servo.1) == LOW)
      digitalWrite (servo.1, HIGH);

question : 1. do i have to use state machine specifically because i expect to use my servos in sequence?
2. is it because i expect to possibly be doing other things at the same time?
3. will the rest of my sketch have to be written in SM just so i can use anything by switch when ever i call upon
something to trigger?

A state machine is just a way of dealing with a system that may be in many different states (or as few as two) and acting appropriately when it is in that state. Even if you do not use the words 'state machine' that is what you will be doing.

  1. As above, you will be moving the system from state to state to control the servos whether you call it a state machine or not
  2. Using millis() timing is what allows you to do several things apparently at once.
  3. How you arrange the rest of the program depends on what you need to do. A program can have several individual state machines each with their own series of states.

Don't get too hung up on the phrase 'state machine'. It provides a structured way of implementing a system of linked actions that follow on from one another depending on inputs received and/or time passing. It allows you to describe the states, inputs, resultant actions and state changes before you plunge into programming. Then, if things don't work out you can test the system against the initial description and correct the faults.