Frequency Counter using ATMega8A, 7 Segment display keeps flickering only shows 1 out of 4 digits

Hi, I want to add the smoothing to the calculated values so that I can take an average of multiple readings and display them. My problem is it is easy to do with adc value but how do i do it on this program :

#include "SevSeg.h"
SevSeg sevseg; //Instantiate a seven segment controller object

volatile float freqCounter = 0.000;  
float preMillis = 0.000;
int indicator=A0;


void isr() //interrupt service routine
{
  freqCounter++;
}

void setup()
{
  Serial.begin(9600);
  pinMode(indicator,OUTPUT);
  byte numDigits = 3;
  byte digitPins[] = {A3, A2, A1};
  byte segmentPins[] = {3,4,5,6,7,8,9,10};
  bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
  byte hardwareConfig = COMMON_ANODE; // See README.md for options
  bool updateWithDelays = false; // Default 'false' is Recommended
  bool leadingZeros = true; // Use 'true' if you'd like to keep the leading zeros
  bool disableDecPoint = false; // Use 'true' if your decimal point doesn't exist or isn't connected
  
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
  updateWithDelays, leadingZeros, disableDecPoint);
  sevseg.setBrightness(45);

displayNumber(freqCounter);
delay(10);
attachInterrupt(0, isr, RISING);
}

void loop()
{
  noInterrupts () ; // read and reset counter in critical section
  float frequency = freqCounter;
  freqCounter = 0;
  interrupts () ;

  preMillis = millis();  // setup time for next sampling

  while((millis()-preMillis)<1000)
    displayNumber(frequency);   // while waiting multiplex the display constantly.
}

void displayNumber(float frequency)
{
  if (frequency < 1000)
  {
    sevseg.setNumber(frequency);
    
  }
  else if (frequency >= 1000.00 && frequency <10000.00)
  {
    sevseg.setNumberF(frequency/1000,2);
    
  }
  else if (frequency >=10000.00 && frequency <100000.00)
  {
    sevseg.setNumberF(frequency/1000,1);
    
  }
  else if (frequency >=100000.00 && frequency <540000.00)
  {
    sevseg.setNumber(frequency/1000);
  }
  else
  {
    sevseg.setChars("OVA");
  }
  Serial.println(frequency);
sevseg.refreshDisplay();
}

A simple low-pass filter is this:

float filteredFreq;

void setup()
{
  get a sample and set 'filteredFreq' to a initial value
}

void loop()
{
  filteredFreq = 99% filteredFreq + 1% newFreq;
}

A low-pass filter might not be the right filter for you. In some situations a moving-average filter is needed.
If someone asks on this forum about a smoothing filter, then many with reply with their own favorite filter. Don't select a filter with code that you don't understand.

A few notes:

  • Always use 'unsigned long' for millis().
  • Does the refreshDisplay() needs to be called all the time ? Then put that in the loop() and use a millis-timer of 1 second to capture the frequency.
  • Use the millis values to calculate the real elapsed millis, and use that for the calculation of the frequency.
  • Can you add "Pin" to a variable that is a pin number ?
  • If you put your 'digitPins' and 'segmentPins' above the setup() function, then all the used pins are together. You can make them 'const'.
  • It is advised to use "digitalPinToInterrupt" with 'attachInterrupt()'.
  • The variable 'freqCounter' is a incremental counter. Please make that a 'unsigned long'.

Why use the Analog pins as Digital pins?

Where/what readings do you want to filter?

There is the GitHub - sebnil/Moving-Avarage-Filter--Arduino-Library-: A moving average, also called rolling average, rolling mean or running average, is a type of finite impulse response filter (FIR) used to analyze a set of datum points by creating a series of averages of different subsets of the full data set. and the SimpleKalmanFilter - Arduino Reference.

I use the SimpleKalman, code demo below.


