Interfacing LCD with button modes and voltages

Ok, I'm trying to make my Arduino display voltages for 12v, 5v and 3v lines. I've got a 16x2 LCD.

First, is it possible to get all 3 displayed at once? As in the top line being "3.3V 5V 12V" spaced evenly, then the bottom line being the 3 readings. I know they won't update all at the same time, but that's no big deal.

Second, if it's not possible, how do I need to set it up so when the unit is turned on it displays a welcome message, then with each button press it switches between 3v, 5v and 12v?

here's my code so far for the second setup (with only 3v and 5v for now, still have to figure out how to read 12v without frying something):

/*Arduino Controlled Voltage Monitor
Code by Will Lyon 12/5/2010
Code for project Power House on TBCS
http://www.thebestcasescenario.com*/

#include <LiquidCrystal.h>
#include <math.h>
int counter = 0;              //Add counter
int buttonPin = 2;            //Attach button to pin 2

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {
  pinMode(buttonPin, INPUT);   //Set button pin to input
  lcd.begin(16, 2);            //Set up the LCD's number of columns and rows
  lcd.print("  POWER  HOUSE");
  lcd.setCursor(0, 1);
  lcd.print("Desktop Pwr Unit");
}

void loop()
{
  digitalRead(buttonPin);      //Read the button pin
  if (buttonPin = HIGH)        //If the button is pressed
  {
    counter + 1;               //Advance to next mode
    if(counter == 2)           //Reset count if over max mode number
    {
      counter = 1;
    }
  }
  if(counter == 1)
  {
    lcd.print("3.3 Volt Line");
    lcd.setCursor(0, 1);
    lcd.print(analogRead(2));
  }
  else if(counter == 2)
  {
    lcd.print("5 Volt Line");
    lcd.setCursor(0, 1);
    lcd.print(analogRead(0));
  }
}

It displays the opening message, but when the button is pressed nothing happens.

Here is how it's wired up:

any ideas? Thanks!

Will

First, is it possible to get all 3 displayed at once?

Yes

how do I need to set it up so when the unit is turned on it displays a welcome message,

In the setup() part do a LCD.print("Welcome SXR"); followed by a delay(2000); or so

As you only have 16 positions I would use the 1st line for the measured voltages and the second line as a message/status line:

0123456789012345   = position
-----------------------------
3.1V  4.8V 12.3V   = line 0
All systems OK     = line 1

(code not compiled or tested)

void loop()
{
  bool OK = true;
  lcd.setCursor(0, 0);
  float f = analogRead(2) * 3.3 / 1024;     // 3.3 => 9.9 
  lcd.print(f, 1);  // print float with one decimal
  if (f > 3.3) OK = false

  lcd.setCursor(0, 6);
  f = analogRead(0) * 5.0 / 1024;           // 5.0 => 9.9
  lcd.print(f, 1);
  if (f > 5.0) OK = false;
  
  lcd.setCursor(0, 11);
  f = analogRead(0) * 12.0 / 1024;           // 12.0 => 25.0
  lcd.print(f, 1);
  if (f > 12.0) OK = false;

  lcd.setCursor(1,0);
  if (OK) lcd.print("All systems OK");
  else lcd.print("Warning !!!");
    
  delay(100);
}

Note: the code above assumes the max voltage is 3.3 cq 5.0 volt . Think it might be better to have both max 9.9 volt (100 different values, with 0.1 accuracy) then you still have enough positions to display but a larger range.

Option, leave out the V for voltage and use this to have an additional digit of accuracy. => lcd.print(f, 2);

0123456789012345   = position
-----------------------------
3.11  4.85 12.32   = line 0
All systems OK     = line 1

Succes

it's got 2 errors, both in the read functions

lcd.setcursor(0, 6);
if = analogRead...

both instances it says "expected '(' before '=' token"

also, it doesnt need to be any kind of a warning. when I'm building circuits and testing parts I just want to be able to tell if the 5v line is actually only running at 4.7v, etc

kinda like this:

1234567890123456
3.3v 5v 12v
rdg1 rdg2 rdg3 => readings

lcd.setcursor(0, 6);
if = analogRead...

The first should be setCursor. The second should be f, not if.

it uploaded, and displays the opening msg, but then I get this:

2.30WER HOUSE
12.0All systems

