time difference between opto signals, using TinyGPS library

You already have those digits:

Current Time: 22:41:29

Just combine them. I'm not sure if you are asking a C programming question here or if there is something deeper that I am not getting.

I already combined the time digits, but can't subtract time_start from time_start. Look at the original sketch. When I do that, the output is always "32"

but can't subtract time_start from time_start

You've lost me now. Can you make up a small sketch that demonstrates this?

Hi Nick,

Here's the original (but simplified) sketch:

#include <TinyGPS.h>

TinyGPS gps;
String SD_date_time = "invalid";

int optoPin = A8; //Optocoupler input

static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_date(TinyGPS &gps);

int start_counter = 0;
int current_time_set = 0;
int current_time = 0;
long time_diff = 0;

unsigned long age, date, time, chars;
int year;
byte month, day, hour, minute, second, hundredths;

unsigned long start_second = 0;
void setup()
{

  pinMode(optoPin, INPUT);
  digitalWrite(optoPin, HIGH);
  Serial.begin(115200);	//	 Be sure to set the serial monitor to the same spoeed
  Serial.println("Testing Time lapse.....");
  Serial3.begin(9600);	//(************This is important is the baud rates don't match nothing works******************)



}

void loop()
{
  bool newdata = false;
  unsigned long start = millis();

  char time_start[32];
  char time_stop[32];


  // Every second we print an update
  while (millis() - start < 1000)
  {
    if (feedgps())
      newdata = true;

  }


  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age); // Extract time from GPS

  second++; 
  if (second==60){
    second=0;
    minute++;
  };
  if (minute==60){
    minute=0;
    hour++;
  }

  if(digitalRead(optoPin) == LOW)
  {


    if(current_time_set == 0)
    {
      current_time_set = 1;
      current_time = current_time + second;

    }

    if (current_time_set == 1)
    {



      if(start_counter == 0)
      {
        sprintf(time_start, "%02d%02d%02d   ", hour, minute, second); //GPS UTC Time when opto signal is detected
        start_counter = 1;
        Serial.print("GPS Current Time: ");
        Serial.print(hour);
        Serial.print(":");
        Serial.print(minute);
        Serial.print(":");
        Serial.println(second);
        Serial.print("GPS Time started: ");
        Serial.println(time_start);

        Serial.println("------------------"); 


      }

    }
  } 
  else {

    char time_stop[32];


    if(start_counter == 1)
    {
      sprintf(time_stop, "%02d%02d%02d ", hour, minute, second); //GPS UTC Time when opto signal lost
      start_counter = 0;
      Serial.print("Current Time: ");
      Serial.print(hour);
      Serial.print(":");
      Serial.print(minute);
      Serial.print(":");
      Serial.println(second);
      Serial.print("Time stopped: ");
      Serial.println(time_stop);

      time_diff = time_stop - time_start;

      Serial.print("time_start: ");
      Serial.println(time_start);  
      Serial.print("time_diff :");
      Serial.println(time_diff);      

      Serial.println("------------------"); 


    }

  }
}
/*

 static void gpsdump(TinyGPS &gps)
 {
 
 print_date(gps);
 
 }
 */

/*
static void print_date(TinyGPS &gps)
 {
 int year;
 byte month, day, hour, minute, second, hundredths;
 unsigned long age;
 gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
 if (age == TinyGPS::GPS_INVALID_AGE)
 Serial.print("*******    *******    ");
 else
 {
 char sz[32];
 sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d   ",
 month, day, year, hour, minute, second);
 Serial.print(sz);
 }
 // print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
 feedgps();
 }
 */


static bool feedgps()
{
  while (Serial3.available())
  {
    if (gps.encode(Serial3  .read()))
      return true;
  }
  return false;
}



static void print_time(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
  {
    //Serial.print("*******    *******    ");
    SD_date_time = "invalid";
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d%02d%02d   ",
    hour, minute, second);
    Serial.print(sz);
    SD_date_time = sz;
  }
  //print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  feedgps();
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    //Serial.print(i<slen ? str[i] : ' ');
    feedgps();
}

And here's the output from the Serial Monitor:

Testing Time lapse.....
GPS Current Time: 9:13:42
GPS Time started: 091342

Current Time: 9:17:35
Time stopped: 091735
time_start: 091342
time_diff :32