void fReadBattery( void * parameter )
{
  float adcValue = 0.0f;
  const float r1 = 50500.0f; // R1 in ohm, 50K
  const float r2 = 10000.0f; // R2 in ohm, 10k potentiometer
  float Vbatt = 0.0f;
  int printCount = 0;
  float vRefScale = (3.3f / 4096.0f) * ((r1 + r2) / r2);
  uint64_t TimePastKalman  = esp_timer_get_time(); // used by the Kalman filter UpdateProcessNoise, time since last kalman calculation
  SimpleKalmanFilter KF_ADC_b( 1.0f, 1.0f, .01f );
  TickType_t xLastWakeTime = xTaskGetTickCount();
  const TickType_t xFrequency = 1000; //delay for mS
  for (;;)
  {
    adc1_get_raw(ADC1_CHANNEL_0); //read and discard
    adcValue = float( adc1_get_raw(ADC1_CHANNEL_0) ); //take a raw ADC reading
    KF_ADC_b.setProcessNoise( (esp_timer_get_time() - TimePastKalman) / 1000000.0f ); //get time, in microsecods, since last readings
    adcValue = KF_ADC_b.updateEstimate( adcValue ); // apply simple Kalman filter
    Vbatt = adcValue * vRefScale;
    xSemaphoreTake( sema_CalculatedVoltage, portMAX_DELAY );
    CalculatedVoltage = Vbatt;
    xSemaphoreGive( sema_CalculatedVoltage );
    
      printCount++;
      if ( printCount == 3 )
      {
      //log_i( "Vbatt %f", Vbatt );
      printCount = 0;
      }
    
    TimePastKalman = esp_timer_get_time(); // time of update complete
    xLastWakeTime = xTaskGetTickCount();
    vTaskDelayUntil( &xLastWakeTime, xFrequency );
    //log_i( "fReadBattery %d",  uxTaskGetStackHighWaterMark( NULL ) );
  }
  vTaskDelete( NULL );
}
////

consider

// running average (leaky integration)

float  avg;
const float K = 0.125;

// -----------------------------------------------------------------------------
void
loop ()
{
    int samp = analogRead (A0);

    if (0 != avg)
        avg += (samp - avg) * K;
    else
        avg = samp;

    Serial.println (avg, 0.01);
    delay (250);
}

// -----------------------------------------------------------------------------
void
setup ()
{
    Serial.begin (9600);
}

@designerveekay
More topics on the same subject merged. Any more and you will get a permanent ban from posting.

Everyone else
Sorry this is now such a mess, this is a good example of why there should only be one topic on a particular subject.

Thank you

I fixed the code for the Serial Output , but it still doesn't go above 63KHz. Can you please help me about that, the original code used the 8MHz external clock while mine is using the 16MHz. Still it saturates at 63KHz. TTL Signal is being fed to PD5 of Atmega8A.

/**************************************************** 
Chip type           : ATmega8
Program type        : Application
Clock frequency     : 8.000000 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 256
*****************************************************/

#define F_CPU 16000000UL
#include <stdlib.h>  // this library is used to display variables on lcd

volatile unsigned long freq;  // to store value of frequency value
volatile int dur; //i=number of overflows in one second
volatile int i;
// dur to store the value of TCNT1 register
char buffer[8]; // to store the frequency value as a string to be displayed on lcd
float freqf; 
// used to display the fractions of frequency with the suitable unit as shown later

// Timer 1 overflow interrupt service routine
ISR(TIMER0_OVF_vect)
{
// Place your code here
i++ ;      // count the number of overflows in one second
}

// Declare your global variables here
int main()
{
// Declare your local variables here

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x04;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;


// Global enable interrupts
sei();
Serial.begin(9600);
while (1)
      {
      // Place your code here
      TIMSK=0x04;
      TCCR1B=0x07; 
      _delay_ms(1000);
      TCCR1B=0x00;  
      TIMSK=0x00;
      dur=TCNT1;
      freq = dur + i*65536;
      Serial.println(TCNT1);
      TCNT1=0x0000;
      i=0; 
      
      if(freq>=1000000)
      {
      freqf=(float)freq/1000000;
      Serial.println(freqf);
      }
      else if (freq>=1000)
      {
      freqf=(float)freq/1000;
      Serial.println(freqf);
      }
      else
      {
      Serial.println(freqf);
      }    
      };
}

Something is likely getting too big for its data type

volatile unsigned long freq; 
. . .
volatile int dur;
volatile int i;

. . .
freq = dur + i*65536;  // probably here

try

freq = dur + (uint32_t)i*65536UL;  // could even use a left shift instead of multiply

Ensure that you have compiler warnings enabled in the Arduino IDE

Still got the same problem. When I simulate it in Proteus it works fine but in the Arduino Serial monitor there is not reading after 63KHz.

