Counting using Atmega328

I have been playing with the counters on the chip

code looks like this

 byte Counts;
int Counts1;
volatile unsigned long timing; 




void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);       
  Serial.println("Counter");
}

void loop() {
  // put your main code here, to run repeatedly:

if (millis() > timing + 500){ 
  Counts = TCNT1 ;
  Serial.println((unsigned int)Counts);
  timing = millis();
}

}

the input pin is D5 and it has a floating wire on it so it is counting randomly

the output is a series of numbers that never goes above 250

am i right to assume the counter has overflowed - how do I know if it has overflowed and how many times it has done so

You haven't been playing with the counter, its still set up to drive 8-bit PWM on pins 9 and 10,
so its counting at 250kHz continuously (prescaler set to divide-by-64).

You have to configure the counter to the relevant counter mode first, and then you'll get
the benefit of it actually reading the T1 pin and counting modulo 2^16.

Ok that sounds more like it

What do i have to do to initalize the counters ?

Is it me or is this a topic that is not very well explained in arduino ?

basically i have been using interrupts on the arduino to count a digital pulse

the interrupt increases a variable every time and i can count the number of pulses

the AVR counters do seem a more suited approach and will not affect the main loop or cause it to be 'interrupted'

it appears this subject is not really arduino related but more AVR specific

what i really need to learn is how to set up the arduino so it can use the counters and then how to read them and also how to know if it has overflowed

Nick Gammon has done a great job with some example code here -- Gammon Forum : Electronics : Microprocessors : Timers and counters

what i really need to learn is how to set up the arduino so it can use the counters and then how to read them and also how to know if it has overflowed

what do all the codes like 'TCCR2A = bit (WGM21) ;' mean

is there a beginners reference for this information ?

Thank you for the info and link

I am moving up in the world of microprocessors !

some light reading - i think not LOL

a few questions

is an "Output Compare Registers" a bit like a interrupt or an event ?

if i start to change the operation of the timer/counters will features that i am using like millis and analogue write stop working ?

"Yes absolutely, if you start messing with the timers then other things may stop working. For example, if you hijack the timer 0 overflow interrupt then millis and delay will no longer work. "

if i just want to count the pulses from a 5v digital input on timer one - will everything still work ok ?

does CTC means counting mode ?

will this set counter1 up ready to go ?

" TCCR1A = bit (WGM21) ; // CTC mode"

Thanks for the info Delta

the plan is to count pulses on 2 channels at up to 6khz each

then 2 more channels at a much lower frequency

i do some calcs based on the numbers and send it to the serial port

if it is too much for a single atmega i guess i can get two of them talking together

i found a good tutorial here

http://www.engblaze.com/microcontroller-tutorial-avr-and-arduino-timer-interrupts/

i have some code that is counting pulses and overflows on pin 5

byte Counts;
int Counts1;
int LEDPIN;
volatile unsigned long timing; 
unsigned long overflowCount;

ISR (TIMER1_OVF_vect)
  {
  ++overflowCount;               // count number of Counter1 overflows  
  }  // end of TIMER1_OVF_vect



void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);       
  Serial.println("Counter program");
  //TIMSK1 = bit (TOIE1);
  TCCR1A = bit (WGM21); // set to ctc
  TIMSK1 = bit (TOIE1);   // interrupt on Timer 1 overflow
  //TIMSK2 = bit (OCIE2A); // set interrupt
  //OCR2A  = 124;     // count up to 125  (zero relative!!!!)
  TCCR1B =  bit (CS10) | bit (CS11) | bit (CS12);  // External clock source on T1 pin (D5). Clock on rising edge.
  
  LEDPIN = 13;
}

void loop() {
  // put your main code here, to run repeatedly:

if (millis() > timing + 500){ 
  Counts1 = TCNT1 ;
  Serial.print((unsigned int)overflowCount);
  Serial.print("--");
  Serial.println((unsigned int)Counts1);
  timing = millis();
  digitalWrite(LEDPIN, !digitalRead(LEDPIN));
}


}

what is interesting is that the counter seems to count up to approx 500 and then down again before an overflow

its been hard to get my head round all these bits and codes that do not really mean anything

I guess its a part of arduino that needs a library

what is interesting is that the counter seems to count up to approx 500 and then down again before an overflow

Not when I tested your code:

Counter program
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62
0--62

What Arduino do you have?

overflowCount is always zero, because you haven't enabled interrupts for that counter.

Gadget999:
I guess its a part of arduino that needs a library

The trouble with libraries is (useful though they often are) something like counters can be used in many ways. You can count pulses, you can time things, you can do PWM output, you can use interrupts, or not, you can use the Input Capture Unit.

If someone wrote a library that handled all that, you would spend as much time working out how to use the library, as you would simply working out how to use the timer in the first place, from the datasheet.

Hi Nick - thanks for taking a look

the board is a Uno (not a clone)

this is the output to the serial monitor

8--242
9--481
10--193
10--150
11--510
12--274
13--52
13--496
13--505
13--480
13--479
13--479

here is the code again

byte Counts;
int Counts1;
int LEDPIN;
volatile unsigned long timing; 
unsigned long overflowCount;

ISR (TIMER1_OVF_vect)
  {
  ++overflowCount;               // count number of Counter1 overflows  
  }  // end of TIMER1_OVF_vect



void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);       
  Serial.println("Counter");
  //TIMSK1 = bit (TOIE1);
  TCCR1A = bit (WGM21); // set to ctc
  TIMSK1 = bit (TOIE1);   // interrupt on Timer 1 overflow
  //TIMSK2 = bit (OCIE2A); // set interrupt
  //OCR2A  = 124;     // count up to 125  (zero relative!!!!)
  TCCR1B =  bit (CS10) | bit (CS11) | bit (CS12);  // External clock source on T1 pin (D5). Clock on rising edge.
  
  LEDPIN = 13;
}

void loop() {
  // put your main code here, to run repeatedly:

if (millis() > timing + 500){ 
  Counts1 = TCNT1 ;
  Serial.print((unsigned int)overflowCount);
  Serial.print("--");
  Serial.println((unsigned int)Counts1);
  timing = millis();
  digitalWrite(LEDPIN, !digitalRead(LEDPIN));
}


}

overflowCount should be volatile. timing should not be.

Thank nick

The counter still counts up to just past 500 and back down again before it overflows

does anyone have any suggestions ?

i guess i have set the counter up wrong

i will study the code -

" TCCR1B = bit (CS10) | bit (CS11) | bit (CS12); // External clock source on T1 pin (D5). Clock on rising edge."

is there a performance gain using the avr counter or do you think an interrupt using normal arduino code is sufficient ?

I guess the answer is the counter can perform asynchronously and will never stop code executing

The counter will be better for high frequencies. Using an interrupt has an overhead of 4 to 5 µS, whereas the hardware counter can count up to the clock speed.

some more resources