Reading "ac voltage pressence" using software only.

I have connected analogRead(An) to a speaker that is driven by low voltage 0.5 - 1.5, that speaker is just a "standard" home interphone system which "rings" when you press the interphone bell.

I am aware that I cannot continously read that voltage because it is AC.

I cannot use bridge rectifier because volteges are to low to pass through standard diodes.

Can you provide a general idea of how can I measure frequency which I will "use" as a voltage present indicator?

The measurment I need is not precise frequency, just to measure if "some" frequency is present than state is HIGH and if no frequency present state is LOW.

Is it doable without using interrupts?

Easy! Make the bridge rectifier out of individual small-signal diodes.



One approach is to use capacitors (e.g. 10 uF) to isolate the speaker from the input, and a voltage divider (10K:10K) between GND and Vcc to set the input to half the power supply voltage. The presence of an AC signal will cause variations in analogRead() values. See below

This assumes that there is no large DC or AC voltage between GND and the speaker output. If there is, you could have a serious problem in connecting the devices.




Can you, if possibile in short, explain the theory behind this circuit.

DO I need "small signal" diodes in this setup?

Capacitors block DC voltages and pass AC voltages. The AC signal that gets through will be added to the Vcc/2 voltage produced by the voltage divider, and can be read out by analogRead(A0).

Expect the output of the analogRead(A0) command to produce a time varying signal when the "ring tone" is present.

No, you do not need small signal diodes.

Edit: A safer alternative is to use a transistor audio output transformer, which you can buy or get out of an old transistor radio, or perhaps from a toy with a speaker. The transformer would also increase the voltage, so I've added an additional resistor (R3) to protect the analog input from damage.



Thank you for this.
Now I know what to read and how to think about this.

I accidentally submitted without finishing.

After few hours of reading this morning, I also think that I have dug up the reason why i need to repair the code.

Signal is AC, the first code runs fast enough to detect positive side more than once in a millisecond.
And the doorlock is opened.

The second code detects voltage positive also and then in the next milli() it detects the end of ringing. The problem is in my ringing part of the code. I will all the same use "IF" = ).

I have posted another thread about counting frequency. But that is too far and advanced. This should work once I fix it. Will postback the final solution.

Conclusion is that this is the code issue. Will post further question in relevant thread.

So is the aim to really detect frequency? Or you're just after a circuit to detect the presence of an ac signal? If it is the latter..... then maybe a peak detector circuit. But your opening post mentions "low voltage 0.5 - 1.5". You should express clearly what is meant by "0.5 - 1.5".

Hi Southpark,

What I meant by 0.5 - 1.5 is AC voltage that is present on the speaker while it is ringing.

Please have in mind this is "simple" door Interphone. I am aware there are various Interphone systems and signals are different.

I have done quick and dirty "hack" to just test my code, arduino and toys I got with arduino kit.

What I need is to sense voltage on Interphone speaker. Voltage is present at the speaker only when Interphone is ringing so there is no special cases.

Because it is AC signal Arduino will detect only positive site of a wave. This is okay if I do.

if( analogRead(A1) > 0 ) just once and then open the door delay(n) timeand I am happy that this works as intended.

Now the logic for "advanced" sensing is what I lack.

Because it is AC I cannot count time of ringing simply with START STOP variables. Because if I measure that with just analogRead(A1) my stop will be immediatelly after the signal goes into negative side.

I think that I should measure.

If at least once in eg. millis(20) there is positive peak.

That way I can tell Arduino that the doorbell is still ringing.

Then, I need to note the time of FIRST positive peak and the last positive peak in this 3 second period.
That way I can calculate that I actually rang for the N seconds duration.

This is where I am stuck.

No code is needed for help. Just a general direction how should I do this.

I beleive that this thread is solution for me.

Because it is AC signal Arduino will detect only positive site of a wave.

You will actually damage the Arduino if you expose the input to negative voltages, or voltages > Vcc.

I am aware of that. This will not be long term solution.

But for the sake of coding I will use this until I manage to understand what I need to do.

This will not be long term solution.


Markoitel.... thanks for explaining. You might be in luck. Try this very basic circuit...... the output of that could go to the input of an analog pin of an arduino

I do not mind to buy another Arduino board if this one is fried.

I know that some of the purists do not even want to try to answer if they see approach like "I don't care if I burn it."

As I said, this is code wise question, can you look at it like that.

So it is not the point will I fry the board or not. It is completely clear what are the consequences.

Here is what I do have so far.

My test got a NEW level of stupid, yes I know but it is perfect environment for this test. I do not have to go downstairs upstairs.

Audio output from my laptop is enough for Arduino sensor analogRead(A1) to read the current when on positive side.

So now I can "emulate" ringing when I play a song. I do have ZERO ( negative side of wave ) and random positive values ( positive side of wave ).

Here is the code that partially works.

void setup() {

unsigned long currentMillis;
unsigned long ringStartTime = 0;
bool ringing = false;

void loop() {
  currentMillis = millis();
  if ( analogRead(A1) > 0 ) {
    if ( !ringing ) {
      ringStartTime = currentMillis;
      ringing = true;
  if ( ringing and currentMillis - ringStartTime > 100 and analogRead(A1) == 0) {
    delay( currentMillis - ringStartTime );

    ringStartTime = 0;
    ringing = false;

  Serial.print("RingStartTime: ");
  Serial.print("CurrentMillis: ");

Idea is that I ignore ZERO each 100 millis. But than again if I still RING and want to RING more than 100 millis. I get into issue that sometimes A1 will be zero and condition is met for OPEN.

My approach is completely wrong I see that from the code. But I've posted it to have something to work with.

I want to achieve to ignore negative reading as long as I am ringing. I know this sounds really stupid because ringing will stop once it hits negative side.

I guess I need backOff time check. So when I really do STOP ringing wait for 1 second before opening.

If under one second there is ringing pressent do nothing again until next backoff time.

I guess I need to reset some checks at some point, but just cant grasp it.

Probably best to use a few components..... resistor (eg. 1 kilo-ohm), basic diode, and capacitor (eg. 100 uF)..... build a peak detector. Then all you need to do with your arduino is to monitor DC voltage level. If it stays above a particular DC voltage level for X milliseconds, then audio is being generated.

At the moment, it's also possible that you could be confused between the words 'frequency' and 'AC signal'. You speak of 'detecting frequency', but you probably actually mean 'detecting presence of an AC signal'.

Hi Southpark,

Yes from my posts I mixed all of the terms. The frequency is not what I need, but at some point I have mentioned frequency also. Reason for that is that maybe I should look in that direction in order to write my code in a good direction. And yes this is AC signal and the tone that I hear is something like a turkey = )

I would guess somewhere at 2khz.

Thanks for the link for peak detector.

Thing is that I am assured that this is so easy once I grasp the concepts and the way of thinking in order to understand the logic.

I am not throwing away suggestions you are giving. This is not about interphone, the goal is programing.
And along the way if I can ease myself opening the door the merrier is the result of my learning.

I guess you understood what I want to do fully?

I guess you understood what I want to do fully?

I think I know what you're trying to do. Let me confirm it. You have an AC source. And whenever the AC source becomes active, you want the arduino to be able to detect it, right?

At the moment, it seems that your aim to detect the AC signal is to use the analog input to constantly sample the voltage. Since the AC signal amplitude will change, and even disappear... this needs consideration. The arduino analog-to-digital converter doesn't convert negative voltages from the negative half of the AC signal. And maybe not a good idea to apply negative voltages to the analog input pin of the arduino. This means you might have to at least use 1 electronic component, like a diode prevent negative voltages from reaching the analog input pin. But if you use 1 cheap component, then might well use 2 more cheap components --- a resistor and a capacitor. The diode, resistor and capacitor can form a 'peak detector' circuit, that basically produces relatively slow-changing voltages. This allows the arduino to detect your AC signal fairly easily. Makes your programming easier to do as well.

Yes that is general idea.

I do not need any detail regardin AC signal. I just need to detect AC signal whenever it is on positive side.

I do not care about the value of the detected signal.

I cara only about the time that signal is present.

So when I press interphone button Arduino starts measuring the time it is being pressed.

THanks for suggestions. If I come up with a code that suits my idea will post it for a code review.