How to obtain a accurate analog reference voltage, with little drift?

I am looking to build a SMS battery monitor for the 12 Volt field battery from the electric fence of our modelairplane field. It has gotten a solar panel, but during these dark months that turned out to be not enough to keep the battery charged. One battery gone :frowning: .

The design will be very simple. A voltage divider from the 12 Volt battery linked to the ADC of a microprocessor and then when the voltage drops below a threshold, turn on the GPS/GPRS module and send an SMS. Maybe add some bling-bling later like an LCD display that show min, max and actual voltage when you press a button.

I am thinking about using a ATtiny1624, because it seems to have a very nice and modern ADC. But another AVR or STM32 is also fine. When looking in the ATtiny1624 datasheet I see that the bandgap voltage reference may have a worst case -5% to +5% inaccuracy.

But I don't know how to interpret this. Is it a temperature drift from -3% to +3% from 0 - 85 Celcius and a -5% to 5% drift from -40 to 125 Celcius? Is there a aging drift?
Or is it a fixed error, that I can compensate for in software, after calibrating the ADC results with a (Fluke) multimeter?

We have the battery in a steel field box, that is half burried and I expect temperatures in that box range from -10 Celcius (winter) to 50 Celcius (summer). In the winter, when the solar panel is not doing much it will be between -10 and 15 Celcius, so less of a temperature spread.

Would an external voltage reference perform better? E.g. using a Voltage regulator, that I need anyhow to get a 5V VCC from the 12V battery. Or using a zener to the VREF pin?

I'm not a 100% sure, but I interpret it as that the internal reference voltage has a drift of ± 5 at a temperature of -40 to 125. So the voltage the analog signal is compared to can drift by that much. You should be fine with the temperatures that it will be in.

Do you need an accuracy bettor than +/-5%?

Fair question.
These are the voltages of the battery

I scaled it with a 3:1 divider to 5 volt VREF for this calculation.

Charge         Voltage         after divider
100%           12.72 V         4.24 V
80%            12.52 V         4.17 V
60%            12.30 V         4.10 V
40%            12.09 V         4.03 V
20%            11.88 V         3.96 V
0%             11.64 V         3.88 V

A 5% error of 5V would be 0.25 V accuracy error.

0.25 V is the difference between 80% and 20% charge. I would like to measure within a 10% charge state, which would be 0.036 Volt

Or my logic must be flawed, but then it's great to get that fixed.

Without solar panel the battery needed replacement every 10 days. So 10% per day consumption. With the solar panel it gets a lot more variable. So to avoid that someone needs to drive to the field to check the voltage It would be great if I can get a SMS when the charge is at 20%. Then we have about a day to go to the field and replace the battery.

Well, if you look at the typical characteristics for the 1624 VREF, you will see that it changes very little over temperature and Vdd (< 0.5%). So you can assume that the +/-5% error is pretty much constant, thus it can be calibrated out. You know what the 100% voltage is, measure it with the ADC and you will know the error.

There's a difference between tolerance and drift.

That +/-5% should be tolerance, so can be calibrated. As long as you keep your Arduino at a reasonably constant temperature and Vcc at a reasonably constant level, it should be very stable.

Alternatively look at a TL431 reference diode. Not zeners - they're not exactly accurate or stable.

Do you have another datasheet or document where you found the VREF vs Temp characteristics being <0.5%?

Mine shows "Plots are not available at this time":

Or am I looking in the wrong chapter.

What a coincidence. I have several of TL431BC in all shapes from 13 year ago when TI was giving away free samples.

I used the latest from Microchip website
DS40002234B

1 Like

You might use the Vref 1V024, that has 2% tolerance. This needs adaptation of the voltage divider. Mind that the cheapest resistors are 5% themselves.
Or you might alternate between measuring the battery and a TL431. Mind that it needs a minimum of 1mA (recommended 10mA) so feed it from an output to save energy.

