I'm using it for simple time delay, where the actually timing of the delay isn't critical, I just want to slow things down (taking an anologue reading every second or two, instead of dozens a second).
the amount of time you need to wait until the bouncing is over needs to be fixed to a minimum, not dependant on what was the millis() value when you pressed..
If you don't care whether the delay is mostly 50, sometimes longer and that in your program you can afford the time to calculate the modulus then feel free to use it
You define an unsigned long as the timing variable.
This enables to have multiple timers without interferring with each other.
void PrintFileNameDateTime()
{
Serial.println("Code running comes from file ");
Serial.println(__FILE__);
Serial.print(" compiled ");
Serial.print(__DATE__);
Serial.print(" ");
Serial.println(__TIME__);
}
boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - periodStartTime >= TimePeriod )
{
periodStartTime = currentMillis; // store new snapshot of time as the new periodStartTime
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // not expired
}
unsigned long MyTestTimer = 0; // variables MUST be of type unsigned long
const byte OnBoard_LED = 2;
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
digitalWrite(IO_Pin,!digitalRead(IO_Pin) );
}
}
void setup() {
Serial.begin(115200);
Serial.println("Setup-Start");
PrintFileNameDateTime();
}
//#define debugTxtVar(abc, def) Serial.print("< "#abc" = "); Serial.print(def); Serial.println('>')
// using the #define "statement" to make the compiler "write" code
// #define can be used to make the compiler replace text that describes something with (almost) anything else
// easy example
// let's assume IO-pin number 4 shall be set to work as output
// the command for defining an IO-pin to be configured as output is
//
// pinMode(4,OUTPUT);
// the number "4" says nothing about he purpose of this IO-pin
// let's assume the IO-pin shall switch On/Off a buzzer
// you would have to add a comment to explain
// pinMode(4,OUTPUT); // IO-pin 4 is buzzer
// the compiler needs the number. To make the code easier to read and understand
// #define BuzzerPin 4
// So the command looks like this
// pinMode(BuzzerPin,OUTPUT);
// the descriptive word "BuzzerPin" gets replaced through the compiler by a "4"
// so what the compiler compiles is still 'pinMode(4,OUTPUT);'
// the #define can do much more than just replace a word by a single number
// it can even take parameters like in this example
#define debugTxtVar(myParameterText, variableName) \
Serial.print(#myParameterText " " #variableName"="); \
Serial.println(variableName);
int myVar = 1234;
int mySecondVar = 999;
void loop() {
BlinkHeartBeatLED(OnBoard_LED,250);
if ( TimePeriodIsOver(MyTestTimer,1000) ) {
debugTxtVar("first line " , myVar);
mySecondVar++;
debugTxtVar("second line" , mySecondVar);
}
}
That first argument should be called "startTime" or something like that, since it's storing the beginning of your timing interval rather than the end of it. Naming is important!
if you look at the code, that parameter gets updated at the end of the delay with the time when the period was really over so whilst it's the start time when you call, it returns the expiration time.
the original example naming currentMillis and previousMillis is very elegant, two millis values are subtracted and compared to an interval
periodStartTime is not a classical time (what you read on a watch), I try to limit "time" in variable names for values containing actual time
the function TimePeriodIsOver has a return value and has side effects (changing periodStartTime) that are not obvious from the name. The function name suggests only the return parameter is "changed".
you used the Arduino naming convention for some of your code and your own style for other parts
While we can argue details of name choices and such, I really don't understand why the "how to use millis()" tutorials seems to be so hesitant to include such a function instead of scattering the logic all around...
I think that all examples are written to make people think about the approach. If you would give people a function that could be copied blindfolded, only a few of them will take the time to learn how it works. And Arduino is all about learning
Yes for using microcontrollers you have to learn. How much learning through going deeper and deeper into the code is the users decision. And to me there is only a gradual difference for each and every "going deeper". @Klaus_K how deep did you go into libraries like "wire.h/.cpp", "lcdgfx.h/.cpp", "hardwareserial.h/.cpp" etc. etc. I guess there were many libraries yiu were just using. There are only a few really "hardcore" coders that go down to the last line of the core-code.
About keeping conventions: there seems to be an unwritten "convention" to reduce documentation in the source-code to a bare minimum. To me this seems to be an attitude of "if you want to use it learn it (almost) from scratch yourself". I did not include a full tutorial as a block comment but there is quite some comments in my function.
Adding more comments enables learning "on the fly"
If it directly involves the microcontroller, I do dig quite deep at occasion.
Those are the ones that write libraries for hardware like graphic displays
When I have time to spend on helping a user here on the forum, I try to document every line of code; that includes the obvious because one never knows who will find a thread or post. If I have to document for myself, I mostly document (in the code) complicated stuff where I might forget why it was implemented that way; this should actually be documented in a separate document, but OK.
Hi @StefanL38,
I listened to some compelling arguments against comments after using verbose comments myself for a long time. I found many arguments to be true for comments in the source code posted especially by beginners. Here are a few arguments I remember from a talk that convinced me:
many comments make the code harder to read
most comments are trivial
many comments are wrong, and the compiler does not check comments
comments get out of sync with the source code
comments are often used as storage for old code
many programmers use comments instead of rewriting the code in a way that it explains itself
because code is read more often than it is written, it is worth spending the time to make it easy to read
There are still good comments that can help others to understand the code. For instance, a high-level description of libraries, classes, interfaces ...
Well, "we" are a bit inconsistent on the idea. We seem happy to ask users to understand and implement pseudo-concurrency by using non-blocking code, or assemble strings as they come in one-byte at a time, but are also convinced that they'll never understand bitmasks well enough to exist without digitalRead()/etc.