Code functions properly on Tinkercad but not on Real device.

Hello Arduino Community,

TLDR of the code: I'm working on a device that uses three buttons, one as a Power button and two that control two different servo motors. The power button turns on the device, for 15 seconds, 6 LEDs light up, and the servo buttons are useable. After the 15 seconds, the lights turn off, and the buttons are turned off. Then, the power button should be able to be pressed again to start the process over. This is where the problem occurs.

My problem is the Power button activates the process only once on the real device, but on Tinkercad (a site where I test my code on a virtual clone of the circuit/device), the Power button can be used as many times as you'd like.

To be clear, the power button should be able to be used more than once. I'm not sure how to debug something when it functions properly on Tinkercad. I'm apart of a school project, I'm tasked with writing the software, so I don't have the real device in front of me.

Please let me know what you think.

I appreciate your time.
Thank you.

Edit: I removed a link to where my code was posted online. My code can be found as a reply to this thread down below.

eggart:
Here is my a link to my code:

The first line is this...

#include

Does that look valid to you? Does that match your actual code?

Rather than posting a link to the code that many will not risk following, it is much preferred to post the code here.
Use code tags.
If you do not know what code tags are then you need to read the stick post at the top of this forum named How to use this forum - please read.

vinceherman:
Rather than posting a link to the code that many will not risk following, it is much preferred to post the code here.
Use code tags.
If you do not know what code tags are then you need to read the stick post at the top of this forum named How to use this forum - please read.

Understood. The reason I linked to the code is I kept receiving the error stating my post was over 9000 characters. I tried to narrow it down by removing unhelpful comments and used a character counter to drop below 9000, but I kept getting denied. I'd guess the counter also includes white space. I didn't want to make a post without the code.

In the meantime, I will post the code in a comment on this thread. I should be able to fit it without the explanation on top of it.

I apologize for the inconvenience.

eggart:
In the meantime, I will...

...attach the code. Good choice.

My bad, here is my code:

#include <Servo.h>

// [Creates two Servo Objects]
// "servoTop" is for the upper motor and "servoBot" is for the lower motor.
Servo servoTop;                 
Servo servoBot;           



// [Define Variable]

// Arduino Pin locations for the buttons that operates Upper Servo, Lower Servo, and Power.
int switchPinTop = 2;       
int switchPinBot = 1;       
int switchPinPow = 3;       
int stepsSet = 0;           // As of 040419, I'm not sure what this does. However, it's used in places, so please don't touch it.
// Arduino Pin locations for the LEDs.
int led1 = 7;               
int led2 = 8;               
int led3 = 9;              
int led4 = 10;              
int led5 = 11;              
int led6 = 12;              


// Power button timer
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 15000;   // "period" is the amount of time (in miliseconds) we want the device to "be on" after the start button is pressed.


// Boolean varialbes to keep track of button and motor
boolean currentTop = LOW;                 
boolean currentBot = LOW;                 
boolean currentPow = LOW;                 
boolean last = LOW;                       // "current" and "last" track the state for the push button. ie: the state before "last" is LOW, the current state is HIGH.
boolean isRunning = false;                // isRunning Checks the state of the motor. For off, it will be marked as false. For on, is will be marked as true
boolean lastGlobal = LOW;                 
boolean isRunningGlobal = false;          



void setup() {
  servoTop.attach(4);                  // Sets Top Servo to pin 1
  servoBot.attach(5);                  
  pinMode(switchPinTop, INPUT);       // Push button is an input, so we define it with Pinmode
  pinMode(switchPinBot, INPUT);       
  pinMode(switchPinPow, INPUT);       
  servoTop.write(0);                // Set original locations for servos.
  servoBot.write(0);
  // Tell lightbulbs that they are in fact light bulbs
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(led6, OUTPUT);
  

  // Keeps the button from being pressed under 30 seconds. 
  startMillis = 9999999999;              
}



// [DEBOUNCE CODE FOR TOP BUTTON]
// Corrects push button bounce (not the best debounce function)
boolean debounceBot(boolean inLast){ 
  boolean inCurrentBot = digitalRead(switchPinBot);  
  if(inLast != currentBot){                      
    delay(5);                                  
    inCurrentBot = digitalRead(switchPinBot);
  }
  return inCurrentBot;

  // The purpose here is to limit the instability when the button is shaking. So, we wait 5 micro seconds for the current to stableize, which enables a clean reading.   
}



// [DEBOUNCE CODE FOR BOTTOM BUTTON]
// Corrects push button bounce (not the best debounce function)
boolean debounceTop(boolean inLast){ 
  boolean inCurrentTop = digitalRead(switchPinTop); 
  if(inLast != currentTop){                       
    delay(5);                                  
    inCurrentTop = digitalRead(switchPinTop);
  }
  return inCurrentTop; 
}



// [DEBOUNCE CODE FOR POWER BUTTON]
// Corrects push button bounce (not the best debounce function)
boolean debouncePow(boolean inLast){ 
  boolean inCurrentPow = digitalRead(switchPinPow);  
  if(inLast != currentPow){                       
    delay(5);                                  
    inCurrentPow = digitalRead(switchPinPow);
  }
  return inCurrentPow;

  // The purpose here is to limit the instability when the button is shaking. So, we wait 5 micro seconds for the current to stableize, which enables a clean reading.   
}




