Ok, it's been quite a while since this thread was active, so I'm resurrecting it.

A few months back I messed around with what I was inquiring about, had some problems, had to put it down for a time, and just started playing again the other day. The deal is that I wanted to hook up a bunch of LM35/TMP36 type of analog temperature sensors to the Arduino through a single analog read pin by way of a CD4051 multiplexer. You know, save pin space on the Arduino for other fun things...
I had used Ladyada's original
Temperature sensor tutorial, though I see that it's changed now. A lot of my questions/findings are based on the last code chunk (that was) there where there was a bit about calibrating the sensor by measuring the bandgap reference pin #14. By the look of the tutorial now, it seems the thinking on that has changed but I haven't yet found out why. Maybe someone here (fat16lib?) can help us all understand what's going on, why the change was made, and why I'm seeing what I'm seeing?
The Setup:
The Arduino uses 3 digital pins set to output to address up to 8 different temperature sensors hooked up to the multiplexer. On my test board I have 3 sensors. During loop(), the board reads the voltage on reference pin 14, cycles through the addresses (001, 010, 011), setting them (on pins 5,6,7), and then reading the mux output on pin 0. During any pin read, I'm using a read-delay-reread-delay method based on earlier posts in this thread to try to avoid weird read impedance issues.
Problem:
I noticed almost right away that the "calibrated" temperature readings were waaaay too high to be correct. It seemed that if I introduced a long enough delay in the loop I could make the output seem more reasonable, but the temperatures it was now giving were a few degrees too low compared to an accurate thermometer on the desk right next to the sensors. Strangely, the "uncalibrated" temperatures agreed very well with the reference thermometer. Needless to say, I was puzzled (and still am) about why it was behaving that way.
Looking at the raw readings coming off of the Arduino ADC (ie, the 0-1023 value before it is converted to a voltage or temperature), the sensor pin reads were fairly constant and independent of the duration of the delay in the loop. Reading the bandgap reference pin is another matter, however. Reading that pin too quickly after switching from another pin (after a short loop delay) results in a lower value from the ADC, which is why the calibrated temperatures were coming out too high.
After discovering this, I changed the sketch, below, to start with a loop delay of 20 ms, and increase the delay by 20 ms each time through.
Code: Select all
#define BANDGAPREF 14 // special pin so we can measure the bandgap
int loopDelay = 20; // ms between loops
int pinReadDelay = 10; // ms delay to stabilize reading on Arduino ADC when switching pin-to-pin?
int muxAddPins[] = { 5, 6, 7 }; // digital pins on Arduino that control all the muxes
int analogReadWithDelays(int pin)
{
analogRead(pin);
delay(pinReadDelay);
int val = analogRead(pin);
delay(pinReadDelay);
return val;
}
float volt2temp(float volt)
{
float tempC = (volt - 0.5) * 100; //Celcius
return (tempC * 9. / 5.) + 32.; //returns Fahrenheit
}
void setup()
{
for (int ii = 0; ii < 3; ii++) { //set multiplexer address switch pins to OUTPUT
pinMode(muxAddPins[ii], OUTPUT);
}
Serial.begin(9600); //Start the serial connection with the computer
delay(2000);
}
void loop()
{
int sensorPin = 0;
int addressbit[] = { 1,2,4 }; // for accounting/pin math
int refReading, reading;
float supplyVoltage, voltage, Uvoltage;
Serial.print(loopDelay);Serial.print(" || "); //start line
refReading = analogReadWithDelays(BANDGAPREF); //use this reference for all sensor reads
// run through pin addresses on the mux (ie, 001, 010, 011 for the three on right now)
for (int mpi = 0; mpi < 3; mpi++ ) {
for (int pi = 3-1; pi>=0; pi--) { // set each address bit
if ( mpi & addressbit[pi] ) { digitalWrite(muxAddPins[pi], HIGH); } else { digitalWrite(muxAddPins[pi], LOW); }
}
// Now read the voltage off the sensor at that mux address
// ...calculate our power supply voltage from the known 1.05 volt reading
supplyVoltage = (1.05 * 1024) / refReading;
// ...get the voltage reading from the temperature sensor, convert that to voltage
reading = analogReadWithDelays(sensorPin);
voltage = reading * supplyVoltage / 1024;
Uvoltage = reading * 5.0 / 1024; // also, look at "uncalibrated" version
Serial.print(volt2temp(voltage),3); Serial.print(" ");
Serial.print(volt2temp(Uvoltage),3);Serial.print(" | ");
}
Serial.println(); //end the line
delay(loopDelay); //WHY DO I NEED THIS TO BE SO LONG???!!!
loopDelay = loopDelay + 20; // in each iteration, add some time to the loop
}
The results of this sketch for loop delays of 20ms through 10,000ms are plotted below. The blue points are for the "uncalibrated" temperatures and the red points are for the "calibrated" temperatures. Additionally, each of the three individual sensors are represented by triangles, circles, and squares, plotted in that order. Remember that a comparison thermometer on the desk next to the sensors reads ~80F.

- Actual temperature is ~80F.
- temptest.png (68.56 KiB) Viewed 54806 times
I'll test this again soon to see if the "circle" sensor (actually, the 2nd sensor read of the 3) really always behaves that noisily for loop delays <~7000ms, or if it is just sporadically noisy. I noticed something weird about it earlier, so that may indeed be the case. Anyway, there it is.
So I still have my original questions, but I'm hoping we can use this to discuss what's going on. Why is it that switching to pin 14 too fast after reading another pin yields low values from the ADC (and high calibrated temps), and why doesn't this happen when going from pin 14 to another pin? Why were we trying to use pin 14 to calibrate the temperature reading in the first place if the temperatures are all off in the end and the uncalibrated temperature was correct? Why is that factor 1.05 there in the original post (and in my code) in the calibration formula? From what I can tell, the 8 or 9 degree difference, as well as the direction of the difference can be accounted for by that extra 0.05...
Any insight would be greatly appreciated! Thanks in advance!
-Brandon