I'm trying to use the analog input of an Arduino Mega as a voltmeter in order to measure the amplified voltage of a load cell. The amplifier works well, but I realised that whith low values, the measurement error was too big.
To verify that, I connected a potentiometer to an analog pin, so the voltage could be varied between 0 to 5V.
The reference was defined as External, with a 5V value, by the use of another potentiometer (I know is not the best way to do this, but it's more accurate than using the arduino reference, wich in this case was 5,086V.)
The load code was the following
int pot = 0;
void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);
}
void loop() {
Serial.println((5000.0 / 1023)*analogRead(pot));
delay(2000);
}
The measured values are shown in the following table.
Values that can be plotted in two graphs, representing the mV error or the relative error.
As can be seen the error becomes lower when the voltage increases.
Being about 5000/1023=4.88mV (The ADC resolution).
I've tried using capacitors and ferrite as filters getting the same result.
28.5.2. ADC Voltage Reference The reference voltage for the ADC (VREF) indicates the conversion range for the ADC. Single ended channels that exceed VREF will result in codes close to 0x3FF. VREF can be selected as either AVCC, internal 1.1V reference, or external AREF pin.
AVCC is connected to the ADC through a passive switch. The internal 1.1V reference is generated from the internal bandgap reference (VBG) through an internal amplifier. In either case, the external AREF pin is directly connected to the ADC, and the reference voltage can be made more immune to noise by connecting a capacitor between the AREF pin and ground. VREF can also be measured at the AREF pin with a high impedance voltmeter. Note that VREF is a high impedance source, and only a capacitive load should be connected in a system.
If the user has a fixed voltage source connected to the AREF pin, the user may not use the other reference voltage options in the application, as they will be shorted to the external voltage. If no external voltage is applied to the AREF pin, the user may switch between AVCC and 1.1V as reference selection. The first ADC conversion result after switching reference voltage source may be inaccurate, and the user is advised to discard this result.
You might want to go over the whole ADC section to see about noise and tolerances. 1.1V / 1024 steps....
Agree with the pot error, I'll try to purchase a voltage reference IC.
I gave the 0V value, but didn't calculate the error due to it's inexistence, so there are no offset when reading 0V.
If you are feeding the "reference" pot from Arduino's 5V, the wiper voltage is still going to vary with the 5V source, use the 3.3V pin for reference, or 3 1.5V batteries in series (4.5V).
And post a diagram of your setup.
I think the offset may be caused by wrong ground reference. I don't know Mega's but I guess it is similar to the ADC of Arduino Uno. All the current "consumed" by the ATMega flows through non-zero resistance of supply traces on the PCB and in the tiny wires inside the chip itself. It is no surprise "internal ground" is a few milivolts over the ground point you use as reference.
I'm trying to use the analog input of an Arduino Mega as a voltmeter in order to measure the amplified voltage of a load cell. The amplifier works well, but I realised that whith low values, the measurement error was too big.
Any suggestion?
Use the internal 1.1V reference and don't amplify the load cell V so much.
JCA34F:
If you are feeding the "reference" pot from Arduino's 5V, the wiper voltage is still going to vary with the 5V source, use the 3.3V pin for reference, or 3 1.5V batteries in series (4.5V).
And post a diagram of your setup.
I also did what you propose before post this question. Everything works in the same way. If it helps, I not only tested this on the Mega, but also in a Nano board, getting similar results.
Smajdalf:
I think the offset may be caused by wrong ground reference. I don't know Mega's but I guess it is similar to the ADC of Arduino Uno. All the current "consumed" by the ATMega flows through non-zero resistance of supply traces on the PCB and in the tiny wires inside the chip itself. It is no surprise "internal ground" is a few milivolts over the ground point you use as reference.
Something like that should be happening, but why with higher voltages the offset gets reduced?
Wawa:
Could we see it, including circuit diagram with parts values.
Leo..
Of course you can, but that's not the question. Forget that circuit, I'm getting the same results using a simple potentiometer, so there must be any problem with the board, code, noise... that I'm not considering.
You never can do better than 0.1% with a 10-bit A/D (1024 values).
Well, maybe a bit with some oversampling.
It is very important that the amplifier is properly matched (voltage/impedance) to the A/D to utilise the A/D to the max, hence the question to see a diagram.
Accuracy is ofcourse going to drop at the lower end of the scale.
If the A/D varies one LSB (normal), then you won't notice that on 1000 values, but you do on 10.
The HX711 has a buildin 24-bit A/D (about 16 usable if you build it right).
A shipload more values at the lower end of the scale.
Leo..
Wawa:
You never can do better than 0.1% with a 10-bit A/D (1024 values).
Well, maybe a bit with some oversampling.
It is very important that the amplifier is properly matched (voltage/impedance) to the A/D to utilise the A/D to the max, hence the question to see a diagram.
Accuracy is ofcourse going to drop at the lower end of the scale.
If the A/D varies one LSB (normal), then you won't notice that on 1000 values, but you do on 10.
The HX711 has a buildin 24-bit A/D (about 16 usable if you build it right).
A shipload more values at the lower end of the scale.
Leo..
Here is the circuit. It's composed by an instrumentation amplifier, referenced to Vcc/2. The output values are always positive, but higher or lower than Vcc/2 if load is not 0. Then, this output is referenced to GND by two more amplifiers, one of them amplifies when Output>(Vcc/2) and the other when Ouput<(Vcc/2). The last stage sum up the two voltages. An OP comparator gives the information of the load sign (traction or compression). With this circuit one can identify not only the load value (0 to 5V) but also its sign. The OP are not the LM358N, finally I used the 72A8PCM that give a low offset (I take it into account in the code).
What I noticed when testing this was a difference between the circuit and the registered value in Arduino. So I decided to only use a potentiometer. 10k was the first selected value, but I also tested a 1k potentiometer with the same results.
Your explaination abou the LSB is very convincing. I think you're right and this is what must be happening. Perhaps the best option is the use of a HX711, as you pointed out in your first post. But first I wanted to know what was happening.
LM358... Did you read the datasheet.
This is not a rail2rail opamp, and output swing is only 0-3.5volt on a 5volt supply.
You must at least use a 1:2.5 (2:5) voltage divider between your circuit and the analogue pin, and use 1.1volt Aref in setup if you want to use (almost) the full range of an Arduino A/D.
Performance near 0volt and >3.5volt output could be poor.
You 'near 0volt compression' could also come from this basic opamp.
You could have avoided this DIY instrumentation amp if you had used an instrumentation amp.
The INA125 would have been a possibility (to learn).
But results of any instrumentation amp in combination with Arduino's 10-bit A/D are always poor.
Leo..
A small stable V could be biased to open a BJT and that used to fill an RC connected to an analog pin. How long that takes can tell you about the signal. The RC can be adjusted towards precision, if you have a few ms to take a reading.
How many ways with stable voltage... power a small coil and use a good linear Hall sensor to read the field?
Wawa:
LM358... Did you read the datasheet.
This is not a rail2rail opamp, and output swing is only 0-3.5volt on a 5volt supply.
You must at least use a 1:2.5 (2:5) voltage divider between your circuit and the analogue pin, and use 1.1volt Aref in setup if you want to use (almost) the full range of an Arduino A/D.
Performance near 0volt and >3.5volt output could be poor.
You 'near 0volt compression' could also come from this basic opamp.
You could have avoided this DIY instrumentation amp if you had used an instrumentation amp.
The INA125 would have been a possibility (to learn).
But results of any instrumentation amp in combination with Arduino's 10-bit A/D are always poor.
Leo..
I read the datasheet, for that reason I said in my previous post I used the 72A8PCM which is a TLV2372, a rail to rail amplifier. The output of the circuit is 0 to 5V when the supply is 12V. I have tested instrumentation amps before design that, like the AD623, and the results were even poorer.
I appreciate your help, but really, I don't see the point of analysing the circuit. I only posted it because of your request. It's not necessary for the solution of this issue. Of course it is not 100% precise, I'm aware. But my question was about the use of a simple potentiometer.
When I connect a simple potentiometer I get the posted errors. That errors are from the pot circuit, with no one OP amp.
ADC - Analog to Digital Converter
28.1. Features
• 10-bit Resolution • 0.5 LSB Integral Non-Linearity • ±2 LSB Absolute Accuracy
• 13 - 260μs Conversion Time
• Up to 76.9kSPS (Up to 15kSPS at Maximum Resolution)
• Six Multiplexed Single Ended Input Channels
• Two Additional Multiplexed Single Ended Input Channels (TQFP and VFQFN Package only)
• Temperature Sensor Input Channel
• Optional Left Adjustment for ADC Result Readout
• 0 - VCC ADC Input Voltage Range
• Selectable 1.1V ADC Reference Voltage
• Free Running or Single Conversion Mode
• Interrupt on ADC Conversion Complete
• Sleep Mode Noise Canceler
There is the half-point and then there is +/-2 step accuracy; 1 of the low 2 bits may dither from read to read.
Averaging many free-run reads will give a closer answer, Arduino word (uint16_t) can hold up to 64 reads as a sum so no array needed to average.
added: figure 8 reads takes about 1 ms to process and load print output.
I dunno, is there any chance that how you meter the pot differs from how Arduino reads it? Like, does the INPUT have a pulldown that the pot measure doesn't read?
GoForSmoke:
328P datasheet sez with my highlighting added,
There is the half-point and then there is +/-2 step accuracy; 1 of the low 2 bits may dither from read to read.
Averaging many free-run reads will give a closer answer, Arduino word (uint16_t) can hold up to 64 reads as a sum so no array needed to average.
added: figure 8 reads takes about 1 ms to process and load print output.
I dunno, is there any chance that how you meter the pot differs from how Arduino reads it? Like, does the INPUT have a pulldown that the pot measure doesn't read?
What gets me angry is the stability of the measure. The read value doesn't seem to be noisy since there is a measurement error but very stable. I think that if the 2 low bits were dithering, there will be values under and above the real one, but there are only lower values.
In spite of that, I think yours is the most plausible hypothesis by the moment.
I'm connecting the voltmeter to the same Arduino pin directly, if there is no effect of the internal resistor I don't know what can be causing this. Should I try using a voltage buffer?