/////////////////////////////////////////////////////////////////////////////////////////////////////
// Addams Family Clock - Control Program by Peter Scott 2020-2023                                  //
// Distributed via Instructables 2023                                                              //
// This code is provided 'as is' with no warranties or guarantees                                  //
// Please feel free to copy or modify this code                                                    //
/////////////////////////////////////////////////////////////////////////////////////////////////////

#include <Servo.h>            // Servo Library
#include <Stepper.h>          // Stepper Motor Library

Stepper stepper1(32, 22, 26, 24, 28); // Initialise Stepper A
Stepper stepper2(32, 23, 27, 25, 29); // Initialise Stepper B 

Servo shutter1;               // create servo object to control shutter 1 - Granny
Servo shutter2;               // create servo object to control shutter 2 - Morticia
Servo shutter3;               // create servo object to control shutter 3 - Gomez
Servo shutter4;               // create servo object to control shutter 4 - Fester
Servo shutter5;               // create servo object to control shutter 5 - Wednesday/Pugsley
Servo shutter6;               // create servo object to control shutter 6 - Lurch
Servo animation1;             // create servo object to control animation 1 - Pugsley Hanging Wednesday
Servo animation2;             // create servo object to control animation 2 - Lurch Sweeping

int ledPin       = 13;        // the pin number of the Fester LED
int buttonPin    = 12;        // the pin number of the pushbutton
int sound1       = 7;         // the pin number of the tick tock sound effect
int sound2       = 6;         // the pin number of the Addams Family Music 1
int sound3       = 5;         // the pin number of the Addams Family Music 2 (Alternative Tune)
int sound4       = 4;         // the pin number of the Rumbling Noise effect
int sound5       = 3;         // the pin number of the Single Chime
int sound6       = 2;         // the pin number of the End Routine

int greenLED     = 1;         // the pin number of the Green LEDs swictch on/off
int buttonState  = 0;         // variable for reading the pushbutton status
int startRoutine = 0;         // variable for the start routine flag

//Modify these two variables if you wish
int hourNumber   = 8;         // variable for 2x the number of chimes required
int tickNumber   = 4;         // variable for the number of clock ticks required (at the beginning & end of the sequence)


//SETUP//////////////////////////////////////////////////////////////////////////////////////////////

void setup()
{

  // Initialize Fester's light bulb and set to OFF
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);   

  // Initialize the start button pin
  pinMode(buttonPin, INPUT);

  // Initialize green LEDs trigger pin and set to LOW
  pinMode(greenLED, OUTPUT);
  digitalWrite(greenLED, LOW);  
 
  // Initialize sound1 pin and set to HIGH
  pinMode(sound1, OUTPUT);
  digitalWrite(sound1, HIGH);

  // Initialize sound2 pin and set to HIGH
  pinMode(sound2, OUTPUT);
  digitalWrite(sound2, HIGH);

  // Initialize sound3 pin and set to HIGH
  pinMode(sound3, OUTPUT);
  digitalWrite(sound3, HIGH);
  
  // Initialize sound4 pin and set to HIGH
  pinMode(sound4, OUTPUT);
  digitalWrite(sound4, HIGH);  

  // Initialize sound5 pin and set to HIGH
  pinMode(sound5, OUTPUT);
  digitalWrite(sound5, HIGH);  

  // Initialize sound6 pin and set to HIGH
  pinMode(sound6, OUTPUT);
  digitalWrite(sound6, HIGH);  
    
  
  // Attach Servos
  shutter1.attach(42);        //attach the servo on pin 42 to servo object - Granny
  shutter1.write(170);        //set servo to start position
  shutter2.attach(43);        //attach the servo on pin 43 to servo object - Morticia
  shutter2.write(170);        //set servo to start position
  shutter3.attach(44);        //attach the servo on pin 44 to servo object - Gomez
  shutter3.write(180);        //set servo to start position
  shutter4.attach(45);        //attach the servo on pin 45 to servo object - Fester
  shutter4.write(180);        //set servo to start position  
  shutter5.attach(47);        //attach the servo on pin 47 to servo object - Wednesday/pugsley
  shutter5.write(170);        //set servo to start position
  shutter6.attach(49);        //attach the servo on pin 49 to servo object - Lurch 
  shutter6.write(160);        //set servo to start position
  animation1.attach(51);      //attach the servo on pin 51 to servo object - Pugsley Hanging Wednesday
  animation1.write(15);       //set servo to start position
  animation2.attach(53);      //attach the servo on pin 53 to servo object - Lurch sweeping
  animation2.write(10);       //set servo to start position

} // End of void setup()

//////////////Start Main Loop Here//////////////////////////////////////////////

