AnalogRead Voltage different when using VIN? (Nano)

Hello,

I will try and give as much information as I can, Really need some expert help solving this

I am working on a little project to read the voltage of my leisure battery and print it out over serial. So far I have worked it all out on a breadboard and it was working well.

Since moving to strip board and changing the Arduino's power source from USB to VIN it has started giving me problems. (Using the same PSU)

I have a 12v step down PSU like the one below, to power the Arduino Nano.

I am using 22k and 10k resistors to divide the voltage from the battery and connecting to the Analog pin (0) Voltage from the battery is around 12.30vdc and using common ground of course since everything is powered from the same source.

The only other things being powered from the Arduino itself is a Bluetooth module although I have tried powering this from the PSU separately still with no results.

The problem must be the Arduino being powerered from VIN @ 5vdc When using the power supply's USB to the Arduino the problem disappears and all works as expected.

Anyone have any ideas? I have searched the forum and internet and decided to post the question as a last means.

EDIT: The voltage read out is a few volts to HIGH when using VIN to power the Nano. I get a reading of around 14-15vdc when the battery is in fact 12.30vdc

Thanks

Reading an analog voltage uses default the 5V as reference. If the 5V changes to a lower value, the Arduino 'thinks' that the battery voltage is higher. You could use the internal reference of 1.1V with a different voltage divider (22k and 1k5). That internal voltage reference is independant of the 5V supply power. http://arduino.cc/en/Reference/AnalogReference

The 5V of the USB is going to the Arduino, but the Vin is going through a voltage regulator. So you need 6-12V at Vin. You could try to use the battery for Vin.

Erdin: Reading an analog voltage uses default the 5V as reference. If the 5V changes to a lower value, the Arduino 'thinks' that the battery voltage is higher. You could use the internal reference of 1.1V with a different voltage divider (22k and 1k5). That internal voltage reference is independant of the 5V supply power. http://arduino.cc/en/Reference/AnalogReference

The 5V of the USB is going to the Arduino, but the Vin is going through a voltage regulator. So you need 6-12V at Vin. You could try to use the battery for Vin.

Thanks for the quick and helpful response Erdin

I would be scared to put 12vdc into the Arduino nano. When the battery is on charge in the van it would be getting 13.8vdc!! Would that not kill the nano?

I ordered a new PSU as the one above is not man enough to power my relay board so I purchased a 5v step down that produces 3Amps. Wish I went for 9v now. Sods law.

I could try the different resistor values and see how I get on.

Hello again, I just read that the 1.1v refrence is for the Mega only?

INTERNAL1V1: a built-in 1.1V reference (Arduino Mega only)

CrazyDiamond: Hello again, I just read that the 1.1v refrence is for the Mega only?

INTERNAL1V1: a built-in 1.1V reference (Arduino Mega only)

Not exactly. The form:

analogReference(INTERNAL1V1); // is for mega boards only as mega boards also have available: analogReference(INTERNAL2V56);

For a Nano (or any 328P based board) you would simply use:

analogReference(INTERNAL); // which would select the internal 1.1vdc reference voltage

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

Lefty

retrolefty:

CrazyDiamond: Hello again, I just read that the 1.1v refrence is for the Mega only?

INTERNAL1V1: a built-in 1.1V reference (Arduino Mega only)

Not exactly. The form:

analogReference(INTERNAL1V1); // is for mega boards only as mega boards also have available: analogReference(INTERNAL2V56);

For a Nano (or any 328P based board) you would simply use:

analogReference(INTERNAL); // which would select the internal 1.1vdc reference voltage

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

Lefty

Thanks for reply.

Mine is a 168 board so I guess it cannot be done?

However, I just read this

The Arduino Nano can be powered via the Mini-B USB connection, 6-20V unregulated external power supply (pin 30), or 5V regulated external power supply (pin 27). The power source is automatically selected to the highest voltage source.

So I can use 5vdc to power the Arduino from pin 27? wouldn't that solve my issue?

http://arduino.cc/en/Main/ArduinoBoardNano

CrazyDiamond:

retrolefty:

CrazyDiamond: Hello again, I just read that the 1.1v refrence is for the Mega only?

INTERNAL1V1: a built-in 1.1V reference (Arduino Mega only)

Not exactly. The form:

analogReference(INTERNAL1V1); // is for mega boards only as mega boards also have available: analogReference(INTERNAL2V56);

For a Nano (or any 328P based board) you would simply use:

analogReference(INTERNAL); // which would select the internal 1.1vdc reference voltage

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

Lefty

Thanks for reply.

Mine is a 168 board so I guess it cannot be done?

It can be used just like on a 328 board as the 168 chip also has the same internal 1.1vdc reference available.

However, I just read this

The Arduino Nano can be powered via the Mini-B USB connection, 6-20V unregulated external power supply (pin 30), or 5V regulated external power supply (pin 27). The power source is automatically selected to the highest voltage source.

So I can use 5vdc to power the Arduino from pin 27? wouldn't that solve my issue?

Maybe. The Nano voltage selection method is a simple diode isolator, so if you wire an external applied regulated +5.00 vdc voltage is higher then the USB +5vdc voltage (minus the diode voltage drop) then it will be what determines the voltage the board 'sees'. Lefty

http://arduino.cc/en/Main/ArduinoBoardNano

Excellent, I have just tested it and it somewhat works (Unregulated PSU) PSU is showing a steady 4.8vdc. The serial output is a little out and fluctuates a lot but its fine for now.

I guess I need a regulated 5vdc PSU or the courage to hook up 12vdc direct to the Arduino. Whats the worst that can happen.. POP!! And a new 328 based board to replace it.

Thanks for you extremely fast help, I haven't experienced this kind of technical help anywhere!

Hello again

Sorry I was too hasty reading your reply and missed

It can be used just like on a 328 board as the 168 chip also has the same internal 1.1vdc reference available.

I have been to Maplins and bought some 1k5 resistors as suggested My voltage divider (22k & 1k5) now divides the Battery voltage to .774vdc

I would much prefer to use the 1.1 reference and get a more accurate reading from the Arduino

So as I understand it, I don't use the Analog pins at all now? I wire the resistors to Ground and AHEF?

Any help or sample to get this working would be much appreciated as my current code looks something like this.

#define R1 22000.0 // Resistor 1 Value
#define R2 10000.0 // Resistor 2 Value

int analogInput = 0; // Analog pin
int refresh = 10000; // Refresh time
int value = 0; // Value
float vout = 0.0;
float vin = 0.0;

Setup()
{
 pinMode(analogInput, INPUT);
Serial.begin(9600);  //serial communication
}

Loop()
{
 while (det == 'j')   //if incoming data is a "j" Battery Test
      {   
        value = analogRead(analogInput); 
        vout = (value * 5.0) / 1023.0;
        vin = (R1+R2)/(R2) * vout;
  
        Serial.print(vin);
        Serial.println(" V");
        delay(refresh);      
        det = check();          
      }
}

I have been to Maplins and bought some 1k5 resistors as suggested My voltage divider (22k & 1k5) now divides the Battery voltage to .774vdc

I would much prefer to use the 1.1 reference and get a more accurate reading from the Arduino

So as I understand it, I don't use the Analog pins at all now? I wire the resistors to Ground and AHEF?

No. You still use the normal analog input pins. And nothing is wired to the Aref pin as you are selecting an internal 1.1vdc reference voltage by placing a analogReference(INTERNAL); statement into your setup function.

Now the arduino analog read statement will return a 1023 count if the voltage applied to the analog pin is 1.1vdc or higher.

Lefty

Any help or sample to get this working would be much appreciated as my current code looks like this.

retrolefty: I have been to Maplins and bought some 1k5 resistors as suggested My voltage divider (22k & 1k5) now divides the Battery voltage to .774vdc

I would much prefer to use the 1.1 reference and get a more accurate reading from the Arduino

So as I understand it, I don't use the Analog pins at all now? I wire the resistors to Ground and AHEF?

No. You still use the normal analog input pins. And nothing is wired to the Aref pin as you are selecting an internal 1.1vdc reference voltage by placing a analogReference(INTERNAL); statement into your setup function.

Now the arduino analog read statement will return a 1023 count if the voltage applied to the analog pin is 1.1vdc or higher.

Lefty

Any help or sample to get this working would be much appreciated as my current code looks like this.

Thanks Lefty

So all I need to change in my code is the resistor 2 value and add reference to setup? So it will look something like this. )

#define R1 22000.0 // Resistor 1 Value
#define R2 1500.0 // Resistor 2 Value

int analogInput = 0; // Analog pin
int refresh = 10000; // Refresh time
int value = 0; // Value
float vout = 0.0;
float vin = 0.0;

Setup()
{
pinMode(analogInput, INPUT);
analogReference(INTERNAL);
Serial.begin(9600);  //serial communication
}

Loop()
{
 while (det == 'j')   //if incoming data is a "j" Battery Test
      {   
        value = analogRead(analogInput); 
        vout = (value * 5.0) / 1023.0;
        vin = (R1+R2)/(R2) * vout;
  
        Serial.print(vin);
        Serial.println(" V");
        delay(refresh);      
        det = check();          
      }
}

I appreciate the help. I have got this far without any but would rather ask than kill my Arduino