look at the comments here:

while (1)
      {
      // Place your code here
      TIMSK=0x04;
      TCCR1B=0x07; 
      _delay_ms(1000);
      TCCR1B=0x00;  
      TIMSK=0x00;
      dur=TCNT1;
      freq = dur + (uint32_t)i*65536UL;  // could even use a right shift instead of multiply
      Serial.println( i ) ;   // **new**
      Serial.println(TCNT1);
      Serial.println( freq ) ; // **new**
      TCNT1=0x0000;
      i=0; 
      
      if(freq>=1000000UL)    // **new** UL
      {
      freqf=(float)freq/1000000.0 ; // **new** .0
      Serial.println(freqf);
      }
      else if (freq>=1000)
      {
      freqf=(float)freq/1000;
      Serial.println(freqf);
      }
      else
      {
      Serial.println(freqf);  // freqf **this has not been set here**
      }    
      };
}

also the additional print statements.
Did you see any compiler warnings ?

This is what I get when I upload the program. There are no warning, atleast from what I can tell. But still the problem remains the same.

avrdude: Version 6.3-20201216
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch

     System wide configuration file is "C:\Users\designerVeeKay\AppData\Local\Arduino15\packages\MiniCore\hardware\avr\2.1.3/avrdude.conf"

     Using Port                    : COM4
     Using Programmer              : arduino
     Overriding Baud Rate          : 115200
     AVR Part                      : ATmega8
     Chip Erase delay              : 10000 us
     PAGEL                         : PD7
     BS2                           : PC2
     RESET disposition             : dedicated
     RETRY pulse                   : SCK
     serial program mode           : yes
     parallel program mode         : yes
     Timeout                       : 200
     StabDelay                     : 100
     CmdexeDelay                   : 25
     SyncLoops                     : 32
     ByteDelay                     : 0
     PollIndex                     : 3
     PollValue                     : 0x53
     Memory Detail                 :

                              Block Poll               Page                       Polled
       Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
       ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
       eeprom         4    20   128    0 no        512    4      0  9000  9000 0xff 0xff
       flash         33    10    64    0 yes      8192   64    128  4500  4500 0xff 0x00
       lfuse          0     0     0    0 no          1    0      0  2000  2000 0x00 0x00
       hfuse          0     0     0    0 no          1    0      0  2000  2000 0x00 0x00
       efuse          0     0     0    0 no          0    0      0     0     0 0x00 0x00
       lock           0     0     0    0 no          1    0      0  2000  2000 0x00 0x00
       calibration    0     0     0    0 no          4    0      0     0     0 0x00 0x00
       signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

     Programmer Type : Arduino
     Description     : Arduino
     Hardware Version: 3
     Firmware Version: 8.0
     Vtarget         : 0.3 V
     Varef           : 0.3 V
     Oscillator      : 28.800 kHz
     SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9307 (probably m8)
avrdude: reading input file "C:\Users\DESIGN~1\AppData\Local\Temp\arduino_build_307886/sketch_may06a.ino.hex"
avrdude: writing flash (3570 bytes):

Writing | ################################################## | 100% 1.15s

avrdude: 3570 bytes of flash written
avrdude: verifying flash memory against C:\Users\DESIGN~1\AppData\Local\Temp\arduino_build_307886/sketch_may06a.ino.hex:
avrdude: load data flash data from input file C:\Users\DESIGN~1\AppData\Local\Temp\arduino_build_307886/sketch_may06a.ino.hex:
avrdude: input file C:\Users\DESIGN~1\AppData\Local\Temp\arduino_build_307886/sketch_may06a.ino.hex contains 3570 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.69s

avrdude: verifying ...
avrdude: 3570 bytes of flash verified

avrdude done. Thank you.

That looks OK but let's see the output the program generates when fed a signal of more than 63kHz with the additional print statements and other changes suggested in post #49.
However, this appears rather low if it is referring to the system clock:

I'm looking at this again:

Does it fail only when you use a physical ATmega8A but works perfectly with a simulated ATMega8A ?

Yes, it only fails when I use a physical Atmega8a.

The uploading output that you showed earlier does not include the compilation output where, for example, you see also, for example, how much memory the sketch uses. Can you find that (for the physical ATmega8A) and add that as well as showing the output, with the additional changes and print statements already requested in post #51.