// [GARAGEACTION CODE FOR TOP BUTTON]
void garageActionTop(float factor){              // Function that moves motor
 
  stepsSet = factor;                          // The amount we want to motor to rotate
  // [Servo speed here?];
  servoTop.write(factor);                        // Activeates the motor. Tells the motor to move factor amount
  if (isRunning == false){                    // If the motor is moving and it was off before, wait three seconds
    delay(3000);
  } else if (isRunning == true) {
    delay(5);
  }
}


// [GARAGEACTION CODE FOR BOTTOM BUTTON]
void garageActionBot(float factor){              // Function that moves motor
 
  stepsSet = factor;                          // The amount we want to motor to rotate
  // [Servo speed here?];                       // Activeates the motor. Tells the motor to move factor amount
  servoBot.write(factor);
  if (isRunning == false){                    // If the motor is moving and it was off before, wait three seconds
    delay(3000);
  } else if (isRunning == true) {
    delay(5);
  }
}


// [GLOBAL CODE FOR POWER BUTTON]
void globalFunction(float factor){
  if (isRunningGlobal == false){
  // Stuff
  } else if (isRunningGlobal == true) {
  // stuff
  }
}
  
  
  
// die Gehirne
void loop() {
 

  
  currentTop = debounceTop(last);                     // Calls the debounce function on the last button: Checks low and the current state. If it's the same, it does nothing. if it's different, it will recheck to get a correct reading
  currentBot = debounceBot(last);
  currentPow = debouncePow(last);
  
  
  // [CHECK BUTTON STATE - CODE FOR POWER BUTTON]
  if(currentPow == HIGH && lastGlobal == LOW && isRunningGlobal == false){  // If the current state is high, the previous was low, and the motor is not moving, then rotate 180 degrees (clockwise)                 

  // Turn the LEDs on
  digitalWrite(led1, HIGH); 
  digitalWrite(led2, HIGH);
  digitalWrite(led3, HIGH);
  digitalWrite(led4, HIGH); 
  digitalWrite(led5, HIGH); 
  digitalWrite(led6, HIGH);  
    
    
  // Store the time when button was pressed   
  currentMillis = millis();
  startMillis = millis();  
       
    
  // ENG MILLIS TRIAL  
  isRunningGlobal = !isRunningGlobal;                           // Change the current state to high.
  
  
    
  }
  
 
  
  currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)
  if ((currentMillis - startMillis) <= period){  //test whether the period has elapsed
  
    
    
     // [CHECK BUTTON STATE - CODE FOR TOP BUTTON]
  if(currentTop == HIGH && last == LOW && isRunning == false){  // If the current state is high, the previous was low, and the motor is not moving, then rotate 180 degrees (clockwise)
  garageActionTop(180);                       //Location 93 Functions as zero.
  isRunning = !isRunning;                           // Change the current state to high.
  }
  if(currentTop == HIGH && last == LOW && isRunning == true){  // if the current state is high, the previous state was low, and the motor is moving, rotate CCW 180 degrees.
    garageActionTop(0);
    delay(1900);    
  
    
   
    isRunning = !isRunning;                         // Then switches is back.
    
  } // [END IF CODE FOR TOP BUTTON]
  
  
  // [CHECK BUTTON STATE - CODE FOR BOTTOM BUTTON]
  else if(currentBot == HIGH && last == LOW && isRunning == false){ 
  garageActionBot(180);                                   
  isRunning = !isRunning;                                    // Change the current state to high.
  }
 
  if(currentBot == HIGH && last == LOW && isRunning == true){ 
      garageActionBot(0);
      delay(1900);    
  
  
    
    isRunning = !isRunning;
  
  }  // [END IF CODE FOR BOT BUTTON]
  
  
  // Or else time out
  else if((currentMillis - startMillis) >= period){
  digitalWrite(led1, LOW); 
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);
  digitalWrite(led4, LOW); 
  digitalWrite(led5, LOW); 
  digitalWrite(led6, LOW); 
  isRunningGlobal = !isRunningGlobal; 
  currentMillis = 99999999;
  }
  
 } // End milli if
  


}   // End void loop()

You're right. I made a mistake while posting my code to that site. I've posted my code below and will remove the link.

I don’t see any code for a power button. Is this just a button cutting power to your Arduino? A schematic would probably be helpful.

pert:
I don't see any code for a power button. Is this just a button cutting power to your Arduino? A schematic would probably be helpful.

In don't think it's a "real" power button, as in supplying/cutting electricity to anything; it seems to me it's more of an "enable" button which controls the process in an already powered and running Arduino.

That's what I originally expected, but I don't see the code for it (admittedly, I didn't read it very thoroughly). Do you see the code for this "enable" button?

pert:
Do you see the code for this "enable" button?

I think this is it:

  currentPow = debouncePow(last);
  
  
  // [CHECK BUTTON STATE - CODE FOR POWER BUTTON]
  if(currentPow == HIGH && lastGlobal == LOW && isRunningGlobal == false){  // If the current state is high, the previous was low, and the motor is not moving, then rotate 180 degrees (clockwise)

Oh, wow. That is tough to miss! I've spent 11 hours on the forum today and I think it's taking a toll.

My advice is to add some Serial.println() statements to strategic locations in your code, then run the code with Tools > Serial Monitor open so that you can get some idea of what’s happening in your code.
https://www.arduino.cc/reference/en/language/functions/communication/serial/println/