Electrical – Measuring the frequency of a square wave with input capture Atmega328 avr

avrinterruptsmicrocontroller

I am currently measuring the frequency of a square wave using input capture on the atmega328p. Once it detects the frequency, I have the code lighting up one LED above a certain cutoff (i.e. about 150 hz) and one below.

volatile uint8_t flag;

volatile unsigned int capture1, capture2, CaptOvr;

volatile unsigned long T1Ovs, timer0_ovflow;


volatile  long ticks;
volatile double period;
unsigned long int frequency;
float Ttime;

void timer1_init(void)
{

  // Starting timer 1 in normal mode
//  TCCR1B= 0x00;
  TCCR1A = 0x00;
  // setting interrupt flag register to 0.
  //TIFR1=0x00;
  // timer 1 setup without any pre scalars, and enabling
  //input capture on rising edge
  TCCR1B =  (1<< ICES1);
  TCCR1B |=(1<<CS12)|(1<<CS10);

  // setting the timer/counter i/o locations to 0.
  //TCNT1H=0x00;
  //TCNT1L=0x00;
  // enabling input capture
 TIMSK1|=(1<<ICIE1)|(1<<TOIE1);
  // enabling global interrupt
  sei();
}


ISR (TIMER1_CAPT_vect)
{

 if (flag==0)
 {

    capture1 = ICR1;
    //setting overflow_counter to 0.
   T1Ovs=0;
    //doubleOverflowError=0;
 }
else if (flag==1)
 {
    capture2 = ICR1;

  //saving the value of overflow_counter to total_overflow
   CaptOvr = T1Ovs; 
  }
  flag++;
}

ISR(TIMER1_OVF_vect)
{
    T1Ovs++;
}


void setup() {
  // put your setup code here, to run once:
 // initialize timer
  Serial.begin(9600);
    timer1_init();
    //timer0_init();
   DDRD = (1<<PORTD7)|(1<<PORTD6);//|(1<<PORTD5);
   PORTD = (0<<PORTD7)|(0<<PORTD6);//|(0<<PORTD5);
}

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

      //while (flag != wait);


   if (flag==2)
      {

      flag=0;

        ticks = (capture2 - capture1) + (CaptOvr * 0x10000L);
       // T1Ovs=0;
       // Ttime= ((256*ticks)/16000000);
          frequency = (16000000/ticks)/1024;
   // frequency= (1/Ttime);

Serial.println ((frequency));

      if ((frequency>=100))
      {
          PORTD = (1<<PORTD7);
          //PORTD=(0<<PORTD6);

      }
    else if ( (frequency<100))
      {
        PORTD = (1<<PORTD6)|(0<<PORTD5);
      //  PORTD=(1<<PORTD6);
        }

      }       


}

so now, I want to turn on a 3rd led which will turn on when there isnt any signal being sent to the interrupt pin.( and it will turn off when a signal is being sent). This is the part i am currently stuck on. any suggestion or help would be greatly appreciated.

Best Answer

Use another timer and set it up to expire after a period equal to the period of the lowest frequency you intend to detect. For example, say you want the "no signal" LED to light when the input frequency is less than 1 Hz. Then set the period of this new timer to 1 second. Anytime an edge is detected, reset this timer's counter so that it will expire in 1 second. This way the timer will never expire as long as you're getting edges more often than once per second. But when you don't get an edge within one second than this timer will expire and in the timer's ISR you can light the "no signal" LED.