# Sensing Voltage with a Digital Pin

I am relatively new with Arduino and did a little bit of research prior to this post. But I am trying to sense when I have voltage coming from an AC/DC converter (12Vdc) so I can switch from my battery to my AC/DC converter. I am using an interrupt on my Arduino Mega to efficiently switch between power sources. I tried just using a voltage divider and reading 5 volts into my digital pin, but it seems that the pin is "floating" regardless of power being supplied or not, and not correctly sensing the voltage coming from my AC/DC converter. Is there a way for me to incorporate capacitors or some other circuit to correctly sense voltage with a voltage divider? Any help is appreciated.

simulate this circuit – Schematic created using CircuitLab

• It's impossible to tell what is wrong with your current circuit without some sort of schematic. You can use the site's CircuitLab editor to enter it. – tcrosley Mar 17 '16 at 21:34
• You wrote "digital pin". If you have the pin configured as a digital input, you will only be able to sense as zero below a somewhat indeterminate and a one above another voltage. These voltages will change with temperature, from unit-to-unit, and so on. Between these two voltages, the result is undefined and may even damage the input. You want to use an analog input instead. – DoxyLover Mar 17 '16 at 22:17
• Have you measured the voltage with a voltmeter at the pin to confirm that the 4V is indeed there? Could this be a software mistake? – DigitalNinja Mar 17 '16 at 22:29
• @DigitalNinja All I'm doing with my code is declaring the pin as the input, and I'm using a Serial.println(digitalRead(2)); and with power applied the signal is still all over the place. I'm reading 5V into my pin, checked with a multimeter. I'm not sure why its acting this way. – Mason Mar 17 '16 at 23:01
• Is the ground on that schematic connected to the Arduino ground? – Roger Rowland Mar 18 '16 at 4:42

You say you are using an Arduino Mega board which implies ATMega1280 or 2560. Both of these have an Analogue Comparator module which is built in. The Arduino boards route out the pin with the alternate function of "AIN1" to what Arduino call "digital pin 5".

If you enable the internal bandgap as the reference as the source for "AIN0" (something which is configured internally), then you can basically use a potential divider on D5 which is calculated so that when the battery voltage drops below a certain threshold, the centre of the divider (connected to the pin) drops below 1.1V. When this happens, the comparator inside the ATMega will change state and this event can be configured to generate an interrupt (ISR(ANALOG_COMP_vect)).

The comparator can be configured using the following C code (compilable with avr-gcc):

//Code to enable comparator
ADCSRB &= ~(1 << ACME); //Connect AIN1/D5 to the comparator
DIDR1 |= (1 << AIN1D); //Disable digital functionality of AIN1 pin so we can use comparator
ACSR = (0 << ACD) | (1 << ACBG) | (1 << ACIS1) | (1 << ACIS0); //Enable comparator, connect bandgap, and set to rising edge sensitivity (AIN1 falls below AIN0)
//-------

//If you want to generate an interrupt, do this to enable it (make sure you have an ISR for ANALOG_COMP_vect):
ACSR |= (1 << ACIE); //Enable interrupt.
...
ISR(ANALOG_COMP_vect) {
//Do something when voltage drops too low
}
//-------

//If you want to do it via polling mode, do this to check the value
if (ACSR & (1 << ACO)) {
//Do something if the voltage drops too low
}
//-------


If you actually want to measure the voltage then you use an analog input and the digital integer value you get from that will be proportional to the input voltage. The resolution will be one in $2^n$, where n is the number of bits in the ADC.