Voltmeter expected display s/b 5.00 getting 4.32V instead.

I trying to use the mega256 board as a voltmeter to measure and display voltages between the range of 4.30V to 5.25V's. The output is going to a 16x2. I have searched the web and found some arduino voltmeter projects, however the sketches provided with those projects are having me go in circle as their output is not what is expected it is off by 1V or by 45V s.

I am new to programming so I would like some guidance, advice, and help. What I am using for this project,, is a variable power supply set to 5V's, a dmm, a voltage divider, R1=99700.k, R2=10k. On the audrino I am using pin A15, which a wire from the middle of the voltage divider is plugged into and the other end of the voltage divider I am using it as positive and negative. I have the power supply connected to the breadboard supplying the 5V's and the dmm is connected to the output of the voltage divider.

I setup the power supply to 5.00V's by using the dmm so I know what my starting point is. When I run the sketch below my expected output should be 5.00V but I am getting 4.32V's. As I decrease the voltage, the voltage should be exact as what is on the dmm, however, no matter what I change the output voltage is off by either .08V or sometimes 2V's. I see this on the lcd and the serial monitor.

To check if my logic is correct and to see if I am going though the correct if statements I used the serial monitor. Which brings up a few questions that I have using the serial monitor. What is the difference in using Serial.print() vs. Serial.printLn()? I have searched the web, but was unable to find a good explanation. Also, how can I display a single line of information on the serial monitor? For example, when I use this statement:

"Serial.print(analogRead(analogInput)); Serial.println(" This is A15"); //added for testing of A15"

the output is printed on two lines, instead of one.

#include <LiquidCrystal.h>
 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


    int analogInput                                = 15;      // this is for analog pin A15
    const int UNDERVOLTAGE            = 4.30;    //test lower voltage 
    const int NOMINAL                         = 4.85;    //s/b this--do we need this?
    const int OVERVOLTAGE               = 5.25;    //test for overvoltage--can we do this?
    const int INPUTVOLTAGE              = 4.95;    //true input voltage
    float voltage                                      = 0.0;
    float vIn                                              = 0.0;
    float R1                                                = 99700.0;   //measured resistor
    float R2                                               = 10000.0;  //measured resistor
    int lcd_refresh                                 = 500;
    int over		                                   = 0;
    int under		                                   = 0;
    
  void setup()
{
           pinMode(analogInput, INPUT);    //declaration of pin modes--does analog need this??  
           lcd.clear();                                           //clr dipslay
          lcd.begin(16, 2);                                  //LCD's number of columns and rows: 
         Serial.begin(9600);                          //for testing to see what is happening
  
}


void loop() 
{

          int sensorValue = analogRead(analogInput);                               // read input on pin 15
         Serial.print(analogRead(analogInput)); Serial.println(" This is A15");  //added for testing of A15
   
         voltage = sensorValue * (INPUTVOLTAGE/ 1023.0);                         //scales sampled voltage
    

         Serial.print(voltage); Serial.println(" voltage converted");            //print out the value you read:
    
    
         vIn = voltage * (R2/(R1+R2));                                        //volt divider= vin * ((R2)/(R1+R2))
   

    
     if (vIn < UNDERVOLTAGE)                                            // Undervoltage check
             {
  		under = under + 1;
                         lcd.clear();
        		 lcd.setCursor(0, 0);
         		 lcd.print("V under"); + lcd.print(vIn);
			 lcd.setCursor(0, 1);
		         lcd.print(" UV ="); + lcd.print(under);
 			 lcd.print(" OV ="); + lcd.print(over);
         		 delay (lcd_refresh);
        
         //added for testing to see if logic is correct
        Serial.print(vIn); Serial.println(" V1"); Serial.println(" V1 only");    //this prn's to see if logic is correct
        delay (lcd_refresh);
        return;
	        }

	if (vIn > OVERVOLTAGE) // Overvoltage check **ONLY TEST THIS WITH A DIVIDER!!
             {
  		over = over + 1;
                         lcd.clear();
        		 lcd.setCursor(0, 0);
         		 lcd.print("V OVER"); + lcd.print(vIn);
			 lcd.setCursor(0, 1);
		      lcd.print(" UV ="); + lcd.print(under);
 			 lcd.print(" OV ="); + lcd.print(over);	
         		 delay (lcd_refresh);
        
         //added for testing
        Serial.print(vIn); Serial.println(" VO"); Serial.println(" V2 over");  //this prn's to see if logic is correct
        delay (lcd_refresh);
        return;
	        }

	else
		   {
		         lcd.clear();
                         lcd.setCursor(0, 0);
         		 lcd.print("Nom: "); + lcd.print(vIn);
         		 delay (lcd_refresh);
        
         //added for testing
        Serial.print(vIn); Serial.println(" V3"); Serial.println(" V3 Nom");     //this prn's to see if logic is correct
        delay (lcd_refresh);
        return;
	        }
  }

Easy Q's first:
Serial.print(analogRead(analogInput)); // prints with no line feed added
// next print will start on same line
Serial.println(" This is A15"); // prints with line feed added to end
// next print will be on next line

 int sensorValue = analogRead(analogInput);                               // read input on pin 15
         Serial.print(analogRead(analogInput)); Serial.println(" This is A15");  //added for testing of A15
   
         voltage = sensorValue * (INPUTVOLTAGE/ 1023.0);                         //scales sampled voltage
    

         Serial.print(voltage); Serial.println(" voltage converted");            //print out the value you read:

Try: voltage = sensorValue * (INPUTVOLTAGE/ 1024.0);

Serial.print will print without new line. Serial.println will print then go to a new line.

const int UNDERVOLTAGE = 4.30;

Don't numnbers with decimal points need to be type float?

