Precise measurements

I encountered a code that supposed to make my Ardu measure voltage more precise.

long readVcc() 
{
  long result;
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<1;
  result = 1125300L / result; // Back-calculate AVcc in mV
  return result;
}

When I tested it seriously it’s precise until the voltage is only 16-17 volts. But When my solar panel produces about 20.90-21 volts the arduino says 19.83 V. Why it that?
Can someone describe what does each line does in the code above?

The volt values above are calculated like this:

double Vcc;
Vcc=readVcc()/1000.0;
  int sensorvalue = analogRead(A0);
  double voltage = ((sensorvalue/1023.0)*Vcc)*4;
  Serial.println(voltage);
delay(1000);

So when I say 16-17 volts the input to the arduino measures 4-4.25 volts.

Thank you in advance!

When I tested it seriously it's precise until the voltage is only 16-17 volts. But When my solar panel produces about 20.90-21 volts the arduino says 19.83 V. Why it that?

You aren't feeding 21 volts into your Arduino, are you?

So when I say 16-17 volts the input to the arduino measures 4-4.25 volts.

How do you "say" 16 volts?

The volt values above are calculated like this

One high-accuracy reading and one low accuracy reading combined do not produce a high-accuracy result.

PaulS: How do you "say" 16 volts?

Peter says, "16 volts".

[quote author=Nick Gammon link=topic=191684.msg1416680#msg1416680 date=1380973489]

PaulS: How do you "say" 16 volts?

Peter says, "16 volts". [/quote] What kind of sensor/circuit do you use to read that?

PaulS: What kind of sensor/circuit do you use to read that?

A microphone. ;)

When I tested it seriously it's precise until the voltage is only 16-17 volts. But When my solar panel produces about 20.90-21 volts the arduino says 19.83 V.

Seriously, you need to describe your circuit.

No, I'm not feeding 21 V to the ardu. I use resistors to reduce it to around 5 volts.

Since I have to reduce the voltage that goes to the arduino, I have to multiplie it to get back the original Voltage produced by my solar panel. So, if my arduino writes 16 to the usb prot it only gets 4V. That's how it works. Safety first! :)

My circuit looks like this. I have 4X10kohm resistors. 3 in paralel and and one is in series with the other 3.

The solar panel is connected to this "resistor pack". Two wires comes from the pack. One goes to the ardu ground and one to the A0 pin.

The solar panel is connected to this "resistor pack". Two wires comes from the pack. One goes to the ardu ground and one to the A0 pin.

You want us to guess where they come from?

Have you actually measured the resistance of the resistors in the voltage divider? Are you certain that the voltage drops by exactly the amount you expect?

What is powering the Arduino?

The ardu powered by usb from my pc.

bigger version: http://kepfeltoltes.hu/view/131005/resistorpack_m_solata_www.kepfeltoltes.hu_.jpg

I'm pretty sure, that my resistors are 10Kohm. I measured them before.

double Vcc;
Vcc=readVcc()/1000.0;

Why is the declaration separated from the initialization? What value is being stored in Vcc?

  int sensorvalue = analogRead(A0);

What value is being stored in sensorvalue?

Where, exactly, is the problem? How are you determining that the Arduino is reporting incorrect results?

But When my solar panel produces about 20.90-21 volts

The voltage divider will drop this to 5.225 to 5.25 volts. The Arduino expects not more than 5.0.

Are you saying your VOC is 20.9 -21 volts? Is that what you read from your panel using a multimeter no load? What do you read from your divider when it is NOT connected to the Arduino?

Edit: Once you draw a current from your panel you lose your VOC voltage and move towards your Vmpp rating.

The sensorvalue stores the value what the A0 pin reads.

I don't really know what the VCC stores, I found the solution here: http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/ . I guess it stores the analog voltage reference in mV that's why you have to divide by 1000 to get it in V.

I read 5 volts from the divider when the ardu is disconnected. The overall resistance of the resistros are 40.24Kohm.

Edit: What is VOC and Vmpp? Yes, 20.9-21 V what my multimeter says, but my arduino sends 19.83 to the serial port. I don't use my solar panel's current. I don't connect anything to it.

The VOC is your panels voltage with NO load connected e.g.: Not drawing any power
The Vmp or Vmpp is the voltage of your panel when you are drawing the max current it produces. e.g: charging a battery
Your panel (if large enough) should state these limits on the sticker on the back of the panel.
Once you connect resistors you lose the VOC, as you are drawing current.

