Timing a digital input. Please can I have Advise.

Dear All,

I woundered if it is possibal to time a digital input and if so how i would go about doing it.

I.e

If pin 12 is high for 30sec do something

else do this.

Thanks for any help given.

Kind regards

Mark

I woundered if it is possibal to time a digital input

Yes.

how i would go about doing it.

Lots of ways. If it is a long time like 30 seconds then copy the value of the millis() timer into an unsigned long variable when the pin first goes high. Then when it goes low subtract this variable from the time given by millis() to get how many milli seconds the pin has been high.

https://www.arduino.cc/en/Reference/Millis

Thank you for the reply, I think I understand and thank you for the link I will try and get my head around this :confused:

Sorry Im a bit confused, I understand and can see how i would start a timer when the pin goes high but im lost on how to stop the timer I.e when it goes low and how to compare.

Sorry i know this is simpal im just being a bit slow.

Kind regards

Mark :confused:

You do not stop the timer at the end, you subtract the start time from the current time to get the duration.

Grumpy_Mike,

Ok i see what you mean. I have set up a basic code that logs the time that the pin is high. but im un sure on how to subtract the values when it goes low and compare. can you point me in the right direction?

  if (switchState == HIGH) 
  {
    Serial.print("     Time: ");
    time = millis();
    Serial.println(time);
    logfile.print(", ");
    logfile.print("-open-");
    Serial.print("-open-");
  }

Kind regards

Mark

Can you follow this? Capture the start time, capture the end time, do the subtraction. I added a flag to indicate whether the timer is running so it doesn't keep restarting itself once started, it just looks for the end.

// declare variables, etc.
void setup(){
Serial.begin(9600);
pinMode (switchpin, INPUT);
}
void loop(){
if (timerRunning == 0 && digitalRead(switchPin) == HIGH){
startTime = millis(); //  micros() for really short events
timerRunning = 1;
}
if (timerRunning == 1 && digitalRead (switchPin) == LOW){
endTime = millis();
timerRunning = 0; // reset for next capture
Serial.print ("elapsed time in mS = ");
elapsedTime = endTime - startTime;
Serial.println (elapsedTime);
}
}

If you want to ensure that a digital pin stays HIGH (or LOW) throughout a given interval this piece of code should do it

btnVal = digitalRead(btnPin);
if (btnVal == HIGH) {    // assumes btn is LOW when pressed
   lastBtnPressMillis = millis();   // btn not pressed so reset clock
}
if (millis() - lastBtnPressMillis > = interval) {
   // button has been pressed for longer than interval
}

At first glance it may seem that the logic is back to front - but try it.

...R

Thank you both for your help and advice, im currently trying crossroads solution but my program is telling me that the ‘timerRunning’ was not declared in this scope.

What dose that mean any ideas where i have gone wrong. I can post the pull code for the progect but the timing is jst a small part.

regards

Mark

i have got rid of my error message, it was a semi colon missing. :)

I have used Cross roads code but i cant seem to get the else statment to work, any ideas.

   if (timerRunning == 0 && digitalRead(gateMotoropen) == HIGH){
startTime = millis(); //  micros() for really short events
timerRunning = 1;
 }

