PDA

View Full Version : I thought this would be simple (average time between 4 switch presses)



HankMcSpank
- 30th October 2011, 20:15
It's not (ok, I'll rephrase...for me it's not!)

Now the high level concept....for a bit of fun (& learning) I'd like to be able to flash some LEDs at the same rate a switch has been manuall pressed (the average of say 4 switch presses), so...

Switch get pressed ....start a timer running.
Switch gets pressed again (1st 'timed press')...store the timer value, clear down the timer
Switch gets pressed again (2nd 'timed press')...store the timer value, clear down the timer
Switch gets pressed again (3rd 'timed press')....store the timer value, clear down the timer
Switch gets pressed again (4th 'timed press')....store the timer value - now add all the timer values & divide by 4- this gives the average count....convert the count into time....use the time to toggle some LEDS?

So what's the problem?

Timer overflows!

If my calculations are correct, even a 16 bit timer at a maximum prescale setting of 8 (@4mhz oscillator), will overflow after 0.524288 seconds - that aint a lot, so then I think ok, let's have an interrupt to track the number of timer overflows too, and then simply use that number multiplied by 65536 and add it to the existing timer count ....that ought to be easy....hmm, maybe not, because if I'm already in an IOC switch interrupt routine, then what happens when the timer overflows?


How should I be approaching this supposedly fun task?!!

HankMcSpank
- 30th October 2011, 23:14
The solution was all too simple (though forced me to go slightly 'off piste')....take the Oscillator down to 1Mhz, which yields about 2 seconds before the 16 bit timer overflows (with a prescaler of 8)


Makes for some interesting calculations in PICBasic though!

rmteo
- 31st October 2011, 00:21
What if you need more than 2 seconds - say 1 minute? Or more? When designing an application think of terms of events that occur in MCU time (microseconds to perhaps a few miliseconds) and those that happen in human time (from seconds to hundreds of hours).

Lowering the clock speed is not the best way to accomplish what you want - it would be like running a car with its brakes applied. Its main use is to lower power consumption. For stuff that happens in MCU time, you use timers in their native mode - just like you described. For human time events, set up a 16-bit timer to interrupt say every 100mS (50,000 counts assuming a full-speed 20MHz clock with a PIC16). In the ISR, increment a 32-bit variable. This will allow you generate delays up to 42,949,672 seconds, 11,930 hours, 497 days. Compare the variable to whatever delay you need (you can have multiple delays), when it matches set a flag that will acted upon appropriately in your mainline code.

rmteo
- 31st October 2011, 00:53
Sorry typo, should be:

set up a 16-bit timer to interrupt say every 10mS

HankMcSpank
- 31st October 2011, 01:03
All good points well made...but what if the maximum time between switch presses is only ever going to be 1 second ...I've therefore got 100% 'headroom' @ 2 seconds.....and what if this was this simple task was the only purpose of the program/PIC .....hey some power consumption 'win' to boot.

I guess where I'm heading, before anyone can decide whether a final solution is 'best' or not, then they'd need to know the full requirements.

I don't agree with the analogy of running a car with the brakes on here ....this is more akin to running the car at very low rpm because that's all that's required! (your family car might be capable of 120mph....but when you go to the corner shop, you're likely going to go there at 30mph, becuase that's 'best' for the situation at hand)

But as ever, there are many ways to skin a cat....and I always welcome all input from those more learned on here!(just about everybody, lol)

Your proposed way sounds good....I'll sleep on it!

prstein
- 1st November 2011, 17:30
Hi Hank,

Late to the game (as usual) and probably haven't read thoroughly enough, but why should that stop me from commenting? 8^)

You said that the times will always be less than 1 second and that the timer can hold just a little more than half a second. Why not clear the overflow flag at the same time you clear the timer. Then when you read the timer also check the overflow flag. If it is set, add $FFFF to your value. The interrupt flags work whether they are used to trigger an actual interrupt or not.

Best Regards,
Paul

HankMcSpank
- 1st November 2011, 18:53
Hi Paul,

Stonking late entry - many thanks!!

Hank.