Sorry but I have no idea what you mean
Please provide a link to the library or your GitHub repository in general
Sorry but I have no idea what you mean
Please provide a link to the library or your GitHub repository in general
To UKHeliBob:
Yes, verified w/ my hex calculator that your snippet in post #24 works too, 0x10 - 0xFFFFFFE0 (masked to low 32 bits) gives 0x30 which would be a perfectly reasonable period. Perhaps that's one permutation of the three values I didn't try. That was nine years ago, after all. Will keep that tidbit in mind for future applications.
To be fair, the code that I posted just used what I know works and which has been the subject of much (much) discussion here over the years. In no way is t my code
I have not examined your solution to deal with rollover to zero as it sounds unnecessarily complicated and I prefer simple solutions. However, as previously requested I would be interested in seeing your version of the BlinkWithoutDelay example using your method
That's a very mature and totally understandable way to deal with criticism.
a7
Glad you like it. ![]()
As it was I who named your code wrong and incorrect, i think i have to answer to all that show.
I'm sorry that you treated my words as a personal abuse. It wasn't my intention.
The only i wanted that you don't give to OP a bad advises.
I'm deeply confident that your "custom method" of treating a millis is result of lacking understanding of the principles of the unsigned arithmetic.
And it is a shame to you of considering science discussion as a personal attack
PS.
I am very sorry to all for my bad English. Unfortunately, it is difficult to use a Google translate from a mobile.
The "unsigned integer arithmetic" behavior that people are describing is dependent on the timer "wrapping" at the same place that the "unsigned int" wraps. Otherwise you have to take additional measures.
I have some "delay_microseconds()" implementations based on the ARM Systick timer, which wraps (on Arduinos, usually) every millisecond, which is an arbitrary count dependent on clock speed. Basically, they figure out ahead of time whether the count will wrap, and modify their decision process accordingly...
by doing so, you destroy the thread of discussion. The result will not help the thread owner @7r0ck3nw4553r in any way.
A brief Github search got the result:
This variable
unsigned long m_nextUpdate; // time of next scheduled update
can be changed to
unsigned long m_lastUpdate; // time of last performed update
and then regular subtraction with no cast or negatives numbers woukd work, I didn't look closely at the code for other implications of this change, but you can tell future or past
if (now - m_lastUpdate < m_updateDelta) {
// the next update is in the future
}
else {
// it is time or past time to do the next update
}
My favorite as a relentless outdenter is to take early returns
if (now - m_lastUpdate < m_updateDelta) return; // notchyet.
// time to do whatever update is
//....
// and note that you have done
m_lastUpdate = now;
a7
The code was jarring, but it was interesting.
unsigned long a = 10000;
unsigned long b = 5000;
void setup() {
Serial.begin(115200);
delay(3000);
// Give them values, then...
if ((long)(b - a) < 0) {
// b is < a
Serial.println("// b is < a");
} else {
// b is >= a
Serial.println("// b is >= a");
}
b += 10000;
// Give them values, then...
if ((long)(b - a) < 0) {
// b is < a
Serial.println("// b is < a");
} else {
// b is >= a
Serial.println("// b is >= a");
}
}
void loop() {
// no Body
}
And OUTPUT:
14:08:23.120 -> // b is < a
14:08:23.120 -> // b is >= a
No need to demolish it. The trick is getting a signed number when comparing unsigned numbers. It might come in handy!
Or you can treat the unsigned value as having no direction where signed values have up and down or right and left, more and less.
It’s not a good idea to mix variable types and in this case I think that to make such a trick work will need more and slower code.
Unsigned numbers are circular like a round clock and work exactly the same. Plus hours moves clockwise, minus hours work CCW. If my end time is 4 and I want to know how many hours have passed since 10, I move the hour hand 10 hours CCW from 4 and the result of 4 - 10 is 6, always correct in 1 step with no if in sight.
Arduino 32 bit clock has over 4 billion steps. The clock at millis speed rolls over in 49.71… Days. The clock at micros speed rolls over in a bit over 70 Minutes.
Why make things complex where an easy way works fine?
In this particular case, when millis overflows, yes, it will work until overflow.
I'm not a C expert, but I'm interested in the fact that unsigned logical operations can produce signed values, so to speak, for the record.
For the record, what you do makes that result.
IF you use signed values to work with time
THEN you will have to write extra lines to handle rollover.
ELSE you can use unsigned math and get it right in one operation.
Oh BTW, Arduino does do 64 bit integer math but the clocks only return 32 bit values. One member here posted clock software that handled that, millis rollover in billions of years.
Why create entities out of thin air? The if(millis() - old_millis >= delta) construct works just fine.
Only if the period desired is less than 49.71 ish days. Otherwise, that's where the 64-bit plan comes in. Surely, an incredibly infrequent edge case, and usually managed otherwise(e.g. using an RTC and thence working in YMD units).
And doing it the "wrong" way, with the cast to get negative values means you can only time 1/2 the interval that the straightforward unsinged subtraction allows.
I woukd prolly not use the technique for anywhere near 25 days anyway, but the same logic obtains in the case of micros(), where the wrong way means 35 minutes max interval.
So it's more complicated and less useful.
a7
Who told you such nonsense?
I think you can find online how to check millis() without waiting 49 days. The millis() topic has been discussed many times before.
If one knows how unsigned math, subtractions, and how you believe casting should work, you can do regular subtractions with no casts or negative numbers:
const unsigned long NEG_THRESHOLD = UINT32_MAX / 2;
const unsigned long interval = 1000;
unsigned long m_nextUpdate; // time of next scheduled update
unsigned long now;
void setup() {
Serial.begin(115200);
m_nextUpdate = 0;
}
void loop() {
now = millis();
if (now - m_nextUpdate > NEG_THRESHOLD) {
// the next update is in the future
return;
}
else {
// it is time or past time to do the next update
Serial.print("Tick ");
m_nextUpdate += interval;
Serial.println(now);
}
}
#include <stdint.h>
extern volatile unsigned long timer0_millis;
const unsigned long NEG_THRESHOLD = UINT32_MAX / 2;
const unsigned long interval = 1000;
unsigned long m_nextUpdate; // time of next scheduled update
unsigned long now;
void setup() {
Serial.begin(115200);
noInterrupts();
timer0_millis = UINT32_MAX -5000+1; // set millis() to just before rollover
interrupts();
m_nextUpdate = timer0_millis + 1000 ;
}
void loop() {
now = millis();
if (now - m_nextUpdate > NEG_THRESHOLD) {
// the next update is in the future
return;
}
else {
// it is time or past time to do the next update
Serial.print("Tick ");
m_nextUpdate += interval;
Serial.println(now);
}
}
The pedantic problem with casting out-of-range unsigneds into signed numbers comes from the difference in the standards pre-C++20 implementation-defined part of Integral Conversions:
- If the destination type is signed, the value does not change if the source integer can be represented in the destination type. Otherwise the result is implementation-defined(until C++20)the unique value of the destination type equal to the source value modulo 2^n
where n is the number of bits used to represent the destination type(since C++20) (note that this is different from signed integer arithmetic overflow, which is undefined).
Normal compilers like gcc/clang/intel use the expected 2s-complement trick of casting out-of-range unsigned into signed numbers, but not all compilers on all architectures must do it the same way.
An awkward thing about translating future-scheduled events conceived as m_nextUpdate events into a m_lastUpdate form is a potential off-by-one error at millis()==0. For instance, if you want an event to happen every N milliseconds starting at 0ms, you can straightforwardly set m_nextUpdate = 0 or you could backdate m_lastUpdate with a wraparound like m_last_update=-N