Author Topic: [arduino] can't subtract two time stamps  (Read 14585 times)

0 Members and 1 Guest are viewing this topic.

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 4395
  • Country: dk
Re: [arduino] can't subtract two time stamps
« Reply #75 on: October 24, 2021, 04:44:17 pm »
Yeah, reading static volatile uint32_t _ulTickCount; is atomic on Cortex-M0+; but if you look at the code, it could be one millisec behind in certain corner cases. I like micros() much better, even if it may iterate a couple of times in those corner cases, because it doesn't just count the interrupts, but uses the counter value that generates the interrupt for better resolution.

you always risk being one behind. You can spin around all you want, the tick could happen right after you decide it's not happend
 

Online Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6177
  • Country: fi
    • My home page and email address
Re: [arduino] can't subtract two time stamps
« Reply #76 on: October 24, 2021, 04:47:36 pm »
The difference is that with millis() you can be a millisecond behind, with micros() a few microseconds behind, because the latter examines the counter used for the systick interrupt.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17729
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [arduino] can't subtract two time stamps
« Reply #77 on: October 24, 2021, 04:54:00 pm »
Right got it. yes that would explain why it didn't work. normally I'd just run a counter on an interrupt..... I'll need ta add a flag variable to say that the tasks have been don already.
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 4395
  • Country: dk
Re: [arduino] can't subtract two time stamps
« Reply #78 on: October 24, 2021, 05:12:52 pm »
The difference is that with millis() you can be a millisecond behind, with micros() a few microseconds behind, because the latter examines the counter used for the systick interrupt.


so when do you stop? when it is atmost 1us? it is a 1ms  timer that is -0,+1ms you could mess about and make it -.5,+.5ms but does that make a difference?
 

Online Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6177
  • Country: fi
    • My home page and email address
Re: [arduino] can't subtract two time stamps
« Reply #79 on: October 24, 2021, 06:01:23 pm »
The difference is that with millis() you can be a millisecond behind, with micros() a few microseconds behind, because the latter examines the counter used for the systick interrupt.
so when do you stop? when it is atmost 1us? it is a 1ms  timer that is -0,+1ms you could mess about and make it -.5,+.5ms but does that make a difference?
At micros(), which uses both the systick counter, and the number of systick interrupts (one every 1ms), of course.  Consider the scale we're working with.

(micros() normally does the loop body only once.  Only when it detects a pending systick interrupt or counter change, does it loop; and then, almost always only one more time.  Additional iterations only occur if interrupted during the looping.  It's quite clever, actually.)

The run-time cost (instructions, median run time, etc.) of micros() is not much more than millis(), and I think the added resolution and smaller jitter is worth it on ATSAMD21 (on all Cortex-M0, M0+, M4, and M7, to be more precise; and on Teensyduino AVRs (AT90USB1280 and ATmega32U4) as they do something very similar, written in efficient assembly).  Don't know about other architectures supported in Arduino, since I haven't looked at them.

Granted, I am assuming sub-second intervals here, used to measure pulses to estimate RPMs, and similar tasks.  For human-scale intervals used for e.g. debouncing buttons and such, millis() is perfectly fine.
« Last Edit: October 24, 2021, 06:05:10 pm by Nominal Animal »
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 9889
  • Country: nz
Re: [arduino] can't subtract two time stamps
« Reply #80 on: October 24, 2021, 10:55:20 pm »
The problem with millis is in the speed calculation which in nested a couple more levels down. When I take that code and put it directly in the if count == 10 it works and displays the speed rather than 0.

Don't get too locked-in to this millis() issue being the problem. 
Yes, I believe you when you say that nesting millis() cause millis() to not work correctly, but that is just a symptom of some other bigger issue, like overwriting memory somewhere.
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4196
  • Country: us
Re: [arduino] can't subtract two time stamps
« Reply #81 on: October 25, 2021, 01:43:19 am »
What retiredfeline said.

Every 2s, your "if (loopcount == 10)" will be true EVERY LOOP until the next time you increment loopcount (ie 200ms), at short intervals.
Because of the way you display your data, you'll probably only see the text generated by the LAST of these display updates.

Easy fix:
Code: [Select]
void loop() {
  if ((millis() - varLastLoopTime) > constLoopIntervalMs) { // check time since last loop counter update
    loopCount ++; // update loop count
    if (loopCount == 10) {
      loopCount = 0; // if loop count has eceeded 10 reset
      task2s();
    }
    varLastLoopTime = millis();
  }
}

Although I'd be inclined to have separate timers for the 2s stuff and the 200ms stuff.  Much more straightforward, and insignificantly more code:
Code: [Select]
boolean periodically (uint32_t *since, uint32_t time) {
  uint32_t currentmillis = millis();
  if (currentmillis - *since >= time) {
    *since = currentmillis;
    return true;
  }
  return false;
}

void loop() {
  static uint32_t timer200ms, timer2s;
  if (periodically(&timer200ms, 200)) {
    task200ms();
  }
  if (periodically(&timer2s, 2000)) {
    task2s();
  }
}
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17729
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [arduino] can't subtract two time stamps
« Reply #82 on: October 25, 2021, 05:26:32 am »
The problem with millis is in the speed calculation which in nested a couple more levels down. When I take that code and put it directly in the if count == 10 it works and displays the speed rather than 0.

Don't get too locked-in to this millis() issue being the problem. 
Yes, I believe you when you say that nesting millis() cause millis() to not work correctly, but that is just a symptom of some other bigger issue, like overwriting memory somewhere.


What retiredfeline said.

However the code written by the student should have worked, but did not, so it looks like there may be something else as he did it differently and certainly not with the trap that I have.
 

Offline macboy

  • Super Contributor
  • ***
  • Posts: 2252
  • Country: ca
Re: [arduino] can't subtract two time stamps
« Reply #83 on: February 22, 2022, 06:17:16 pm »
Although I realize this thread is several weeks old and the issue is likely resolved, I want to add a two important tidbits about using the Arduino millis()

The millis() is incremented once per rollover/overflow of the system timer (Timer0 on AVR commonly). This usually occurs once per 1024 microseconds or 1.024 milliseconds (on AVR). The 0.024 extra ms are accumulated until there is another >=1 ms to add to the millis counter. This means that in one second, the counter only increments 976 (or 977) times, skipping a count approxmately each 42 counts. If you want to do something every say 100 ms, it isn't a big deal. If you want to do something 1000 times (or 500 times etc.) per second, it is a very big deal. If you need accurate short time intervals, use micros() instead. If you need a counter that is approximately 1 ms but never skips a count, you can use the timer 0 overflow counter (look inside the millis() function itself). Beware that it is incremented inside an ISR so make sure to use some form of atomic access (probably disabling and enabling interrupts).

Some have made note of the overflow issue. This can be an issue, but only if you do the comparison in the wrong way. For example, if you directly compare the millis() count to an expected number [e.g. if (millis() > nextCount) ] then overflow will bite you. However, if you cast millis() return value to an unsigned number and subtract the previous timestamp, then compare to some interval, you will not have this issue. For example, if the previous timestamp was 5 less than the maximum (0xFFFFFFFA or 4294967290) and twelve "millis" have elapsed, then millis() returns 6 (0x00000006). Using unsigned 32b numbers, performing (6 - 4294967290) will still give 12, the correct count. This value can then be compared to the desired interval to determine whether to perform some action. Note that if you know for certain that you will check the interval regularly, you can save a few processing cycles and RAM on 8 or 16 bit micros, by using 16b signed numbers to store the present and previous millis() counts. Then that 16 bit representation of millis() will overflow once each ~ 65.5 seconds. If you do this, test your code well; different compilers (and optimization settings) can do unexpected things when casting and performing arithmetic on differently-sized numbers (32b/16b/8b).
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17729
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [arduino] can't subtract two time stamps
« Reply #84 on: February 23, 2022, 03:16:02 pm »
Yea, I solved it, I designed my own !Arduino using a SAMC. I run on a counter firing an interrupt every 100µs. Of course now that I have counter interrupts I can use those instead of convoluted use of a global timer that needs comparing to it's past self to see if it ticked once. For those really short thing I use a flag variable.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf