My \$0.05 solution to this problem is as following. As people earlier in the thread have indicated the arduino itself has a multiplexer and only one ADC. Problem occurs when flipping between different voltage sources that they introduce transient which takes a while to disappear. Source of the transient is the input capacitance of the ADC and its huge input resistance (hence the large time constant).

This said, of 6 input channels of arduino, I take one - say A0 - and through a 5k resistor I ground it. Then, before I try to read any other analog channels, I first connect the ADC to the ground by reading from A0.

!!Code snippet
delay (20); // wait a little
delay (20); // doze a little
!!End of code snippet

With this approach I was able to read 4 additional analog inputs - in my case these were 4 x TMP36 temperature sensors at rate 50, or so, milliseconds per sensor.

Hope this helps,
PhysicsOnion
physicsonion

Posts: 2
Joined: Wed Jan 04, 2012 10:10 am

Hi All,

I'm having a similar problem. I'm running a photoresistor and a TMP36 and logging the data on an arduino.
The temperature sensor is fine but the photoresistor is very noisy. Any tips?

Details, the photoresistor is in a voltage divider with a 1K resistor (the lower resistor is there to increase the range).
I've tried the tricks suggested and then some, here's an excerpt of code for example:

Code: Select all
`  analogRead(gndPin);  delay(100);  analogRead(photocellPin);  delay(100);   int photocellReading = analogRead(photocellPin);    delay(100);  analogRead(gndPin);  delay(100);  analogRead(tempPin);   delay(100);  int tempReading = analogRead(tempPin);      delay(100);  // converting that reading to voltage, for 3.3v arduino use 3.3, for 5.0, use 5.0  float voltage = tempReading * aref_voltage / 1024;  float temperatureC = (voltage - 0.5) * 100;  float voltage1 = photocellReading * aref_voltage / 1024;   // float temperatureF = (temperatureC * 9 / 5) + 32;  //Converts Photocell Reading to Lux Reading, This will be unique for each Sensor and will change between diodes/Photoresistors  // Sensor 12 (C) = y = 626.06x6 - 3395.4x5 + 7395.5x4 - 7264.1x3 + 3743.7x2 - 148.26x  double luxReading = ((626.06*(pow(voltage1,6)) -(3395.4*(pow(voltage1,5))) + (7195.5*(pow(voltage1,4))) - (7264.1*(pow(voltage1,3))) + (3743.7*(pow(voltage1,2))) - (148.26*voltage1)));`

The ground pin is a 5K resistor tied to ground to try and flush the ADC cap between measurements. The 6th order polynomial is my attempt to get an accurate lux measurement from one of these sensors. (I calibrated using an OLED taped to the top of a dremel tube and a lux meter)

Here's an output under a controlled light source
Code: Select all
`Seconds (S)   Light (10 bit)   Light (lux)1   244   544.592   265   607.213   275   638.494   251   565.035   245   547.496   276   641.677   256   579.898   247   553.39   276   641.6710   272   62911   254   573.9212   253   570.9513   276   641.6714   254   573.9215   245   547.4916   271   625.8617   276   641.6718   248   556.2219   250   562.0920   275   638.49`

The measurements quoted above under fluorescent, I must dig out the response times of these sensors in case its light flicker I'm seeing...

Any help would be greatly appreciated guys, micro's are not my strong point!
gregario

Posts: 3
Joined: Fri Jun 11, 2010 8:18 am

CdS cells are fairly slow, but the fluorescent flicker could be part of the problem. You can minimize the 60Hz flicker and other noise as well by taking the average of multiple samples over some multiple of 16ms. If you are only logging once per second, you have plenty of time to take multiple samples.

Posts: 15918
Joined: Sat Feb 07, 2009 9:11 am

Hi! Seems I have problems w/ reading sensors too.

I have arduini uno board, seeeduino wifly-shield http://www.seeedstudio.com/wiki/Wifi_Shield and extension DFRduino shield.
I need to send results from IR and Ultra Sound length-meters via WiFi on PC, just making a robot.

Simple code of my programm is
Code: Select all
`#include "Wifly.h"#include <SoftwareSerial.h>WiflyClass Wifly(2,3);int sensors[6];void setup(){  Serial.begin(9600);//use the hardware serial to communicate with the PC  bool wifi = true;  if(wifi){    Wifly.init();//Initialize the wifishield    Wifly.setConfig("MyWiFi","12345678");//here to set the ssid and password of the Router    Wifly.join("MyWiFi");    Wifly.checkAssociated();    while(!Wifly.connect("192.168.137.1","40020"));//connect the remote service    Wifly.writeToSocket("Connected!");  }}void loop(){  Serial.print("Sensors:");  for( int i = 0 ; i < 6 ; i++ ){    analogRead(i);    delay(10);    sensors[i] = analogRead(i);    Serial.print(sensors[i]);    Serial.print(", ");    delay(30);  }  Serial.println(";");  }`

