This will be a longer message, but I hope that some of you will find it useful.
With the default use of the Arduino library software, you got no issue. Then an ADC clock frequency of 125 kHz is used, and the ADC conversion time then becomes about 104 usec. However, according to this document page 10 from the the producer of the chip, Microchip,
“The ADC accuracy also depends on the ADC clock. The recommended maximum ADC clock frequency is limited by the internal DAC in the conversion circuitry. For optimum performance, the ADC clock should not exceed 200kHz. However, frequencies up to 1MHz do not reduce the ADC resolution significantly. Operating the ADC with frequencies greater than 1MHz is not characterized.”
Many other sources confirm the use up to 1 MHz ADC clock frequency, but I discovered, that you get a serious problem with the ADC multiplexer of the analog inputs, when you use this higher frequency without a correction. Perhaps this has been reported before, but then I did not find it. The multiplexer is set by writing to the ADMUX register, and it is normally done by the AnalogRead() function just before the AD-convertion is started. The problem is, that the multiplexer needs time to shift the input. You have 1½ clock cycle for the multiplexer and sample hold circuit to work, and at 1 MHz it is 1.5 usec. This is not sufficient and you partly gets some analog signal from the previous input. When you use the same analog input all the time, you will not see this issue.
When you measure the input voltage of supply of +5V and GND on each of two inputs and exchange the pin reading every time, you see the measured values come like this from analogReadread:
ADC result High = 995 ADC result Low = 0
ADC result High = 1003 ADC result Low = 0
ADC result High = 1003 ADC result Low = 0
ADC result High = 995 ADC result Low = 0
ADC result High = 995 ADC result Low = 79
ADC result High = 995 ADC result Low = 0
ADC result High = 1003 ADC result Low = 0
ADC result High = 1003 ADC result Low = 0
ADC result High = 1004 ADC result Low = 0
The right results are 1023 and 0.
In this link you find a test code, that is used to show this problem. I hope that some of you will try to test for the same problem on your Arduino:
https://forum.arduino.cc/t/arduino-nano-adc-clock-and-quantization-error/1204040/45
I suggest a solution to this problem with a minor change to the code for analogRead(), that is written in the library file wiring_analog.c. You can find the code in your library provided. In order to show the code in some more readable way, I have removed code not relevant for the 328P chip here:
int analogRead(uint8_t pin) {
if (pin >= 14) pin -= 14; // allow for channel or pin numbers
ADMUX = (analog_reference << 6) | (pin & 0x07);
// without a delay, we seem to read from the wrong channel
//delay(1);
ADMUX = (analog_reference << 6) | (pin & 0x07); // 8 lines inserted more to make some time
ADMUX = (analog_reference << 6) | (pin & 0x07); // consumption of 1 usec extra for 1 MHz
ADMUX = (analog_reference << 6) | (pin & 0x07); // ADC clock on Arduino Nano. Measurements reveal
ADMUX = (analog_reference << 6) | (pin & 0x07); // each line of this code is 2 16 MHz clock cycles.
ADMUX = (analog_reference << 6) | (pin & 0x07); // With 2 MHz ADC clock you would need to add 6
ADMUX = (analog_reference << 6) | (pin & 0x07); // more lines.
ADMUX = (analog_reference << 6) | (pin & 0x07);
ADMUX = (analog_reference << 6) | (pin & 0x07);
// start the conversion
sbi(ADCSRA, ADSC);
// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC));
// ADC macro takes care of reading ADC register.
// avr-gcc implements the proper reading order: ADCL is read first.
return ADC;
}
You find 8 lines extra lines of code, that I put in only for the purpose of consuming 1 us of execution time. In this way this problem disappears. I measured the time difference of 15 lines of this code and 75 lines of this code by setting of a digital output and use of an oscilloscope. The time difference was about 8 usec meaning 0.133 us each extra code line. Two CPU clock cycles are 0.125 us, so it is the right value for each line of this repeated code. Perhaps someone would suggest the use of some other kind of code. Actually the problem was solved at 6 extra lines of code on my Arduino, but I added extra two line to put in extra safety. Some other Arduino Nano might need some more or less time. Furthermore two other combinations of two analog inputs may also perform somewhat different.
Actually the original code already got a remark about this problem, and a possible solution by delay(1), but this delay will be about 1000 times longer than needed.
I did not find specifications in the datasheet regarding the needed time. But the datasheet recommends to use a clock frequency of max 200 kHz for “maximum performance”. The first 1½ ADC clock cycle is part of the time for this mux change and the sample hold circuit, and it is 1.5 us at 1 MHz. But I could see that 1 us more was needed, so you needed 2.5 us in all.
A test at 2 MHz ADC clock was tried. Then you need 0.75 us + 1.75 us = 2.5 us to get right results. In this way the extra code should consume 1.75 us. At 500 kHz ADC clock, you already have got 3 usec, and then no extra code is needed.