using watchdog to pass time

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have to know when 2 ms passes in a loop where elapsed code time is not predictable.  The timing is not critical a few 100 us resolution is fine. I was thinking the watch dog could do this for me. How can I check the status of the watch dog? I'd like to avoid interrupts if possible.

 

Something like this, so that my code will run for around 2 ms.

 

init watchdog

while (1)

{

   DoThisCode();// could take from 100 us to 1ms.

   If ( watchdogTime > 2ms ) break

}

 

 

This topic has a solution.
Last Edited: Sun. Sep 9, 2018 - 02:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

S_K_U_N_X wrote:
How can I check the status of the watch dog?

You can't. You can only:
1) reset the watchdog
2) know when the watchdog has expired
As such, you can make an approximately 15ms timer. 2ms is not possible. Use a regular timer/counter.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Timers then. Trying to set up a timer for 1ms @ 16m=Mhz

 

My debug's are .92 us apart. What did I do wrong?

 

                // Set the Timer Mode to CTC
                TCCR0A |= (1 << WGM01);

                // Set the value that you want to count to
                OCR0A = 0xF9;

 

                DEBUG_HI() DEBUG_LO()
                
                 // start the timer
                TCCR0B |= (1 << CS01) | (1 << CS00);
                while(1)
                {
                    if ( (TIFR0 & (1 << TOV0) ) == 0 ) {   TIFR0 |= (1 << TOV0);break;}
                }
                DEBUG_HI() DEBUG_LO()

Last Edited: Sat. Sep 8, 2018 - 09:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

S_K_U_N_X wrote:
My debug's are .92 us apart. What did I do wrong?
Well, at 16 MHz, that's 15 cpu cycles.

 

You haven't mentioned which AVR, but your last thread was about the m328, so let's assume that.

 

Let's look at your while loop:

while(1) {
  if ( (TIFR0 & (1 << TOV0) ) == 0 ) { // True if the overflow flag is NOT set
    TIFR0 |= (1 << TOV0);              // Clears ALL flags, not just TOV0
    break;
  }
}

I've added the comments.

 

Note that in CTC mode, the counter will never get above the value of OCR0A.  Not also that the overflow flag is only set when the timer reaches MAX, which is 0xFF.  So, in your case, the flag will never get set.

 

This, combined with the flaw in the logic of your if() means that the while loop will break immediately.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If I were to use a while when > 0 I guess I could avoid that?

 

while(1) {

 while ( (TIFR0 & (1 << TOV0) ) > 0)        // wait for the overflow event
       {
       }
    TIFR0 |= (1 << TOV0);              // Clears ALL flags, not just TOV0
  }
}

If so am I correct in understanding that setting my compare value to 0x30 would be significantly less? I'm not seeing what I woudl expect here, of does my logic still fail me.

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You missed the part where I said the timer doesn't overflow in CTC mode.

 

What you want is:

while(!(TIFR0 & (1 << OCF0A));

With your original TOP value of 0xF9, the timer period is 0xFA = 250.  With the prescaler of 64, that's 16,000 cpu cycles.  At 16 MHz, that's 1 ms.

 

Changing to 0x30 give TOP = 0x31 = 49 x 64 = 3,136 cycles @ 16 MHz = 196 us.

 

If you want 2 ms, that's 32,000 cpu cycles.  Use a prescaler of 256 and a period of 125, i.e. TOP of 124.

 

Be careful to restart the timer and clear the flag before entering your while:

 

TCCR0A = (1 << WGM01);
TCCR0B = (1 << CS02);
OCR0A  = 124;
.
.
.
DEBUG_HI() DEBUG_LO()

TCNT0 = 0;
TIFR0 = (1 << OCF0A);
while(!(TIFR0 & (1 << OCF0A));

DEBUG_HI() DEBUG_LO()

 

Does your app not already use a timer for general timekeeping?

 

EDIT: corrected prescaler in code block

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sun. Sep 9, 2018 - 03:06 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No the app uses a usb bit bang code (SOE) to keep time. I base the code off of the 8ms poll rate. The usb is interrupt heavy so I needed a software counter way of checking.

 

but yes all is clear now, thx for the help.

Last Edited: Sun. Sep 9, 2018 - 04:35 AM