I need "time_diff" to be "393", in this case, instead of "32". For some unknown reason it's always 32.

I have tried the following options already:

int time_diff = 0;
long time_diff=0;
unsigned long time_diff=0;

or even

int time_diff;
long time_diff;
unsigned long time_diff;

but "time_diff" is always "32"

Your time_stop and time_start variables are both char arrays. Since an array variable actually represents the address of the first element of the array it has a numeric value and the compiler will allow you to compare them, but this pointer arithmetic is meaningless in this context and nothing to do what what you're trying to achieve. If you want to know the interval between two time values you need to have the time values stored as numbers (not strings) and subtract the numeric values.

PeterH:
Your time_stop and time_start variables are both char arrays. Since an array variable actually represents the address of the first element of the array it has a numeric value and the compiler will allow you to compare them, but this pointer arithmetic is meaningless in this context and nothing to do what what you're trying to achieve. If you want to know the interval between two time values you need to have the time values stored as numbers (not strings) and subtract the numeric values.

Hi Peter,

What you're saying makes a lot of sense but I don't know how else to get the time_start and time_stop values from the TinyGPS timestamp. Unless you know of another way?

        sprintf(time_start, "%02d%02d%02d   ", hour, minute, second); //GPS UTC Time when opto signal is detected

I'm confused about what you are wanting here. Hour, minute and second were originally numbers. You turned them into a string with sprintf. Now you want them to be numbers again?

If you want them to be seconds, just multiply hours by 60, then add minutes, multiply by 60 again, and then add seconds.

Ok, maybe I don't understand time conversion very well.

I basically need to know:
a) At which time the opto coupler's signal is detected.
b) At which time the opto couplers signal was lost
c) the time difference between those two events.

Right now I can get the signal detect and lost times, as UTC time in the following format:

hhmmss (or hh:mm:ss)
I used sprintf to concatenate those 3 values, in order to subtract them from each other and get the difference. But I see now where my mistake is....

So, getting back to the original suggestion of using:

johnwasser:
Calculate the time in seconds:

time = ((hours * 60) + minutes) * 60 + seconds;

Then you can subtract old time from new time to get the difference in seconds.

And the other suggestion, of using "unsigned long" which seems to work better:

At first, your explanation to convert the time to HEX confused me and I didn't really see that the conversion is purely converting the whole time stamp (i.e. for example 21:34:18) into seconds. As such, when I tried it, I got an unexpected value back and didn't realize it's just the time stamp, converted into seconds ((hours * 60) + (minutes * 60) + second). But I understand the conversion now and see how it gives me the differences in the start_time and stop_time variables.

Now I just need to find an easy way to convert the seconds back to human readable time, which in itself is proving to be a bit trickier than I thought, probably because the seconds will differ, depending on how long the opto coupler's signal was active.
i.e. sometimes I have "13786" seconds, or "33056" or even "1974" seconds.

Ok, I finally got it working the way I wanted to. Here's the output no the Serial Monitor:

í??yúTesting Time lapse.....
Time started: 8:26:2

Current Time: 8:26:6
Time Started: 30362
Time stopped: 30366
Time Difference in Seconds :4
4s

Time started: 8:27:28

Current Time: 9:30:3
Time Started: 30448
Time stopped: 34203
Time Difference in Seconds :35
1h: 2m: 35s

Time started: 9:30:6

Current Time: 9:36:27
Time Started: 34206
Time stopped: 34587
Time Difference in Seconds :21
6m: 21s

Time started: 9:40:58

Current Time: 9:54:19
Time Started: 34858
Time stopped: 35659
Time Difference in Seconds :21
13m: 21s

Time started: 9:54:21

Current Time: 12:43:51
Time Started: 35661
Time stopped: 45831
Time Difference in Seconds :30
2h: 49m: 30s

And here's the code:

#include <TinyGPS.h>
#include <LiquidCrystal.h>



TinyGPS gps;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
void printFloat(double f, int digits = 2);
String SD_date_time = "invalid";

//int run_time = 0;
int start_counter = 0;


int optoPin = A8;
static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_date(TinyGPS &gps);

int current_time_set = 0;
int current_time = 0;
int secs=0;
int minutes=0;
int hours=0;
long s=0;
long m=0;
long h=0;
long d=0;



