Okay, I did a bunch of testing to characterize the bug. The results are interesting, but still unclear what could be going on.
I first modified the code with the little changes suggested, just in case.
unsigned int analogvalue4, analogvalue5;
uint8_t analog[16000];
// analogRead(4);
delay(1);
for(int i=0; i<16000; i=i+4) {
analogvalue4 = analogRead(0);
analogvalue5 = analogRead(1);
analog[i] = (analogvalue4 >> 8) & 0xFF;
analog[i+1] = analogvalue4 & 0xFF;
analog[i+2] = (analogvalue5 >> 8) & 0xFF;
analog[i+3] = analogvalue5 & 0xFF;
delayMicroseconds(ADCdelay);
}
SerialUSB.write(analog, 16000);
The result of reading and parsing this data in LabVIEW is the following:
which matches my scope.
If I modify this to do a single A4 read, channel A1 now reads the wrong data.
unsigned int analogvalue4, analogvalue5;
uint8_t analog[16000];
analogRead(4);
delay(1);
for(int i=0; i<16000; i=i+4) {
analogvalue4 = analogRead(0);
analogvalue5 = analogRead(1);
analog[i] = (analogvalue4 >> 8) & 0xFF;
analog[i+1] = analogvalue4 & 0xFF;
analog[i+2] = (analogvalue5 >> 8) & 0xFF;
analog[i+3] = analogvalue5 & 0xFF;
delayMicroseconds(ADCdelay);
}
SerialUSB.write(analog, 16000);
Okay, so I then tried switching the read order of A0 and A1 inside the for loop like this.
unsigned int analogvalue4, analogvalue5;
uint8_t analog[16000];
//analogRead(4);
delay(1);
for(int i=0; i<16000; i=i+4) {
analogvalue4 = analogRead(1);
analogvalue5 = analogRead(0);
analog[i] = (analogvalue4 >> 8) & 0xFF;
analog[i+1] = analogvalue4 & 0xFF;
analog[i+2] = (analogvalue5 >> 8) & 0xFF;
analog[i+3] = analogvalue5 & 0xFF;
delayMicroseconds(ADCdelay);
}
SerialUSB.write(analog, 16000);
but this gave new bizarre behavior, as shown.
This looks good, except that switching which ADC input went to which set of data didn't change the data in the packet! The red channel is supposed to be the second input channel, so it should have flipped the colors of the two plots!
So apparently, the loop reading pairs of values is totally ignoring the actual settings I give it and reads A0 first followed by A1 even when I tell it to do it in the other order!
Then I put back the order of A0/A1 in reading, but read A5 first instead of A4. A5 is the same frequency as A4 but a lower voltage amplitude.
unsigned int analogvalue4, analogvalue5;
uint8_t analog[16000];
analogRead(5);
delay(1);
for(int i=0; i<16000; i=i+4) {
analogvalue4 = analogRead(0);
analogvalue5 = analogRead(1);
analog[i] = (analogvalue4 >> 8) & 0xFF;
analog[i+1] = analogvalue4 & 0xFF;
analog[i+2] = (analogvalue5 >> 8) & 0xFF;
analog[i+3] = analogvalue5 & 0xFF;
delayMicroseconds(ADCdelay);
}
SerialUSB.write(analog, 16000);
and doing this gave me what appears to be A5 in place of A1 in the data.
so now the problem looks like it isn't anything special about A4 either, but rather something again that has to do with data read order.
In case the problem had to do with reading from A4/A5 while sampling A0/A1 (not sure why this would be an issue), I flipped it around and sampled the pair A4/A5 without touching A0/A1.
unsigned int analogvalue4, analogvalue5;
uint8_t analog[16000];
//analogRead(5);
delay(1);
for(int i=0; i<16000; i=i+4) {
analogvalue4 = analogRead(4);
analogvalue5 = analogRead(5);
analog[i] = (analogvalue4 >> 8) & 0xFF;
analog[i+1] = analogvalue4 & 0xFF;
analog[i+2] = (analogvalue5 >> 8) & 0xFF;
analog[i+3] = analogvalue5 & 0xFF;
delayMicroseconds(ADCdelay);
}
SerialUSB.write(analog, 16000);
which gave me apparently good looking data for channels A4 and A5.
Predictably, a single read of A0 now messes up the A4/A5 pair.
unsigned int analogvalue4, analogvalue5;
uint8_t analog[16000];
analogRead(0);
delay(1);
for(int i=0; i<16000; i=i+4) {
analogvalue4 = analogRead(4);
analogvalue5 = analogRead(5);
analog[i] = (analogvalue4 >> 8) & 0xFF;
analog[i+1] = analogvalue4 & 0xFF;
analog[i+2] = (analogvalue5 >> 8) & 0xFF;
analog[i+3] = analogvalue5 & 0xFF;
delayMicroseconds(ADCdelay);
}
SerialUSB.write(analog, 16000);
with A0 now apparently replacing A4.
Finally, I tried reading A5 followed by A4 followed by the pair reading of A0/A1 to see if it had to do with the most recent channel sampled or if it was something else.
unsigned int analogvalue4, analogvalue5;
uint8_t analog[16000];
analogRead(5);
analogRead(4)
delay(1);
for(int i=0; i<16000; i=i+4) {
analogvalue4 = analogRead(0);
analogvalue5 = analogRead(1);
analog[i] = (analogvalue4 >> 8) & 0xFF;
analog[i+1] = analogvalue4 & 0xFF;
analog[i+2] = (analogvalue5 >> 8) & 0xFF;
analog[i+3] = analogvalue5 & 0xFF;
delayMicroseconds(ADCdelay);
}
SerialUSB.write(analog, 16000);
which gave
showing that A5 is still replacing A0! This is not remotely what I would expect, so I still clearly am understanding the bug wrong. It's not even the most recent channel sampled, measuring A5, then A4, and then the pair A0/A1 does the same error as if I didn't measure A4 in between.
I also tried with the A1/A4 pair. I won't continue to post the code and results, but A1/A4 looked good as a pair. Adding a single sample of A0 however replaced A1 with A0 data.
This is all incredibly strange to me. The ADC is clearly collecting real data, it matches at least one of the input signals in each case, matches my oscilloscope readout (but not the right channel), and it even has glitches that I would expect from the multiplexer. It appears to be doing analog reads based only on the order of requests, instead of on the argument to AnalogRead(). But the first time AnalogRead is called it seems to set a channel.
I don't even know where to start here. I doubt it's electrical since the scope isn't showing anything strange and there is some configuration in each case with which the data is correct. Really I feel like this level of characterization of the bug means there's almost nothing it could be other than the library or hardware.