I was cleaning up my code of magic numbers and added a few #define statements for the frequency values. But after uploading the program to the board I didn't understand why the the colors on the light were not changing at the correct rate. So I added a couple serial output debug prints saw that my frequency was not set properly.
Code
// Time constants
#define SECONDS_PER_MIN 60.0
#define MINUTES_PER_HOUR 60.0
#define SECONDS_PER_HOUR SECONDS_PER_MIN * MINUTES_PER_HOUR
// Cycle time for ColorClock object 0
// Should equal 0.00333____
#define CC0_CYCLE_TIME_HOURS 12.0 / SECONDS_PER_HOUR
//...
Serial.print("SECONDS_PER_HOUR: ");
Serial.println(SECONDS_PER_HOUR);
Serial.print("CC0_CYCLE_TIME_HOURS: ");
Serial.println(CC0_CYCLE_TIME_HOURS);
Serial Output
I was expecting CC0_CYCLE_TIME_HOURS to print as 0.00333 or even 0.00. Why was it printing 12.00??
CC0_CYCLE_TIME_HOURS: 12.00
SECONDS_PER_HOUR: 3600.00
I figured out that it had something to do with my #define statement. I stared at the code for way too long before deciding to do away with the SECONDS_PER_HOUR constant and just hard code the values directly:
#define CC0_CYCLE_TIME_HOURS 12.0 / 3600.00
And this worked, so whatever. I just figured that the Arduino compiler is weird and doesn't treat preprocessor directives the same as gcc. I started writing this post to complain about the Arduino compiler, so to illustrate my point, I coded up the following simple program to compile on my desktop.
Code
#include <stdio.h>
#define SECONDS_PER_MIN 60.0
#define MINUTES_PER_HOUR 60.0
#define SECONDS_PER_HOUR SECONDS_PER_MIN * MINUTES_PER_HOUR
#define CC0_CYCLE_TIME_HOURS 12.0 / SECONDS_PER_HOUR
int main()
{
printf("\nSECONDS_PER_HOUR: %f", SECONDS_PER_HOUR);
printf("\nCC0_CYCLE_TIME_HOURS: %f", CC0_CYCLE_TIME_HOURS);
return 0;
}
But to my surprise, the console output displayed the same value as the Arduino serial out!
Console Output
SECONDS_PER_HOUR: 3600.000000
CC0_CYCLE_TIME_HOURS: 12.000000
The Problem
I stared at the code again and realized that the lack of parenthesis in the definition for SECONDS_PER_HOUR was the source of my problem. The #define macro is a simple find and replace, so what the compiler saw was:
#define SECONDS_PER_MIN 60.0
#define MINUTES_PER_HOUR 60.0
// The compiler sees:
// #define SECONDS_PER_HOUR 60.0 * 60.0
#define SECONDS_PER_HOUR SECONDS_PER_MIN * MINUTES_PER_HOUR
// The compiler sees:
// #define CC0_CYCLE_TIME_HOURS 12.0 / 60.0 * 60.0
#define CC0_CYCLE_TIME_HOURS 12.0 / SECONDS_PER_HOUR
The compiler was basically seeing 12 / 60 60 instead of 12 / (60 60). And because of order of operations, CC0_CYCLE_TIME_HOURS was indeed 12, not the 0.003333 that I was hoping for 🤦♀️
Lesson learned 😳
ความคิดเห็น