// Power
   int PB_OnOff = 34;  // Power PB
   int PwrON    = 35;   // Power LED
// Annealing
   int PB_Annl  = 36; // Annealing PB  
   int PwrAN    = 37;   // Annealing LED
// Mode Sel  Switch  
   int PinONE =  30;  // Sel Switch - TEST, ONE, AUTO
   int PinAUTO = 31;  // Sel Switch - TEST, ONE, AUTO   
// Lift Sel Switch
   int PinDN = 32;    // Sel Switch Lift DN
   int PinUP = 33;    // Sel Switch Lift UP
// Traffic Lights
   int PinGRN = 38;   //   Green
   int PinYLO = 39;   //   Yelow
// Relays
   int PwrR1 = 46;    // Relay 1 Power Supply
   int StepR = 47;    // Relay 1 Step power select
   int PwrR2 = 48;    // Relay Anneal
// Analog reading
   int PinV = A1;     // Volts
   int PinA = A2;     // Amps
   int PinIR = A3;    // IR Sensor
// FUNCTIONS Declaration
   void DropGate();
   void SelSwitch();
   void StartStop();
   void TheLift(boolean Up);
   void Anneal();
   void BillBoard(int N);
   void AnnSwitch(boolean ON);
   void TempKeep();
   boolean E_Stop();
// == GLOBAL VARABLES ==
   boolean SysIni = true;
   int Task = 0;
   int AnnTime = 0;
   int AnnCount = 0;
   int SelSw = 0;
   int Lvl = 0;
   int T = 0;
   int Steps = 585*2; //////int Steps = 200;
   int Level[] = {18, 24, 30}; int LvlN = 3; // .284, .260, 6 mm  
// Step Motor Library
   #include <Stepper.h>
   Stepper Lift(Steps, 8,10,9,11);
   Stepper Gate(Steps, 8,10,9,11);
// Screen Display library
   #include <LiquidCrystal_I2C.h>
   #include <Wire.h>
   #include <EEPROM.h>
   LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4); 
// =============
// === setup ===
// =============
   void setup() {
// Serial Port
   Serial.begin(115200); 
// Initiate the LCD:
    lcd.init(); lcd.backlight(); 
// Initialize Memory
    Lvl = EEPROM.read(10);
// EEPROM.write(10, 10); establishing reference level - one time only    
  
// Start, Stop, Annealing
     pinMode(PB_OnOff,INPUT_PULLUP); digitalWrite(PB_OnOff,HIGH); // Start/Stop Push Button
     pinMode(PB_Annl, INPUT_PULLUP); digitalWrite(PB_Annl, HIGH); // Annealing Push Button   
// Power Supply and Annealing - LED, Relays
     pinMode(PwrON, OUTPUT);  digitalWrite(PwrON, LOW);           // ON/OFF LED    / Relay 1
     pinMode(PwrAN, OUTPUT); digitalWrite(PwrAN, LOW);            // Annealing LED / Relay 2 
// Selector Switches
     pinMode(PinONE,  INPUT); digitalWrite(PinONE,  HIGH);   // Sel Switch - TEST, ONE, AUTO
     pinMode(PinAUTO, INPUT); digitalWrite(PinAUTO, HIGH);   // Sel Switch - TEST, ONE, AUTO
     pinMode(PinUP, INPUT_PULLUP); digitalWrite(PinUP, HIGH); // Sel Switch Lift UP
     pinMode(PinDN, INPUT_PULLUP); digitalWrite(PinDN, HIGH); // Sel Switch Lift UP    
// Traffic signals
     pinMode(PinGRN, OUTPUT); digitalWrite(PinGRN, LOW);      // Trafic Signal Green
     pinMode(PinYLO, OUTPUT); digitalWrite(PinYLO, LOW);      // Trafic Signal Green
// Pwr Relays
     pinMode(PwrR1, OUTPUT); digitalWrite(PwrR1, HIGH);     // On/Off 
     pinMode(PwrR2, OUTPUT); digitalWrite(PwrR2, LOW);      // Anneal
     pinMode(StepR, OUTPUT); digitalWrite(StepR, HIGH);     // Step Motor Pwr Select
// Step Motors
     Lift.setSpeed(35); Gate.setSpeed(30);
}
// =================
// === Main Loop ===
// =================
   void loop() {
// Inititializing 
   if (SysIni == true){
      SysIni = false; // On Time execution
      if (digitalRead(PinONE) == HIGH && digitalRead(PinAUTO) == LOW) {SelSw = 1;}  // TEST
      if (digitalRead(PinONE) == LOW  && digitalRead(PinAUTO) == LOW) {SelSw = 2;}  // ONES
      if (digitalRead(PinONE) == LOW  && digitalRead(PinAUTO) == HIGH){SelSw = 3;}  // AUTO  
      int N = 0;      
      for (N = 0; N <= 3; N++){
         BillBoard(N); SysIni = false;
      }
   }   
// Volts
    BillBoard(3);
// Task Assignment
   if (digitalRead(PB_OnOff) == LOW) // Strat Stop
      {Task = 1;}
  if (digitalRead(PB_Annl) == LOW)   // Annealing
      {Task = 2;}
   if (digitalRead(PinUP) == LOW)    // Cartridge Lift Up
      {Task = 3;}
   if (digitalRead(PinDN) == LOW)    // Cartridge Lift Dn
      {Task = 4;}
// Monitor SelSw  
    SelSwitch();   // monotors TEST, ONE, AUTO Sel Sw.                                              
// Do the Task
   switch (Task){
     case (1):  StartStop()  ; Task = 0; delay(250); break;
     case (2):  Anneal()     ; Task = 0; delay(250); break;
     case (3):  TheLift(true); Task = 0; delay(10); break;
     case (4):  TheLift(false); Task = 0; delay(10); break;
   }
   for (int y = 8; y <= 11; ++y){digitalWrite(y, LOW);}  // Deenergize the step motors    
}
// ================
// ==== Anneal ====
// ================
   void Anneal(){
   int y=0; boolean InList=false;
// Anneal Time
   BillBoard(1);                   // AUTO, ONESHOT
   if (SelSw == 1) {AnnTime=6500;} // TEST
   if (digitalRead(PwrON)==false)  // No Power
      {AnnTime = 0;}
// The LED and the Anneal Relay
   AnnSwitch(true); 
// Start Annealing 
   int bTime = millis(); int cTime = 0;                                
   while (cTime<AnnTime){
      cTime = millis()-bTime; T = cTime;    
      delay(100); BillBoard(3);                // Show Count Down Time        
      if (E_Stop() == true){return;}           // Interrupt Annealing
   }
// Stop Annealing
   AnnSwitch(false); DropGate();         
   ++AnnCount; BillBoard(2);
// Traffic Signals
    if (SelSw == 3){ // AUTO     
       digitalWrite(PinGRN, HIGH); cTime = 0; bTime = millis();
       while (cTime<2000){                 // Green Traffic
         cTime = millis()-bTime;
         if (E_Stop() == true){return;}    // Stop Annealing                    
       }
       digitalWrite(PinGRN, LOW); cTime = 0; bTime = millis();
       BillBoard(2);       
       while (cTime<2000){                 // Green Traffic
         cTime = millis()-bTime;
         if (E_Stop() == true){return;}    // Stop Annealing
         digitalWrite(PinYLO, HIGH); delay(250);
         if (E_Stop() == true){return;}    // Stop Annealing
         digitalWrite(PinYLO, LOW);   delay(250);
                   
       }               
       Anneal(); // Anneal Again  on AUTO
    }
} 
// =================
// === BillBoard ===
// =================
   void BillBoard(int N) {
// Line 1 - "Tesla Oakley Annealing"
// Line 2 - Set Selected caliber or Level
// Line 3 - TEST, ONES, AUTO, COUNTS
// Line 4 - VOLTS, AMPS, TIMING
// Line 1 Variables
   String sLvl = ""; int sVolt = 0; int sTime = 0; int y = 0; int S = 0;  
// Line 2 Variables
   String sMode = ""; boolean inList = false;
   Lvl = EEPROM.read(10);  
// Line 3 Variables
   int V = 0; int A = 0;
// Is it on The List
   for (y = 0; y < LvlN; ++y){                   
       if (Level[y] == Lvl){inList = true; S = y; break;}
   }
   lcd.setCursor(0,N);
   switch (N){
      case 0:
           lcd.print("Tesla Oakley Anneal"); break;
      case 1:
           AnnTime = 0;                             
           if (inList == true && SelSw != 1){     
              switch (S){
                  case 0: sLvl = ".284 "; sVolt = 46; sTime = 3600; break;
                  case 1: sLvl = ".260 "; sVolt = 46; sTime = 4400; break;
                  case 2: sLvl = "6 mm "; sVolt = 40; sTime = 3800; break;
               }
               AnnTime = sTime;                     
               lcd.print("Set: ");    
               lcd.print(sLvl);lcd.print(sVolt);lcd.print(" V ");
               lcd.print(AnnTime/1000.0,1); lcd.print("s ");                
           }           
            if (inList == false || SelSw == 1){
               lcd.print("Level "); lcd.print(Lvl); lcd.print("      ");
               lcd.print(AnnTime/1000.0,1); lcd.print("s ");
           }
           break;
      case 2: // Line 2       
           switch (SelSw){
                case 1:  sMode = "TEST "; AnnTime = 5000;
                         break;                                              
                case 2:  sMode = "ONES ";
                         if (inList == false){AnnTime = 0;}break;
                case 3:  sMode = "AUTO ";
                         if (inList == false){AnnTime = 0;} break;        
           }                    
           lcd.print("Mode: ");  lcd.print(sMode);
           lcd.print("Cnt "); lcd.print(AnnCount);
           break;                  
      case 3: // Line 3     
           V = 50.0*analogRead(PinV)/1023.0;    
           A = analogRead(PinA)-527; A = - 50*A/1023;
           if(abs(V)<1){V=0;} 
           if (abs(A)<1) {A=0;}      
           lcd.print("Annl: "); 
           lcd.print(V);lcd.print(" V ");
           lcd.print(A);lcd.print(" A ");
           lcd.print(T/1000.0,1);lcd.print("s");
           break;
      }
   }