The differences between a simulated and physical system can be hardware related: clock speed, fuse settings etc. etc.

Maybe also add the following after the Serial.begin(9600) :

Serial.println( F_CPU ) ; // clock speed

Sir, I resolved the problem for going more than 100KHz by using a different method I found online in someone's code. I am using the PD5 pin now for the input and used the external interrupt. But now when I try to code in arduino it gives me an error.

C code is as follows which works fine and gives the result in Serial Monitor.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>

 
/* TIMER0_PRELOAD_VAL=255-((F_CPU/Prescaler)*Time - 1).
  For F_CPU 16 MHz, Time 1 msec is 6. */
#define TIMER0_PRELOAD_VAL 6

void startcounter(uint16_t);
 
uint16_t gate_time;               // The time in msec that the gate will remain open.
volatile uint16_t timer0_ticks;   // The number of Timer0 ticks.
uint8_t counter1_overflows;       // The number of Timer / Counter1 overflows.
volatile uint8_t ready_flag;      // Flag of completion of the measurement.
volatile uint32_t counter_val;    // The total value of the measurement.
 
int main(void){
 
    DDRB |= (1<<PB0);
 
    Serial.begin(9600);
 
    sei();
 
    uint16_t gate=1000; // Σε milliseconds.
 
    uint32_t frequency;
 
    uint8_t i; // A little trick to not "clog"
               // the UART when we have a short gate time.
 
    while(1){
 
        i++;
 
        startcounter(gate);
 
        while(!ready_flag){};
 
        PORTB ^= (1<<PB0); // Strobe LED.
 
        frequency = counter_val*(1000/gate);
 
        if (i>=1000/gate) {
            Serial.println(frequency);
            i=0;
        };
    };
 
    return 0;
}
 
void startcounter(uint16_t msecs){
 
    gate_time=msecs;
    counter1_overflows=0;
    timer0_ticks=0;
    ready_flag=0;
 
    TIMSK |= (1<<TOIE1);  // Enable Overflow Interrupt for Timer / Counter1.
    TIMSK |= (1<<TOIE0);  // Enable Overflow Interrupt for Timer0.
 
    // Initialize Timer0. Causes Interrupt each msec.
 
    TCNT0 = TIMER0_PRELOAD_VAL;   // Preload with the price for a time of 1 msec.
    TCCR0 |= (1<<CS01)|(1<<CS00);  // Activation with Prescaler 64.
 
    // Reset TCNT1?
    TCNT1=0;
    // Increase TCNT1 by applying pulse to PD5.
    TCCR1B |= (1<<CS10)|(1<<CS11)|(1<<CS12);
 
}
 
 
ISR(TIMER1_OVF_vect){
 
    counter1_overflows++;
}
 
 
ISR(TIMER0_OVF_vect){
 
    uint16_t counter1_ticks;
 
    // Counter value of Counter1.
    counter1_ticks = TCNT1;
 
    TCNT0 += TIMER0_PRELOAD_VAL;  // Preload TCNT0 for 1 msec.
 
    timer0_ticks++;
 
    // Check if gate_time has been completed. If not ISR exit?
    if (timer0_ticks < gate_time) return;
 
    // If we lost a Timer / Counter1 interrupt increase the meter.
    if (bit_is_set(TIFR,TOV1)) counter1_overflows++;
 
    TIMSK &= ~((1<<TOIE1)|(1<<TOIE0)); // Disable Interrupt overflow for Timer0, Timer / counter1.
 
    TCCR1B &= ~((1<<CS10)|(1<<CS11)|(1<<CS12)); // Stop Timer / Counter1.
 
    TCCR0 &= ~( (1<<CS01)|(1<<CS00)); // Stop Timer0.
 
    counter_val = (counter1_overflows*65536)+counter1_ticks;
 
    ready_flag = 1;
}

But when I rewrite it for arduino as follows:

#define TIMER0_PRELOAD_VAL 6

void startcounter(unsigned short);

unsigned short gate_time;               // The time in msec that the gate will remain open.
volatile unsigned short timer0_ticks;   // The number of Timer0 ticks.
int counter1_overflows;       // The number of Timer / Counter1 overflows.
volatile unsigned char ready_flag;      // Flag of completion of the measurement.
volatile uint32_t counter_val;    // The total value of the measurement.