Well let me take a quick stab at it. I'll add comments and changes:

#define R1 22000.0 // Resistor 1 Value
#define R2 1500.0 // Resistor 2 Value

// int analogInput = 0;  Use first analog pin name as alread defined as A0
int refresh = 10000; // Refresh time
int value = 0; // Value
float vout = 0.0;
float vin = 0.0;

Setup()
{
// pinMode(analogInput, INPUT);  // not needed, analogRead sets pin as needed. And doing a 
                                     // pinMode(0, INPUT); anyway would end up setting digital pin 0 to input  
                                     //mode
analogReference(INTERNAL);
value = analogRead(A0);  // datasheet say to do a 'dummy' read after changing reference type
                                  // as first read is mostly garbage value after a reference change
Serial.begin(9600);  //serial communication
}

Loop()
{
 while (det == 'j')   //if incoming data is a "j" Battery Test
      {   
        value = analogRead(A0); 
        vout = (value * 1.1) / 1023.0;  // the reference is now 1.1 not 5.0 
        vin = (R1+R2)/(R2) * vout;
  
        Serial.print(vin);
        Serial.println(" V");
        delay(refresh);      
        det = check();          
      }
}

Not tested of course.

Lefty

Lefty, I owe you a Beer if your ever in the UK :D

I changed the (5.0) to (1.1), Modified the code as your directions and it is working 100% perfect My multi meter shows 12.28 and the Serial output shows 12.26, This is pretty good and I can live with .02 of a volt difference. And no more random changes or fluctuations. Steady 12.26 every 10 seconds. Awesome

Thankyou so much, this has really made my day.

CrazyDiamond: Lefty, I owe you a Beer if your ever in the UK :D

I changed the (5.0) to (1.1), Modified the code as your directions and it is working 100% perfect My multi meter shows 12.28 and the Serial output shows 12.26, This is pretty good and I can live with .02 of a volt difference. And no more random changes or fluctuations. Steady 12.26 every 10 seconds. Awesome

Thankyou so much, this has really made my day.

You very welcome, good to see another happy Arduino user.

By the way the 1.1 volt internal reference has a tolerance value on every specific chip. So you might play with the actual value you use in your sketch if you want to try and tweak it to agree with your multimeter (which has a tolerance value of it's own ;) )

So: vout = (value * 1.1) / 1023.0; // the reference is now 1.1 not 5.0

Might be vout = (value * 1.07) / 1023.0; // the reference is now 1.1 not 5.0 or vout = (value * 1.13) / 1023.0; // the reference is now 1.1 not 5.0

Ect., I'm sure you get the idea.

Lefty

Thanks for the further information, What a great community.

I actually tried something similar to this when I was using 5v as reference as was getting confused why it no longer worked using VIN. After measuring the voltage and finding it was 4.6vdc I changed my code to vout = (value * 4.6) / 1023.0;

As you would expect, the results were not correct. :blush:

Having checked my leisure battery with 2 multimeters and getting a reading of 12.28 from both, I might do as you suggested and tweak it a little before soldering my bluetooth sheild back into place. For some reason the bluetooth shield messes with the RX and TX and stops me from uploading my sketch.

Very happy with the Arduino, Knew I would find another use for it after my robot died. I can now control 8 relays and read the battery voltage in my camper van, All through Bluetooth on an Android device.

Again, Thanks very much and hope this thread helps someone else in the future.

Only 8 relays and the battery voltage ? What about the temperature; the humidity; a barometer; an accelerometer to see if the camper is leveled; a wind speed meter; a real time clock; a sun strenght meter; a rain meter; gps for location and the height; detectors for burglars (perhaps wireless detectors); and so on.

Erdin: Only 8 relays and the battery voltage ? What about the temperature; the humidity; a barometer; an accelerometer to see if the camper is leveled; a wind speed meter; a real time clock; a sun strenght meter; a rain meter; gps for location and the height; detectors for burglars (perhaps wireless detectors); and so on.

Stop it lol!

I was thinking of adding some extra features ;)

Locking and unlocking the central locking Temperature Gas sensor GPS

Wind speed meter? I am a Kitesurfer :D My website has live wind and Tidal information that I will port to my App

You have me really thinking now

retrolefty:

value = analogRead(A0); 

vout = (value * 1.1) / 1023.0;  // the reference is now 1.1 not 5.0
        vin = (R1+R2)/(R2) * vout;[/quote]




Not that it makes a lot of difference in the grand scheme of things, but for the sake of understanding how the ADC works, that 1023.0 should be a 1024.0.

![ADC factor.png|903x279](upload://oqEwm7mwo7Bue8LrR3ZRXKXSuL2.png)