Counter Rollover & Timer Interrupts
- TYelectronics
- Jun 5, 2023
- 4 min read
How to deal with counter rollover. (this is using arduino as reference).
What is counter rollover?
Counter rollover happens when it's value becomes larger then the amount it is allocated in the memory. for example. A two bit counter with two bits of storage would look like this.
count 0 = 00.
count 1 = 01.
count 2 = 10.
count 3 = 11.
See how there is no more space in the memory for the next value 100, as this is three bits long. So in this situation the counter needs to be reset in order to continue counting. so the count would look like
this: 01230123012301230123 and so on.
So now we have a functioning counter. How can we make use of this it?
Lets say we wanted to make something happen every two counts without delaying the rest of the main function. We could say.
if (counter == 1 || counter == 3 ) {
RunCode.
}
This works, but imagine if the counter had 8bits of storage, that's 255 counts, that would mean putting every odd number in that if statement. (not so fun). So this is another way.
Setup StartTime = 0.
if (counter - StartTime == 2){
RunCode.
StartTime = counter.
}
Lets run through the first couple of counts for this statement with an 8bit counter.
count 0 //counter - StartTime = 0 - 0 = 0, code does not run
count 1 //counter - StartTime = 1 - 0 = 1, code does not run
count 2 //counter - StartTime = 2 - 0 = 2, StartTime gets set to 2, code does run
count 3 //counter - StartTime = 3 - 2 = 1, code does not run
count 4 //counter - StartTime = 4 - 2 = 2, StartTime gets set to 4, code does run
count 5 //counter - StartTime = 5 - 4 = 1, code does not run
count 6 //counter - StartTime = 6 - 4 = 2, StartTime gets set to 6, code does run
This will continue until count is 255 at after that the next count will be 0 again. And this is the part that causes the issue. as shown below.
count 253 //counter - StartTime = 253 - 252 = 1, code does not run
count 254 //counter - StartTime = 254 - 252 = 2, StartTime gets set to 254, code does run
count 255 //counter - StartTime = 255 - 254 = 1, code does not run
count 0 //counter - StartTime = 0 - 254 = -254, code does not run
count 1 //counter - StartTime = 1 - 254 = -253, code does not run
count 2 //counter - StartTime = 2 - 254 = -252, code does not run
This will continue forever and the code will never run again until it is turned off and on again.
So what do we need to fix this?
We need something to check to see if the value of the counter minus the last counter value is less then 0, because if it is the counter has not incremented upwards. If it is less then 0 we need to reset StartTime and make it equal to counter. We need something like this running every count to check for this occurrence.
if (counter - lastCount < 0){
StartTime = counter.
}
lastCount = counter.
Lets run through what we just looked at but incorporating this new statement.
count 253 //counter - lastCount = 253 - 252 = 1, lastCount = 253, no rollover
//counter - StartTime = 253 - 252 = 1, code does not run
count 254 //counter - lastCount = 254 - 253 = 1, lastCount = 254, no rollover
//counter - StartTime = 254 - 252 = 2, StartTime gets set to 254, code does run
count 255 //counter - lastCount = 255 - 254 = 1, lastCount = 255, no rollover
//counter - StartTime = 255 - 254 = 1, code does not run
count 0 //counter - lastCount = 0 - 255 = -255, StartTime gets set to 0, lastCount = 0, counter rollover.
//counter - StartTime = 0 - 0 = -254, code does not run
count 1 //counter - lastCount = 1 - 0 = 1, lastCount = 1, no rollover
//counter - StartTime = 1 - 0 = 1, code does not run
count 2 //counter - lastCount = 2 - 1 = 1, lastCount = 2, no rollover
//counter - StartTime = 2 - 0 = 2, StartTime gets set to 2, code does run
count 3 //counter - lastCount = 3 - 2 = 1, lastCount = 3, no rollover
//counter - StartTime = 3 - 2 = 1, code does not run
count 4 //counter - lastCount = 4 - 3 = 1, lastCount = 4, no rollover
//counter - StartTime = 4 - 2 = 2, StartTime gets set to 4, code does run
count 5 //counter - lastCount = 5 - 4 = 1, lastCount = 5, no rollover
//counter - StartTime = 5 - 4 = 1, code does not run
count 6 //counter - lastCount = 6 - 5 = 1, lastCount = 6, no rollover
//counter - StartTime = 6 - 4 = 2, StartTime gets set to 6, code does run
So this bit of analysis shows that we have fixed the issue some what. But as you may have noticed there is a delay of 3 counts between count 254 and count 2 as supposed to just 1 count between each RunCode. This may cause you some issues with really tight timings but in most cases it should be ok and the rollover event doesn't happen that often and also has less of an impact when larger delays are used
i.e. if (counter - StartTime > 1000). //notice how I have used a greater then sign instead of ==, this is used incase this statement does not get run for a couple of counts because the code is doing something else.
This would mean that in the rollover event the delay could be 1003 instead of 1000 which is less of a substantial difference.
Now lets look at the full code all put together in the arduino IDE

Now lets look at a diagram which I made which looks confusing but its a way to visualize all the different variables

Hopefully this makes some sense.
コメント