unsigned short gate=1000;
uint32_t frequency;
 
uint8_t i; // A little trick to not "clog"
               // the UART when we have a short gate time.
void setup() {
  DDRB |= (1<<PB0);
  Serial.begin(9600);
  // put your setup code here, to run once:
noInterrupts();
startcounter(gate);
interrupts();


}

void loop() {
  i++;
  startcounter(gate);
  while(!ready_flag){};
  PORTB ^= (1<<PB0); // Strobe LED.
  frequency = counter_val*(1000/gate);
  if (i>=1000/gate) 
  {
  Serial.println(frequency);
  i=0;
  };

}

void startcounter(unsigned short msecs){
    
    gate_time=msecs;
    counter1_overflows=0;
    timer0_ticks=0;
    ready_flag=0;
 
    TIMSK |= (1<<TOIE1);  // Enable Overflow Interrupt for Timer / Counter1.
    TIMSK |= (1<<TOIE0);  // Enable Overflow Interrupt for Timer0.
 
    // Initialize Timer0. Causes Interrupt each msec.
 
    TCNT0 = TIMER0_PRELOAD_VAL;   // Preload with the price for a time of 1 msec.
    TCCR0 |= (1<<CS01)|(1<<CS00);  // Activation with Prescaler 64.
 
    // Reset TCNT1?
    TCNT1=0;
    // Increase TCNT1 by applying pulse to PD5.
    TCCR1B |= (1<<CS10)|(1<<CS11)|(1<<CS12);
    
}

ISR(TIMER1_OVF_vect){
 
    counter1_overflows++;
}
 

ISR(TIMER0_OVF_vect){
 
    uint16_t counter1_ticks;
 
    // Counter value of Counter1.
    counter1_ticks = TCNT1;
 
    TCNT0 += TIMER0_PRELOAD_VAL;  // Preload TCNT0 for 1 msec.
 
    timer0_ticks++;
 
    // Check if gate_time has been completed. If not ISR exit?
    if (timer0_ticks < gate_time) return;
 
    // If we lost a Timer / Counter1 interrupt increase the meter.
    if (bit_is_set(TIFR,TOV1)) counter1_overflows++;
 
    TIMSK &= ~((1<<TOIE1)|(1<<TOIE0)); // Disable Interrupt overflow for Timer0, Timer / counter1.
 
    TCCR1B &= ~((1<<CS10)|(1<<CS11)|(1<<CS12)); // Stop Timer / Counter1.
 
    TCCR0 &= ~( (1<<CS01)|(1<<CS00)); // Stop Timer0.
 
    counter_val = (counter1_overflows*65536)+counter1_ticks;
 
    ready_flag = 1;
}

Gives me error:
Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB
C:\Users\DESIGN~1\AppData\Local\Temp\arduino_build_808190/..\arduino_cache_29448\core\core_c0b58a630375852fd283f9fcec03bc34.a(wiring.c.o): In function __vector_9': C:\Users\designerVeeKay\AppData\Local\Arduino15\packages\MiniCore\hardware\avr\2.1.3\cores\MCUdude_corefiles/wiring.c:159: multiple definition of __vector_9'
sketch\sketch_may07a.ino.cpp.o:C:\Users\designerVeeKay\Documents\Arduino\sketch_may07a/sketch_may07a.ino:69: first defined here
collect2.exe: error: ld returned 1 exit status
exit status 1
Error compiling for board ATmega8.

If you use main() you don't get this problem. However, if you use setup() and loop() then the Arduino environment takes over the timer0 overflow vector (for millis(), delay(), etc.) so you get a conflict if you try also to use it in your program.

I resolved this by sticking to the AVR C programming instead on going with Arduino. But now my display keep flickering. I have changed the delay values between 1ms to 100ms but problem remains there. Can you please have a look if I am missing something here.
Note: I am using 7 Segment Common Cathode display with a=pd2, b=pd3, c=pd4, d=pd6, e=pd7, f= pb0, g=pb1, dp=pb2.
Display 1 = pc0, display 2 = pc1, display 3= pc2.


#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>

/* TIMER0_PRELOAD_VAL=255-((F_CPU/Prescaler)*Time - 1).
  For F_CPU 16 MHz, Time 1 msec is 6. */