thankx Paul, posted too quickly, modified the code :-[

2.30WER HOUSE
12.0All systems

You need to do a clrscreen or print a bunch of spaces

ok this is the current code:

/*Arduino Controlled Voltage Monitor
Code by Will Lyon 12/5/2010
Code for project Power House on TBCS
http://www.thebestcasescenario.com*/

#include <LiquidCrystal.h>

//Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {
  lcd.begin(16, 2);            //Set up the LCD's number of columns and rows
  lcd.print("  POWER  HOUSE");
  lcd.setCursor(0, 1);
  lcd.print("Desktop Pwr Unit");
  delay(5000);
  lcd.setCursor(0, 0);
  lcd.print("                ");
  lcd.setCursor(0, 1);
  lcd.print("                ");
}

void loop()
{
  bool OK = true;
  lcd.setCursor(0, 0);
  float f = analogRead(2) * 5.0 / 1023;     // 5.0 => 9.9
  lcd.print(f, 2);  // print float with two decimals

  lcd.setCursor(0, 6);
  f = analogRead(0) * 3.3 / 1023;           // 3.3 => 9.9
  lcd.print(f, 2);

  lcd.setCursor(0, 11);
  f = analogRead(0) * 5.0 / 1023;           // 5.0 => 25.0
  lcd.print(f, 2);

  delay(1000);
}

it blanks it, but it's still displaying the readings on 2 different lines. it's showing 3.44 on the top and 5.0 on the bottom

kinda like this:

1234567890123456

3.3v     5v        12v
rdg1     rdg2     rdg3 => readings

=>

(code not compiled or tested)

setup()
{
  // display welcome;
  // delay(sometime);
  // clearcreen();
  
  lcd.setCursor(0,0);
  lcd.print("3.3v     5v        12v");
}

void loop()
{
  lcd.setCursor(0,1);
  float f = analogRead(2) * 3.3 / 1024;     // 3.3 => 9.9
  lcd.print(f, 1);  // print float with one decimal
  if (f > 3.3) OK = false

  lcd.setCursor(6,1);
  f = analogRead(0) * 5.0 / 1024;           // 5.0 => 9.9
  lcd.print(f, 1);
  if (f > 5.0) OK = false;
  
  lcd.setCursor(11,1);
  f = analogRead(0) * 12.0 / 1024;           // 12.0 => 25.0
  lcd.print(f, 1);
  if (f > 12.0) OK = false;
    
  delay(100);
}

hopes this helps you to get the idea


Need to swap X and Y my mistake - It's just getting too late :slight_smile: Zzzzzzz

ok here's the current setup:

/*Arduino Controlled Voltage Monitor
Code by Will Lyon 12/5/2010
Code for project Power House on TBCS
http://www.thebestcasescenario.com*/

#include <LiquidCrystal.h>

//Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup()
{
    lcd.begin(16, 2);            //Set up the LCD's number of columns and rows
  lcd.print("  POWER  HOUSE");
  lcd.setCursor(0, 1);
  lcd.print("Desktop Pwr Unit");
  delay(5000);
  lcd.setCursor(0, 0);
  lcd.print("                ");
  lcd.setCursor(0, 1);
  lcd.print("                ");
  lcd.setCursor(0,0);
  lcd.print(" 3v    5v   12v");
}

void loop()
{
  lcd.setCursor(0, 1);
  float f = analogRead(0) * 3.3 / 1024;     // 3.3 => 9.9
  lcd.print(f, 2);  // print float with one decimal

  lcd.setCursor(6, 1);
  f = analogRead(2) * 5.0 / 1024;           // 5.0 => 9.9
  lcd.print(f, 2);

  lcd.setCursor(11, 1);
  f = analogRead(0) * 12.0 / 1024;           // 12.0 => 25.0
  lcd.print(f, 2);

  delay(1000);
}

Works great! except for the fact that my 5v is showing 3.44 lol

now the hard(er) part. How do I hook an analog pin to a 12v line without frying the arduino?

now the hard(er) part. How do I hook an analog pin to a 12v line without frying the arduino?

This is actually quite simple. Use a voltage divider (google hint). Make sure both resisters are of the correct wattage to match the current drop across them.

Works great! except for the fact that my 5v is showing 3.44 lol

float f = analogRead(0) * 3.3 / 1024; Change 3.3 in 5.0

