//Based on xI97's code on The RPF.
//Pin 3 = Button
//Pin 4 = LEDs
//Pin 5 = Servo 1
//Pin 6 = Servo 2
#include <Servo8Bit.h>
//servo object names
Servo8Bit myservo; // create servo object to control a servo
Servo8Bit myservo1;
const int buttonPin = 3; // the pin that the pushbutton is attached to
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
// led control pins (need to be PWM enabled pins for fading)
const int Eye = 4; // the number of the left eye/pcb LEDs
unsigned long fadeDelay = 10; //speed of the eye 'fade'
unsigned long callDelay = 700; //length to wait to start eye flicker after face plate comes down
unsigned long blinkSpeed = 100; //delay between init blink on/off
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
#define S_SERVOWAIT 10
//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() {
//start it off
state = S_BLINKON;
myservo.attach(5); // attaches the servo on pin 9 to the servo object
myservo1.attach(7); // 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){
state = S_SERVODOWN;
}
else{
//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:
//do blink routine here
//one blink
analogWrite(Eye, 155);
delay(blinkSpeed);
analogWrite(Eye, 0);
delay(10);
//two blinks
analogWrite(Eye, 155);
delay(blinkSpeed);
analogWrite(Eye, 0);
delay(10);
//one blink
analogWrite(Eye, 155);
delay(blinkSpeed);
analogWrite(Eye, 0);
delay(10);
//two blinks
analogWrite(Eye, 155);
delay(blinkSpeed);
analogWrite(Eye, 0);
delay(50);
state = S_LEDON;
break;
case S_LEDON:
lastTime = millis(); // Remember the current time
analogWrite(Eye, 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 + fadeDelay)){
if(currentPWM < 255){
currentPWM += 5;
state = S_LEDON;
}
else{
state = S_IDLE;
//state = S_LEDOFF; //no auto turn off.. set to idle state
}
}
break;
case S_LEDOFF:
lastTime = millis(); // Remember the current time
analogWrite(Eye, currentPWM);
state = S_WAITOFF;
break;
case S_WAITOFF:
// If one second has passed, then move on to the next state.
if(millis() > (lastTime + 0.5)){
if(currentPWM > 0){ //change 0 to higher number to init face 'up' function sooner.
currentPWM -= 1;
state = S_LEDOFF;
}
else{
state = S_SERVOUP; //leds off..raise faceplate
}
}
break;
case S_SERVOUP:
myservo.write(100);
myservo1.write(100);
state = S_IDLE;
break;
case S_SERVODOWN:
lastTime = millis(); // Remember the current time
myservo.write(0);
myservo1.write(0);
state = S_SERVOWAIT;
break;
case S_SERVOWAIT:
// If enough time has passed, call the eye flicker routine
if(millis() > (lastTime + callDelay)){
state = S_BLINKON;
}
else{
}
break;
default:
state = S_IDLE;
break;
}
}