//int time_diff=0;
unsigned long start_time;
unsigned long stop_time;


unsigned long age, date, time, chars;
int year;
byte month, day, hour, minute, second, hundredths;

unsigned long start_second = 0;
void setup()
{
  lcd.begin(16, 2);
  //Print a message to the LCD.
  lcd.print("GPS Data Logger");

  pinMode(optoPin, INPUT);
  digitalWrite(optoPin, HIGH);
  Serial.begin(115200);	//	 Be sure to set the serial monitor to the same spoeed
  Serial.println("Testing Time lapse.....");
  Serial3.begin(9600);	//(************This is important is the baud rates don't match nothing works******************)



}

void loop()
{
  bool newdata = false;
  unsigned long start = millis();
  //unsigned long time_diff = 124154;
  unsigned long time_diff = 0;
  char time_start[32];
  char time_stop[32];

  // Every second we print an update
  while (millis() - start < 1000)
  {
    if (feedgps())
      newdata = true;

  }


  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);

  second++; 
  if (second==60){
    second=0;
    minute++;
  };
  if (minute==60){
    minute=0;
    hour++;
  }

  if(digitalRead(optoPin) == LOW)
  {



    if(current_time_set == 0)
    {
      current_time_set = 1;
      current_time = current_time + second;

    }

    if (current_time_set == 1)
    {

      //  char time_start[32];

      if(start_counter == 0)
      {
        //  sprintf(time_start, "%02d%02d%02d   ", hour, minute, second);
        start_counter = 1;
        //start_time = ((hour * 60) + minute) * 60 + second;
        start_time = (((unsigned long) hour * 60UL) + (unsigned long) minute) * 60UL + second;

        Serial.print("Time started: ");
        Serial.print(hour);
        Serial.print(":");
        Serial.print(minute);
        Serial.print(":");
        Serial.println(second);
        Serial.println("------------------"); 

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Start: ");
        lcd.print(start_time);

      }

    }
  } 
  else {

    char time_stop[32];

    if(start_counter == 1)
    {
      sprintf(time_stop, "%02d%02d%02d ", hour, minute, second);
      //stop_time = ((hour * 60) + minute) * 60 + second;
      stop_time = (((unsigned long) hour * 60UL) + (unsigned long) minute) * 60UL + second;
      start_counter = 0;
      Serial.print("Current Time: ");
      Serial.print(hour);
      Serial.print(":");
      Serial.print(minute);
      Serial.print(":");
      Serial.println(second);
      time_diff = stop_time - start_time;


      long d  = time_diff / 86400;    
      time_diff -= d  * 86400; 
      long h = time_diff / 3600;   
      time_diff -= h * 3600; 
      long m  = time_diff / 60;    
      time_diff -= m  * 60; 
      long s  = time_diff; 


      Serial.print("Time Started: ");
      Serial.println(start_time);
      Serial.print("Time stopped: ");
      Serial.println(stop_time);
      Serial.print("Time Difference in Seconds :");
      Serial.println(time_diff);
      if (d > 0)
      { 
        Serial.print(d);
        Serial.print("d: ");
      }

      if (h > 0)
      { 
        Serial.print(h);
        Serial.print("h: ");
      }
      if (m > 0)
      { 
        Serial.print(m);
        Serial.print("m: ");

      }
      Serial.print(s);
      Serial.print("s");
      Serial.println("");
      Serial.println("------------------"); 

      lcd.setCursor(0,1);
      lcd.print("Stop: ");
      lcd.print(stop_time     );

    }

  }
}


static void gpsdump(TinyGPS &gps)
{

  print_date(gps);

}

static void print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
    Serial.print("*******    *******    ");
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d   ",
    month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  // print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  feedgps();
}

static bool feedgps()
{
  while (Serial3.available())
  {
    if (gps.encode(Serial3  .read()))
      return true;
  }
  return false;
}



static void print_time(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
  {
    //Serial.print("*******    *******    ");
    SD_date_time = "invalid";
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d%02d%02d   ",
    hour, minute, second);
    Serial.print(sz);
    SD_date_time = sz;
  }
  //print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  feedgps();
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    //Serial.print(i<slen ? str[i] : ' ');
    feedgps();
}

Thanx for all your help guys!

P.S. Comments an critique welcome