Frequency Counter help

Hi,

We are currently in the midst of doing an assignment relating to liquid level sensing.

Our main aim is to be able to measure the level of liquid in a water tank and display it using LCD.

Our sensor (probe) is made up of a metal tubing with a wire (coated with a thin layer of non conducting material) similar concept to Level measurement

Firstly, a 555 timer is used to convert the capacitance generated from the sensor probe into a frequency (~50% duty cycle) that varies from 100K Hz to 10K Hz with the increasing liquid levels.

The frequency generated will be used as an input to Arduino Uno to generate a reading for each water levels (e.g empty, 1/4, 1/2, 3/4, full), it is understandable that the reading might jump around a little, but we are unable to get a stabilized range for each levels. So is there anyway we could obtain a stabilized range for it?

We have tried running pulseIn() which gave us the readings that varies from 0 > 10+ > 20+ > ... when it is at empty liquid level.
We have tried "Smoothing", which also gives us the same results as above.

We are hoping that we do not have to implement the use of ic. But we may consider if the ic is easily available in Singapore...

Do you have a real frequency counter or an oscilloscope to confirm your 555 circuit is doing what you expect?

Have you tried a straightforward 555 oscillator with a regular capacitor?

You could also try a low frequency oscillator (say 10Hz or less) with an LED so you can see the oscillation/frequency and that will allow you to test pulsein() and your software.

My memory could be faulty, but from what I recall it's not easy to make a 555 timer with a 50% duty cycle. You don't really need a 50% duty cycle as long as the you are reading/measuring the part of the cycle that's varying with capacitance.

Wouldn't it be easier to do the capacitive sensing directly in the arduino? There is a library for that

DVDdoug:
Do you have a real frequency counter or an oscilloscope to confirm your 555 circuit is doing what you expect?

Have you tried a straightforward 555 oscillator with a regular capacitor?

You could also try a low frequency oscillator (say 10Hz or less) with an LED so you can see the oscillation/frequency and that will allow you to test pulsein() and your software.

My memory could be faulty, but from what I recall it's not easy to make a 555 timer with a 50% duty cycle. You don't really need a 50% duty cycle as long as the you are reading/measuring the part of the cycle that's varying with capacitance.

^^
We used the oscilloscope to observe our 555 timer output.

Initially we used a very small fixed capacitor(in uF) as a representative of what we could expect if we use the actual probe sensor, from there we added in variable resistors that allows us to obtain a near 50% duty cycle.
In the later part, we replaced the fixed capacitor with the actual probe and is able to obtain varying freq with varying liquid levels. But what puzzles me is the inconsistent increment and decrement when we uses the Arduino to read the HIGH time..

I will try the low oscillator method you've provide and see how it goes. :slight_smile:

If you posted your code, we might be able to find the discrepancy.

nilton61:
Wouldn't it be easier to do the capacitive sensing directly in the arduino? There is a library for that

Hi,

We wanted to stick to making the project somewhat similar to this, which is to measure the capacitance and convert it into a digital signal, so that we will be able to read and display. EP2414792A2 - Fuel gauging system utilizing a digital fuel gauging probe - Google Patents

That is to show our project manager that we understand the concept behind the actual capacitance probe used for liquid measurement, so that we can use easily available ic, programming to show.

Hi all, I've found this code that seems to work pretty well with my ongoing project, the results of the range of freq seems pretty reasonable with some occasional spike. i.e. Empty level (24k to 25k hz), spike 29k hz.

However we don't understand what some parts of the coding does, thus are we on the right path??

// This code measure the frequency of an incoming 
// square-wave signal using Timer/Counter 1 and the onboard 
// comparator. The signal I am measuring has a duty-cycle of 
// 50% but the code should work regardless of the duty-cycle.
// It should also work for non-square-wave signals so long as
// the signal voltage drops below the bandgap voltage of the
// onboard comparator (approximately 1.1 V) and is sufficiently
// clean to prevent bouncing. 

// A variable to keep track of the number of overflows on 
// Timer/Counter 1.
volatile unsigned int overflows = 0; 

// A variable to keep track of how many rising edges of the 
// signal have been counted.
volatile unsigned long edges = 0; 

// A variable to keep track of the count on Timer/Counter 1
// when I start counting the edges of the signal.
volatile unsigned long tstart = 0;

// A variable to keep track of the count on Timer/Counter 1
// when I stop counting the edges of the signal.
volatile unsigned long tstop = 0;

// A variable to store temporarily store the count on 
// Timer/Counter 1.
volatile unsigned long tnow = 0;

// This specifies how many cycles over which I want to 
// average the frequency.
const unsigned long cycles = 1000; 

// A variable to store the currently measured frequency
float frequency = 0;

void setup(void) {
pinMode(7,INPUT); // This is the analog comparator negative input.
// This is where the input signal enters the Arduino.

SREG = SREG | B10000000; // Enable gobal interrupts. They should 
// already be enabled but I like to do this out of good measure.

Serial.begin(9600); // For printing the frequency to the terminal
}

void loop(void) {
delay(500);
measureFreq();
Serial.println(frequency);
delay(500);
}

void measureFreq(void) {
edges = 0;

ACSR = ACSR | B01000010; // enable analog comparator interrupt 
// on failing edge (bit 1) which would actually capture a rising
// edge of the signal and use the internal bandgap reference
// voltage as the positive input (bit 6).
delay(5); // A short wait for bandgap voltage to stabilize.

overflows = 0;

TCCR1A = B00000000; // Set Timer/Counter 1 in normal mode where 
// it will count to 0xFFFF then repeat.
TIMSK1 = TIMSK1 | B00000001; // Turn on Timer/Counter 1 overflow 
// interrupt (bit 0).

// Turn on the counter with no prescaler.
TCCR1B = TCCR1B | B00000001;

ACSR = ACSR | B00001000; // Enable analog comparator interrupt 
// (bit 3).

while (edges < (cycles+1)) {
// Do nothing.
}

// Calculate the frequency.
frequency = (float)16000000*(float)cycles/(float)(tstop - tstart);

}

ISR(TIMER1_OVF_vect)
{
overflows += 1;
}

ISR(ANALOG_COMP_vect)
{
tnow = TCNT1; // current time
edges += 1;
if (edges == 1) { // Start counting edges.
tstart = overflows*65536 + tnow;
}
else if (edges == cycles + 1) { // Stop counting edges.
tstop = overflows*65536 + tnow;
// Turn off Timer/Counter 1 and the comparator.
ACSR = 0;
TCCR1B = 0;
}
}
1 Like