Arduino Timing

So i’m trying to time a servo without a delay, so when i press a button the servo moves, then 7.5 seconds later it moves back. This works sometimes, but once every 2-3 attempts, the variable that equals time ends up being a large negative number (around -27000). How do I fix this?

i.e.

servo moves
variable = timer

if variable =< timer - 7500
servo moves back

but then sometimes the variable sets to -27000 instead of the instantaneous value for time.

Probably because you are not using ‘type’ ‘unsigned long’ in code you did not show us :frowning:

Sorry, it’s part of so much irrelevant crap that i thought I’d make it easier. I’ll post all the relevant code:

#include <Servo.h>

Servo servo;

unsigned long rtime;
int var = 0;
int timer = 0;
const int buttonPin = 11;
int buttonState = 0;

void setup() {
servo.attach(2);
pinMode(buttonPin, INPUT);
}

void loop(){

buttonState = digitalRead(buttonPin);

if(buttonState == HIGH){
servo.write(60);
timer = rtime;
var = 1;
}

if(var != 0){
if(timer <= rtime - 7500) {
servo.write(0);
timer = 0;
var = 0;
}}

Crap :frowning:

Off hand,
int timer = 0;
make this
unsigned long timer = 0;

You never do anything with ‘rtime’, why?

However, you should use proper delay techniques using BWD.
See Robin2’s discussion.

See if you can follow this example:

//Blink without Delay skeleton 
//4 examples demonstrated
//

//LED wiring options
//=============================================
//Depending which way your LEDs are wired, uncomment the next line.
//#define PlusEqualsON 

#ifdef PlusEqualsON
//wired so +5V turns LED ON
#define ledON  HIGH
#define ledOFF LOW
//=========================
#else
//wired so +5V turns LED OFF
#define ledON  LOW
#define ledOFF HIGH
//=========================
#endif

//switch wiring options
//=============================================
//Depending which way your switches are wired, uncomment the next line.
#define PushEqualsLOW 

#ifdef PushEqualsLOW 
//pushing the switch makes pin LOW
#define Pushed   LOW
#define Released HIGH
//=========================
#else
//pushing the switch makes pin HIGH
#define Pushed   HIGH
#define Released LOW
//=========================
#endif

//=============================================
unsigned long currentMillis;
unsigned long pin13Millis;
unsigned long pin12Millis;
unsigned long pin11Millis;
unsigned long SwitchMillis;

//if these are not changed in the sketch, they can be const
unsigned long debounceMillis = 100UL;     //100ms
unsigned long ledOnTime      = 5*1000UL;  //5 seconds

byte laststartSwitchState    = HIGH;
byte buttonState             = HIGH;
byte counter                 = 0;

//the following are enable/disable flags
//some of these might not be used in this sketch
boolean flag13 = true;
boolean flag12 = true;
boolean flag11 = true;
boolean flag10 = true;

const byte startSwitch = 2; //pushed = LOW
const byte testSwitch  = 3; //pushed = LOW

//**********************************************************************

void setup()
{
  Serial.begin(9600);
  
  digitalWrite(13,ledOFF);
  pinMode(13, OUTPUT); 

  digitalWrite(12,ledOFF);
  pinMode(12, OUTPUT);

  digitalWrite(11,ledOFF);
  pinMode(11, OUTPUT);
  
  digitalWrite(10,ledOFF);
  pinMode(10, OUTPUT);

  pinMode(startSwitch, INPUT_PULLUP); //pushed = LOW
  pinMode(testSwitch,  INPUT_PULLUP); //pushed = LOW

} //  >>>>>>>>>>>>>> E N D  O F  s e t u p ( ) <<<<<<<<<<<<<<<<<

void loop()
{
  //save the current time
  currentMillis = millis();

  //************************************* E x a m p l e  1
  //toggle pin 13 every 200mS
  //has 200ms or more gone by?
  if (currentMillis - pin13Millis >= 200UL)
  {
    //code here runs every 200ms
    //get ready for next iteration
    pin13Millis = pin13Millis + 200UL;
    //toggle pin 13
    digitalWrite(13,!digitalRead(13));
  }

  //************************************* E x a m p l e  2
  //at power up, pin 12 LED goes ON, after 3 seconds goes OFF and stays OFF
  //could be used as a powerup reset signal
  if (flag12 == true && currentMillis - pin12Millis <= 3000UL)
  {
    //code here runs for 3 seconds after power up, then stops
    digitalWrite(12,ledON);
  }
  else
  {
    digitalWrite(12,ledOFF);
    //disable further pin 12 control
    flag12 = false;
  }

  //************************************* E x a m p l e  3
  //if testSwitch is pushed and released
  //pin 11 LED goes ON for 5 seconds, then goes OFF 
  buttonState = digitalRead(testSwitch);
  
  //are we are allowed to check the switch and is it pressed?
  if(flag11 == true && buttonState == Pushed)
  {    
    //enable timing of LED on pin 11
    flag11 = false; //false --> timing is enabled
    //turn LED ON
    digitalWrite(11,ledON);
    //record the time LED turned ON
    pin11Millis = currentMillis;
  }
    
  //are we allowed and is it time to control pin 11
  if (flag11 == false && currentMillis - pin11Millis >= ledOnTime)
  {
    //if enabled, code here runs after ledOnTime ms goes by
    digitalWrite(11,ledOFF);
    //allow switch press detection again
    flag11 = true; //true --> switch monitoring is enabled
  }

  //************************************* E x a m p l e  4
  //is it time to check the switches?
  //in particular, pushing startSwitch will turn ON/OFF (toggle) an output pin 10
  //is it time to check the switches
  if (currentMillis - SwitchMillis >= debounceMillis)
  {
    //code here runs every debounceMillis ms
    //get ready for the next iteration
    SwitchMillis += debounceMillis; 
    //go and check the switches
    checkSwitches();    
  } 

  //*********************************
  //put other non-blocking stuff here
  //*********************************

} //  >>>>>>>>>>>>>> E N D  O F  l o o p ( ) <<<<<<<<<<<<<<<<<


//======================================================================
//                      F U N C T I O N S
//======================================================================


//****************** c h e c k S w i t c h e s ( ) *********************
//switches are checked every debounceValue milli seconds 
//no minimum switch press time is validated with this code (i.e. No glitch filter)
void checkSwitches()  
{
  //re-usable for all the switches  
  boolean thisState;    

  //************************************* E x a m p l e  Push ON push OFF (toggle)   
  //check if this switch has changed state
  thisState = digitalRead(startSwitch);
  if (thisState != laststartSwitchState)
  {  
    //update the switch state
    laststartSwitchState = thisState;  

    //this switch position has changed so do some stuff

    //"HIGH condition code"
    //switch went from LOW to HIGH
    if(thisState == HIGH)        
    {
      //Do some HIGH switch stuff here
    }

    //"LOW condition code"
    //switch went from HIGH to LOW
    else                          
    {
      //Do some LOW switch stuff here  
      digitalWrite(10, !digitalRead(10));
      //print number of pushes
      counter++;
      Serial.println(counter);
    }

  } //END of startSwitch code

  //*****************************************  
  //similar code for other switches goes here 
  //*****************************************  

} //END of checkSwitches()

//**********************************************************************

//======================================================================
//                      E N D  O F  C O D E
//======================================================================

shit sorry, i also have

rtime = millis();

in the loop

and isnt timer just gonna be the variable which is equal to rtime's instantaneous value when i have timer = rtime? so it should start as timer = 0?

What does this do?

#include <Servo.h>

Servo servo;

unsigned long rtime;
unsigned long timer = 0;

const byte buttonPin = 11;

byte buttonState = LOW;
byte lastButtonState = LOW;

boolean servoFlag = false;



void setup()
{
  Serial.begin(9600);

  servo.attach(2);
  pinMode(buttonPin, INPUT);
}

void loop()
{
  rtime = millis();

  buttonState = digitalRead(buttonPin);

  if (servoFlag == false && lastButtonState != buttonState)
  {
    lastButtonState = buttonState;

    if (buttonState == HIGH)
    {
      servo.write(60);

      Serial.println("servo at 60");

      timer = rtime;
      servoFlag = true;
    }
  }

  if (servoFlag == true && rtime - timer >= 7500)
  {
    servo.write(0);

    Serial.println("servo at 0");

    servoFlag = false;
  }

} //END of loop()

Yeah that seems to work well, thanks for that. Idk what it all means tho :§

If you do not understand any lines of code in the sketch, ask about them.

Its pretty much everything boolean, don’t really understand what it is/does. The boolean lines, ServoFlag lines, && etc.

I feel like it’s quite basic, but I’ve only taught myself what I’ve needed so far.

Also why wasn’t the old code working?

Read the comments in the attached code below.

boolean is a data ‘type’ you can attach to a variable.
Other data types are: byte, int, unsigned int, char, unsigned long etc.
https://www.arduino.cc/reference/en/language/variables/data-types/boolean/

Flags in programming can be used to indicate if things are enabled or disabled.
Since enabled/disabled is two conditions, ‘type’ boolean is used here as it has two conditions, true/false.
You could use ‘type’ byte, but byte is 0-255 values (you would then use LOW or HIGH).
We try to use the best data ‘type’ when we program.

&& simply means AND, i.e. this AND that must both be true before we validate an ‘if’ line of code.

Note: when you read switches you usually are interested only when the switch changes state, hence the need for the this section of code (change in state)
//when we are not timing, has the switch’s state changed?
if (servoFlag == false && lastButtonState != buttonState)
{

Compare your code to this code to see what you left out.

Any further questions?

#include <Servo.h>

Servo servo;

unsigned long rtime;

//time when the servo goes to 60
unsigned long timer = 0;

const byte buttonPin = 11;

//the state we are currently in now
byte buttonState = LOW;

//the state we were in before now
byte lastButtonState = LOW;

//a flag that indicates if we are currently in timing mode. 'true' means we are timing
boolean servoFlag = false;

//**************************************************************************************

void setup()
{
  Serial.begin(9600);

  servo.attach(2);
  pinMode(buttonPin, INPUT);
}

void loop()
{
  //capture the current time
  rtime = millis();

  //read the current state of the switch
  buttonState = digitalRead(buttonPin);

  //when we are not timing, has the switch's state changed?
  if (servoFlag == false && lastButtonState != buttonState)
  {
    //the switch state has changed, update to the new state
    lastButtonState = buttonState;

    //did we just go to a switch pressed state (HIGH)
    if (buttonState == HIGH)
    {
      servo.write(60);

      Serial.println("Servo at 60");

      //the time that the servo went to 60
      timer = rtime;
      
      //enabling timing
      servoFlag = true;
    }
  }

  //when timing is enabled, has the servo timer expired?
  if (servoFlag == true && rtime - timer >= 7500)
  {
    servo.write(0);

    Serial.println("Servo at 0");

    //we are now finished, disable timing
    servoFlag = false;
  }


} //END of loop()

Thanks boss, this helps a lot actually. I have state changes in other parts of my code, it just looks much uglier and it doesn't use booleans. So my code would have worked if it included this before the buttonstate was read?

So my code would have worked if it included this before the buttonstate was read?

We would have to see what you mean by looking at actual code.

Enjoy your new hobby.

Always: