Hi,
Worked this weekend on a frequency counter that also reports the duty cycle. Several variations passed and the current proto is working quite well.
The sketch measures the frequency from 5Hz to 30KHz (~1%) and the duty cycle quite well from 5Hz to 1000Hz.
Above 1000 Hz effects come in that reduces the working range of the duty cycle measurement. I do not understand the cause here yet.
Todo:
- compare the sketch with a logic analyser.
- investigate the cause of the drop in working range at higher frequencies.
- wrap it in a box
As frequency generator I used an Arduino with HW timer for medium frequencies (500 - 30KHz) and an Arduino using (micro)delays for low frequencies (5 - 2000Hz)
As always remarks are welcome
//
// FILE: freqCounter06.ino
// AUTHOR: Rob Tillaart
// DATE: 2013-04-13
//
// PURPOSE: freq counter
//
// tested working range
//
// FREQ MIN DC MAX DC
// -----------------------
// 5 1% 98%
// 10 1% 98%
// 50 1% 98%
// 100 1% 98%
// 250 1% 98%
// 500 1% 98%
// 1000 1% 98%
// 2500 3% 96%
// 5K 6% 94%
// 10K 12% 88%
// 15K 17% 82%
// 20K 23% 77%
// 25K 29% 70%
// 30K 35% 65%
//
#define DISPLAY_INTERVAL 1000000L
#define IRQPIN 2
volatile unsigned int count = 0;
volatile unsigned int ovf = 0;
unsigned long frequency = 0;
unsigned long highCount = 0;
unsigned long totalCount = 0;
float dutyCycle = 0;
unsigned long lastDisplay = 0;
void setup()
{
Serial.begin(115200);
Serial.println("* Frequency Counter 0.6 *");
Serial.println(" ");
Serial.println("Connect pulse TTL to Arduino pin 2");
Serial.println("Connect pulse GND to Arduino GND");
pinMode(IRQPIN, INPUT);
attachInterrupt(0, pulse, CHANGE);
TIMSK1 = (1 << TOIE1); // timer overflow interrupt enabled
TCCR1A = 0x00; //
TCCR1B = 1; // prescaler == 1 => timer runs at clock speed: 16 MHz
}
void loop()
{
uint32_t now = micros();
if (now - lastDisplay > DISPLAY_INTERVAL)
{
lastDisplay = now;
cli();
{
frequency = count;
count = 0;
totalCount = highCount;
highCount = 0;
}
sei();
frequency /= 2;
dutyCycle = totalCount/160000.0;
Serial.print(frequency);
Serial.print(" Hz. - ");
Serial.print(dutyCycle, 1);
Serial.println(" %");
}
}
ISR(TIMER1_OVF_vect)
{
ovf++;
}
void pulse()
{
if (PIND & 0x04)
{
TCNT1 = 0x0000;
ovf = 0;
}
else
{
highCount += TCNT1;
highCount += ovf*65536L;
}
count++;
}