Saturday, 26 April 2014

FREQUENCY MEASUREMENT USING AVR ATMEGA8

     Often frequency measurement is needed, but one cannot afford a DSO or an appropriate meter for that. So we have designed it in AVR microcontroller which is easily available and much easier to program.

    This frequency measurement uses Input Capture module in Timer1 via ICP pin PB0. For ease of programming, we have designed a low frequency measurement for frequencies lesser than 1KHz, but can be increased upto several 100KHz, through prescalar.

       The circuit diagram is



freq mtr

The MCU runs on 1MHz internal Oscillator. The T1 frequency is Fosc/64 using prescalar.

When S1 is pressed, the MCU jumps to Frequency measurement loop. The ICP module generates an interrupt on the rising edge of the input signal. The ICP ISR takes five samples on the T1 count values and stores it in an array. Once five samples are taken then it goes for calculation. Then measure frequency is displayed in LCD with a decimal point & it continues till stopped my pressing S1.

This can measure frequency less than 1KHz, but can be modified to measure high frequeny my reducing the prescalar value.

Click here to get the LCD header file [1]  or in Mirror2

The code for frequency measurement is
// // // // // // // // // // // // // // // // // // // // // // // // // //
// Author: ElecDude
//         admin@elecdude.com        
//
// Copyright - 2014 - ElecDude
//
// DISCLAIMER:
//
// THIS SOURCE FILE MAY BE USED AND DISTRIBUTED WITHOUT      
// RESTRICTION PROVIDED THAT THIS COPYRIGHT STATEMENT IS NOT 
// REMOVED FROM THE FILE AND THAT ANY DERIVATIVE WORK CONTAINS
// THE ORIGINAL COPYRIGHT NOTICE AND THE ASSOCIATED DISCLAIMER.
//
// This is provided without any  express or implied warranties,
// including, but not limited  to, the implied warranties of merchantability
// and fitnessfor a particular purpose. FOR EDUCATIONAL PURPOSE ONLY.
//
// // // // // // // // // // // // // // // // // // // // // // // // // //
#define F_CPU 1000000UL
/*****************MACRO's DEFINITION*********************************/
#ifndef BIT
#define BIT(x)    _BV(x)
#endif

#ifndef SETBIT
#define SETBIT(x,b)     x|=_BV(b);
#endif

#ifndef CLEARBIT
#define CLEARBIT(x,b)     x&=~_BV(b);
#endif

#ifndef TOGGLEBIT
#define TOGGLEBIT(x,b)     x^=_BV(b);
#endif

#ifndef CHECKBIT
#define CHECKBIT(x,b)     (x & _BV(b))
#endif
/*******************************************************************/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd4b.h"

void WaitMs(unsigned int ms) // waits (pauses) for ms milliseconds
{
    unsigned int m;
    for(m=0;m<=ms/10;m++)
    {
        _delay_ms(10);
    }
}

#define PRT PIND
#define sw1 0
#define sw2 1
#define sw3 2
#define sw4 3
#define TIME 150
unsigned int button(unsigned char PIN)
{
    if(CHECKBIT(PRT,PIN) == 0)
    {
        WaitMs(TIME);
        if(CHECKBIT(PRT,PIN) == 0)
            return 1;
        else
            return 0;
    }
    return 0;
}
// Fosc= 1 MHz
// Run T1 @ Fosc/64=> 64us per pulse for 50Hz(or 20ms), count=312
// Freq = Fosc/PS/count => 1M/64/count=> 15625/count
#define CONST 15625
#define RunT1() TCCR1B|=( 1<<CS01 | 1<<CS00 )
#define StopT1() TCCR1B&= ~( 1<<CS01 | 1<<CS00 )
#define NoS 5
uint16_t time[4];
char s[6]="0000.0";
volatile uint8_t n;
volatile uint8_t flag;
ISR(TIMER1_CAPT_vect)
{ //T1 InCapture
    time[n]=ICR1;
    n++;
    if(n==NoS)
        flag=1;
}
uint16_t freq;
void calc()
{
    uint8_t i;
    float tm=0;
    for(i=1;i<NoS;i++)
    {       //t1 > t0
        if(time[i]>time[i-1])
            tm+=(time[i]-time[i-1]); //Tdifference t1-t0 (t1>t0)
        else
            tm+=( time[i]+(65536-time[i-1])); //t1+MAX-t0 (t1<t0)
    }
    tm=tm/(NoS-1); //average
    tm=CONST/(tm); //calc Freq
    freq=tm*10; //with 1 decimal point
    _delay_ms(50);
    LCD_putsPXY(0,0,"F= ");
    s[5]= (freq%10) | 0x30; //point
    freq/=10;
    s[3]= (freq%10) | 0x30; //1s
    freq/=10;
    s[2]= (freq%10) | 0x30; //10s
    freq/=10;
    s[1]= (freq%10) | 0x30; //100s
    s[0]= (freq/10) | 0x30; //1000s
    LCD_puts(s);
    LCD_puts("Hz");
//clear variables for next calculation
    n=0;
    //freq=0;
}

int main()
{  //wait for some time to settle
    WaitMs(100);
    SETBIT(DDRB,5)
    CLEARBIT(PORTB,5)
  
    _delay_ms(50);
    DDRD=0xC0; PORTD=0x0F;//enable PD as i/p & enable pull-ups
    LCD_init(CULINE);
    SETBIT(TIMSK,TICIE1)
    TCCR1A=0x00;
    TCCR1B=0x40; //ICP RISING EDGE, without Noise Canceller
  
    LCD_puts2XY(3,0,"Welcome to");
    LCD_puts2XY(2,1,"ElecDude.com");
    WaitMs(800);
    LCD_clearall();
  
    LCD_putsPXY(2,0,"Low Frequency");
    LCD_putsPXY(3,1,"Measurement");
    WaitMs(1100);
    LCD_putsPXY(2,0," Acc +/- 1%");
    LCD_putsPXY(2,1,"F < 1KHz only");
    WaitMs(1500);

begin:
    LCD_putsPXY(0,0,"Press S1 to strt");
    while(button(sw1)==0);
    LCD_clearall();WaitMs(500);
    LCD_putsPXY(0,1,"Press S1 to STOP");
    while(1)
    {
        RunT1();
        WaitMs(50);
        flag=0;
        sei();
        while(1)    //Wait till the 5 samples are taken
        { if(flag==1)
            {
                cli(); //disable interrupt once all samples are taken, then continue calculus
                break;
            }
        }
        StopT1();
        calc();
        WaitMs(1200);
        if(button(sw1)==1)
            {
              WaitMs(1100);
              while(button(sw1)==1);
              LCD_clearall();
              goto begin;    }
    }
 return 0;
}

The output snapshot of the Frequency measurement project

1

2

3

4

output2

output

Click here to get the LCD header file [1]  or in Mirror2

Click here to download FreqMeter HEX file.


0 comments:

Post a Comment

Search Here...