Very non-linear voltage readings with analog input

This one's got me stumped. It's probably something simple that I'm overlooking. :-[ I built a circuit to monitor and control my solar water heater. The circuit is based on an Arduino design, but I made a custom circuit board. One of things that this board will do is monitor and report the voltage of the 12v battery powering it, and the voltage of the solar photovoltaic panel that charges the battery and powers the circulation pump. I'm using identical voltage dividers on both circuits (positive - 10K - 4.7K - ground) with an analog pin at the junction of the two resistors. The PV panel has a diode between it and the battery, and the positive side of the battery also goes to a 7805 to drive the rest of the board.

Ok, if you're still with me after that description, here's the problem: I hooked up the board to an adjustable power supply instead of the battery, so I could figure out the right multiplier to convert the analog reading to the correct voltage. I adjusted the power supply in 1/2 volt steps from 4.5 volts to about 15 volts, and plotted a graph of voltage vs. value read from the input pin. The resulting graph looks something like a checkmark. At 5 volts the analogRead() returned about 460. It dropped more-or-less linearly to about 430 at 6.5 volts, then increased in a straight line, as one would expect, from there all the way to about 1000 at 15 volts. This has really got me scratching my head. What could cause the nonlinearity below 6.5 volts? Unless I can figure this out, I won't be able to measure the battery voltage below about 7.5 volts, because I won't know which side of the curve my measurement is on. I realized that I had forgotten to connect the AVCC and AGND pins on the ATMEGA168, so I connected them to Vcc and GND, respectively. All that did was slide the graph down a bit on my chart, but it didn't change the shape of the curve. Does anyone have any ideas?

The only idea I have is one you won't like ... by not powering AVCC you damaged the A/D subsystem of the chip.

Can you try this again with another chip?

Ouch! You are right about me not liking it. :P It's not that big of a deal really, as I'm planning to replace the chip with a '328 anyway. I ran out of memory space on the '168. I'll try it tonight or tomorrow and post the results here. Thanks for the tip.

Will not powering AVCC really damage the chip? I'm sure the voltage on the analog pins never got above 5V - that's the reason I put in the voltage divider. Seems like I read something in the datasheet about only having to power it if you needed to adjust the range of the ADC. Maybe I should go back and re-read that section.

You're thinking of AREF. That's what can be used to adjust the range of the ADC. AVCC always has to be powered and be the same as VCC. They make it a separate pin so you have the option to keep it "cleaner" (electrically) and improve accuracy of readings.

I don't actually have much faith in the theory that the A/D part of the system was damaged, I just can't think of anything else :-) Don't forget software errors, too. That's still a possibility.

How good is the power supply? Some cheap unregulated wall-warts have a much higher no-load voltage than their rating. For example, I have one that's rated 12V, but with no load attached it measures more like 17V.

-j

What else is connected to the Analog inputs?

I've noticed some bleed-over between analog channels. I've minimized this by using channels physically far apart on my Duemilanove (i.e. A0 and A5).

I'm using only two analog inputs; zero and one. One is to monitor the voltage of the gel-cell powering it, and the other monitors the voltage on the solar PV panel. I'm sure it's not bleed-over because my test was without the PV panel plugged in. Regarding the power supply, I monitored the voltage with a DVM while testing. I tried replacing the chip to rerun the test, but all I have is an atmega328 to replace it with. It's supposed to be a drop-in replacement, but I can't get the sketch download to start on the darn thing. Every time I try, I get the "avrdude: stk500_getsync(): not in sync: resp=0x00" error. I searched the forums and it seems that a lot of folks get this problem, but nobody knows how to fix it. :(

As a side not, I get this error with the '168 plugged in too, but only on every other attempt to download a sketch. Never could figure that one out either, but maybe it has a bearing on this problem.

The upload baud-rate in the bootloader is normally different between 168 and 328s. 328s usually upload at 57600 baud and 168s at 19200 baud.

Make sure you have a compatible board selected.

Thanks, that fixed the upload problem. Increasing the baud rate makes sense when you think about it. Someone should write that down! :smiley:

Back to the original problem. With the new '328 installed and the test program uploaded to it, the shape of the graph did not change. It follows the same checkmark-shaped plot exactly as it did with the '168. I guess that’s good, since it means I didn’t burn up my processor, but it’s bad because we’re out of theories for the nonlinearity.

Thinking out loud here - you don’t suppose that the battery being connected to the input of a 7805 voltage regulator could be the culprit, do you? During the test, I measured and adjusted the voltage at the input to the board (where the battery goes). This connection goes to the first resistor of the voltage divider, but it also goes to the 7805 to power the rest of the board. Maybe I’ll try isolating that this evening and rerunning the test. It never occurred to me to put the DVM right on the analog pin. If that turns out to be the problem, though, not sure what I can do about it. The board has to have power.

If the voltage to the chip drops, then it'll be a problem. The input voltage to the AVR is used as the reference voltage that you are comparing against. Thinking about it, you have to be undervolting the regulator, the minimum input voltage is 7.2V.

*** UPDATE *** I was wrong about the default state of the AREF pin(http://arduino.cc/en/Reference/AnalogReference)

The default configuration on all Arduino implementations is to have nothing connected externally to the AREF pin (Atmega pin 21).

*** END UPDATE ***

Anyhoo, there is a 1.1V bandgap voltage that you can compare against instead of Vcc, which won't change with the input voltage. You !!!HAVE TO!!! disconnect the Aref pin from the 5V source!!! Pretty much every Arduino out there connects Aref to 5V. DO NOT just select the 1.1V reference voltage.

The check-mark shape still doesn't make sense, but I don't know that much about the characteristics of the 7805 when it doesn't get enough power. Could you try using a separate battery for the Arduino?

Right! If the ADC's reference voltage isn't stable/known, the ADC readings will be garbage. Been there, done that, did the "doh!" headsmack when I figured it out.

A 7805 needs 2V to regulate, and a standard arduino includes a diode, so you'll need about 7.6V minimum input to get a stable 5V out of the regulator.

Do your experiment again, only this time also check the 5V line on the arduino to see if it's really 5V. If not, mystery solved.

-j

Aw, geez, I bet you're right. Kinda like sawing off the limb that you're sitting on. I knew it had to be something dumb that I did. :-[

I'll test that this evening, but it's pretty obvious now that that's the problem!

Hmm... am I just wrong about Aref normally going to 5V? I was looking at the Duemilanove and it doesn't... now I feel kinda stupid about the warnings.

Anyhoo, changing your voltage divider and using a 1.1V reference would work as long as your Arduino functions on the voltage supplied by the regulator.

*** UPDATE *** Ya, just totally wrong (http://arduino.cc/en/Reference/AnalogReference)

The default configuration on all Arduino implementations is to have nothing connected externally to the AREF pin (Atmega pin 21).

I was thinking AVCC, which is just wired to VCC, but that's different.

Mystery solved, that was it. I changed the voltage divider resistors to the appropriate values where 20v = 1v, set the analog reference to internal, and now the graph plot is a beautiful straight line.

Thanks for all of the help!