#define TIMER0_PRELOAD_VAL 6

void startcounter(uint16_t);
 
uint16_t gate_time;               // The time in msec that the gate will remain open.
volatile uint16_t timer0_ticks;   // The number of Timer0 ticks.
uint8_t counter1_overflows;       // The number of Timer / Counter1 overflows.
volatile uint8_t ready_flag;      // Flag of completion of the measurement.
volatile uint32_t counter_val;    // The total value of the measurement.

int main()
 { 

 DDRD = (1<<2) | (1<<3) | (1<<4) | (1<<6) | (1<<7);
 DDRB = (1<<0) | (1<<1) | (1<<2);
 DDRC = (1<<0) | (1<<1) | (1<<2);
 
 sei();
 
    uint16_t gate=1000; // Se milliseconds.
 
    uint32_t frequency;
 
    uint8_t i; // A little trick to not "clog"
               // the UART when we have a short gate time.
    
    while(1) 
    {
    i++;
 
        startcounter(gate);
 
        while(!ready_flag){};
 
        
 
        frequency = counter_val*(1000/gate);
 
        if (i>=1000/gate) 
	     displayNumber(frequency);
	     
	     i=0;
        
    };
   return 0;
 }
 
 void startcounter(uint16_t msecs){
 
    gate_time=msecs;
    counter1_overflows=0;
    timer0_ticks=0;
    ready_flag=0;
 
    TIMSK |= (1<<TOIE1);  // Enable Overflow Interrupt for Timer / Counter1.
    TIMSK |= (1<<TOIE0);  // Enable Overflow Interrupt for Timer0.
 
    // Initialize Timer0. Causes Interrupt each msec.
 
    TCNT0 = TIMER0_PRELOAD_VAL;   // Preload with the price for a time of 1 msec.
    TCCR0 |= (1<<CS01)|(1<<CS00);  // Activation with Prescaler 64.
 
    // Reset TCNT1?
    TCNT1=0;
    // Increase TCNT1 by applying pulse to PD5.
    TCCR1B |= (1<<CS10)|(1<<CS11)|(1<<CS12);
 
}
 
 
ISR(TIMER1_OVF_vect){
 
    counter1_overflows++;
}
 
 
ISR(TIMER0_OVF_vect){
 
    uint16_t counter1_ticks;
 
    // Counter value of Counter1.
    counter1_ticks = TCNT1;
 
    TCNT0 += TIMER0_PRELOAD_VAL;  // Preload TCNT0 for 1 msec.
 
    timer0_ticks++;
 
    // Check if gate_time has been completed. If not ISR exit?
    if (timer0_ticks < gate_time) return;
 
    // If we lost a Timer / Counter1 interrupt increase the meter.
    if (bit_is_set(TIFR,TOV1)) counter1_overflows++;
 
    TIMSK &= ~((1<<TOIE1)|(1<<TOIE0)); // Disable Interrupt overflow for Timer0, Timer / counter1.
 
    TCCR1B &= ~((1<<CS10)|(1<<CS11)|(1<<CS12)); // Stop Timer / Counter1.
 
    TCCR0 &= ~( (1<<CS01)|(1<<CS00)); // Stop Timer0.
 
    counter_val = (counter1_overflows*65536)+counter1_ticks;
 
    ready_flag = 1;
}
 

void displayNumber(int num)
{
int i;
  for (i = 0 ; i < 3 ; i++)  // display trailing digit first so can do %, / loop
  {
    pickDigit (i) ;
    pickNumber(num % 10);
    num /= 10 ;
    _delay_ms(1);
  }
}

void pickDigit(int x)
{
  // Initially turn _all_ lines off to avoid ghosting
  clearLEDs () ;
  

  // select digit (still dark)
  switch(x)
    {
    case 0:
      PORTC = (1<<3);
      break;
    case 1:
      PORTC = (1<<2);
      break;
    case 2:
      PORTC = (1<<1);
      break;
    default:
      PORTC = (1<<0);
      break;
    }
}
 //Function to display a number:
 void pickNumber(int x)
{
   switch(x)
   {
      default:
      zero();
      break;
      case 1:
      one();
      break;
      case 2:
      two();
      break;
      case 3:
      three();
      break;
      case 4:
      four();
      break;
      case 5:
      five();
      break;
      case 6:
      six();
      break;
      case 7:
      seven();
      break;
      case 8:
      eight();
      break;
      case 9:
      nine();
      break;
   }
}
 
