Go Down

Topic: Trouble with counter (Read 680 times) previous topic - next topic

brennon

I need a counter for an initialization sequence.  I'm using Timer0, so millis() isn't available to me.  Here's what I have right now:

unsigned long init_counter = 0;

// Inside a Timer/Counter1's ISR:
// Interrupt service routine called to generate PWM compare values
ISR(TIMER1_COMPA_vect) {
  if (init_counter < 50000)
    init_counter++;
}

void setup() {
  Serial.begin(9600);

// To debug:
void loop() {
  Serial.println(init_counter);
}


And here's typical output:

5570660
5570659
5636195
5636195
5636195
5636195
5636195
5636195
5636195
5636194
5570658
5570658
5570658
5570658
5570658
5570658
5570658
5570658
5570651
5570651
5570651
5570651
5570651
5570651
5570651
5570651
5570653
5832797
...


Any idea why my counter is counting up?  Reversing the direction (--init_counter) makes no difference.

Thanks,
Brennon

Nick Gammon


I need a counter for an initialization sequence.  I'm using Timer0, so millis() isn't available to me.  Here's what I have right now:

unsigned long init_counter = 0;

// Inside a Timer/Counter1's ISR:
// Interrupt service routine called to generate PWM compare values
ISR(TIMER1_COMPA_vect) {
 if (init_counter < 50000)
   init_counter++;
}

void setup() {
 Serial.begin(9600);

// To debug:
void loop() {
 Serial.println(init_counter);
}




Results:

Code: [Select]

sketch_feb05e.cpp: In function 'void setup()':
sketch_feb05e:13: error: a function-definition is not allowed here before '{' token
sketch_feb05e:15: error: expected `}' at end of input


Once I add the missing brace, my output is:

Code: [Select]
0
0
0
0
0
0
0
0
0
0
0
0


So, sorry, can't reproduce that. Maybe copy and paste the actual code?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

johnwasser

And don't forget to declare init_counter to be 'volatile'.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

brennon


And don't forget to declare init_counter to be 'volatile'.


Already tried this...doesn't change anything.

brennon

#4
Feb 05, 2012, 04:04 pm Last Edit: Feb 05, 2012, 04:07 pm by AWOL Reason: 1

So, sorry, can't reproduce that. Maybe copy and paste the actual code?


Well, I have to excerpt things--I'm not allowed to post the entirety of the program.  Let me try again:

Code: [Select]
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>

volatile static unsigned long init_counter = 0;

void setup() {
 
 // Disable global interrupts
 cli();
 
 // Setup Timer/Counter1 Control Registers (TCCR1) with the following options:
 //    Timer/Counter Mode of Operation  |  CTC
 //                                TOP  |  OCR1A
 //                 Update of OCR1x at  |  Immediate
 //                   TOV1 Flag Set on  |  MAX
 TCCR1A &= ~(_BV(WGM11) | _BV(WGM10)); // Clear bits WGM11 and WGM10 in TCCR1A
 TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12); // Clear bit WGM13 and set bit WGM12 in TCCR1B
 
 // Setup clock prescaler for TCCR1 as clk_IO/8
 TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS10))) | _BV(CS11);
 
 // Set compare value (OCR1A) to value equivalent to:
 //    F_CPU  = Core clock frequency
 //    PS     = This counter's prescaler value
 //    B      = Base frequency of generated waveform
 //    L      = Wavetable length
 //    C      = Timer compare value
 //    C = F_CPU / (PS * B * L)
 unsigned long ocr1a_divisor = (unsigned long) 8 * 100 * 100;
 OCR1A = F_CPU / ocr1a_divisor; // Clock Speed / Target Interrupt Frequency (4kHz)
 
 // Enable Timer/Counter1 Output Compare A Match Interrupt
 TIMSK1 |= _BV(OCIE1A);
 
 // The PWM compare-set ISR fires at 8MHz / 8 (prescaler) / OCR1A, or 25.641kHz
 // To have our init settings in place for 5 seconds, we want:
 // init_counter = (F_CPU / 8 / OCR1A) * 1;

 // Re-enable global interrupts
 sei();
 
 Serial.begin(9600);  
}

void loop() {
 while(true) {
   Serial.println(init_counter);
 }
}

// Interrupt service routine called to generate PWM compare values
ISR(TIMER1_COMPA_vect) {

 unsigned long sine_0, sine_1;
 if (init_counter < 50000)
   init_counter++;
}


Moderator edit: CODE TAGS

johnwasser

Very strange.  I put in a 500 millisecond delay and the outputs only come out every 5 seconds.  WTF?

At what rate did you want the interrupts?  4 KHz?

I notice you clear some bits in TCCR1A but leave the other bits unchanged.  How do you assure that the other bits are already set as you desire?
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

PeterH



Well, I have to excerpt things--I'm not allowed to post the entirety of the program.  Let me try again:


Cut down the sketch to a minimum sketch that demonstrates the actual problem, and post that.
I only provide help via the forum - please do not contact me for private consultancy.

brennon




Well, I have to excerpt things--I'm not allowed to post the entirety of the program.  Let me try again:


Cut down the sketch to a minimum sketch that demonstrates the actual problem, and post that.


Did you read the rest of that message?  That's what I did...

brennon


Very strange.  I put in a 500 millisecond delay and the outputs only come out every 5 seconds.  WTF?

At what rate did you want the interrupts?  4 KHz?

I notice you clear some bits in TCCR1A but leave the other bits unchanged.  How do you assure that the other bits are already set as you desire?


Sorry about that--that comment and a couple of others were relics of old code that I missed when trimming.  The other bits in those registered are initialized to zero, according to the Atmel docs, so in actuality, I don't need to manually clear anything at all.  Here's an update:

Code: [Select]
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>

volatile static unsigned long init_counter = 0;

void setup() {
 
  // Disable global interrupts
  cli();
 
  // Setup Timer/Counter1 Control Registers (TCCR1) with the following options:
  //    Timer/Counter Mode of Operation  |  CTC
  //                                TOP  |  OCR1A
  //                 Update of OCR1x at  |  Immediate
  //                   TOV1 Flag Set on  |  MAX
  TCCR1B |= _BV(WGM12); // Clear bit WGM13 and set bit WGM12 in TCCR1B
   
  TCCR1B |= _BV(CS11);  // Setup clock prescaler for TCCR1 as clk_IO/8
 
  unsigned long ocr1a_divisor = (unsigned long) 8 * 100 * 100;
  OCR1A = F_CPU / ocr1a_divisor;
 
  // Enable Timer/Counter1 Output Compare A Match Interrupt
  TIMSK1 |= _BV(OCIE1A);

  // Re-enable global interrupts
  sei();
 
  Serial.begin(9600); 
}

void loop() {
  while(true) {
    Serial.println(init_counter);
  }
}

ISR(TIMER1_COMPA_vect) {
  if (init_counter < 50000)
    init_counter++;
}


With the I/O clock running at 16MHz, OCR1A is set to 200.  So, that ISR should be firing at 10kHz.  (Please feel free to correct my calculation if it's wrong.)  Where were you putting the delay?

Nick Gammon

With the amended code it appears to work for me:

Code: [Select]
48265
48337
48410
48482
48555
48627
48700
48772
48844
48917
48989
49062
49134
49207
49279
49352
49424
49496
49569
49641
49714
49786
49859
49931
50000
50000
50000
50000
50000
50000
50000
50000
50000
50000
50000
50000
50000
50000
50000


That's what you are expecting, right? What board/processor are you using?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

And does the amended code, posted above, behave differently for you?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

johnwasser

I just tried the amended code and it seems to work correctly now for me, too.

Perhaps a comparison between the two would point to the problem.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Go Up