Frequency Counter Library

I am using this:
http://interface.khm.de/index.php/lab/experiments/frequency-measurement-library/

Are we talking about the same library? Is the above library in the link able to detect zero RPM and speed?

This is the hall effect sensor we use: http://www.digital-speedos.co.uk/hall-effect-speed-sensor-for-drift-gauges-non-magnetic-382-p.asp

Have you considered using a light based counter? Shine an IR light at whatever is spinning and fix piece of something shiny to it. Then point an IR detector at it which should detect rotation.

How can I do this with a car? Especially the engine rpm?

matinzk:
How can I do this with a car? Especially the engine rpm?

Maybe you can fix something shiny or use shiny paint on one of the main belts?

Please do not paint belts. The paint may damage the belt (thanks to the enclosed / entrained solvents) and lead to premature cracking. Not only are modern belts very expensive to replace, losing one will usually leave you stranded. Not the best way to impress the missus.

Instead use a hall-effect or optical rig on a sprocket or similar device that does not need physical modification.

Constantin:
The paint may damage the belt (thanks to the enclosed / entrained solvents) and lead to premature cracking.

Honestly this is not my place to expertise but it would seem there is certain types of paints that would not be a problem.

Not only are modern belts very expensive to replace, losing one will usually leave you stranded. Not the best way to impress the missus.

Last time I looked, the belts were not all that expensive. But losing one can indeed leave you stranded but alas this is a risk with any type of engine modification.

SmeezeKitty, do as you wish.

All I can tell you is that I had to replace every rubber hose on a diesel engine because some lugnut sprayed them with the same 'Perkins blue' as the rest of the engine. And to do that, we got to lift the engine out of the boat, drain it of all fluids, etc. Not the fastest fix.

Every hose had cracked thanks to this painting treatment. Given how important belts are, I wouldn't mess with them and pick up the desired signal elsewhere.

I got this to work well on one sensor, using my Arduino UNO.

