proper way to modify millis functions

update* I found the answer myself through more google work and digging

For anyone interested just declare

extern volatile unsigned long timer0_overflow_count;

and reference "timer0_overflow_count" instead of the millis function

might be best to make your own millis function and disable interupts while reading it like the millis functions does

eg.

unsigned long stable_millis()
{
unsigned long m;
uint8_t oldSREG = SREG;

// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_overflow_count;
SREG = oldSREG;

return m;
}

and just to recap.. the reason to do this would be cause you need

A stable millis() value.. one that does not occasionally skip values(eg.millis will NEVER return 42, 83, etc..)
A stable millis() that will keep the interval between each value the exact same (skips cause a variance in the actual_time/mstime ratio)

but y doing this you accept that your new "stable_millis()" time is 1.024ms per tick. and thus will drift from real time if that is a problem then dont use this method
**

so im controling a motor and using an as5600 mag encoder

I need to create a history of the last 256 readings

I want each record 1 ms apart

so I'm basically doing buffer[millis()&B11111111]

but readings were insane and spiking.. it took me a while to figure out that there is a "missing millisecond" every 42 ms due to FRACT_INC. so there are empty records in my buffer

I want to remove the FRACT counter

I realize this will make millis drift compared to real time.. but i dont care

my questions are
1)will this affect anything else (I am not using any libraries.. just serial and analogRead.. which i don't think should care about the millis timer.. right?)
2)is there proper way to do this (i can just modify the source code in the arduino library.. but i would prefer to change it in a way that only affects this project)

any help greatly appreciated

I realize i could do buffer[(millis()>>1)&B11111111] to get a working 2ms interval buffer.. and i might be willing to accept this.. but i would much prefer to be able to do a smaller interval

follow up

if i also change the overflow to make millis do say .. half a millisecond.. will that affect anything else?

**and fyi.. yes i have modified the adc settings to read high freq

If you remove the fractional part, you will NOT get records exactly one millisecond apart, because the clock ticks 1024 times per second.

yes.. as i said.. i dont care if it is off a little..
the records need to be regular intervals apart and no gaps.. not exactly 1ms apart

vasten:
I realize this will make millis drift compared to real time.. but i dont care

the records need to be regular intervals apart

So, once an hour is good? No need to modify millis() then.

PaulS:
So, once an hour is good? No need to modify millis() then.

1.024 milliis is fine

obviously i want it somewhere around 1 ms :stuck_out_tongue: 1 hour is obviously not ok

**I will be referencing this millis() in various ways to calculate changes and rates..

i dont need them to be based on exactly milliseconds.. but the interval needs to be stable and no gaps

if i do buffer[(millis()>>1)&B11111111]
it would kinda work

but the intervals would be mostly 2.048ms but sometimes 1.024ms.. not a stable interval

DON'T DOUBLE POST

I already answered your other Thread

I am suggesting to the Moderator to merge the Threads

...R

Robin2:
DON'T DOUBLE POST

I already answered your other Thread

I am suggesting to the Moderator to merge the Threads

...R

ok.. sorry and thank you.

but your answer isn't quite what i'm looking for.. i would prefer not use the extra logic required to use the micros counter

1000 would cause overflow problems... but 1024 might work.. but still requires an extra bitshift
(micros()>>10)&B11111111

there is a perfectly good counter already running.. i just want to remove some logic from it.

There must be a simple way of overriding it in one project.. right?

I should also mention

micros() would overflow every hour or so right?

well i still need this tied to an absolute time that will last longer than that.. millis overflow is in the order of months.. thats another reason i want to stick with millis

i just want a millis that does not skip and has regular intervals.. a simple hack.. i just want to know is there is a proper way to modify the arduino library without affecting other projects..

honestly i am considering just modifying the millis permanently because NEVER EVER have I required it to be in any way tied to real time so accurately

i cant imagine now how many times my calculations were screwy because the ms interval was unstable

SOLVED! :smiley: :smiley: :smiley:

see answer added to the top of my first post

vasten:
see answer added to the top of my first post

I seems you have you completely screwed up this Thread for other readers by replacing the text in your Original Post.

Please restore the Original Post to its original text and post your solution after this Reply.

And, from your other Thread ...

what about micros overflow?
that would screw it up..

No it won't screw up. If you use subtraction as in my example you can run the code forever.

...R

Robin2:
I seems you have you completely screwed up this Thread for other readers by replacing the text in your Original Post.

Please restore the Original Post to its original text and post your solution after this Reply.

And, from your other Thread ...

what about micros overflow?

that would screw it up..




No it won't screw up. If you use subtraction as in my example you can run the code forever.

...R

basing it on micros causes ulong rollovers often.. once an hour or so right?

then I need to account for that in all my logic

if I just use a stable version of Millis I overflow well over a month.

...

basically everything worked well until I got below a certain resolution..

