analogReference(INTERNAL1V1) Conflict between two analog readings

Hi,
Once again I need to ask the community for advice. Currently I'm building a weather station based on a MEGA2560 with a V2 SensorShield. The stand alone weather station is powered by a PV-panel and a lead-acid battery. I've got about 15 sensors connected and everything was running fine until I added the functionality to measure the battery voltage (So that I can keep an eye of the charging state of the battery).

One of my sensors is a Rotronic humidity sensor. It measures humidity through change in capacitance.
The output signal goes from 0V to 1V. So 50% humidity is equal to a voltage of 0.5V. This signal is read from A08.
Here is the code for this particular function block:

void Rotronic() {
  analogReference(INTERNAL1V1); //Set reference voltage to 1.1V, works only for the MEGA2560
  sensorValue8 = analogRead(A8);
  rotronicHum = sensorValue8 * (1.0 / 1023.0) *100;
}

To measure the battery voltage I have incorporated a voltage divider (10k and 22k Ohm respectively) which allow me to measure a potential difference between 0V and 20V. The battery is normally around 13.5V. The voltage is read by polling A0.
Here is the code for this particular function block:

void battVoltage() {
  sensorValueA0 = analogRead(A0);
  batteryVoltage = sensorValueA0 * (5.0 / 1023.0);
}

When I run both functions individually then they both work fine.
However, when I try to run them in the same program then the humidity probe will work but the battery will show 20V.

I worked out that the problem is caused by the analogReference(INTERNAL1V1) command.
It seems like the analogReference(INTERNAL1V1) is not able to switch off when I go from one function to another.
I have tried the command analogReference(DEFAULT) at the end of the humidity function but this doesn't seem to work.

Basically the conflict is caused by trying to read an analog voltage between 0 to 1V and a voltage between 0 and 5V.

How would you guys tackle this problem? Is there a way around that both analog readings will happily work together?

I can upload the whole program but all in all it's about 500 lines of code and I'm afraid this would it make very hard for you to decipher. I will upload if there's a need for it.
Cheers,

Luc

Modify the voltage divider on the battery voltage to give 0 to 1 volt so that you don't have to switch the reference back and forth.

Or switch the reference back and forth:

void Rotronic() {
  analogReference(INTERNAL1V1); //Set reference voltage to 1.1V, works only for the MEGA2560
  analogRead(A8); // Datasheet recommends a double-read after change of Aref
  sensorValue8 = analogRead(A8);
  rotronicHum = sensorValue8 * (1.0 / 1023.0) *100;
}
void battVoltage() {
  analogReference(DEFAULT); //Set reference voltage to VCC (5V)
  analogRead(A0); // Datasheet recommends a double-read after change of Aref
  sensorValueA0 = analogRead(A0);
  batteryVoltage = sensorValueA0 * (5.0 / 1023.0);
}

Thanks Johnwasser,

I thought about that but I also read that this will take a fair bit of time and that the initial results will not be precise.
As I'm reading 15 sensors every second this could lead to incomplete readings.
I will try it though and see how it goes. Thanks for the advice!

LRAT:
Thanks Johnwasser,

I thought about that but I also read that this will take a fair bit of time and that the initial results will not be precise.
As I'm reading 15 sensors every second this could lead to incomplete readings.
I will try it though and see how it goes. Thanks for the advice!

A fair bit of time?!? I just ran a test on an Arduino UNO and it took only 480 microseconds to do both of these reads, including changing Aref and double-reading. Figure 240 microseconds per sensor. Your 15 sensors would take a total of about 7.2 milliseconds, leaving 992.8 milliseconds for everything else.
If that is too slow you could minimize the number of Aref changes (and their double-read). That cuts the sensor read time almost in half: maybe 4 milliseconds total.

Thanks Johnwasser,

I must have been incorrectly informed then :slight_smile:
Yes, that will allow plenty of time to read them all within one second :slight_smile:
I will make the changes to the code tonight.
Thanks for the advice and testing it out!
Karma added!
Cheers,

Luc

Leaving Aref on 1.1volt, and changing the voltage divider to output <=1volt should give a more stable result.
Then battery voltage readout is not depending on the potentially unstable default Aref (5volt supply).

batteryVoltage = sensorValueA0 * (5.0 / 1023.0);

That line has to be changed to reflect the exact reference voltage (not 5.0 but ~1.1volt) and the ratio of the voltage divider.

Say you use a 1:15 ratio, made with a 2k2 resistor to ground and a 33k resistor to battery+
Then that line becomes

batteryVoltage = analogRead(A0) * 0.01679; // calaibrate by changing the last digit(s) of 0.01679

No other lines needed, and this takes ~100us.
Leo…

Thanks Leo,

I just worked out a solution to my problem. Here’s that code block:

void battVoltage() {                        // R1 = 21590 Ohm, R2 = 9940 Ohm  
  analogReference(DEFAULT);                     //Set reference voltage to Vcc (5V)  
  analogRead(A0);                                   //Datasheet recommends a double-read after change of Aref
  while(sampleCount < batterySamples) {
    sensorValueA0 += analogRead(A0);
    sampleCount ++; }  
  batteryVoltage = (sensorValueA0 / batterySamples * 15.95) / 1024.0;
  sampleCount = 0;                                //Reset the sampleCount to 0
  sensorValueA0 = 0;                              //Reset the reading of A0 to 0
}

I measured the battery voltage under all sorts of circumstances and it seems to be quite accurate.

However, your code sample seems to make sense. At least it looks more efficient. I will play around with it tomorrow.
Thank you very much for your help. Karma added!
Cheers,

Luc

Salut LRAT, je suis aussi entrain de travailler sur un projet IOT avec un capteur d'humiditté et de température Rotronic hc2-s3 et je voudrais savoircomment tu as relier ton capteur rotronic a la carte arduino et si il y'a des composants a rajouté pour éviter dabimer le capteur. Merci bien