# Frequency counter using Analog Pin

Hi There,

I am trying to read the frequency or a time period of an analog signal (AC grid signal which I already know 50 Hz frequency or one positive cycle is 10 ms) using chipkit 32mx using Arduino platform.

My intention is to read the analog input at pin AO and initiate the counter as the positive pulse started from zero until it reach the next zero. Ideally it should give me the time period of 10 ms as I am applying a analog signal of 50 Hz.

My program is :

int out = 13;
int counter=0;

void setup() {

pinMode(out, OUTPUT);
pinMode (A0, INPUT);

}

void loop() {
digitalWrite (out, HIGH);
delay(counter);
digitalWrite (out, LOW);
delay(counter);

}

after reading its time period I want to save its time in one register (name as counter) and later generate output of same period using PWM pin.

But unfortunately after running this program my controller is giving output of 1 us only.

Kindly advice me what approach I should use to calculate and save the required time period.

I do not know about the chipkit but the analog inputs on the arduino are single ended positive values only. That means that in order to measure a ac voltage you will either have to add a offset voltage=Vref/2 or rectify the ac voltage.
Also there are portions of your code that make little sense to me:
for (analogRead(A0)==0;-> here a lvalue is required
...counter++ ); ->just increases a counter as fast as it can, there is no correlation to the delay() whis counts in milliseconds. I believe what you want to do is something like this:

``````while(!/*expression for zero crossing*/);//wait for first zero crossing
unsigned long mark = micros();//record time of first zero crossing
while(!/*expression for zero crossing*/);//wait for second zero crossing
while(!/*expression for zero crossing*/);//wait for third zero crossing
unsigned long period = micros()-mark;
``````
``````for (analogRead(A0)==0; analogRead(A0)>0;counter++ );
``````

What is this nonsense? You have a useless initial condition, an absolutely silly while condition, and a completely useless increment condition for a loop that accomplishes nothing.

nilton61:
I do not know about the chipkit but the analog inputs on the arduino are single ended positive values only. That means that in order to measure a ac voltage you will either have to add a offset voltage=Vref/2 or rectify the ac voltage.
Also there are portions of your code that make little sense to me:
for (analogRead(A0)==0;-> here a lvalue is required
...counter++ ); ->just increases a counter as fast as it can, there is no correlation to the delay() whis counts in milliseconds. I believe what you want to do is something like this:

``````while(!/*expression for zero crossing*/);//wait for first zero crossing
``````

unsigned long mark = micros();//record time of first zero crossing
while(!/expression for zero crossing/);//wait for second zero crossing
while(!/expression for zero crossing/);//wait for third zero crossing
unsigned long period = micros()-mark;

Thank you very much for your reply. Actually the same thing I am trying to do I am passing AC signal through a half bridge then the positive cycle of approx 10 ms I am applying to Analog pin AO.

By also using while statement my counter is not increasing its like its counting for only one cycle which is 1 us.

If you can help me out with its program I will appreciate because actually I am new to arduino platform.

Regards.

PaulS:

``````for (analogRead(A0)==0; analogRead(A0)>0;counter++ );
``````

What is this nonsense? You have a useless initial condition, an absolutely silly while condition, and a completely useless increment condition for a loop that accomplishes nothing.

Thank you for your reply I really appreciate your response. However Sir, I am new to arduino platform and I am trying my best to learn it. I will appreciate if you can suggest any idea or example for reading the time period of pulse instead of while or for statements.

Regards.

What is the voltage? And do you really need to use a analog pin? If you only want to dertermine the period a digital pin will work better, when the level is low you will have the negative half period, when the level is high you are on the positive half period

nilton61:
What is the voltage? And do you really need to use a analog pin? If you only want to dertermine the period a digital pin will work better, when the level is low you will have the negative half period, when the level is high you are on the positive half period

Voltage varies from 0-4V.

Actually I have to determine the period of the AC pulse which is sine wave.

Thanks

zshahid:
Voltage varies from 0-4V.

Actually I have to determine the period of the AC pulse which is sine wave.

Has the sine wave had any bias applied to it else I would expect -4 to +4 volts for a sign?
As has probably been stated here already the Arduino pins cannot handle negative voltages so you will need to half/full wave rectify or bias the zero point and maybe voltage divide that to remain on or below 5V.

I would consider reading this excellent article and using the comparator interrupt to measure the frequency.

Well I am applying only positive pulse of the AC sinusoidal by using half bridge rectifier and I have step down the voltage from 220 V to 4.4 V as Maximum input range at analog pin is 5 V.

So, what you have done is basically this? I certainly hope that you realize how dangerous this circuit is if connected to mains voltage

Perhaps you would do better to sense the current indirectly through a coil or linear Hall sensor?

Consider using a zero crossing detector with an optocoupler instead. Connect the output to a digital pin

PaulS:

``````for (analogRead(A0)==0; analogRead(A0)>0;counter++ );
``````

What is this nonsense? You have a useless initial condition, an absolutely silly while condition, and a completely useless increment condition for a loop that accomplishes nothing.

Ah, but Paul: That's what they want you to think.

I have step down the AC 220V to 12V using step down transformer and than later I am clipping its negative cycle using half bridge rectifier then using a potentiometer or voltage divider to get 4V from 220V input.

nilton61:
Consider using a zero crossing detector with an optocoupler instead. Connect the output to a digital pin

Thank you but Sir my task is to use analog pin ... and that is where the difficulty arrives..

As long as the wire is not shielded or paired, a linear Hall sensor will analog detect the pulse without need to step down or even touch the wire metal. Your circuit will be minimal.

Ok, 12V rms sinus gives you a peak amplitude of 17V. If you chose Vref/2 as your AC zero you can build a circuit like the one attached. The voltage vill swing from about 50mV for ACV = -17V to 5V for ACV = 17V. with 2,5 being equal to ACV=0. This will give you a analog reading of 512. Your code will then be:

``````const int aIn = A0;
int positive;
unsigned long period;
unsigned long mark;

void setup(){
while(analogRead(aIn)>512);//wait for positive half period to expire
while(analogRead(aIn)<512);//wait for negative half period to expire
mark = micros();//zero crossing from negative to positive found
while(analogRead(aIn)>512);//wait for positive half period to expire
while(analogRead(aIn)<512);//wait for negative half period to expire
period = micros()-mark;
}//setup()

void loop(){
}//loop()
``````

Thank you nilton61.

Did you make it work?