SparkFun Forums 

Where electronics enthusiasts find answers.

General project discussion / help
Did you make a robotic coffee pot which implements HTCPCP and decafs unauthorized users? Show it off here!
By uChip
Over the last few months I've done a few projects that made use of the analog inputs on the Arduino/ATmega processor. I found that trying to debug the software at the same time as debugging and calibrating the hardware was cumbersome (to put it mildly). The more I dealt with this, the more I thought that a programmable voltage reference would simplify things. With a programmable reference I could simulate an analog sensor input and debug the software without worrying about whether the sensor hardware is working or not. The voltage reference makes it easier to manipulate the input, test boundary conditions or check the accuracy of the ADC.

Consider this example of a simple temperature probe. The probe uses an ATtiny85 8-pin processor connected to an LMT84 analog temperature sensor and two LEDs, one red and one green. As long as the temperature stays in range the green LED flashes once every 15 seconds. If the temperature goes out of range, either high or low, for more than a few samples the red LED flashes instead until the unit is reset. The whole thing is powered by a coin cell and physically is about the size of the cell holder and twice as thick. The battery needs to last for a few months.

The design is simple, but has a couple of tricky aspects. How do you debug a processor that has no serial port and is asleep most of the time? There weren't even any spare pins to send out debug signals. The processor controls the power to the sensor so that's not on all the time either. The sensor is putting out a signal only one millisecond out of every 15,000. Measuring that is a tough job for a DMM or for my old analog scope. And even if you assume the sensor is working perfectly how do you manipulate the sensor accurately to test the range thresholds?

By substituting a voltage reference for the sensor the development is simplified. By supplying a known voltage to the ADC input I can debug the software by writing test code to flash the LEDs and get the ADC working right. Once I know I'm getting good readings I can then vary the reference input through a range of values to check that the software handles all input values correctly and triggers when it should. Once I know the ADC is reading correctly and the software is doing the right thing with the ADC values, I can put the sensor back in the circuit and verify it using the software.

So having decided that a voltage reference would be a good thing to have, I looked around on eBay and other places. I don't seem to have Dave Jones' eBay luck. Everything I could find was hundreds of dollars. I don't have that much to spend, so instead I decided to build my own.
I need to go on a tangent here for a moment. I keep using the term voltage reference. If you do a search for voltage reference on eBay, or your favorite parts supplier, you will get lots of hits and what you find will cost only a few dollars. However, most of these provide only a single voltage and have accuracies in the 0.05% range. That means that at 4 volts they could be off by as much as 2 mV. I’d like something that is accurate to at least 100 uV or about twenty times better. The things that I’m talking about and what Dave Jones has are called voltage standards and can be set for many different values. The difference is that a voltage standard has been calibrated to a particular accuracy specification using an instrument that has been certified to have an even higher accuracy (typically ten times higher accuracy). And that instrument has been calibrated by an instrument certified to higher accuracy yet. This “chain of trust” goes back all the way to some standards body that holds the absolute gold standard for that particular chain. The best meter that I own is a 5 ½ digit (200,000 count) Fluke. It has been calibrated by a certified calibration lab so I have access to that chain of trust. And while I think I can achieve the level of accuracy I want, it might be presumptuous of me to call my device a voltage standard. So I’ll keep calling it a reference even though I hope it behaves like and I can use it like a standard.

Getting back to the design of the device: The goal would be to set voltages with the same or better resolution than the ATmega's ADC input across a reasonable input range. Since the ADC is 10 bit it has 1024 levels. If you choose the band-gap reference for the ADC, that's roughly 1 millivolt resolution. If instead we choose AVcc as the reference the resolution would be ~5 mV (on a 5 V system), but let's shoot for 1 mV across the whole range. A nice round number for the range would be 4.095 volts. That's 12-bits worth of 1 mV steps. For accuracy, I'd like when I set the reference to 1.234 mV that it be significantly closer to that value than to 1.233 or 1.235. Same thing when I set the value to 0.005 or 4.095. Let's call it within 100 uV of the target value. Of course, accuracy and resolution are no good if there's too much noise, so it must be low noise as well. This is a voltage reference, not a power supply, so a limit of a few milliamps is acceptable. The last spec is budget. As I said voltage standards on eBay go for hundreds of dollars. I am targeting a budget of $50 parts cost.

A voltage reference is really a simple device. In fact it could be as simple as a potentiometer and an OpAmp. Hook the output of the OpAmp to a good voltmeter and set the voltage level you need using the pot. But that ties up the meter and setting the pot to millivolt values across a multi-volt scale is at best fiddly. So let's complicate things a bit. Let's make the selection digital and include a 4-digit LED display. If we build the control around an Arduino core, the software development is simpler, plus we can re-use the programming serial port for remote control.

Interestingly enough, though I've finished the project already, I just recently watched Ian Johnson's video on hacking a voltage standard he bought on eBay. Inside his EDC 501J I expected to see a high end integrated precision DAC. Instead what was inside was a DAC built from discrete resistors and many more trim pots than I expected. The expense must have been in trimming all those resistors!

I want to be able to calibrate as well, but let's hold that to a single trim pot and do the rest in software. For the core of my design I chose the REF5040ID voltage reference chip paired with the AD5060BRJZ DAC. I chose the 5040 because it starts with good accuracy, good temperature stability, good aging and is trimmable. The 5040 is accurate to 0.05% or about 2 mV, but has a trim input. By using a trimmable reference I should be able to get the error well under 1 mV. The 5060 is a 16-bit DAC with plus or minus 2 LSB relative accuracy (INL) and 1 LSB differential nonlinearity (DNL). If you recall, the output resolution needs to be 12 bits. By using a 16-bit DAC the output can be set to the proper 12-bit value and then calibrated with another 4 bits. If the 12-bit step is 1 mV then 4 more bits is 1/16 or 0.0625 mV which should enable me to calibrate to well within the spec. Note that together these two parts are over $20. They are relatively expensive compared to the microcontroller, display or even the PCB, but since they also are the heart of the device I think they are worth it.

All of the rest of the circuitry is there to provide the control interface and to support those two chips. There is a voltage-follower OpAmp driving the output. The OpAmp doesn’t have any more drive than the DAC itself, but it’s better to expose the output of a $2 part rather than a $13 part. The display is a 4 digit 7 segment LED that I have used before. The control knob is a rotary encoder with push button. Turning the encoder right or left steps the output up or down by 1 mV. Pressing the encoder knob push button jumps the output by 250 mV. The output steps up to a max value of 4.095 mV and then rolls around to its lowest setting of 1 mV. In the other direction stepping down past 1 mV rolls around again to 4.095 V. This allows any valid value to be set without too much work. The device will also accept an ASCII string on the serial port to set the voltage level.

To answer some anticipated questions:

* Why doesn't the output go to 0 V? I wanted to power the device from battery or USB and to keep the cost down I wanted it to be a single-ended supply. But a single-ended supply means that devices that drive voltage have a hard time getting all the way to ground so I allowed a 1 mV minimum to ease the design. Besides if you really need 0 volts you can remove the voltage reference and ground that signal. You can even ground the output with the voltage reference still in the circuit (the output will not be damaged according to the OpAmp spec) but I advise against it.

* Why doesn't the output go to 5 V? Most of the sensors I’m working with are powered by 3.3 V, so a range of 4.095 V is more than adequate. By powering the voltage reference from USB I have only 5V (plus or minus 10%) available and the reference chip needs a few hundred millivolts of headroom to do its work. Plus by using a 4.096 volt reference, the math for the project is simplified. I could have used a boost regulator but that would have added more cost. If I had chosen a 5 V reference I would have also needed to go to a more expensive 17 or 18 bit DAC to meet the resolution and accuracy spec.

The circuit is burned in for 250 hours before calibrating and the reference is trimmed to as close to 4.096 V as I can make it. Then to calibrate the DAC I wrote a program to set each valid 12-bit value on the DAC and then read it back from the Fluke’s GPIB port. From these I compute a correction factor for that value which gets stored in the microcontrollers EEPROM memory. Since there is not enough EEPROM to store all 4096 correction factors they are run-length encoded before being stored.
That's about it. You can see a fair number of capacitors and a couple inductors in the schematic. Those are to prevent and reduce signal noise. The rest of the circuit is pretty straight forward.