CrossRoads is right.

    const int UNDERVOLTAGE = 4.30;    //test lower voltage 
    const int NOMINAL      = 4.85;    //s/b this--do we need this?
    const int OVERVOLTAGE  = 5.25;    //test for overvoltage--can we do this?
    const int INPUTVOLTAGE = 4.95;    //true input voltage

Will be treated by the compiler as:

    const int UNDERVOLTAGE  = 4;    //test lower voltage 
    const int NOMINAL       = 4;    //s/b this--do we need this?
    const int OVERVOLTAGE   = 5;    //test for overvoltage--can we do this? 
    const int INPUTVOLTAGE  = 4;    //true input voltage

That might account for your discrepancies.

digiguy:
I trying to use the mega256 board as a voltmeter to measure and display voltages between the range of 4.30V to 5.25V's.

If the board is running at 5V then the maximum value from the ADC will be 1023 at 5V and thus you cannot test for anything over that.

Thank you all for your quick response!!! I really appreciate your comments. I have corrected the declarations from int to float. Changed the OVERVOLTAGE from 5.25 to 5.00. However, for some odd reason I am now getting 0.40 on the lcd and on the serial monitor (still trying to find the best way to print out legibility) this is what is being displayed see attached and on the dmm displays 4.81V.

Any thoughts??
again, thanks for your help!!

Screen Shot 2014-09-04 at 3.49.32 PM.png

another question, since I am using analog do I need to declare pinMode?? I thought that pinMode was only for digital. Does anyone know a way to keep the serial monitor on the screen. Every time I upload the serial monitor closes. I would the serial monitor to still visible so that I may see the output printed.

again, thank you...

Copy and paste from the serial monitor (eg. to Notepad) before uploading again. You can copy the text rather than taking a screenshot. You may have to turn off "autoscroll" for that to work.

Can you post your new code please? As an attachment if necessary.

How to use this forum

The first thing I would try is to reduce the values of your divider resistors.
The ADC works by charging an internal capacitor from the pin and then measuring the voltage on the capacitor.
If your input resistance is too high, the capacitor may not charge up fully and your measurement will be low.
As a first approximation try 10k for the top and 1k for the bottom resistor and see if it helps.

Thanks Nick, see attached for sketch... And next time I will definitely turn off autoscroll... :blush:

PhilC, thanks to you, I will try that and let you know what the results are..

sketch_use_this_for_testing_only_chgs_made_here.ino (4.71 KB)

  int sensorValue = analogRead(analogInput);                               // read input on pin 15
  Serial.print(analogRead(analogInput));

You aren't printing what you read. It would be better to do:

  int sensorValue = analogRead(analogInput);                               // read input on pin 15
  Serial.print(sensorValue);
  pinMode(analogInput, INPUT);    //declaration of pin modes--does analog need this??

All ports default to input at startup.

Can you copy and paste the current output? The other one you did was pretty unreadable. Good debugging output is the start to good debugging.

Hi Nick,

this is the output from the serial monitor:

858 This is A15
4.19 voltage converted
0.38 volt divider
0.38 V1 only
858 This is A15
4.19 voltage converted
0.38 volt divider
0.38 V1 only
858 This is A15
4.19 voltage converted
0.38 volt divider
0.38 V1 only
859 This is A15
4.19 voltage converted
0.38 volt divider
0.38 V1 only
859 This is A15
4.19 voltage converted

The output calculations look OK. Can you sketch or post the wiring please?

Particularly this bit:

What I am using for this project,, is a variable power supply set to 5V's, a dmm, a voltage divider, R1=99700.k, R2=10k. On the audrino I am using pin A15, which a wire from the middle of the voltage divider is plugged into and the other end of the voltage divider I am using it as positive and negative. I have the power supply connected to the breadboard supplying the 5V's and the dmm is connected to the output of the voltage divider.

Hi Nick,

this is what I have, the lcd 16x2 is a shield that covers the power and part of the analog in connectors. The blue wire from A15 goes to the voltage divider and the outside wires (red and black) are connected to a dmm to verify the output voltage, which should be pretty close to the voltage displayed on the lcd. Its a very simple circuit. I am using larger values of resistors, in case of the device under test might have more than 5V, which would damage the arduino.

So, my testing goes like this, using a 5V variable power supply (before connecting the ps to the beardboard I check the voltage using the dmm setting the voltage to 5.00V's) then I plug the ps into the beardboard. The arduino is plugged to my mac. I lower the voltage on the ps, which shows up on the dmm, but on the lcd the voltage delta is anywhere from .08V to 1.05Vs.

My next step is to use 10k and 1k resistors as PhilC suggested. That might bring the output voltage closer to what is being displayed on the lcd.

Nick, thanks for your help...

You already described the wiring. I was asking for a schematic. A photo will do if it is very clear. Or a sketch on a bit of paper, if it neat, or make something with a digital paint program.

ExpressPCB is free software for Windows. I use that for my schematics.

http://www.expresspcb.com/index.htm

You get two programs in the download. ExpressPCB is for laying out PCB boards, and ExpressSCH is for doing schematics.

Hi Nick,

I attached a screen shot of the schematics, the only thing that the schematics does not show is the wire connected to as inputs for R1 and R2. Since those wires will be used as the probes for the voltmeter. Also, I am using a mac and schematic software is limited compared to a PC.

Again, thanks for your help!!!!

Those two wires (connected to R1 and R2) are the critical ones. Where are they connected? Ground? Something else?

Nick,

the wires for R1 is the positive and for R2 is the negative. So there should be a red wire connected to R1 and a black wire connected to R2. However, the CAD software won't allow me to just add a wire to just one node. The other wire is placed in between R1and R2 which goes to A15 of the arduino. I dont believe that a ground is needed to be plugged into the arduino, since the A15 pin is used as an analog read.

thanks...