Timer1/Counter1 Issue

Hey all,

I am using an arduino with an ATmega326p. I am trying to count pulses of a signal to determine its frequency. Counter1 is used for that and for frequencies under 256 Hz it works great, no problem at all. However, as soon as I hit 256 Hz the display starts to display less (@255 it shows 255, @256 is shows 254, @257 it shows 253…). I use unsigned ints as suggested by the controllers datasheet (section 15.3 explains how to read the 16bit counter register TCNT1).
Bottom line is that counter1 should be able to count to 65536 and I’m only getting values as high as 255.

Attached is the code I’m using.
Any ideas why this is happening??
I checked a lot of forum posts as well as other example code online. To me it seems that I do everything right, but I’m sure that I missed something.

Setup function

void setup() {
        SetupTimer1();                      //Setup Timer1 for input counting
        SetupTimer2();                      //Setup Timer2 for time counting
        sei();
        lcd.begin(20,4);
      oldSecond = second;
        pinMode(pulsePin,INPUT);
        Serial.begin(9600);
}

Loop

void loop() {
  if (oldSecond != second) {    
    Disp_Time();                  //Display Time
    Disp_Speed();                 //Disply Frequency
    oldSecond = second;
  }
}

This is where Timer1 is setup

void SetupTimer1(){
  TCCR1B |= (1<<CS10) | (1<<CS11) | (1<<CS12);                        // Use external clock (T1)
  TCCR1B &= ~((1<<ICNC1) | (1<<ICES1));                               // Disable input capture
  TCCR1B &= ~((1<<WGM12) | (1<<WGM13));                               // Use normal mode
  TIMSK2 &= ~((1<<ICIE1) | (1<<OCIE1B) | (1<<OCIE1A) | (1<<TOIE1));   // Disable all interrupts
  RESET_TIMER1;
}

Here’s where I read the counter value

void Disp_Speed(){
    cli();
    counter = (unsigned int)TCNT1;
    sei();
    RESET_TIMER1;
    lcd.setCursor(0,1);
    lcd.print("Frequency: ");
    lcd.print(counter);
}

Timer2 is used to execute the code in the loop function every second. Once it overruns, it will increment the seconds variable which will then cause the code to be executed.

Can't help you with your code as I'm not up on low level register stuff. However there might be a simpler way to determine the frequency of a input pulse stream using the pulseIn() function. If you determine the pulseIn LOW time and then the pulseIn HIGH time, add them together you will have the pulse period. The frequency can be calculated as the simple reciprocal of the period. Might be worth a check out.

http://arduino.cc/en/Reference/PulseIn

Lefty

I am aware of the PulseIn function. Actually, I considered using it at first, but I don't like the delay that it introduces. If I understand it correctly, PulseIn waits until it detects a transition to low or high. Since I'm using timer2 with its overflow interrupt for a timed sensor read, I was afraid that it might screw with the pulseIn function if the interrupt fires in the wrong moment. Using the hardware to count the pulses for me seems to be a lot better and won't slow the process down. Other than that I agree with you that pulseIn might be easier to use.

Any other suggestions?

Set WGM11 and WGM10 to zero in TCCR1A.

@Coding Badly: Awesome, that fixed it!! Would you mind explaining why they need to be set to zero? According to the datasheet they are initially zero. Now the first thing I do in my setup function is setting them to zero. Can they be automatically set to one when other bits are set unless you specifically write a zero in that location?

Thanks a lot

You are welcome.

The core sets Timer1 to a PWM mode (before setup is called). The code of interest is in…

{Your Arduino Install Directory}\hardware\arduino\cores\arduino\wiring.c