Then measure the voltage at the AREF pin. Use that voltage in the calculation.
int analogPin = A0;
float measuredReference = 1.15; // just an example, measure it
void loop() {
val = analogRead(analogPin);
voltage = (float(val) + 0.5) * measuredReference / 1024.0;
Serial.println(voltage);
delay(200);
}
I read the webpage of your link, but it is missing a few practical things.
To get a good measurement, a number of samples should be captured and the average should be calculated. With only a few samples, a lot of electronic noise is reduced.
I wrote a averageRead.ino a while ago. It tries to keep every bit and only change to floating point when needed. By making use of the noise, the resolution increases beyond the 10-bit of the ADC. The overall accuracy is not increased, because that depends on the linearity and other things.
I say this only because you are focused on accuracy. This is not technically correct. The resolution would be 1.1/1024 = 1.074 mV. I understand this doesn't address your problem but I feel it's better to work with the most accurate formulas.
Actually, you did perform the calculation correctly in the voltage calculation line, although it is over-optimistic about input precision. The input is actually imprecise enough that the floating point calculation (and rounding) is not really worth it, you could
long mv = val * 1100L / 1024;
except that after calibration, you would need to substitute something like 1093 instead of 1100 if the reference was really 1.093V for example.
Edit - afterthough... also the compiler will optimize the /1024 to a left shift operation. This completely cuts out the division as well as the floating point. Multiplication is very fast compared with division when there is no FPU.
Another refinement, if you're intending to read more than one AI, and using the abovementioned multiple-read averaging to improve accuracy. Bear in mind that, when you change channel, the first one or two readings will be impacted by charging the input stage, particularly if your voltage source is high-impedance. Therefore, it might be best when trying for a really accurate reading from any AI to read a couple of throw away values, then capture your set for averaging. I.e. "read(1), read(1), read(10)" will achieve a better result than "read(10)".
Best of luck. I've always found trying to read more "accuracy" than the native resolution to be fraught with difficulties.
C
Right, another suggestion, use a long variable instead of an int as an accumulator, which would allow you to take for example 200 samples instead of the current 20 in the same time period.
It's not commented, but 20 is a seat of the pants value close to the maximum before overflow occurs.