void loop()
{

  // If start button is pressed - set a flag to start the main routine
  buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH) {
    startRoutine = 1;
  }

  
  // Start the main routine here if flagged to do so
  if (startRoutine == 1)  {

      //CLOCK TICKING SOUNDS///////////////////////////////

      // Play tick tock sound in a loop based on the variable set for tickNumber
      for (int counter = 0; counter < (tickNumber); counter++)  {
      
        // Play ONE Tick Tock
        digitalWrite(sound1, LOW);
        delay(200);
        digitalWrite(sound1, HIGH); 
        delay(1900);    
        
      }
        
      /////////////////////////////////////////////////////
      //You can choose from two theme tunes

      // Play Addams Family Theme Tune 1
      //digitalWrite(sound2, LOW); 
      //delay(200);
      //digitalWrite(sound2, HIGH);
      //delay(13000);

      // Play Addams Family Theme Tune 2
      digitalWrite(sound3, LOW); 
      delay(200);
      digitalWrite(sound3, HIGH);
      delay(19000);      
    
      /////////////////////////////////////////////////////

      // Open Gomez roof shutter
      shutter3.write(-5); 
      delay(100);
    
      // Play sound of Rumbling
      digitalWrite(sound4, LOW); 
      delay(600);
      digitalWrite(sound4, HIGH); 
        
      // Bring Gomez out of his house    
      stepper1.setSpeed(100);
      stepper1.step(600);

      /////////////////////////////////////////////////////

      // Open Morticia roof shutter    
      shutter2.write(0);
      delay(100);    
    
      // Play sound of Rumbling
      digitalWrite(sound4, LOW); 
      delay(600);
      digitalWrite(sound4, HIGH);     
    
      // Bring Morticia out of her house
      stepper2.setSpeed(100);
      stepper2.step(550);

      /////////////////////////////////////////////////////

      // Small timing delay
      delay(1000);
      
      // Turn on Green LEDs
      digitalWrite(greenLED, HIGH);

      // Open window shutters
      shutter6.write(0);     // Lurch   
      shutter4.write(10);    // Fester
      shutter5.write(30);    // Wednesday/Pugsley
      shutter1.write(10);    // Granny      
    
      // Small timing delay before starting animations
      delay(1000);

      // CHIMES & ANIMATIONS LOOP /////////////////////////

      // Operate servo animations and chimes in a loop based on the variable hour number
      for (int counter = 0; counter < (hourNumber); counter++)  {

          // Sound One Single Strike of the CHIME
          digitalWrite(sound5, LOW);
          delay(200);
          digitalWrite(sound5, HIGH);
      
          // Animation Servos position 1
          animation1.write(45);    // Pugsley hanging wednesday - pull down on rope
          animation2.write(20);    // Lurch sweeping - first action
      
          // Turn the flashing Fester LED ON
          digitalWrite(ledPin, LOW);    
          delay(1200);
      
          // Animation Servos position 2
          animation1.write(25);     // Pugsley hanging wednesday - return 
          animation2.write(-5);     // Lurch sweeping - second action

          // Turn the flashing Fester LED OFF
          digitalWrite(ledPin, HIGH);   
          delay(1200);

      }
    
      // CLOSE EVERYTHING UP //////////////////////////////

      // Turn the green LEDs OFF
      digitalWrite(greenLED, LOW);      
      
      // Close shutters
      shutter6.write(170);     // Lurch close shutters                
      shutter4.write(170);     // Fester close shutters
      shutter5.write(170);     // Wednesday/Pugsley close shutters
      shutter1.write(170);     // Granny close shutters      
      
      // Reset the animations
      animation1.write(15);    // Pugsley hanging wednesday - reset back to centre position
      animation2.write(10);    // Lurch sweeping - back to centre position               

      // Small timing delay
      //delay(100);    
    
      /////////////////////////////////////////////////////

      // Play sound of Rumbling
      digitalWrite(sound4, LOW); 
      delay(200);
      digitalWrite(sound4, HIGH); 
      
      //Put Morticia back into her house
      stepper2.setSpeed(100);
      stepper2.step(-550);

      // Close Morticia roof shutter
      shutter2.write(180);
    
      /////////////////////////////////////////////////////
      
      // Small timing delay
      delay(2000);    

      /////////////////////////////////////////////////////

      // Play sound of Rumbling
      digitalWrite(sound4, LOW); 
      delay(200);
      digitalWrite(sound4, HIGH);     

      // Put Gomez back into his house
      stepper1.setSpeed(100);
      stepper1.step(-600);

      // Close Gomez roof shutters
      shutter3.write(170);

      /////////////////////////////////////////////////////
      
      // Small timing delay
      delay(500);     

      /////////////////////////////////////////////////////      
      
      // Play end music
      digitalWrite(sound6, LOW); 
      delay(200);
      digitalWrite(sound6, HIGH);
    
      /////////////////////////////////////////////////////

      // Reset startRoutine back to 0
      startRoutine = 0;

  }

} // end of void loop()