if (timerRunning == 1 && digitalRead (gateMotoropen) == LOW){
endTime = millis();
timerRunning = 0; // reset for next capture
elapsedTime = endTime - startTime;

if (elapsedTime >= 30000)
{
Serial.print ("Gate Fully Open");
}
else
{
Serial.print ("-Obstacle Detect ");
}
Serial.print ("(Time for Gate to Open = ");
Serial.print (elapsedTime);
Serial.print ("mS)");
logfile.print(", ");
logfile.print(elapsedTime);

sireal monitor shows the time and the result.

22/1/2016 18:56:19-Gate opening- 22/1/2016 18:56:20-Gate opening- 22/1/2016 18:56:21-Gate opening- 22/1/2016 18:56:22-Gate opening- 22/1/2016 18:56:23-Gate opening- 22/1/2016 18:56:24-Gate opening- 22/1/2016 18:56:25-Gate opening- 22/1/2016 18:56:26-Gate opening- 22/1/2016 18:56:27-Gate opening- 22/1/2016 18:56:28-Gate opening- 22/1/2016 18:56:29-Gate opening- 22/1/2016 18:56:30-Obstacle Detect (Time for Gate to Open = -31536mS)

the sireal monitor should be showing "Gate Fully Open"

What am i doing wrong?

thanks

Mark

What am i doing wrong?

You are not posting ALL your code, so we can't see the whole of what you are doing.

but im un sure on how to subtract the values when it goes low and compare.

Well CrossRoads showed you one way. I was more of thinking just using

elapsedTime = millis() - start time;

Hi Grumpy_Mike and All,

Yes i see what you mean about not posting all of the code so below you will find the full cod.
It is for a gate data logger that is printing to sireal and an sd card.

It is all working exsept the timmers, if only one is used and the “int” for the timer is put in global (top of the code that is // out) then it will works fine but only upto about 15second anything longer and it gets confused.

My issue is that i need to use two timer one for motor open and one for motor closed.
as soon as i add the second timer the code dose not see the if/else statments and dose not loge a time.

any help is much apriceated.

Mark

#include <SD.h>
#include <SPI.h>
#include <RTClib.h>
#include <Wire.h>


/*
int timerRunning = 0;
int startTime = 0;
int endTime = 0;
int elapsedTime = 0;
int timerRunning1 = 0;
int startTime1 = 0;
int endTime1 = 0;
int elapsedTime1 = 0;
*/
int switchState = 0;

                                  // how many milliseconds between grabbing data and logging it. 1000 ms is once a second
#define LOG_INTERVAL  1000        // mills between entries (reduce to take more/faster data)

                                  // how many milliseconds before writing the logged data permanently to disk
                                  // set it to the LOG_INTERVAL to write each time (safest)
                                  // set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to 
                                  // the last 10 reads if power is lost but it uses less power and is much faster!
#define SYNC_INTERVAL 1000        // mills between calls to flush() - to write data to the card
uint32_t syncTime = 0;            // time of last sync()

#define ECHO_TO_SERIAL   1         // echo data to serial port
#define WAIT_TO_START    0         // Wait for serial input in setup()

// the digital pins that connect to the LEDs
#define redLEDpin 2
#define greenLEDpin 3

// The analog pins that connect to the sensors
#define gateOpenpin 22                  // digital pin 22
#define gatePhotopin 23                // digital pin 23
#define gateMotoropen 24                // digital pin 24
#define gateMotorClose 25              // digital pin 25


//int lastPhotoState = LOW;
//int lastOpenState = LOW;



RTC_DS1307 RTC; // define the Real Time Clock object

// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10; 

// the logging file
File logfile;

void error(char *str)
{
  Serial.print("error: ");
  Serial.println(str);
  
  // red LED indicates error
  digitalWrite(redLEDpin, HIGH);

  while(1);
}

void setup(void)
{
  Serial.begin(9600);
  Serial.println();
  
  // use debugging LEDs
  pinMode(redLEDpin, OUTPUT);
  pinMode(greenLEDpin, OUTPUT);
  pinMode(gateOpenpin, INPUT);
  pinMode(gatePhotopin, INPUT);
  pinMode(gateMotoropen, INPUT);
  pinMode(gateMotorClose, INPUT);
  
#if WAIT_TO_START
  Serial.println("Type any character to start");
  while (!Serial.available());
#endif //WAIT_TO_START

  // initialize the SD card
  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT); 
  
  // see if the card is present and can be initialized:
  if (!SD.begin(10, 11, 12, 13)) {
    error("Card failed, or not present");
  }
  
  Serial.println("card initialized.");
  Serial.println("GateLogger By Kinetic Automation"); // company branding
  
  // create a new file
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (! SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE); 
      break;  // leave the loop!
    }
  }
  
  if (! logfile) {
    error("couldnt create file");
  }
  
  Serial.print("Logging to: ");
  Serial.println(filename);

  // connect to RTC
  Wire.begin();  
  if (!RTC.begin()) {
    logfile.println("RTC failed");
#if ECHO_TO_SERIAL
    Serial.println("RTC failed");
#endif  //ECHO_TO_SERIAL
  }
  
  logfile.println("Site Address:,7 Ha'penny Dell Waterlooville "); // Type in the site address hear
  logfile.println("Site ID, 001:");
  logfile.println(" Date,  Time,  LOG ENTRY");    
#if ECHO_TO_SERIAL
  Serial.println("  Date  ,   Time  , LOG ENTRY");
#endif //ECHO_TO_SERIAL
 
}


