This is a little something I put together when I wanted to play with a frequency counter.
I measure the period and converts that to a frequency. If it period is relatively short, it increases the number of periods measured to average the measurements.
The output is to a cheap 16x2 LCD display.
// The LCD is usually interfaced via 16 pins which are labelled as shown below:
//Connections to Arduino
// LCD Connection
// 1. GND - Ground GND
// 2. VDD - 3 - 5V 5V
// 3. VO - Contrast (Tap off a 5K - 10K pot across VCC and Ground)
#define LCD_RS 12 // 4. RS - Register Select - 0=Command / 1=Character Arduino Pin as defined
// 5. RW - Read/Write - 0=Write or 1=Read GND
#define LCD_ENABLE 11 // 6. E - Enable - Enable data transmit Arduino Pin as defined
// 7. DB0 - Data Bit 0 N/A
// 8. DB1 - Data Bit 1 N/A
// 9. DB2 - Data Bit 2 N/A
// 10. DB3 - Data Bit 3 N/A
#define LCD_DB4 4 // 11. DB4 - Data Bit 4 - used in 4 bit operation Arduino Pin as defined
#define LCD_DB5 6 // 12. DB5 - Data Bit 5 - used in 4 bit operation Arduino Pin as defined
#define LCD_DB6 7 // 13. DB6 - Data Bit 6 - used in 4 bit operation Arduino Pin as defined
#define LCD_DB7 8 // 14. DB7 - Data Bit 7 - used in 4 bit operation Arduino Pin as defined
#define LCD_Backlight 9 // 15. BL1 - Backlight + Emitter of 2N3904, Collector to VCC, Base to D9 via 10K resistor
// 16. BL2 - Backlight - GND
// I2C
// A4 - Data (SDA)
// A5 - Clock (SCL)
#include <Wire.h>
#include <Time.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(LCD_RS, LCD_ENABLE, LCD_DB4, LCD_DB5, LCD_DB6, LCD_DB7);
#define SAMPLE_SIZE 1
static uint16_t iSample_Size = SAMPLE_SIZE;
volatile uint32_t iSample;
volatile char bSamplesCtl = -1; // -1= Stop, not taking samples 0=Start taking samples 1=Sample are ready
void setup () {
Wire.begin();
lcd.begin(16, 2); lcd.clear();
pinMode(LCD_Backlight, OUTPUT); analogWrite(LCD_Backlight, 128); // Set the brightness of the backlight using PWM
pinMode(2, INPUT_PULLUP);
attachInterrupt(0, Pin2_ISR, FALLING);
bSamplesCtl = 0; // Start taking timing samples
}
void loop() {
delay(500);
lcd.setCursor(0, 0);
if (bSamplesCtl != 1) { // Sampling not complete
lcd.print('*');
} else { // we have a set of samples
uint32_t iFreq;
if (iSample_Size <= 4000) {
iFreq = (1000000L * iSample_Size) / iSample;
} else {
iFreq = 1000000L / (iSample / iSample_Size);
}
lcd.print(iFreq); lcd.print("Hz ");
lcd.print(iSample);
lcd.print(" ");
lcd.print(iSample_Size);
if (iSample < 1000) { // Less than one millisecond worth of samples
iSample_Size *= 2; // double the samples
if (iSample_Size > 4000) iSample_Size = 4000;
}
bSamplesCtl = 0; // Take another samples
}
}
void Pin2_ISR()
{
static uint32_t iPrev = 0;
static uint16_t iSampleCnt = 0;
uint32_t iTemp = micros();
if (bSamplesCtl == -1) return; // -1= Stop, not taking samples
if (bSamplesCtl == 1) return; // 1= Sample ready for use.
// 0= Taking samples
if (iSampleCnt == 0)
iPrev = iTemp;
iSampleCnt++;
if (iSampleCnt > iSample_Size) { // Sampling complete
iSample = iTemp-iPrev; // Save results
iPrev = 0; iSampleCnt = 0; // Clean-up ready for next use.
bSamplesCtl = 1; // 1= Sample is ready for use.
}
}