void clearLEDs()
{
   PORTD = (1<<2) | (1<<3) | (1<<4) | (1<<6) | (1<<7);
   PORTB = (1<<0) | (1<<1) | (1<<2);
}


void zero()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (0<<7);
   PORTB = (0<<0) | (1<<1) | (1<<2);
}

void one()
{
   PORTD = (1<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (1<<0) | (1<<1) | (1<<2);
}

void two()
{
   PORTD = (0<<2) | (0<<3) | (1<<4) | (0<<6) | (0<<7);
   PORTB = (1<<0) | (0<<1) | (1<<2);
}

void three()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (1<<7);
   PORTB = (1<<0) | (0<<1) | (1<<2);
}

void four()
{
   PORTD = (1<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void five()
{
   PORTD = (0<<2) | (1<<3) | (0<<4) | (0<<6) | (1<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void six()
{
   PORTD = (0<<2) | (1<<3) | (0<<4) | (0<<6) | (0<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void seven()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (1<<0) | (1<<1) | (1<<2);
}

void eight()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (0<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void nine()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

To have a clean, flicker free multiplexed display, the digits must be cycled every about 4ms or less.
You appear to be blocking the display (actually the whole code) for 1 second periods during the sampling of the input pin.

You could use another timer, timer2 running at say 250Hz, to drive the display. Reducing the sampling period might help a bit but may impact the accuracy/resolution of the results.

How can I do that, can you guide me please.

  1. Before the while(1) in main, configure timer2 to generate interrupts at 250Hz (approx).

  2. In the ISR of timer2 call displayNumber().

  3. Modify and complete displayNumber() as below:

void displayNumber()
{
    // on each call, calculates and displays the number at the next digit position 
    // call every 4 ms by a timer

    static int i = 0 ;   // static variables are initialised once only
    pickDigit (i) ;

    // calculate the number (x) to be displayed at postion 'i' based on the frequency.
    pickNumber(  x  )  ;   // display it
    
    if ( ++i >= 4 ) i = 0 ;
}

Is it correct now


#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>

/* TIMER0_PRELOAD_VAL=255-((F_CPU/Prescaler)*Time - 1).
  For F_CPU 16 MHz, Time 1 msec is 6. */
#define TIMER0_PRELOAD_VAL 6

void startcounter(uint16_t);
volatile uint32_t frequency;
 
uint16_t gate_time;               // The time in msec that the gate will remain open.
volatile uint16_t timer0_ticks;   // The number of Timer0 ticks.
uint8_t counter1_overflows;       // The number of Timer / Counter1 overflows.
volatile uint8_t ready_flag;      // Flag of completion of the measurement.
volatile uint32_t counter_val;    // The total value of the measurement.

int main()
 { 

 DDRD = (1<<2) | (1<<3) | (1<<4) | (1<<6) | (1<<7);
 DDRB = (1<<0) | (1<<1) | (1<<2);
 DDRC = (1<<0) | (1<<1) | (1<<2) ||(1<<3);
 OCR2 = 125;
 TCCR2 |= (1 << WGM21);
 TIMSK |= (1 << OCIE2);
 TCCR2 |= (1 << CS22); 
 sei();
 
    uint16_t gate=1000; // Se milliseconds.
 
    
 
    uint8_t i; // A little trick to not "clog"
               // the UART when we have a short gate time.
    
    while(1) 
    {
    i++;
 
        startcounter(gate);
 
       while(!ready_flag){
        
       };
 
        
 
        frequency = counter_val*(1000/gate);
 
        if (i>=1000/gate) 
       
       
       i=0;
        
    };
   return 0;
 }
 volatile char disp_di = 0, ms_count=0;
ISR (TIMER2_COMP_vect)
{
  displayNumber(frequency);
 
 
}
 void startcounter(uint16_t msecs){
 
    gate_time=msecs;
    counter1_overflows=0;
    timer0_ticks=0;
    ready_flag=0;
 
    TIMSK |= (1<<TOIE1);  // Enable Overflow Interrupt for Timer / Counter1.
    TIMSK |= (1<<TOIE0);  // Enable Overflow Interrupt for Timer0.
 
    // Initialize Timer0. Causes Interrupt each msec.
 
    TCNT0 = TIMER0_PRELOAD_VAL;   // Preload with the price for a time of 1 msec.
    TCCR0 |= (1<<CS01)|(1<<CS00);  // Activation with Prescaler 64.
 
    // Reset TCNT1?
    TCNT1=0;
    // Increase TCNT1 by applying pulse to PD5.
    TCCR1B |= (1<<CS10)|(1<<CS11)|(1<<CS12);
 
}
 
 
ISR(TIMER1_OVF_vect){
 
    counter1_overflows++;
}
 
 
ISR(TIMER0_OVF_vect){
 
    uint16_t counter1_ticks;
 
    // Counter value of Counter1.
    counter1_ticks = TCNT1;
 
    TCNT0 += TIMER0_PRELOAD_VAL;  // Preload TCNT0 for 1 msec.
 
    timer0_ticks++;
 
    // Check if gate_time has been completed. If not ISR exit?
    if (timer0_ticks < gate_time) return;
 
    // If we lost a Timer / Counter1 interrupt increase the meter.
    if (bit_is_set(TIFR,TOV1)) counter1_overflows++;
 
    TIMSK &= ~((1<<TOIE1)|(1<<TOIE0)); // Disable Interrupt overflow for Timer0, Timer / counter1.
 
    TCCR1B &= ~((1<<CS10)|(1<<CS11)|(1<<CS12)); // Stop Timer / Counter1.
 
    TCCR0 &= ~( (1<<CS01)|(1<<CS00)); // Stop Timer0.
 
    counter_val = (counter1_overflows*65536)+counter1_ticks;
 
    ready_flag = 1;
}
 
void displayNumber(num)
{
    // on each call, calculates and displays the number at the next digit position 
    // call every 4 ms by a timer

    static int i = 0 ;   // static variables are initialised once only
    pickDigit (i) ;

    // calculate the number (x) to be displayed at postion 'i' based on the frequency.
    pickNumber(  num  )  ;   // display it
    
    if ( ++i >= 4 ) i = 0 ;
}


void pickDigit(int x)
{
  // Initially turn _all_ lines off to avoid ghosting
  clearLEDs () ;
  PORTC = (0<<0) | (0<<1) | (0<<2);
  

  // select digit (still dark)
  switch(x)
    {
    case 0:
      PORTC = (1<<0);
      break;
    case 1:
      PORTC = (1<<1);
      break;
    default :
      PORTC = (1<<2);
      break;
    
    }
}
 //Function to display a number:
 void pickNumber(int x)
{
   switch(x)
   {
      default:
      zero();
      break;
      case 1:
      one();
      break;
      case 2:
      two();
      break;
      case 3:
      three();
      break;
      case 4:
      four();
      break;
      case 5:
      five();
      break;
      case 6:
      six();
      break;
      case 7:
      seven();
      break;
      case 8:
      eight();
      break;
      case 9:
      nine();
      break;
   }
}
 
void clearLEDs()
{
   PORTD = (1<<2) | (1<<3) | (1<<4) | (1<<6) | (1<<7);
   PORTB = (1<<0) | (1<<1) | (1<<2);
}


void zero()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (0<<7);
   PORTB = (0<<0) | (1<<1) | (1<<2);
}

void one()
{
   PORTD = (1<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (1<<0) | (1<<1) | (1<<2);
}

void two()
{
   PORTD = (0<<2) | (0<<3) | (1<<4) | (0<<6) | (0<<7);
   PORTB = (1<<0) | (0<<1) | (1<<2);
}

void three()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (1<<7);
   PORTB = (1<<0) | (0<<1) | (1<<2);
}

void four()
{
   PORTD = (1<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void five()
{
   PORTD = (0<<2) | (1<<3) | (0<<4) | (0<<6) | (1<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void six()
{
   PORTD = (0<<2) | (1<<3) | (0<<4) | (0<<6) | (0<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void seven()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (1<<0) | (1<<1) | (1<<2);
}

void eight()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (0<<6) | (0<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}

void nine()
{
   PORTD = (0<<2) | (0<<3) | (0<<4) | (1<<6) | (1<<7);
   PORTB = (0<<0) | (0<<1) | (1<<2);
}