I recently ran in to an issue at my day job where I had to write some time functions for a project. My work system did not have <time.h> and related functions like gmtime(), which I needed.
Unfortunately, once I implemented my version of gmtime() routine (based on some code I found online), I found it did not work on my target system. Testing on a PC using GNU-C worked fine, so I expected it had something to do with the code not being written for systems with 16-bit “ints” — like the Arduino.
I narrowed down the problematic code, and used the Arduino to test it. Here is the sample:
#define SECS_DAY (24*60*60)
void setup()
{
long time;
unsigned long dayclock;
Serial.begin(9600);
time = 1396342111;
dayclock = (unsigned long)time % SECS_DAY;
Serial.println(time);
Serial.println(dayclock);
}
void loop()
{
}
On the PC, dayclock would print as 31711. On an Arduino, it would print as 18911. Initially I just tried to cast things to “unsigned long” but that did nothing. When I realized my mistake, I felt rather dumb since I learned this long ago.
Numeric constants, like that #define, are treated as “int” values meaning that on the PC (where int is 32-bits) they were different than on my target system (where int is 16-bit).
When dealing with long constants, you add “L” to the number like this:
#define THISISANINT 123456
#define THISISALONG 123456L
To fix my problem, all I did was throw in the Ls:
#define SECS_DAY (24L*60L*60L)
The code I used as reference was written by someone who probably only considered it running on machines with 32-bit ints. Most desktop (PC/Mac/etc.) programmers tend to code this way.
Maybe this reminder will help someone else as they try to port code to an Arduino project.
Side note: Rather than use “int” and “long”, if you use a new enough compiler (C99 standard), include and use the actual type you want, such as uint8_t, uint16_t, or uint32_t. As you can see, “int” on the PC would be 32-bits, and “int” on Arduino (or MSP430, or…) would be 16-bits. It’s not portable code that way, and the C standard has finally solved this challenge.
Here’s another example for you to try… It should print out 86400 (24*60*60), which it does on a PC/32-bit system, but not on a system where ints are 16-bits. Have fun!
// This will fail (ints, 16-bit)
#define SECS_DAY (24*60*60)
// This works (longs, 32-bit)
//#define SECS_DAY (24L*60L*60L)
void setup()
{
Serial.begin(9600);
Serial.println(SECS_DAY);
}
void loop()
{
}