But I have not been able to get it to work at all on a Leonardo. [ Serial doesn't even print the 'Frequency Library' line at the start] Have there been major changes to serial for Leonardo?

Another question is, how would I be able to expand this to multiple sensors without using multiple Arduinos?

Hello to everybody, first of all I'm not an expert altought I have succeed so far with some small Arduino based project.
I'm now trying to develop a radioastronomic receiver (radiometer) controlled by Arduino.
Now the topic:

  • I have an Arduino Uno rev.2 with an Ethernet shield with microSD slot (both not yet used, but useful later on)
  • In order to control the receiver I have to program 2 different PWM on 2 different pins
  • for what I read on the web pages, I can use the instruction analog.write(pin,pwm) on the pins 3,5,6,9,10,11 if not already used by other devices
  • the pin 5 (T1) is used to read the OL frequency of the receiver by means of the library FreqCounter.h herewith discussed..
  • pin 3 seems to be used by the Eth shield as well as the pins 0,1,2,4,10,14,15
  • thus, "fre to be used" for my purpose, remain the pins 6,9,11

Unfortunately only the output on the pin 6 works. Pins 9 and 11 always are at low level, no PWM, even with no shield on top of the Arduino Uno.
The board works fine is I do not call the frequency reading routine.
What I'm doing wrong? Waht shall I do to fix the trouble?
On the following a draft of the cose I'm using. Please note it's a very early draft of what I would do, so several variables are defined but not used yet.

Many thanks to all for the help!
Pierluigi

#include <FreqCounter.h>

// OL input on digital pin #5

const short pwm1=9; // pin 9 is 8 MSB PWM
const short pwm2=6; // pin 6 is 8 LSB PWM

long int frq; //frequency read
long int IF=10700000; // first IF of the Rx
const short prescaler=8; // scale factor of the ext. prescaler
const long int fastro1=25610000; // astro1 = 1st frequency
const long int fastro2=13385000; // astro2 = 2nd frequency
long int OLnow; // current OL frequency
long int RXnow; // current RX frequency
long int errore=0; // frequency error

int pwmh; // 8 MSB of PWM
int pwml; // 8 LSB of PWM

float Vastro1=0.2035; // VCO nominal input for fastro1
// float Vastro2=3; // VCO nominale per rx frequenza fastro2

int bitbase1=Vastro165535/5; // total PWM bits (res.16) of feed forward VCO a freq. astro1
// int bitbase2=Vastro2
65535/5; // bit di PWM totali (risoluzione 16) del feed forward tensione VCO a freq. astro1

void setup() {
Serial.begin(9600); // connect to the serial port
Serial.println("Frequency Counter");
}

void loop() {

FreqCounter::f_comp= 5; // Set compensation
FreqCounter::start(1000); // Start counting with gatetime of 100ms
while (FreqCounter::f_ready == 0) // wait until counter ready

frq=FreqCounter::f_freq; // read result
OLnow= frq*prescaler; // OL frequency calculation
RXnow= OLnow-IF; // RX frequency from IF and OL
errore= RXnow-fastro1; // tuning freq. errorcalcolo errore di sintonia

pwmh= bitbase1/256;
pwml= bitbase1-256*pwmh;

analogWrite(pwm1, pwmh);
analogWrite(pwm2, pwml);

Serial.print("bitbase1= ");
Serial.print(bitbase1);
Serial.print(" pwmh= ");
Serial.print(pwmh);
Serial.print(" pwml ");
Serial.print(pwml);
Serial.print(" frq= ");
Serial.print(frq);
Serial.print(" OLnow= ");
Serial.print(OLnow);
Serial.print(" RXnow= ");
Serial.print(RXnow);
Serial.print(" Errore= ");
Serial.println(errore);
delay(20);
}

How about a variation on the frequency counter lib that takes its input from the analog comparator? This would avoid the need for a preamplifier. You wouldn't be able to count the input directly in counter 2 because AFAIK it can't be clocked from the analog comparator output. However, you could use the analog comparator interrupt to count pulses, and use timer 1 as before to define the gate time.

Hey,
first of all, thanks for the great library!

I have a small issue with my LEDs and this library. They are working if I give them the value "HIGH" or "255". But however they are not working with a lower value. I have tested the leds in an other sketch. So they are correctly wired and working fine, also the arduino. It seems to be a problem with the "FreqCounter::start(100);", if I remove it, the lower values are working, but of course the frequency counter not...

has someone an idea? thanks in advance!

Assuming you mean the frequency counter library at http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/, it uses timers 1 and 2, and disables timer 0 during the gate time. This means that none of the PWM pins on a Uno will work while you are measuring a frequency.

If the frequency you want to measure is less than about 10kHz, there are other ways of measuring it that take over only one timer, or even no timers at all.

Sorry, I forgot to mention it ... you are right, I am using this library: http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/. And I am using a Arduino Duemilanove.

The frequency I'd like to measure are under 10kHz. Do you have an example code in which one or more timers are disabled? I tried to look for an other library, but all of them are using the 3 timers ... so I would be really glad if you can help me out!
thanks in advance.

  1. What will be the approximate frequency, and how accurately do you need to measure it?

  2. Will the input be a 5V square wave, or would you like to use the built-in analog comparator to allow much smaller input signals?

The frequency will be between 85 and 255Hz.
I am using a pulse Generator which gives sqare waves with a maximum of 5V.

The frequency will be between 85 and 255Hz. 
I am using a pulse Generator which gives sqare waves with a maximum of 5V.

then using an interrupt might be the easiest way - check attachInterrupt example

Try this:

// Frequency counter sketch, for measuring frequencies low enough to execute an interrupt for each cycle
// Connect the frequency source to the INT0 pin (digital pin 2 on an Arduino Uno)

volatile unsigned long firstPulseTime;
volatile unsigned long lastPulseTime;
volatile unsigned long numPulses;

void isr()
{
  unsigned long now = micros();
  if (numPulses == 0)
  {
    firstPulseTime = now;
  }
  else
  {
    lastPulseTime = now;
  }
  ++numPulses;
}

void setup()
{
  Serial.begin(19200);
}

// Measure the frequency over the specified sample time in milliseconds, returning the frequency in Hz
unsigned int readFrequency(unsigned int sampleTime)
{
  numPulses = 0;                      // prime the system to start a new reading
  attachInterrupt(0, isr, RISING);    // enable the interrupt
  delay(sampleTime);
  detachInterrupt(0);
  return (numPulses < 2) ? 0 : (1000000UL * (numPulses - 1))/(lastPulseTime - firstPulseTime);
}

void loop()
{
  unsigned int freq = readFrequency(1000);
  Serial.println(freq);
  delay(1000);
}

Here is an improved version of the frequency counter sketch. There were a couple of problems with the previous version:

  • when you attach the interrupt, you can get an immediate interrupt if this input is already high. This resulted in some jitter in the frequency reading. So I now ignore the first interrupt.

  • if the pulse count (i.e. frequency multiplied by the sample time in seconds) was greater than about 4000 then the calculation would overflow. So I have changed it to use floating point calculation instead. This also give a more precise result when the number of cycles counted is low.

// Frequency counter sketch, for measuring frequencies low enough to execute an interrupt for each cycle
// Connect the frequency source to the INT0 pin (digital pin 2 on an Arduino Uno)

volatile unsigned long firstPulseTime;
volatile unsigned long lastPulseTime;
volatile unsigned long numPulses;

void isr()
{
  unsigned long now = micros();
  if (numPulses == 1)
  {
    firstPulseTime = now;
  }
  else
  {
    lastPulseTime = now;
  }
  ++numPulses;
}

void setup()
{
  Serial.begin(19200);    // this is here so that we can print the result
  pinMode(3, OUTPUT);     // put a PWM signal on pin 3, then we can connect pin 3 to pin 2 to test the counter
  analogWrite(3, 128);
}

// Measure the frequency over the specified sample time in milliseconds, returning the frequency in Hz
float readFrequency(unsigned int sampleTime)
{
  numPulses = 0;                      // prime the system to start a new reading
  attachInterrupt(0, isr, RISING);    // enable the interrupt
  delay(sampleTime);
  detachInterrupt(0);
  return (numPulses < 3) ? 0 : (1000000.0 * (float)(numPulses - 2))/(float)(lastPulseTime - firstPulseTime);
}

void loop()
{
  float freq = readFrequency(1000);
  Serial.println(freq);
  delay(1000);
}

Very good sample DC42,
another argument to use float division is that integer division truncates.

(you just beat me :slight_smile:

Oh great! Thanks alot!!
This Frequency counter works really really good for me! Now I can move on :slight_smile: ...