This is the sketch.
//********************************************************************************
// UselessBox.ino by LarryD
//
// Version YY/MM/DD Description
//
// 1.0 20/10/19 Running code
// 1.1 20/10/20 Added State Machines
// 1.2 20/11/11 Calibrated the servo foot extended postion to be ~85 degrees
// 1.3 20/11/28 Added the owl and user fight animation i.e. animationSeven()
//
//********************************************************************************
#include <Servo.h>
Servo doorServo;
Servo footServo;
// M A C R O S
//********************************************************************************
//
#define LEDon HIGH
#define LEDoff !LEDon
#define isPUSHED LOW
#define isRELEASED !isPUSHED
#define OFF LOW
#define ON HIGH
#define ENABLED true
#define DISABLED false
#define doorSlow 20
#define doorHalfwayOpen 90
#define doorOpenPostion 115
#define doorOpen doorOpenPostion
//#define doorClose 0
#define doorClose 35
#define switchOffPosition 85 // <-------<<< Foot extended
#define footExtended switchOffPosition
#define footRetract 0
//********************************************************************************
const byte S2 = A1; //pin----[0R ]-----[N.O. switch]----GND
const byte S3 = A2; //pin----[0R ]-----[N.O. switch]----GND
const byte userSwitch = 9; //pin---------------[N.O. switch]----GND
const byte relay = 8; //pin----[240R]-----[MOSFET switch]
const byte door = 7; //pin----[240R]-----[servo motor]
const byte foot = 6; //pin----[240R]-----[servo motor]
const byte spareServo = 5; //pin----[240R]-----[servo motor]
const byte piezo = 4; //pin----[220R]-----[piezo]----------GND
const byte RTCinterrupt = 3; //pin----[0R ]-----[Jumper]---[RTC SQW]
const byte heartbeatLED = 2; //pin----[220R]-----[>|]-------------GND
boolean powerTimingFlag = false;
boolean animationFlag = false;
boolean scoldFlag = false;
byte lastUserState = isRELEASED;
byte doorPosition = doorClose;
byte footPosition = footRetract;
byte sharedState = 0;
//timing stuff
unsigned long heartbeatMillis;
unsigned long powerDownMillis;
unsigned long machineMillis;
unsigned long switchMillis;
unsigned long sharedMillis;
unsigned long sharedInterval = 20;
unsigned long fightDelay = 10000ul; //10 seconds
unsigned long powerDownDelay = 20000ul; //20 seconds to power down
// M A C H I N E S T A T E S
//State Machine stuff
enum STATES {startup, stateA3, stateA5, stateB5, stateC5, stateD5, stateE5, stateF5, stateG5, stateZ5};
STATES mState = startup;
//STATES firstState = stateE5; // T E S T I N G
STATES firstState = stateA3;
STATES lastState = stateZ5;
int angulo = 0;
int counter = 0;
int val = 0;
// s e t u p ( )
//********************************************************************************
void setup()
{
pinMode(userSwitch, INPUT_PULLUP);
pinMode(piezo, OUTPUT);
pinMode(relay, OUTPUT);
//latch the power relay
digitalWrite(relay, ON);
//restart the TIMER
powerDownMillis = millis();
//enable power down TIMER
powerTimingFlag = ENABLED;
pinMode(heartbeatLED, OUTPUT);
//connect and reset the servos
doorServo.attach(door);
doorServo.write(0);
footServo.attach(foot);
footServo.write(0);
//wait for servos to go home
delay(500);
}//END of setup()
// l o o p ( )
//********************************************************************************
void loop()
{
//***************************************
//time to toggle the heartbeat LED ?
if (millis() - heartbeatMillis >= 1000)
{
//restart the TIMER
heartbeatMillis = millis();
//toggle LED
digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
}
//***************************************
//time to service the state machine ?
if (millis() - machineMillis >= 50)
{
//restart the TIMER
machineMillis = millis();
//service the state machine
stateMachine();
}
//***************************************
//time to check the switches ?
if (millis() - switchMillis >= 100)
{
//restart the TIMER
switchMillis = millis();
checkSwitches();
}
//***************************************
//time to turn OFF the power ?
if (powerTimingFlag == ENABLED && millis() - powerDownMillis >= powerDownDelay)
{
//if the switch is still on at this time turn it off
if (digitalRead(userSwitch) == isPUSHED)
{
//opening the door fast
doorServo.write(doorOpen);
delay(500);
//extend the foot fast
footServo.write(footExtended);
delay(700);
//retract the foot fast
footServo.write(footRetract);
delay(700);
//closing the door fast
doorServo.write(doorClose);
delay(500);
}
//confirm servo home positions
doorServo.write(0);
footServo.write(0);
delay(500);
//say goodbye (intensity, numberOfChirps)
lowChirp(angulo * 4, 5);
//power off the Arduino
digitalWrite(relay, OFF);
delay(10000);
}
} //END of loop()
//********************************************************************************
// c h e c k S w i t c h e s ( )
//********************************************************************************
void checkSwitches()
{
byte currentState = digitalRead(userSwitch);
//we want to look at the 'user switch' level not 'user switch' change in state
if (animationFlag == DISABLED);
{
//update to the new state
lastUserState = currentState;
//is the 'user switch' pushed (ON) ?
if (currentState == isPUSHED)
{
//have we finished with all the animations ?
if (mState == lastState)
{
//restart the power down TIMER
//powerDownMillis = millis();
mState = firstState;
animationFlag = ENABLED;
sharedInterval = doorSlow;
//restart the shared TIMER
sharedMillis = millis();
sharedState = 0;
doorPosition = doorClose;
}//END of if (mState == lastState)
//enable the next 'state' animation
animationFlag = ENABLED;
//restart the power down TIMER
powerDownMillis = millis();
}
} //END of user switch
//next switch
} //END of checkSwitches()
// s t a t e M a c h i n e ( )
//********************************************************************************
void stateMachine()
{
//***************************************
//have we just turned on the power ?
if (mState == startup)
{
lastUserState = isRELEASED;
//restart the power down TIMER
powerDownMillis = millis();
//initializing to the beiginning of the animation sequences
mState = firstState;
animationFlag = ENABLED;
sharedInterval = doorSlow;
//restart the shared TIMER
sharedMillis = millis();
sharedState = 0;
doorPosition = 0;
// doorPosition = doorClose;
}
//***************************************
if (animationFlag == ENABLED)
{
//**************************
if (millis() - sharedMillis >= sharedInterval)
{
//restart the shared TIMER
sharedMillis = millis();
//restart the power down TIMER
powerDownMillis = millis();
switch (mState)
{
//*****************
case startup:
{
} //END of case:
break;
//*****************
case stateA3:
{
animationOne();
} //END case:
break;
//*****************
case stateA5:
{
animationTwo();
} //END case:
break;
//*****************
case stateB5:
{
animationThree();
} //END case:
break;
//*****************
case stateC5:
{
animationFour();
} //END case:
break;
//*****************
case stateD5:
{
animationFive();
} //END case:
break;
//*****************
case stateE5:
{
animationSix();
} //END case:
break;
//*****************
case stateF5:
{
animationSeven();
} //END case:
break;
//*****************
case stateG5:
{
animationEight();
} //END case:
break;
//*****************
//this is the 'last state' <-----------<<<< L a s t S t a t e
case stateZ5:
{
//do nothing
} //END of case:
break;
} //END of switch/case
} //END of if (millis() - sharedMillis >= sharedInterval)
//**************************
// F I G H T with the user to keep the switch OFF
else if (millis() - sharedMillis < sharedInterval && mState == stateF5 && sharedState == 2)
{
//did the user press the switch ?
if (digitalRead(userSwitch) == isPUSHED)
{
//(intensity, numberOfChirps)
lowChirp(5, 1);
//turn the switch OFF
footServo.write(footExtended);
delay(300);
//retract the foot just a little
footServo.write(switchOffPosition - 20);
delay(300);
//restart the Timer
sharedMillis = millis();
//restart the power down TIMER
powerDownMillis = millis();
}
} //END of else if(millis() - sharedMillis < sharedInterval && mState == stateF5)
//**************************
//scold the user
else if (millis() - sharedMillis < sharedInterval && mState == stateE5 && sharedState == 2 && scoldFlag == true)
{
//(intensity, numberOfChirps)
highChirp(5, 10);
scoldFlag = false;
}
} //END of if(animationFlag == ENABLED)
} //END of stateMachine()
// h i g h C h i r p ( )
//********************************************************************************
void highChirp(int intensity, int numberOfChirps)
{
int i;
int x;
for (int veces = 0; veces <= numberOfChirps; veces++)
{
//for (i = 100; i > 0; i--) //Original
//200/150 sounds good
for (i = 200; i > 0; i--)
{
for (x = 0; x < intensity; x++)
{
digitalWrite (piezo, HIGH);
delayMicroseconds (i);
digitalWrite (piezo, LOW);
delayMicroseconds (i);
}
}
}
} //END of highChirp()
// l o w C h i r p ( )
//********************************************************************************
void lowChirp(int intensity, int numberOfChirps)
{
int i;
int x;
for (int veces = 0; veces <= numberOfChirps; veces++)
{
//for (i = 0; i < 200; i++) //original
//300 sounds good
for (i = 0; i < 300; i++)
{
digitalWrite (piezo, HIGH);
delayMicroseconds(i);
digitalWrite(piezo, LOW);
delayMicroseconds(i);
}
for (i = 90; i > 80; i--)
{
for ( x = 0; x < 5; x++)
{
digitalWrite (piezo, HIGH);
delayMicroseconds (i);
digitalWrite (piezo, LOW);
delayMicroseconds (i);
}
}
}
} //END of lowChirp()
// t w e e t ( )
//********************************************************************************
void tweet(int intensity, int numberOfChirps)
{
int i;
int x;
//normal numberOfChirps 3, normal intensity 5
//for (int veces = 0; veces < numberOfChirps; veces++) //original
for (int veces = 0; veces < numberOfChirps; veces++)
{
for (int i = 80; i > 0; i--)
{
for (int x = 0; x < intensity; x++)
{
digitalWrite (piezo, HIGH);
delayMicroseconds (i);
digitalWrite (piezo, LOW);
delayMicroseconds (i);
}
}
}
} //END of tweet()
//=============================================================================================================================
// a n i m a t i o n O n e ( )
//******************************************************************************** A n i m a t i o n s
void animationOne()
{
switch (sharedState)
{
//opening the door slowly
case 0:
{
doorServo.write(doorPosition);
doorPosition++;
if (doorPosition == doorHalfwayOpen)
{
//close door quickly
doorServo.write(doorClose);
doorPosition = doorClose;
sharedInterval = 3000;
sharedMillis = millis();
sharedState = 1;
}
}
break;
//waiting 3 seconds
case 1:
{
sharedInterval = doorSlow;
sharedMillis = millis();
sharedState = 2;
}
break;
//opening the door slowly
case 2:
{
doorPosition++;
doorServo.write(doorPosition);
if (doorPosition >= doorHalfwayOpen)
{
//time for servo operation
sharedInterval = 20;
footPosition = footRetract;
sharedMillis = millis();
sharedState = 3;
}
}
break;
//extend foot slow
case 3:
{
footPosition++;
footServo.write(footPosition);
if (footPosition == footExtended)
{
sharedInterval = 20;
sharedMillis = millis();
sharedState = 4;
}
}
break;
//retract foot slow then close the door fast
case 4:
{
footPosition--;
footServo.write(footPosition);
if (footPosition == footRetract)
{
//close door fast
doorServo.write(doorClose);
doorPosition = doorClose;
sharedInterval = 500;
sharedMillis = millis();
sharedState = 5;
}
}
break;
//finish up this animation
case 5:
{
animationFlag = DISABLED;
//start out in the first shared case
sharedInterval = doorSlow;
//sharedMillis = millis();
sharedState = 0;
//the next animation 'state'
mState = stateA5;
}
break;
} //END switch/case
} //END of animationOne()
// a n i m a t i o n T w o ( )
//********************************************************************************
void animationTwo()
{
switch (sharedState)
{
//opening the door slowly then extend foot fast
case 0:
{
doorServo.write(doorPosition);
doorPosition++;
if (doorPosition == doorOpen)
{
//extend the foot fast
footServo.write(footExtended);
//time for servo operation
sharedMillis = millis();
sharedInterval = 700;
sharedState = 1;
}
}
break;
//retract foot fast
case 1:
{
footServo.write(footRetract);
//time for servo operation
sharedInterval = 700;
//start the Timer
sharedMillis = millis();
sharedState = 2;
}
break;
//close door fast
case 2:
{
doorServo.write(doorClose);
doorPosition = doorClose;
//time for servo operation
sharedMillis = millis();
sharedInterval = 500;
sharedState = 3;
}
break;
//finish up this animation
case 3:
{
animationFlag = DISABLED;
//start out in the first shared case
sharedInterval = doorSlow;
//sharedMillis = millis();
sharedState = 0;
//the next animation 'state'
mState = stateB5;
}
break;
} //END switch/case
} //END of animationTwo()
// a n i m a t i o n T h r e e ( )
//********************************************************************************
void animationThree()
{
switch (sharedState)
{
//opening the door fast
case 0:
{
doorServo.write(doorOpen);
doorPosition = doorOpen;
//time for servo operation
sharedMillis = millis();
sharedInterval = 500;
sharedState = 1;
}
break;
//sing and extend foot fast
case 1:
{
//(intensity, numberOfChirps)
highChirp(5, angulo / 10);
//(intensity, numberOfChirps)
lowChirp(angulo * 4, 5);
//extend the foot fast
footServo.write(footExtended);
//time for servo operation
sharedMillis = millis();
sharedInterval = 700;
sharedState = 2;
}
break;
//retract the foot fast
case 2:
{
footServo.write(footRetract);
//time for servo operation
sharedInterval = 700;
//start the Timer
sharedMillis = millis();
sharedState = 3;
}
break;
//closing the door fast
case 3:
{
doorServo.write(doorClose);
delay(500);
//time for servo operation
sharedMillis = millis();
sharedInterval = 500;
sharedState = 4;
}
break;
//finish up this animation
case 4:
{
animationFlag = DISABLED;
//start out in the first shared case
sharedInterval = doorSlow;
//sharedMillis = millis();
sharedState = 0;
//the next animation 'state'
mState = stateC5;
}
break;
} //END switch/case
} //END of animationThree()
// a n i m a t i o n F o u r ( )
//********************************************************************************
void animationFour()
{
switch (sharedState)
{
//opening the door fast
case 0:
{
doorServo.write(doorOpen);
doorPosition = doorOpen;
//time for servo operation
sharedMillis = millis();
sharedInterval = 500;
sharedState = 1;
}
break;
//sing and extend foot fast
case 1:
{
//(intensity, numberOfChirps)
lowChirp(5, 10);
//(intensity, numberOfChirps)
highChirp(5, 10);
//extend the foot fast
footServo.write(footExtended);
//time for servo operation
sharedMillis = millis();
sharedInterval = 700;
sharedState = 2;
}
break;
//retract the foot fast
case 2:
{
footServo.write(footRetract);
//time for servo operation
sharedInterval = 700;
//start the Timer
sharedMillis = millis();
sharedState = 3;
}
break;
//closing the door fast
case 3:
{
doorServo.write(doorClose);
doorPosition = doorClose;
//time for servo operation
sharedMillis = millis();
sharedInterval = 500;
sharedState = 4;
}
break;
//finish up this animation
case 4:
{
animationFlag = DISABLED;
//start out in the first shared case
sharedInterval = doorSlow;
//sharedMillis = millis();
sharedState = 0;
//the next animation 'state'
mState = stateD5;
}
break;
} //END switch/case
} //END of animationFour()
// a n i m a t i o n F i v e ( )
//********************************************************************************
void animationFive()
{
switch (sharedState)
{
//opening the door fast
case 0:
{
doorServo.write(doorHalfwayOpen);
doorPosition = doorHalfwayOpen;
//time for servo operation
sharedInterval = 500;
//start the timer
sharedMillis = millis();
sharedState = 1;
}
break;
//closing the door fast
case 1:
{
//(intensity, numberOfChirps)
lowChirp(5, 1);
doorServo.write(doorClose);
doorPosition = doorClose;
//time for servo operation
sharedInterval = 500;
//start the Timer
sharedMillis = millis();
sharedState = 2;
}
break;
//opening the door fast
case 2:
{
doorServo.write(doorHalfwayOpen);
doorPosition = doorHalfwayOpen;
//time for servo operation
sharedInterval = 500;
//start the Timer
sharedMillis = millis();
sharedState = 3;
}
break;
//closing the door fast
case 3:
{
//(intensity, numberOfChirps)
lowChirp(5, 1);
doorServo.write(doorClose);
doorPosition = doorClose;
//time for servo operation
sharedInterval = 500;
//start the Timer
sharedMillis = millis();
sharedState = 4;
}
break;
//opening the door fast
case 4:
{
doorServo.write(doorOpen);
doorPosition = doorOpen;
//time for servo operation
sharedInterval = 500;
//start the Timer
sharedMillis = millis();
sharedState = 5;
}
break;
//extend the foot fast
case 5:
{
//(intensity, numberOfChirps)
lowChirp(5, 1);
footServo.write(footExtended);
//time for servo operation
sharedInterval = 700;
//start the Timer
sharedMillis = millis();
sharedState = 6;
}
break;
//retract the foot fast
case 6:
{
footServo.write(footRetract);
//time for servo operation
sharedInterval = 700;
//start the timer
sharedMillis = millis();
sharedState = 7;
}
break;
//closing the door fast
case 7:
{
doorServo.write(doorClose);
doorPosition = doorClose;
//time for servo operation
sharedInterval = 500;
//start the Timer
sharedMillis = millis();
sharedState = 8;
}
break;
//finish up this animation
case 8:
{
animationFlag = DISABLED;
//restart the TIMER
powerDownMillis = millis();
//start out in the first shared case
sharedInterval = doorSlow;
//sharedMillis = millis();
sharedState = 0;
//the next animation 'state'
mState = stateE5;
}
break;
} //END switch/case
} //END of animationFive()
// a n i m a t i o n S i x ( )
//********************************************************************************
void animationSix()
{
switch (sharedState)
{
//opening the door fast
case 0:
{
doorServo.write(doorOpen);
doorPosition = doorOpen;
//time for servo operation
sharedInterval = 500;
//start the Timer
sharedMillis = millis();
sharedState = 1;
}
break;
//extend foot fast
case 1:
{
//extend the foot fast
footServo.write(footExtended);
//allow scolding during the 5 seconds that follow
scoldFlag = true;
//going to wait 5 seconds
sharedInterval = 5000;
//start the Timer
sharedMillis = millis();
sharedState = 2;
}
break;
//waiting 5 seconds
case 2:
{
//(intensity, numberOfChirps)
lowChirp(5, 1);
//time for servo operation
sharedInterval = 500;
//start the Timer
sharedMillis = millis();
sharedState = 3;
}
break;
//retract the foot fast
case 3:
{
footServo.write(footRetract);
//time for servo operation
sharedInterval = 700;
//start the Timer
sharedMillis = millis();
sharedState = 4;
}
break;
//closing the door fast
case 4:
{
doorServo.write(doorClose);
//time for servo operation
sharedInterval = 500;
//start the Timer
sharedMillis = millis();
sharedState = 5;
}
break;
//finish up this animation
case 5:
{
//(intensity, numberOfChirps)
highChirp(5, angulo / 10);
//(intensity, numberOfChirps)
lowChirp(angulo * 4, 5);
animationFlag = DISABLED;
sharedInterval = 500;
//start the Timer
sharedMillis = millis();
sharedState = 0;
//the next animation 'state'
mState = stateF5;
}
break;
} //END switch/case
} //END of animationSix()
// a n i m a t i o n S e v e n ( )
//********************************************************************************
// F I G H T with the user animation
void animationSeven()
{
switch (sharedState)
{
case 0:
{
doorServo.write(doorHalfwayOpen);
//time for servo operation
sharedInterval = 500;
//start the Timer
sharedMillis = millis();
sharedState = 1;
}
break;
//turn off the switch, retract the foot just a little, wait for fightDelay seconds
case 1:
{
footServo.write(footExtended);
delay(700);
footServo.write(switchOffPosition - 20);
delay(500);
sharedInterval = fightDelay;
//start the Timer
sharedMillis = millis();
sharedState = 2;
}
break;
//after fightDelay seconds of no action, retract the foot fast
case 2:
{
footServo.write(footRetract);
//time for servo operation
sharedInterval = 700;
//start the Timer
sharedMillis = millis();
sharedState = 3;
}
break;
//closing the door fast
case 3:
{
doorServo.write(doorClose);
//time for servo operation
sharedInterval = 500;
//start the Timer
sharedMillis = millis();
sharedState = 4;
}
break;
//finish up this animation
case 4:
{
animationFlag = DISABLED;
//start out in the first shared case
sharedInterval = doorSlow;
//sharedMillis = millis();
sharedState = 0;
//the next animation 'state' <------<<<< we now are finished with all the animations
mState = lastState;
}
break;
} //END switch/case
} //END of animationSeven()
// a n i m a t i o n E i g h t ( )
//********************************************************************************
void animationEight()
{
} //END of animationEight()
//********************************************************************************
//
// E N D O F F i l e
//
//********************************************************************************