ms timestamp since 2020.

amensch

Well-known member
Hello All,
Been futzing with making a millisecond resolution timestamp for data logging. Thought a good approach would be a millisecond timer since Jan 1, 2020, a sort of 'covid epoch', but in milliseconds. This is running on a Teensy 4.0, but in the step where I multiply times 1000 (to make mS from seconds) it acts like the upper bits are wrapping around & I'm getting unexpected numbers in the bottom 3 decimal places (where I want to put the milliseconds).

Thoughts? Better way to do it? I'd really like to end up with a single 32 bit number which is mS from Jan 2020.

Thank You,
John
Code:
/* This is supposed to generate a sort of 'timestamp since Covid in milli seconds',
 *  starting at Jan 1 2020, and getting rid of the bits you save by subtracting the 
 *  time from Jan 1970 to Jan 2020.  Then that number is supposed to be multiplied * 1000
 *  to become the time in mS, then add to that the number of milliseconds in the Teensy ms timer.
 */
 
#include <TimeLib.h>
void setup() {
  Serial.begin(115200);
  while (!Serial);                // Wait till user opens serial monitor
  Serial.println("setup done, good to print to user.");   
}

// Ref: the date Jan 1, 2020 0h:0m:0s is 1577836800 seconds from epoch Jan 1 1970.
// So from the Jan 1970 epoch start, 50 years, or 1577836800 seconds have elapsed.

void loop() {
  long epochTime = 0;
  time_t tt = Teensy3Clock.get();
  epochTime = tt;  
  Serial.print("epoch = ");                 Serial.print(epochTime); 
  Serial.print("     epoch - 50yrs = ");    Serial.print(epochTime - 1577836800 ); 
  Serial.print("     epoch-50yr*1000 = "); Serial.print((epochTime - 1577836800 ) * 1000); 

  int millis_now = millis() % 1000; // only care about the millis < 1000 

  Serial.print("      with mS added = ");   Serial.println(((epochTime - 1577836800 ) * 1000) + millis_now ); 

  delay(200);
}
 
I feel like I'm missing something obvious, but after a quick glance I got this:

86400 seconds in a day.
That's 86400000 mSecs in a day.
unsigned long is 32 bits, with a maximum value of 4294967295.
4294967295/86400000 ~= 49.7 days. That's the maximum length of time you can count mSecs in an unsigned long before the value wraps. A signed long would only last half as long.

Wouldn't you have to do this with a 'unsigned long long' type and start with the full 64 bits from the RTC and divide that by 32.768 to get mSec?
 
I also feel like I'm missing something obvious, and you may be on to it. The apparent wrap around issue. But even if that is the issue, I would think the 3 LSbits in the epochTime variable after the multiplication would be 000.

Thank You, John
 
If you change that to an unsigned long long and run that program again, what is the output?

If that doesn't fix it, try sprintf() instead of letting Serial.print() figure it out.
 
Pilot is right, Serial.print() does not always work well with big numbers.
Here is a piece of code that shows you how to use sprintf():
Code:
// see https://arduinobasics.blogspot.com/2019/05/sprintf-function.html
// see http://www.cplusplus.com/reference/cstdio/sprintf/

void setup() {
  Serial.begin(115200);
  while (!Serial);
  Serial.println("Serial output started...");
}

void loop() {
  char buffer[30];
  unsigned long long number1 = 12345678901234;
  unsigned long long number2 = number1 * 1000;
  
  sprintf(buffer, "number2 = %llu", number2);
  Serial.println(buffer);

  delay(1000);
}

Paul
 
Back
Top