Edit: If you want a reading closer to VOC(what you read on your multimeter) try making your divider out of higher resistance resistors, so you draw less current.
What is your multimeter’s input impedance for measuring voltage? 10M ohm? That’s why it has little effect on the VOC reading.
Edit2: I see the link you gave is for a BATTERY tester. Did you try this with a battery to see how accurate a reading you get?

I understand that, if you connect resistors you loose VOC, but, the ardu measures accurately. I know, because the multimeter shows the same value. But why it looses accuracy at 20 V? That's why I think it's a programming mistake. I just don't know where.

Edit: It's accurate until the voltage won't go above 19.83. Right now at the end of my resistors I measure 5.07V with the multimeter. 5.07*4= 20.28V. That's the origianl voltage before the resistors. But my ardu never shows a value higher than 19.83.

But my ardu never shows a value higher than 19.83.

Is it all that difficult to type Arduino?

Serial.print() the values from readVcc() and from analogRead(). I suspect that you will see why the highest value you are ever going to see is 19.83, unless you change the voltage divider.

You should not be feeding a value greater than 5.0 into the Arduino.

So if the Aduino(just for you I'll type it :) ) reads a wrong value, if the voltage at the end of the resistors is higher than 5 V ? That causes the problem?

I knew that too high voltage damages it, but I never connected the Arduino to the system if it was above 5.5V The highest was 5.3 I think.

That causes the problem?

Since you don't seem interested in finding out for yourself, yes. The Arduino (yes, it has an r in it) compares the voltage on the pin to the reference voltage, and returns a value between 0 and 1023, indicating the relationship. Input values higher than the reverence voltage will not result in values higher than 1023.

If your reference voltage is not exactly 5.0, assuming it is is wrong. You can tell what the reference voltage is by printing the value in Vcc. But, again, you don't seem interested in doing so.

Stop judging me!

Believe it or not, I actually printed the VCC value when you said. It said 4957 or something like that. So it wasn't 5 volts, as it should be. So I understood why it won't give me more than 19.83 V. Because 4.957*4 is 19.828. What is the best solution for this? More resistance, or how should I set the reference number. I tried to set it to five. The page I linked said this: "1125300L"... " 1125300 = 1.1*1023*1000" So I calculated a bit with 5 volts as reference so it was 5*1023*1000 and it gave 5115000. But it measured too much. So I didn't know what to do. Also. Can more resistors solve the problem? That way I can prevent the the input voltage to go above 5 volt, so the measurements would stay accurtae. Right?

Stop judging me!

Believe it or not, I actually printed the VCC value when you said. It said 4957 or something like that.

Where did you say that?

So it wasn't 5 volts, as it should be.

I don't know why you think it should be 5.0 volts. The reason for measuring is so you know.

What is the best solution for this?

Change the voltage divider to keep the input voltage less than the reference voltage.

Stop judging me!

Don't worry, some people in the forum have issues that they apparently can't control. As to your project, do you have a specific voltage range you are wanting to monitor, such as 19.0v to 21.0v, instead of the full voltage range?

To get a more precise voltage reading as compared to your multimeter reading of the panel VOC do this. Create your voltage divider to have an input voltage below the reference voltage like PaulS said. Connect the divider to the Arduino, and measure the voltage coming out of the panel(V1), write it down. Now measure the voltage (V2) going into the Arduino, write it down. Divide V2 into V1, write down that number. Change the 4 in this line to the number you came up with.

double voltage = ((sensorvalue/1023.0)*Vcc)*4;

You said

4.957*4 is 19.828

. Yup it is BUT you first said

But When my solar panel produces about 20.90-21

4 will only be accurate IF there is a 4x difference between the panel voltage and the divided voltage. So if you get a reading of 21 from the panel while connected to your voltage divider and a reading of 4.957 at the divided voltage then. 21/4.957 = 4.236, you would replace the 4 with 4.236 BUT remember what PaulS said:

Change the voltage divider to keep the input voltage less than the reference voltage.

So measure your reference voltage. And to keep closest to the panel VOC use higher value resistors in your divider. For your benefit, also you said:

The overall resistance of the resistros are 40.24Kohm.

From the circuit you posted you don't have that. Maybe look into how to calculate resistance in a circuit, it WILL come in handy.