I don't care about my code time being tightly tied to real time so much. and it causes sporadic noise in what could be a smooth signal as you approach a certain time resultion.

I found a simple way to stablize that. just use the overflow counter instead of the Millis counter

without any messy timers or interiors.

not the most advanced way..not often needed.. but I nice hack for some moments :slight_smile:

vasten:
basing it on micros causes ulong rollovers often.. once an hour or so right?

then I need to account for that in all my logic

if I just use a stable version of Millis I overflow well over a month.

I think you are not listening ...

If you use millis() and micros() properly (the way I suggested) the fact that they rollover will not matter - the timing will always be correct.

...R

Robin2:
I think you are not listening …

If you use millis() and micros() properly (the way I suggested) the fact that they rollover will not matter - the timing will always be correct.

…R

no because there are more complex calculations happening as well… all using the same time references…

i need one absolute timestamp that can be used across multiple rollovers
and to calculate ranges and rates and positions over time
and I don’t want to add logic lines to detect when 2 records cross roll overs

not to mention the clock cycles

you suggested
if (micros() - prevSampleMicros >= 1000) {
prevSampleMicros += 1000;
// take sample
buffer[record++]=value;
}
vs

buffer[millis()&B11111111]=value;
and I’m using the millis value many times in my loop so the function is called once and stored per loop

so it actually looks like
buffer[mstime&B11111111]=value;

just a mask , a pointer addition, and value load

i suppose i could do
*(buffer_ptr+((micros()>>10)&B11111111))=value;

but still more clock cycles from the shift and messier code
anything else requires if statements… which i would like to avoid if possible

also this way my current buffer value does not wait to update… my loop runs many times per milli. so i can have the current record update several times, run the whole loop several times until it ticks over to the next record.

eg.

time 1ms : buffer[1]=10
//do loop
time 1.4ms :buffer[1]=11
//do loop
time 1.8ms : buffer[1]=12
//do loop
time 2.2ms : buffer[2]=14
//do loop
etc…

there are definite advantage to this method… depending on what you are doing.

I could do a smaller resolution with micros
but 1 milli is just about perfect

this method only breaks down when there are missing milliseconds which produces empty records and variance in the interval

yes my method has a small variance as well due to samples not landing directly on the milli mark

but its less than the 1 tick=1.024ms or 2 ticks=1.024ms that the current ms timer produces

finally
when i do my math on times in other sections of code
I can just use simple > or < logic in ways you cant if you have rollovers

in summary…

yes there are other ways to accomplish this one specific similar results

but for scale-ability and maintainability I would prefer just use a stable millis counter so i can use that value all over the place akin to the way I can use a unix timestamp. I can compare stuff over a month apart before I need to concern myself with rollovers.

I can reuse it all over the place in many projects. allowing me full perfect resolution on a 1.024ms clock that overflows a month and half after boot

and yes… timer interrupts would do the job too… and be more precise…
but right now I dont need that… i just need this… it fulfills a specific scope of requirements quite well and allows elegant simple code

I don't want to add logic lines to detect when 2 records cross a roll over

You really are not listening are you ?

Used properly the millis() and micros() rollover does not cause a problem and no extra logic is needed to deal with it

vasten:
buffer[millis()&B11111111]=value;
and I’m using the millis value many times in my loop so the function is called once and stored per loop

IMHO this is a circular buffer that will get overwritten every time 255 counts. so that get does not matter if millis() overflows or not as your buffer will overwrite itself way before that (millis() being long type)!

UKHeliBob:
You really are not listening are you ?

Used properly the millis() and micros() rollover does not cause a problem and no extra logic is needed to deal with it

ok.. so what about when i check the value compared to something 3 hours ago?

this 256 long buffer is NOT the only thing happeneing

I use the millis val all over the place

I DO know how overflow math works. I am listening.

its you guys who are not listening

1.clock cycles
2. elegance of having a single timestamp that wont overflow for over a month

I can use 1 timestamp for everything, long and short period

sherzaad:
IMHO this is a circular buffer that will get overwritten every time 255 counts. so that get does not matter if millis() overflows or not as your buffer will overwrite itself way before that (millis() being long type)!

yes.. but this buffer is just one part of the code

its just the part that cause me to identify the skipped millis values

this buffer "overflows every 256 millis"

other parts dont

vasten:
I can use 1 timestamp for everything, long and short period

use one of those time modules then if its a "true" timestamp you after. whether you like or not millis() will reset(overflow) once it reached its maximum value.

sherzaad:
use one of those time modules then if its a "true" timestamp you after. whether you like or not millis() will reset(overflow) once it reached its maximum value.

i don't need a real time clock

just a relative tick timer like the overflow counter

millis resents after a month and half

thats fine by me. i think i can expect a reboot at least once a month

so what about when i check the value compared to something 3 hours ago?

What about it ?

I DO know how overflow math works.

So why do you think that a comparison with something that happened 3 hours ago is a problem ?