If i set wifi = true, then sensors show me some rubbish, every pin shows value is about 1010, and does not change on differenr ranges.
But when I set wifi = false, i.e. do not do wifly initialisation, everything works propally. I found that priblem in function WiFly.init() which do the next:

Code: Select all
`void WiflyClass::init() {      pinMode(WIFLY_RST, OUTPUT);   pinMode(WIFLY_GPIO6, INPUT);   SoftwareSerial::begin(9600);   reset();   unavailConn = 0;}`

This WiFly class is a child of SoftwareSerial class. I guess here some conflict between serial prints. Dd anyone face this problem?
Cheers!
Strohkopf

Posts: 2
Joined: Sat Nov 24, 2012 5:44 am

If i set wifi = true, then sensors show me some rubbish, every pin shows value is about 1010, and does not change on differenr ranges.

Could be interference from the WiFly radio. Have you posted this over at Sparkfun to see if it is a known issue?

Posts: 15918
Joined: Sat Feb 07, 2009 9:11 am

adafruit_support wrote:Could be interference from the WiFly radio. Have you posted this over at Sparkfun to see if it is a known issue?

Nope, they said that they do not support this shield.
Strohkopf

Posts: 2
Joined: Sat Nov 24, 2012 5:44 am

Nope, they said that they do not support this shield.

Sorry, I meant SeeedStudio instead of SparkFun. They make a version of this shield also.
We do not have any experience with these shields and do not sell or support them here.

Posts: 15918
Joined: Sat Feb 07, 2009 9:11 am

Just registered here to say thanks for the informative thread. Had stability issues reading only a single TMP36 with my Uno while working on a smart web-enabled thermostat project where I would like to keep the temperature with 1 degree F.

I used the mentioned solution of just taking many samples and finding an average. In my case I'm sticking with 64 samples. Speed isn't a big issue as even with the over-sampling all other project functions seems responsive (web server, user parameter parsing, NTP time synchronization, etc).

Without this fix I would get swings of multiple degrees. With 16 samples it still wasn't to my liking. 64 seems to do the trick.

I'm using the default 5v reference, with power from USB. TMP36 current on breadboard via some cheap jumper cables.

Didn't explore hardware fixes like low-pass RC/LC filters as there's no need to increase physical space with the above software fix.

Here's the code in case it helps someone:

Code: Select all
`#define tsp 5                  //temp sensor input port#define ADCsamples 64          //Number of temperature sensor values to take for averagefloat tempCurrent = 0.0;       //current temperaturevoid readTemp() {  float tempFlast = tempCurrent;                    //For monitoring temperature sensor/ADC noise  float ADCavg = 0.0;                               //To store average ADC value  float ADCsum = 0.0;                               //Store sum of ADC samples  for (int i = 0; i < ADCsamples; i++) {    ADCsum += analogRead(tsp);  }  ADCavg=ADCsum / (float)ADCsamples;  float tspVolts = ADCavg * (aRef/1024.0);           //convert ADC value to voltage  float tempC = (tspVolts - 0.5) * 100.0;            //convert voltage to Centigrate temp for TMP36 temp sensor  float tempF = (tempC * 9.0 / 5.0) + 32.0;          //Convert Centigrade to Farenheit   tempCurrent = tempF;                               //Set current temperature to user expected Farenheit value  Serial.println(tempF - tempFlast);                 //Output difference from last average}`
manrussian

Posts: 2
Joined: Tue Jan 15, 2013 7:45 pm

I'm using the default 5v reference,

This does tend to be the noisiest reference on the Arduino, since it supplies all the digital logic too. The 3.3v reference is typically the most stable on this platform.

Posts: 15918
Joined: Sat Feb 07, 2009 9:11 am

Any thoughts on whether the 3.3V is more or less stable than the "INTERNAL" analog reference described here?

http://arduino.cc/en/Reference/AnalogReference

Seems for my Uno that would be 1.1V. If my arithmetic is correct, with a TMP36 (.5v offset and 10mV per degree C) I can still measure up to 60 degrees C, or 140 degrees F. This would be plenty for my home thermostat project.

The advantages I see to this are:

1 - Less external connections (no need to connect 3.3V pin to aRef pin)
2 - Doesn't rely on external 3.3V regulator on Arduino.

Of course in all of the above I'm ignoring other noise sources like stray capacitance and unshielded cables that have been discussed earlier, but I'm willing to take what I can get while keeping external parts/connection to a minimum.
manrussian

Posts: 2
Joined: Tue Jan 15, 2013 7:45 pm

In theory, it ought to be more stable. But our experience says otherwise.
viewtopic.php?f=25&t=11597&p=83455