Problem reading two sensors with analogRead()
Moderators: adafruit_support_bill, adafruit

Re: Problem reading two sensors with analogRead()

by adafruit_support_bill on Sun Aug 12, 2012 1:02 pm

You haven't told us how you have this connected. You could very well be picking up noise in the wiring. And as John444 says, excess capacitance in the wiring can make it unstable too.
User avatar
adafruit_support_bill
 
Posts: 31061
Joined: Sat Feb 07, 2009 10:11 am

Re: Problem reading two sensors with analogRead()

by physicsonion on Wed Nov 14, 2012 10:43 pm

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
analogRead(A0); // dummy read to discharge ADC
delay (20); // wait a little
analogRead(A1); // now hook up ADC to the channel we really want to read
delay (20); // doze a little
temp = 100*(analogRead(A1)*5/1025 -0.5); // now read once more
!!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 11:10 am

Re: Problem reading two sensors with analogRead()

by gregario on Fri Nov 16, 2012 7:53 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 | TOGGLE FULL SIZE
  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 | TOGGLE FULL SIZE
Seconds (S)   Light (10 bit)   Light (lux)
1   244   544.59
2   265   607.21
3   275   638.49
4   251   565.03
5   245   547.49
6   276   641.67
7   256   579.89
8   247   553.3
9   276   641.67
10   272   629
11   254   573.92
12   253   570.95
13   276   641.67
14   254   573.92
15   245   547.49
16   271   625.86
17   276   641.67
18   248   556.22
19   250   562.09
20   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 9:18 am

Re: Problem reading two sensors with analogRead()

by adafruit_support_bill on Fri Nov 16, 2012 11:34 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.
User avatar
adafruit_support_bill
 
Posts: 31061
Joined: Sat Feb 07, 2009 10:11 am

Re: Problem reading two sensors with analogRead()

by Strohkopf on Sat Nov 24, 2012 7:09 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 | TOGGLE FULL SIZE
#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 | TOGGLE FULL SIZE
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?
Sorry for bad english.
Cheers!
Strohkopf
 
Posts: 2
Joined: Sat Nov 24, 2012 6:44 am

Re: Problem reading two sensors with analogRead()

by adafruit_support_bill on Sat Nov 24, 2012 7:19 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?
User avatar
adafruit_support_bill
 
Posts: 31061
Joined: Sat Feb 07, 2009 10:11 am

Re: Problem reading two sensors with analogRead()

by Strohkopf on Wed Dec 05, 2012 3:50 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 6:44 am

Re: Problem reading two sensors with analogRead()

by adafruit_support_bill on Wed Dec 05, 2012 6:48 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.
User avatar
adafruit_support_bill
 
Posts: 31061
Joined: Sat Feb 07, 2009 10:11 am

Re: Problem reading two sensors with analogRead()

by manrussian on Tue Jan 15, 2013 8:57 pm

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 | TOGGLE FULL SIZE

#define tsp 5                  //temp sensor input port
#define ADCsamples 64          //Number of temperature sensor values to take for average
float tempCurrent = 0.0;       //current temperature

void 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 8:45 pm

Re: Problem reading two sensors with analogRead()

by adafruit_support_bill on Tue Jan 15, 2013 9:00 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.
User avatar
adafruit_support_bill
 
Posts: 31061
Joined: Sat Feb 07, 2009 10:11 am

Re: Problem reading two sensors with analogRead()

by manrussian on Wed Jan 16, 2013 4:56 pm

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 8:45 pm

Re: Problem reading two sensors with analogRead()

by adafruit_support_bill on Wed Jan 16, 2013 5:33 pm

In theory, it ought to be more stable. But our experience says otherwise.
viewtopic.php?f=25&t=11597&p=83455
User avatar
adafruit_support_bill
 
Posts: 31061
Joined: Sat Feb 07, 2009 10:11 am

Re: Problem reading two sensors with analogRead()

by Midway on Fri Sep 06, 2013 5:01 pm

Hi,

I have the same porblem, but dont know how/where to add (write) the code inside this project.
When I integrate the PAvalue it will influenced the Temp / Fan control.