void loop(void)
{
  DateTime now;

  // delay for the amount of time we want between readings
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
  
  digitalWrite(greenLEDpin, HIGH);
  
  // fetch the time
  now = RTC.now();
  logfile.print(now.day(), DEC);
  logfile.print("/");
  logfile.print(now.month(), DEC);
  logfile.print("/");
  logfile.print(now.year(), DEC);
  logfile.print(" ");
  logfile.print(", ");
  logfile.print(now.hour(), DEC);
  logfile.print(":");
  logfile.print(now.minute(), DEC);
  logfile.print(":");
  logfile.print(now.second(), DEC);
  
  


#if ECHO_TO_SERIAL
  
  Serial.print(now.day(), DEC);
  Serial.print("/");
  Serial.print(now.month(), DEC);
  Serial.print("/");
  Serial.print(now.year(), DEC);
  Serial.print(" ");
  Serial.print(now.hour(), DEC);
  Serial.print(":");
  Serial.print(now.minute(), DEC);
  Serial.print(":");
  Serial.print(now.second(), DEC);

  
#endif //ECHO_TO_SERIAL

   switchState = digitalRead(gateOpenpin);
 
  if (switchState == HIGH) 
  {
    logfile.print(", ");
    logfile.print("-OPEN-");
    Serial.print("-OPEN-");
  }
 
   switchState = digitalRead(gatePhotopin);
 
  if (switchState == HIGH) 
  {
    logfile.print(", ");
    logfile.print("-Photo Cell-");
    Serial.print("-Photo Cell-");
  }
  
  switchState = digitalRead(gateMotoropen);
  
   if (switchState == HIGH) 
  {
    logfile.print(", ");
    logfile.print("-Gate Opening-");
    Serial.print("-Gate Opening-");
  }
  
int timerRunning = 0;
int startTime = 0;
int endTime = 0;
int elapsedTime = 0;
   
   if (timerRunning == 0 && digitalRead(gateMotoropen) == HIGH){
startTime = millis(); //  micros() for really short events
timerRunning = 1;
 }

if (timerRunning == 1 && digitalRead (gateMotoropen) == LOW){
endTime = millis();
timerRunning = 0; // reset for next capture
elapsedTime = endTime - startTime;

if (elapsedTime >= 10000)
{
Serial.print ("Gate Fully Open");
}
else
{
Serial.print ("-Obstacle Detect on Opening ");
}
Serial.print ("(Time for Gate to Open = ");
Serial.print (elapsedTime);
Serial.print ("mS)");
logfile.print(", ");
logfile.print(elapsedTime);
}


switchState = digitalRead(gateMotorClose);
    
   if (switchState == HIGH) 
  {
    logfile.print(", ");
    logfile.print("-Gate Closing-");
    Serial.print("-Gate Closing-");
  }
   
int timer1Running = 0;
int startTime1 = 0;
int endTime1 = 0;
int elapsedTime1 = 0;

   if (timer1Running == 0 && digitalRead(gateMotorClose) == HIGH){
startTime1 = millis(); //  micros() for really short events
timer1Running = 1;
 }

if (timer1Running == 1 && digitalRead (gateMotorClose) == LOW){
endTime1 = millis();
timer1Running = 0; // reset for next capture
elapsedTime1 = endTime1 - startTime1;

if (elapsedTime1 >= 10000)
{
Serial.print ("Gate Fully Closed");
}
else
{
Serial.print ("-Obstacle Detect on Closing ");
}
Serial.print ("(Time for Gate to Close = ");
Serial.print (elapsedTime1);
Serial.print ("mS)");
logfile.print(", ");
logfile.print(elapsedTime1);
}
  
  
  logfile.println();
#if ECHO_TO_SERIAL
  Serial.println();
#endif // ECHO_TO_SERIAL

  digitalWrite(greenLEDpin, LOW);

  // Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
  // which uses a bunch of power and takes time
  if ((millis() - syncTime) < SYNC_INTERVAL) return;
  syncTime = millis();
  
  // blink LED to show we are syncing data to the card & updating FAT!
  digitalWrite(redLEDpin, HIGH);
  logfile.flush();
  digitalWrite(redLEDpin, LOW);
  
  }

The way your code is written the values of

int timerRunning = 0;
int startTime = 0;
int endTime = 0;
int elapsedTime = 0;

are set to 0 every time loop() repeats - is that what you want?

I would expect loop() to be repeating hundreds or thousands of times per second.

If you want the values to be remembered between iterations of loop() either use global variables (defined at the top of the program) or add the word static for local variables defined in loop()

static int timerRunning = 0;

...R

wow thanks Robin2, the "static int" seems to have fixed the issue, well at the moment the timer is back i need to run some more tests but i think that may have just solved my probleam.

thanks so much.

Mark :)