I've found this regulator to be low cost and very stable.

I was just going to trash a number of my leaded devices. I pulled a LH0070-2H out of the trash. If you want it, pay for shipping and I'll send it to you.
The LH0070-2 is within 10V ± 0.05% at room temp. It does however require at least 12 volts input.

How far is the panel from your house? Maybe a LoRa solution could work and make it cheaper too?

The VREF temperature drift I saw in the newer datasheet that @jim-p referred to is indeed minimal. So I will do some tests first and hook up the ADC to a 12V battery for some time and let it report the minimum and maximum measured voltage and check with my Fluke multimeter.
If I get noise I can do oversampling and/or implement a rolling average to further optimize the accuracy. The battery voltage should not change quickly, however I do not know if the electric fence load creates voltage dips when generating the 8000 volt pulse. Most likely not and uses a capacitor internally.

@stitech I assume that the 5% resistor inaccuracy is a fixed offset that does not change over time or temperature, so I should be able to calibrate that away in software.

@JohnRob Thank you for the offer. I think that with the TL431 that I already have, I am set for using them as alternative. I live in The Netherlands, so shipping could be expensive, since EU customs require all goods to be shipped with track and trace.

@apf1979 I live about 25Km from the field, so LoRa may be a challenge over ground. With a prepaid simcard and 15 cent per SMS I estimate the cost will be less than 10 Euro per year. We just destroyed our €237,- one year old battery, so I think the business-case will not be a problem.

Thanks for all of your help. Much appreciated.

Try www.conrad.nl. They sell the TL431 for € 0.21 and resistors 0.1% for € 0.48.

I agree the TL431 would be my first choice, I just happened to go through my old devices getting rid of the things I will never use.

This would be my idea:


unsigned int measureBattery() {                      // This function returns the Battery Voltage in millivolts
  const unsigned int R1 = 18000;                     // first resistor of voltage divigder
  const unsigned int R2 = 10000;                     // second resistor
  unsigned int tmp0 = analogRead(A0);                // get raw data from input Battery
  digitalWrite(2, HIGH);                             // supply for Ref ON
  unsigned int tmp1 = analogRead(A1);                // analogRead leaves enough time for Ref to settle
  digitalWrite(2, LOW);                              // supply for Ref OFF
  return ((tmp1 * 2500UL / tmp0) * (R1 + R2) / R2);  // Ref voltage in millivolts, unsigned long forces calculation in 32 bits
}  // This will run on a ATmega328, can't check for ATtiny1624

The ads1115 brings a nice reference on board and 16 bits of resolution.

You have c 2.2V across the 220 ohm R3 so 10ma. You could reduce that to about 2mA (1k2) and still have plenty of headroom.
Similarly you could increase R1, R2 by at least a factor of 10, and connect a capacitor - say 10uF ceramic - across A0 - GND
That would reduce the drain on the battery (not a major issue, I agree)
but also protect the A0 input from battery voltage dips and pick up from the 8kV pulses.
Probably best to put a cap A1-GND also and GND will be a star point.

How will you power the ATtiny1624 - its not shown on your schematic?

We still have not determined what accuracy @hmeijdam actually needs to be able to make their percentage measurements. I think it will be less than 2%

I did leave out many things.

I expect the processor to sleep and be woken once every few hours, so the powerdrain of the reference module during several milliseconds is not important.

In the original, the ATmega328, it is recommended to have a signalsource for the analog inputs of <10kOhm. The same for it’s successor, the ATmega4809. I haven’t found a similar recommendation in the datasheet of the ATtiny1624.

The system I described works while not knowing the ADC resolution, anything from 8 up to 16 bits. The ATtiny1624 can be cranked up to 17 bits requiring register access. A more ‘standard’ set up would have the reference module connected to the AREF input.

The OP might be comfortable with accessing registers, or using another IDE than Arduino, the algorithm in my example is hopefully easy to read.