Code: Select all | TOGGLE FULL SIZE
#include <LiquidCrystal.h>

float Voltage;
float TempC;

int FAN = 9;                            // FAN Optocoupler (CNY74-2) connected to digital PWM pin 9
int Temperature;
int PAvalue;
int PAVin = 0;

const int LM35 = 0;                     // analog pin 0 (LM35CZ).
const int PA = 2;                       // analog pin 2 (PA signal Input).

const int LowTemp = 30;                 // Setting LOW Temperature setpoint. The Fan reach full speed then temperature is more than 10°C above setpoint.


LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


void setup()
{
  lcd.begin(16,2);
  pinMode(FAN, OUTPUT);                 // Set pin for output to control FAN Optocoupler.
  pinMode(TempC, INPUT);                // sets analog pin 0 for input
  pinMode(PA, INPUT);                   // sets analog pin 2 for input
}
void loop()
{
  Temperature = analogRead(LM35);                         // read the value from the LM35 sensor
  Voltage = Temperature * (5.0/1024);                     // convert reading to voltage (in V), for 5V input
  TempC = ( 5.0 * Temperature * 100.0) / 1024.0;          // convert voltage to temperature

  analogWrite(FAN, constrain( (TempC - LowTemp) * 25, 0, 255));   // If the temperature is highher than the set point, run the fans.

  lcd.setCursor(0,1);
  lcd.print(TempC);                                       // Print Celsius temperature to LCD
  lcd.print((char)223);                                   // degree symbol
  lcd.print("C ");
  {
  }
  PAvalue = analogRead(PA);                               // read the value from the PA output driver.
  float PAVin = PAvalue * (4.5 / 1024.0);

  if (PAVin>4)
  {
    lcd.setCursor(8, 0);
    lcd.print("10");
  }
  else
    if (PAVin>3 && PAVin<4)
    {
      lcd.setCursor(8, 0);
      lcd.print(" 8");
    }
    else
      if (PAVin>2 && PAVin<3)
      {
        lcd.setCursor(8, 0);
        lcd.print(" 6");
      }
      else
        if (PAVin>1 && PAVin<2)
        {
          lcd.setCursor(8, 0);
          lcd.print(" 4");
        }
        else
          if (PAVin>0.5 && PAVin<1)
          {
            lcd.setCursor(8, 0);
            lcd.print(" 3");
          }
          else
            if (PAVin>0 && PAVin<0.5)
            {
              lcd.setCursor(8, 0);
              lcd.print(" 2");
            }
  {
    lcd.setCursor(0, 0);
    lcd.print("Output:");
    lcd.setCursor(11, 0);
    lcd.print("Watt");
    lcd.setCursor(10, 1);
    lcd.print(PAVin);
    lcd.setCursor(15, 1);
    lcd.print("V");
  }
}

Any help will appriciate.

Thanks
Ed.
Midway
 
Posts: 2
Joined: Fri Sep 06, 2013 4:50 pm

Re: Problem reading two sensors with analogRead()

by adafruit_support_rick on Fri Sep 06, 2013 5:06 pm

Just duplicate the analogRead lines to read everything twice:

Code: Select all | TOGGLE FULL SIZE
  Temperature = analogRead(LM35);                         // read the value from the LM35 sensor
  Temperature = analogRead(LM35);                         // First time was for practice. Now read it for real.

Code: Select all | TOGGLE FULL SIZE
  PAvalue = analogRead(PA);                               // read the value from the PA output driver.
  PAvalue = analogRead(PA);                               // read it again, just to make sure.

If you want to change the analog reference to 3.3V, then you would also add this line at the end of your setup() function:
Code: Select all | TOGGLE FULL SIZE
analogReference(EXTERNAL);

You also have to attach a jumper wire between the 3.3V output pin and the AREF input pin.

adafruit_support_rick
 
Posts: 13083
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: Problem reading two sensors with analogRead()

by Midway on Fri Sep 06, 2013 6:51 pm

Many thanks!!

it work fine now.

regards,
Ed.
Midway
 
Posts: 2
Joined: Fri Sep 06, 2013 4:50 pm