problem with frequency counter (using timer 1 and 3)

I use graphic LCD to display the value of frequency.
I modified the code from Arduino frequency counter/duty cycle meter | electronicsblog.net

Interrupt 2 uses Timer 1.
Interrupt 3 uses Timer 2.

Problem:
If signal frequency is higher than about 13Hz, it shows the exact value.
But if the signal is lower than 13Hz, the value is swing between the exact value and another value.

How to fix this problem. It's urgent situation for me.
Signal source is function generator. It works fine.

#include <glcd.h>
#include <fonts/SystemFont5x7.h>

int divider1[6] ={
  0,1,8,64,256,1024};
int divider3[6] ={
  0,1,8,64,256,1024};
int prescaler1=5;
int prescaler3=5;

double count1 =0;
double middle1 =0;
double usage1 =0;

double count3 =0;
double middle3=0;
double usage3 =0;

char x=0;
char y=0;

ISR(TIMER1_OVF_vect) {

  if (prescaler1<4) {
    prescaler1++;
  }

}
ISR(TIMER3_OVF_vect) {

  if (prescaler3<4) {
    prescaler3++;
  }

}

void interrupt1()
{
  if (!x) {
    count1=TCNT1;
    TCNT1=0x000; 
    TCCR1B=prescaler1;
    attachInterrupt(2, interrupt1, FALLING);

  }

  else {
    middle1=TCNT1;
    attachInterrupt(2, interrupt1, RISING);

  }

  x=~x;
}

void interrupt3()
{
  if (!y) {
    count3=TCNT3;
    TCNT3=0x000; 
    TCCR3B=prescaler3;
    attachInterrupt(3, interrupt3, FALLING);

  }

  else {
    middle3=TCNT3;
    attachInterrupt(3, interrupt3, RISING);
  }

  y=~y;
}

void setup()   {

    GLCD.Init();
    GLCD.ClearScreen(WHITE);
 
    TIMSK1 = 0x01; // enabled global and timer overflow interrupt;
    TCCR1A = 0x00; // normal operation page 148 (mode0);
    attachInterrupt(2, interrupt1, RISING);
 
    TIMSK3 = 0x01; // enabled global and timer overflow interrupt;
    TCCR3A = 0x00; // normal operation page 148 (mode0);
    attachInterrupt(3, interrupt3, RISING);

}

void loop()
{GLCD.ClearScreen(WHITE);
    GLCD.SelectFont(SystemFont5x7);
    GLCD.CursorToXY(5,20);
    GLCD.print("freq");
    GLCD.CursorToXY(50,20);
    GLCD.print(16000000.0/divider1[prescaler1]/count1);
    GLCD.CursorToXY(110,20);
    GLCD.print("Hz");
   
    GLCD.SelectFont(SystemFont5x7);
    GLCD.CursorToXY(5,50);
    GLCD.print("freq");
    GLCD.CursorToXY(50,50);
    GLCD.print(16000000.0/divider3[prescaler3]/count3);
    GLCD.CursorToXY(110,50);
    GLCD.print("Hz");
   
           if (prescaler1>1)
        {
            if (usage1<0.15)
            {
              prescaler1--;
              delay(80);
            }
        }
      
        if (prescaler3>1)
        {
            if (usage3<0.15)
            {
              prescaler3--;
              delay(80);

            }
        }
}

This is the video. I increase the signal frequency to 24Hz and then decrease to about 11Hz. You will see the problem if frequency below 13Hz

Sorry for the video orientation.

If you have digital pin 5 open, look up the freqcounter library. It'd take about 8 lines o code to do what you're wanting to do.

At long period inputs counter overflow is going to be an issue, as master clock/nstages will be less time than your input cycle time. You may have to capture the timer overflow flag in the SFR and tally overflows and do math calculations based on number of overflows and the counter value at the time of the ISR call. In a benchtop counter prescalers are used to multiply and divide rates as necessary to keep the count rate in the realm of repeatability and then the display is corrected to reflect the influence of the prescaler. You can tell the chip to use XTAL2 and configure a different timebase than the mpu clocks at. This approach with a few external line selector logic circuits would allow you to autorange as appropriate.

Thank you for your advice.

I am newbie. I cannot fix this problem by myself.

Could you help me?

Which approach do you want to try first? External timebases or overflow counts?

I think overflow counts may be a proper solution.

Now to find the symbol avr c exposes for the access to the SFR.....oay! macro code! I'll keep you posted feel free to email too if you choose to.

Are you clipping and squaring the incoming waveform? Square waves are easier to obtain accurate timing from, sinewaves are somewhat ambiguous as trigger levels are subject to incoming amplitude variations.

The incoming waveform is square wave with 5V vpp.

Thank you so much for your help. I'm mechanical engineer.

This is my first project. Deadline is Jan 3,2012. Bad luck, it doesn't work.

The help desk is open throughout the weekend.....662-357-8257. I know all about impossible deadlines. Key is not to give up hope and not quit.

Now, I added this code.

 if(freq<15){
      duration = pulseIn(21, HIGH); // High to low period
      freq = (1000/2)/(duration/1000);
    }
    else {
      freq = 16000000.0/divider[prescaler]/count;
    }

I hope it will be work fine. Actually I don't want to pause the program by using pulseIn function.

still not understanding why you're not using freqcounter library?

http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/

#include <FreqCounter.h>

void setup() {
  Serial.begin(57600);                    // connect to the serial port
  Serial.println("Frequency Counter");
}

long int frq;
Void loop() {

 FreqCounter::f_comp= 8;             // Set compensation to 12
 FreqCounter::start(100);            // Start counting with gatetime of 100ms
 while (FreqCounter::f_ready == 0)         // wait until counter ready
 
 frq=FreqCounter::f_freq;            // read result
 Serial.println(frq);                // print result
 delay(20);
}

i use arduino mega 2560 and pin 5 is already use.

I want to measure frequency of 2 signals. I don't think freqcounter library is suit for this job.