// ===============
// === TheLift ===
// ===============
   void TheLift(boolean Up) {
      int y = 0;
   // Obey Travel Limits or Pause at Next Cartridge Level 
      while (digitalRead(PinUP) == LOW || digitalRead(PinDN) == LOW){     
         if (Up == false && Lvl == 10){return;}
      // Is it in the list?     
         for (y = 0; y < LvlN; ++y){
            if(Level[y] == Lvl)
              {BillBoard(1); delay(1000);break;}
         }
      // Spin it
          digitalWrite(StepR, LOW);       
         if (Up == true) {Lift.step( Steps); ++Lvl;}      
         if (Up == false){Lift.step(-Steps); --Lvl;}
         EEPROM.write(10, Lvl); BillBoard(1);                               
      }
      digitalWrite(StepR, HIGH);
   }               
// ====================
// ==== DROP_GATE =====
// ====================
   void DropGate(){
    int y; int Move = 227; // 15 degree Gate.setSpeed(30); Lift.setSpeed(35);
    Gate.step(-Move); delay(1250);
    Gate.step(Move);  ;                  
    for(y = 8; y<=11; ++y){digitalWrite(y, LOW);}                 
    }
// =============
// == E-Stop ===
// =============
   boolean E_Stop() {
   boolean STOP = false;
   boolean AnnON = false;
      if (digitalRead(PwrR2)==HIGH)
         {AnnON = true;}
      if (digitalRead(PB_OnOff) == LOW) {
         AnnSwitch(false); // Stop Annealing
         if (AnnON == true)
            {DropGate();}
         digitalWrite(PinGRN, LOW);
         digitalWrite(PinYLO, LOW);
         STOP = true;
      }      
      return STOP;        
   }
//====================
//==== START_STOP ====
//===================
  void StartStop(){   
  if (digitalRead(PwrON)==LOW)
     {digitalWrite(PwrON, HIGH);digitalWrite(PwrR1,LOW);return;}
  if (digitalRead(PwrON)==HIGH)
     {digitalWrite(PwrON, LOW);digitalWrite(PwrR1,HIGH); return;}            
  }
//====================
//==== SelSwitch ====
//===================
  void SelSwitch(){
   int S = 0;
   if (digitalRead(PinONE) == HIGH && digitalRead(PinAUTO) == LOW)  {S = 1;}  // TEST
   if (digitalRead(PinONE) == HIGH  && digitalRead(PinAUTO) == HIGH){S = 2;}  // ONES
   if (digitalRead(PinONE) == LOW  && digitalRead(PinAUTO) == HIGH) {S = 3;}  // AUTO
   if (digitalRead(PwrON)  == HIGH){BillBoard(3);} // Show Volatage all the time
   if(SelSw == S)
     {return;}
   if(SelSw != S)
     {SelSw = S; AnnCount = 0; BillBoard(1);BillBoard(2);}    
  }
// =================
// === AnnSwitch ===
// =================
   void AnnSwitch(boolean ON){
      if (ON == true){
         digitalWrite(PwrAN, HIGH); digitalWrite(PwrR2, HIGH); // Contactor and LED ON    
      }
      if (ON == false){
         digitalWrite(PwrAN, LOW); digitalWrite(PwrR2, LOW); // Contactor and LED OFF
      }
   }