You probably want to know when the voltage is to high too, that means that you should prepare your software to display high ranges (and your hardware to read them.

To read 12 Volt you could build a Voltage divider:

+12V ------| R1 | ----+----- | R2 | --- GND

COnnect Arduino analog at +
R1 : R2 = 7 : 5

However as you might expect higher voltages e.g. 15 or even 25 Volt you need to change the values of R1 : R2 = 20 : 5 so the AnalogIn (and the whole Arduino) will not be fried.

Best way to do this is to take two resitors with the approx the right ratio e.g. 20K and 5K together 25K. Put a known voltage 12Volt to it (check with calibrated voltmeter) and adapt the N in the formula f = analogread(0) * N /1024 so the Arduino displays the right value. Another way is to have one fixed resistor and one variable (potmeter) and one could calibrate the voltage displayed.


Note if the 12Volt comes from a car battery better check out postings of GrumpyMike as he has warned several people lately

ok current code:

/*Arduino Controlled Voltage Monitor
Code by Will Lyon 12/5/2010
Code for project Power House on TBCS
http://www.thebestcasescenario.com*/

#include <LiquidCrystal.h>

//Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup()
{
  lcd.begin(16, 2);                      //Set up the LCD's number of columns and rows
  lcd.print("  POWER  HOUSE");           //First line opening message
  lcd.setCursor(0, 1);
  lcd.print("Desktop Pwr Unit");         //Second line opening message
  delay(5000);
  lcd.setCursor(0, 1);                   //Clear bottom line
  lcd.print("                ");
  lcd.setCursor(0,0);
  lcd.print(" 3v    5v   12v");          //Update top line readout
}

void loop()
{
  lcd.setCursor(0, 1);
  float f = analogRead(0) * 5.0 / 1023;     // 3.3 => 9.9
  lcd.print(f, 2);  // print float with one decimal

  lcd.setCursor(6, 1);
  f = analogRead(1) * 5.0 / 1023;           // 5.0 => 9.9
  lcd.print(f, 2);
  
  
  lcd.setCursor(11, 1);
  f = analogRead(2) * 12.0 / 1023;           // 12.0 => 25.0
  lcd.print(f, 2);

  delay(1000);
}

I used a 51K resistor from the 12v to the input to arduino, and a 68K from there to ground for the divider circuit.

The readings need to be calibrated though, as they differ by quite a bit (in electronics terms) from what my multimeter says.

Display Actual
3v 3.43v 3.36v
5v 5.00v 4.85v
12v 12.00v 12.40v in from PSU
5.40 after 51K going to arduino

how should I go about calibrating the numbers?

another strange thing I just noticed. When I take voltage away from each input, the display should say 0.00, but it doesn't.

the 3v goes anywhere between 0.32 and 2.29

the 5v goes between 2.85 and 3.46. however if I ground the line it stays 0.00

the 12v goes to 0.000

should I put a 10k to ground on each of the input pins as a pulldown? or can I set the Arduino's internal pulldown on the analog pins?

makes perfect sense.

now if I can just straighten out the 5v and 12v not reading anything. all the display outputs is whatever I set the multiplier to :o

I used a 51K resistor from the 12v to the input to arduino, and a 68K from there to ground for the divider circuit.

That brings too much voltage to the Arduino Analog IN pin you should swap them. So the +12 V drops 7 Volts to the arduino pin which drops 5Volts to GND

I swapped them and now I've got 5.2 going into the sense pin, bit it still doesnt fix the 5v and 12v input readings :-/

Alright well I got it sorted. :slight_smile:

here's the setup:

and the code:

/*Arduino Controlled Voltage Monitor
Code by Will Lyon 12/5/2010
Code for project Power House on TBCS
http://www.thebestcasescenario.com*/

#include <LiquidCrystal.h>

//Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup()
{
  lcd.begin(16, 2);                      //Set up the LCD's number of columns and rows
  lcd.print("  POWER  HOUSE");           //First line opening message
  lcd.setCursor(0, 1);
  lcd.print("Desktop Pwr Unit");         //Second line opening message
  delay(5000);
  lcd.setCursor(0, 1);                   //Clear bottom line
  lcd.print("                ");
  lcd.setCursor(0,0);
  lcd.print(" 3v    5v   12v");          //Update top line readout
}

void loop()
{
  lcd.setCursor(0, 1);
  float f = analogRead(0) * 4.88 / 1023;   // 3.3 => 9.9
  lcd.print(f, 2);                        // print float with two decimals


  lcd.setCursor(6, 1);
  float g = analogRead(1) * 8.5 / 1023;        // 5.0 => 9.9
  lcd.print(g, 2);

  
  lcd.setCursor(11, 1);
  float h = analogRead(2) * 17.25 / 1023;  // 12.0 => 25.0
  lcd.print(h, 2);

  delay(1000);
}

Looks good, you could write an article about in on the playground (including the callibration part) and you will get eternal fame :wink: