reading multiple analog inputs

Hi Guys,

We are working on a project where we are using an arduino uno in order to read battery voltage and solar panel voltage. As we tried this, we run into a big issue: when we try to read in from one analog pin, it works perfectly, but if we read from two analog pins at the same time, none of the two readings are accurate even though we used the same code as before. Please if anybody can shed some light into this issue??? We pretty much just hit a wall as we have tried eveything possible. We will really appreciate your help!

but if we read from two analog pins at the same time,

Technically this isn't possible, can you post your code?


Rob

Shcematics would be a good idea as well. Do they have same ground potential? Are those batteries in parallel or serial?

Cheers,
Kari

here is the code. Maybe I did not explain myself right. We are reading from two different analog pins on the arduino. They do have the same ground potential.hopefully, this code will give you guys an idea.

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
// variables for input pin and control LED
int solarV = 7;
int batteryV= 3;
float vout = 0.0;
float vin = 0.0;
float vin1=0.0;
float vout1=0.0;
float R1 = 4.7;
float R2 = 1.005;
float R11=4.690;
float R22= .998;
float solarPanelVoltage = 0;
float batteryVoltage =0;

void setup(){
Serial.begin(9600); // begin sending over serial port
lcd.begin(20, 4);
// declaration of pin modes
analogReference(DEFAULT);
pinMode(solarV, INPUT);
pinMode(batteryV, INPUT);
}

void loop(){
// read the value on analog input
//Serial.print("value=");
//Serial.println(value);

solarPanelVoltage = analogRead(solarV);
vout = (solarPanelVoltage * 5.0) / 1024.0;
vin = vout / (R2/(R1+R2));

batteryVoltage = analogRead(batteryV);
vout1=(batteryVoltage * 5.0) / 1024.0;
vin1= vout1 / (R22/(R11+R22));

Serial.print("voltage=");
Serial.println(vin);
lcd.setCursor(0,0); //column and row of lcd
lcd.print("Voltage=");
lcd.setCursor(8, 0);
lcd.print(vin);
lcd.setCursor(13, 0);
lcd.print("V");
//delay(1000);

Serial.print("battery=");
Serial.println(vin1);
lcd.setCursor(0,1); //column and row of lcd
lcd.print("Battery=");
lcd.setCursor(8, 1);
lcd.print(vin1);
lcd.setCursor(13, 1);
lcd.print("V");
delay(1000);

}

Yes, I understood that. By the code, it seems ok to me, but the schematic would help to understand what is going on. There's probably something floating...?

Kari

Doesn't the solarV in this

pinMode(solarV, INPUT);

refer to digital pins and in here

solarPanelVoltage = analogRead(solarV);

it refers to analog pins. So you are working with different pins.

However I don't think it matters because I think analogRead() will set the pin direction anyway.


Rob

Try putting some delay in between these reads

   solarPanelVoltage = analogRead(solarV);
   vout = (solarPanelVoltage * 5.0) / 1024.0;
   vin = vout / (R2/(R1+R2)); 
  
  batteryVoltage = analogRead(batteryV);
  vout1=(batteryVoltage * 5.0) / 1024.0;
  vin1= vout1 / (R22/(R11+R22));

You may be running into this, section 23 of the datasheet, we can't say for sure as no schematic has been posted:

"The analog input circuitry for single ended channels is illustrated in Figure 23-8. An analog
source applied to ADCn is subjected to the pin capacitance and input leakage of that pin, regardless
of whether that channel is selected as input for the ADC. When the channel is selected, the
source must drive the S/H capacitor through the series resistance (combined resistance in the
input path).
The ADC is optimized for analog signals with an output impedance of approximately 10 k? or
less. If such a source is used, the sampling time will be negligible. If a source with higher impedance
is used, the sampling time will depend on how long time the source needs to charge the
S/H capacitor, with can vary widely. The user is recommended to only use low impedance
sources with slowly varying signals, since this minimizes the required charge transfer to the S/H
capacitor.
Signal components higher than the Nyquist frequency (fADC/2) should not be present for either
kind of channels, to avoid distortion from unpredictable signal convolution. The user is advised
to remove high frequency components with a low-pass filter before applying the signals as
inputs to the ADC."

I had the same problem reading temperature sensors.. The trick when using multiple analog sensors is to read them twice, with a small delay after each read (10ms is good), then discard the first reading. This is because the ADC multiplexer needs switching time and the voltage needs time to stabilize after switching.. Basically the first analogRead call causes the multiplexer to switch, the delay gives the voltage time to stabilize, then your second read should be much more accurate with less jitter. You should have something like this:

  solarPanelVoltage = analogRead(solarV);
  delay(10);
  solarPanelVoltage = analogRead(solarV);
  delay(10);
   vout = (solarPanelVoltage * 5.0) / 1024.0;
   vin = vout / (R2/(R1+R2));
 
  batteryVoltage = analogRead(batteryV);
  delay(10);
  batteryVoltage = analogRead(batteryV);
  delay(10);
  vout1=(batteryVoltage * 5.0) / 1024.0;
  vin1= vout1 / (R22/(R11+R22));
3 Likes

One question popped in my mind now, does the analogPin() function in the Arduino library use the low noise sleeping mode to make a conversion?

HELLO!!

The solution posted by jondecker76 worked for me

THANKS A LOT!


gopi

I have a bunch of the dallas 1 wire temperature sensors. I have yet to be able to find any way to find their addresses or read them. I have found several sketches for discovering the addresses of the sensors and for reading them. Not one sketch I have found so far will compile. They are all full of syntax errors. I have copied and pasted them and had others try also and none of them work. It seems everything posted on the internet is an Arduino language with a different syntax than what we use. I am running the latest version of the Arduino language and have made several sketchs of my own and they have worked. I do not know enough about the Arduino compiler and its syntax and error codes to fix the problems with someones elses sketch. Does anyone out there have a sketch - that actually works - that will read a single one wire temperature sensors address and will read its temperature value.

Thanks

Jim

Hi!

for me the best solution after doing a lot of test is to do two differents loop for reading each variable, like this:

void loop()

{
reading = 0;
water = 0;
for(int i = 0; i < 10; i++) { // Average 10 readings for accurate reading

delay(100);

reading += analogRead(tempPin); // reading = reading + analogRead(tempPin) lo es que lo mismo suma 10 medidas

delay(100);

}
for(int i = 0; i < 10; i++) { // Average 10 readings for accurate reading

delay(100);

water += analogRead(waterPin);

delay(100);

}

tempC = (referenceVoltage * reading * 10) / 1023; // viene del datasheet 10mV/ºC
WaterContent =(water)*0.0097;

Serial.print(tempC, 1); //Print one decimal, it's not accurate enough for two
Serial.println(" C");
Serial.print(WaterContent); //Print one decimal, it's not accurate enough for two
Serial.println("waterContent");
Serial.println();
Serial.println();
Serial.println();
//
delay(150);
}

now it works fine

jlefevre1:
Does anyone out there have a sketch - that actually works - that will read a single one wire temperature sensors address and will read its temperature value.

This is the code I use for temperature sensors. You have to know the address of the sensor. They should be easy to use.

#include <OneWire.h>
#include <DallasTemperature.h>

DeviceAddress Probe01 = {
  0x28, 0xFF, 0x1E, 0x2A, 0x68, 0x14, 0x04, 0xCB
};

#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup()
{
  sensors.begin();
  sensors.setResolution(12);
}

void loop()
{
  sensors.requestTemperatures();
  float temp=sensors.getTempC(Probe01);
}

yes u are right
i have also tried to read two analogue pin but so far failed
can any one help me

1 Like

Is it possible to connect around six sensors to a Uno and, using an LCD have the data from each sensor read individually by pushing a button to connect each sensor as you want to access the data from that specific sensor?

hi to all

i have the slightly different prob.

i m reading DC Volt of Battery (while getting charged),Current it taking for being charged

i explaining it.

look i m using Volt Divider(50/5) for volt and shunt(50/5) for current.

when i connect only one at a time to analog pin. it works fine.

but when i connected both A0 and A1 for Volt and Current respectively. it burned the arduino.

please anyone can tell my mistake....?

because i have burnt three arduino bords

thanks in advance

I too was having this problem and hence found this thread.

Basically I was reading battery voltage off A0. Had no problems.

I then added another analog sensor to A2 and my A0 readings then starting giving errors. I then removed my sensor from A2 but still did an analog read of A2. This still caused problems with my A0 readings.

The explanation and solution provided in this thread by "jondecker76" made sense and more importantly it fixed the problem instantly.

THANKS jondecker76 you helped resolve this problem that has bugged me for weeks.

@jondecker76

Great job of documenting your tip: "The trick when using multiple analog sensors is to read them twice, with a small delay after each read (10ms is good), then discard the first reading. This is because the ADC multiplexer needs switching time and the voltage needs time to stabilize after switching.. Basically the first analogRead call causes the multiplexer to switch, the delay gives the voltage time to stabilize, then your second read should be much more accurate with less jitter."

As an FYI, this is also true on the Adafruit ESP32 Feather HUZZAH when reading capacitance with touchRead(). The first read is always wonky, but the second and subsequent channel reads are all fine after a ~10 microsecond delay. You can easily see it with the serial plotter.

Eg:

 unsigned int dumpRead = touchRead(T5);
 delayMicroseconds(10);
 unsigned int goodRead = touchRead(T5);
1 Like