So how well does it work? Let's review the specs.
* Range: 1 to 4095 mV. By design. Check
* Resolution: 1 mV steps. By design. Check
* Accuracy: For values in the range of 1 to 1.999 V I’m measuring 50 uV accuracy. Unfortunately at that point my 200,000 count meter hits its own limits and I can only measure to plus or minus 100 uV, but I believe with a better meter I could calibrate to better than 50 uV across the full range. Even at plus or minus 100 uV the spec has been met.
* Noise: I have never seen more jitter than the least significant digit on the DMM even when the meter range is down in the microvolts. I don’t have a quantitative measure, but the output seems pretty quiet.
* Current: Loading the output with a 1k resistor does not change the output voltage but heavier loading quickly starts affecting the output. A few milliamps of drive is all we designed in so it’s not surprising that’s all we get.
* Cost: the total parts cost including PCB was $43.89.

Is it useful? Unquestionably yes. I find myself reaching for this tool whenever I'm building a circuit with an ADC or writing the associated code. It is very valuable to have a reliable reference that I can check against or that can fill in for a sensor or other signal source in a controllable, reliable and repeatable way. I highly recommend it.

As usual you can find the schematic, board layout, parts list and source code on my Github site. Or I'm contemplating selling (assembled, tested and calibrated) a batch of these to earn myself a new scope and/or better DMM. If you are interested in having one, let me know.

Good luck with your projects! & Happy New Year!
- Chip
You do not have the required permissions to view the files attached to this post.
By altitude

Thanks for the great project, super useful device.

Have a question however: Can you post a link to the appropriate include libraries for the sketch? I have my board built and working on getting the software compiled and loaded and admittedly my Arduino Kung-fu is a bit rusty so I am getting a bunch on *.h not found errors when trying to build the hex file.

By uChip
The software for the voltage reference references five libraries.
Code: Select all
#include <ProfileTimer.h>
#include <SPI.h>
#include <EEPROM.h>
#include <Rotary.h>
#include <Bounce.h>
The ProfileTimer.h library was used in tuning the display timing but is not used by the final version of the software. The #include for ProfileTimer.h can be removed or commented out. ProfileTimer.h is a library written by Nick Gammon. You can find it here:

The SPI.h and EEPROM.h libraries are part of the Arduino distribution. You should not have to do anything special to make use of them.

The Bounce.h library is from the Arduino playground, here:
Note that Bounce.h has gone through some changes since I used it. The modifications necessary are documented on the site.

The Rotary.h library is from Brian Low and can be found here:

Thanks for the question!
- Chip
By altitude

Looks like I tracked down the same files but now I have another problem, I cant get the program to flash to the chip correctly, I got all the modification to the programmer and boards files to use my avrisp mk2 but I get a signature verification check failure for the 328, is that supposed to be a 328 or 328P?
Last edited by altitude on Sun Apr 12, 2015 6:34 am, edited 1 time in total.
By altitude
found a work around to get the code uploaded (change the device signature for the 328P in the avrdude,conf) and everything looks like it's working except nothing on the output. No shorts
By uChip
The 328/328P is a common problem. Arduino assumes 328P but frequently refers to the part as 328. In this case either part will work in the circuit. You just have to tell the ISP which one you used.

As for the "nothing on output" problem, it could be any of several potential errors. To try to track it down, measure the output with a voltmeter. When you say "nothing", do you mean zero volts? or some other value?

There are several test points on the board. Check them to see if they have correct values:
- VREF should be 4.096 volts - could be a few millivolts off if you haven't calibrated yet.
- 5V should be between 4.75 and 5.25 volts.
- A5V should be 0.1 to 0.2 volts less than 5V.
- NEG should be between -2 and -3.5 volts referenced to ground.
- DAC should be 1.0 volts a few seconds after boot (before any changes from the rotary encoder).
- The output should be within a millivolt of the DAC value.
Measure these and report what you find. That will give us some clues as to what is going wrong.

Also, what does the display show when you boot up?

A picture is worth a thousand text postings. Can you post a picture of your assembled board?

- Chip
By altitude
Thanks for getting back..

So here is where I am at:

Display/encoder works fine (Steps 0.5v when pressed, 0.001 when turned)

vRef: 4.095V
V+: 0.015V when display is set to 1V
0.030 / 2V
0.045 / 3V

so something is scaling correctly there

+5 = 4.95V
A5E: 4.873V
DAC: 0.01 <- always a few milivolts, never anything close to 1V

So this would point to the DAC, I went over the part thoroughly and there are no shorts or bad connections, this is the part I used: ... REEL7CT-ND
By uChip
Uh oh. I think I see the problem. If you look back to my posting you will see a sentence that says "For the core of my design I chose the REF5040ID voltage reference chip paired with the AD5060BRJZ DAC." Those two part numbers are pretty close. Worse, the schematic uses the same library component for the AD5060 and its little sibling the AD5040 which is only 14 bits. The schematic value propagated to the BOM as well. That's my error, sorry. I should have changed the value on the schematic to AD5060.

There are two ways to fix this. One is to remove the AD5040 and replace it with the AD5060. The other way would be to change the software to use correction factors that fit in only two bits. I don't think two bits is enough. I've calibrated a couple of units now and correction factors are not large, but they do get to + or - 3. You can give this a try first if you like, but I think in the end you will wind up replacing the chip.

I will make appropriate changes to the files and update github.

Again, my apologies.
- Chip
By uChip
Okay. I have updated the schematic and BOM files on GitHub. Anyone else reading this thread BEWARE! If you pulled the GitHub files before this posting, the schematic & BOM list the wrong DAC. The correct DAC is AD5060BRJZ.

Oops. :oops:
- Chip
By altitude
Ah the dreaded "use one part's footprint for another part" SNAFU :P

I came by the project via OSHpark actually and grabbed all the documentation from GIT so I didnt even see this thread till I went searching for help.

One thing I would consider would be to call out all the passives as 0603, not 0805 (Tants excluded obviously), those are some really tight footprints for 0805 parts so you're almost soldering from the side. 0603 is smaller but would be easier to hand solder since more of the pad would be exposed.
By uChip
Hmmm, I haven't had any problem soldering the 0805's. The 0805 footprint is directly from the SparkFun library. If 0603's fit and are easier for people, that's definitely an option.

Thanks for the input.
- Chip
By altitude
They fit and it's fine but those sparkfun pads are way smaller than the standard eagle 0805 pads:


I can see the point of having smaller pads for better density and when you solder in an oven that is a better choice anyway but I hand stuff SMD stuff and having a bit more pad is always easier to get the parts on, here is a comparison of 805 vs 603 parts

By uChip
Fair enough. I will so note in the BOM docs. I'll leave it up to folks to choose for themselves though.
- Chip
By altitude

Well done sir. That's not too shabby.

This thing is going into service calibrating analog synthesizers shortly and will be highly useful.

One last comment: C17, consider changing this to a ceramic or making sure you make it clear that it has to be a part that is rated over the input power voltage. 6.3V is the most common value and those explode when you put over 10V on them (as I figured out :P). I stuck a 10uF ceramic there and all is well

Thanks for the support and great projet!

By uChip
I'm glad you got it working! I have found this to be a really useful little gadget. You are right though, the output is a bit fragile. It's fine being shorted to ground, but there is no feedback when the current draw starts affecting the reference voltage and no protection when higher voltages are fed back into the output. I agree with specify a higher voltage rating on C17.

I am in the process of designing a new version. Here is a list of improvements.
  • - in a case
    - case should have room for a battery
    - also support wall-wart power
    - banana jack outputs
    - higher current capability; goal is to maintain reference voltage into a 50 ohm load
    - overload detection
    - over-voltage protection
    - low battery detect
    - same or better accuracy
I am prototyping the new version now. We'll see how I do. :)
Thanks for posting your results.
- Chip
long long title how many chars? lets see 123 ok more? yes 60

We have created lots of YouTube videos just so you can achieve [...]

Another post test yes yes yes or no, maybe ni? :-/

The best flat phpBB theme around. Period. Fine craftmanship and [...]

Do you need a super MOD? Well here it is. chew on this

All you need is right here. Content tag, SEO, listing, Pizza and spaghetti [...]

Lasagna on me this time ok? I got plenty of cash

this should be fantastic. but what about links,images, bbcodes etc etc? [...]