# Help with voltmeter and 1602 lcd bargraph progress

Hello everyone, so basically im wanting to read a voltage from a sensor of my bike´s engine which goes from 0 to 1.1 volts maximum, and im having some trouble making a bargraph that uses the bottom line of the lcd (1602a , normal 6 pin connection) to correspond to this reading making it easyer for me to understand whats happening in my engine.
So far i have been able to set up the reading pin (A0) and its measuring correctly, but i do not understand how to associate values to “graphics” in the bottom line of the lcd!
if someone could enlighten me on how to do this i would be really thankful, i´ve watched all videos on youtube but none of them explain how to associate the voltage to some progress or filling characters.
Heres my working sketch so far:

#include <LiquidCrystal.h>
int Vpin = 0;
float voltaje;
float V;
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // pines RS, E, D4, D5, D6, D7 de modulo 1602A

void setup() {
lcd.begin(16, 2); // inicializa a display de 16 columnas y 2 lineas
}

void loop() {
V = voltaje / 1024 * 5.0;
lcd.print("SondaV= ");
lcd.print(V);
delay(500);
lcd.clear();
}

You can try this:

``````#include <LiquidCrystal.h>

//make 5 custom characters that fill in a character space from left to right
//to give more progressive bar graph
unsigned char bars[][8] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },     //_____
{ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },     //|____
{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 },     //||___
{ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c },     //|||__
{ 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e },     //||||_
{ 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }      //|||||

};

int Vpin = 0;
int

float V;

//internal representation of the bar
byte
grBar[16];

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);  // pines RS, E, D4, D5, D6, D7 de modulo 1602A

void setup()
{
lcd.begin(16, 2);     // inicializa a display de 16 columnas y 2 lineas

//use the arrays above to create 5 custom characters representing fractional fills for the bar graph
for( int i=0; i<6; i++ )
lcd.createChar( i, bars[i] );

lcd.setCursor(0,0); //col,row
lcd.print("SondaV= ");
//Serial.begin(9600);   //debug/dev

}//setup

void loop()
{
static unsigned long
timeUpdate = 0;
unsigned long
timeNow;

timeNow = millis();
if( timeNow - timeUpdate >= 100 )    //update frequently (10 times a second) for smooth bar graph
{
timeUpdate = timeNow;

//only update if current reading not the same as last
{
lcd.setCursor( 8, 0 );
lcd.print( V, 2 );
//Serial.println( V ); //debug/dev

//draw the bar graph
UpdateBar( V );

}//if

}//if

}//loop

void UpdateBar( float volts )
{
int
i,
numBlanking,
numfullbars;
float
fnumSubBars;

//draw the bar graph in its entirety
//assume that full scale voltage reading is 5V and that this equates to 15 full bars
//  if volts = 3.35
//      # of full bars = (int)(2.61 * 3.0) = (int)(7.83) = 7
//
//      The remainder will be used to fractionally fill the next bar
//          Our character set allows up to 5 "sub-bars"
//          the remainder of the # full bars calc
//          multiplier: 0.9 * x = 5; x = 5.5
//              5.5 * ((volts * 3.0) - numfullbars )
//              5.5 * (7.83 - 7)
//              5.5 * 0.83 = 4.565 (int = 4)
//
//
numfullbars = (int)(volts * 3.0);                       //number of "full" bars (custom char #5)
fnumSubBars = 5.5 * ((volts * 3.0) - numfullbars );     //last char is 0-5, custom char for partial fill of last bar
if( numfullbars < 15 )
numBlanking = 15 - numfullbars - 1;
else
numBlanking = 0;

//erase the array representing the bar by setting custom char 0 (blank)
memset( grBar, 0, sizeof( grBar ) );

//draw in the number of full bars using character 5
for( i=0; i<numfullbars; i++ )
grBar[i] = 5;
//in the last active bar, add the sub-bar value
grBar[i] = (byte)fnumSubBars;

//draw the bar to the LCD
lcd.setCursor( 0, 1 );
for( i=0; i<sizeof( grBar ); i++ )
{
lcd.write( grBar[i] );
//Serial.print( grBar[i] ); //debug/dev

}//for

//Serial.println(); //debug/dev

}//DoBar
``````

If it works (untested except in the serial mon) you can try to optimize it so you don’t redraw the whole bar but instead only update the parts that need updating.

Thanks man, big help and got it running in the first try! But the bar seem to fill 15 full characters (or blocks ) at 5 volts, and i need to be full at maximum 1.1 volts!, which part of the (dividers?) i need to tune to fullfill all blocks to my desired voltage, im still a little confused to that.. plus in a reddit forum they suggested me using the 3.3 volts reference as it can be more accurate reading this value an using the AREF pin.. Is this true or isnt worth the change? Thanks for the reading and the help, i need indeed more arduino code understanding...

Maz95:
Thanks man, big help and got it running in the first try! But the bar seem to fill 15 full characters (or blocks ) at 5 volts, and i need to be full at maximum 1.1 volts!, which part of the (dividers?) i need to tune to fullfill all blocks to my desired voltage, im still a little confused to that… plus in a reddit forum they suggested me using the 3.3 volts reference as it can be more accurate reading this value an using the AREF pin… Is this true or isnt worth the change?
Thanks for the reading and the help, i need indeed more arduino code understanding…

You’ll lose a little accuracy only using 1.1V out of 5V but for your purposes – a relatively coarse bar graph and voltage display, it probably won’t matter. If you’re using this data for logging or adjusting fuel trims then I would recommend a different reference.

For now, with some revised scaling:

``````#include <LiquidCrystal.h>

//make 5 custom characters that fill in a character space from left to right
//to give more progressive bar graph
unsigned char bars[][8] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },     //_____
{ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },     //|____
{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 },     //||___
{ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c },     //|||__
{ 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e },     //||||_
{ 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }      //|||||

};

int Vpin = 0;
int

float V;

//internal representation of the bar
byte
grBar[16];

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);  // pines RS, E, D4, D5, D6, D7 de modulo 1602A

void setup()
{
lcd.begin(16, 2);     // inicializa a display de 16 columnas y 2 lineas

//use the arrays above to create 5 custom characters representing fractional fills for the bar graph
for( int i=0; i<6; i++ )
lcd.createChar( i, bars[i] );

lcd.setCursor(0,0); //col,row
lcd.print("SondaV= ");
//Serial.begin(9600);   //debug/dev

}//setup

void loop()
{
static unsigned long
timeUpdate = 0;
unsigned long
timeNow;

timeNow = millis();
if( timeNow - timeUpdate >= 100 )    //update frequently (10 times a second) for smooth bar graph
{
timeUpdate = timeNow;

//only update if current reading not the same as last
{
lcd.setCursor( 8, 0 );
lcd.print( V, 2 );
//Serial.println( V ); //debug/dev

//draw the bar graph
UpdateBar( V );

}//if

}//if

}//loop

void UpdateBar( float volts )
{
int
i,
numBlanking,
numfullbars;
float
fnumSubBars;

//draw the bar graph in its entirety
//assume that full scale voltage reading is 1.1V and that this equates to 15 full bars
//  if volts = 0.45
//      # of full bars = (int)(0.45 * 13.6364) = (int)(6.136) = 6
//
//      The remainder will be used to fractionally fill the next bar
//          Our character set allows up to 5 "sub-bars"
//          the remainder of the # full bars calc
//          multiplier: 0.9 * x = 5; x = 5.5
//              5.5 * ((volts * 13.6364) - numfullbars )
//              5.5 * (6.136 - 6)
//              5.5 * 0.136 = 0.750 (int = 4)
//
//
if( volts > 1.1 )
volts = 1.1;

numfullbars = (int)(volts * 13.6364);                   //number of "full" bars (custom char #5)
fnumSubBars = 5.5 * ((volts * 13.6364) - numfullbars );     //last char is 0-5, custom char for partial fill of last bar
if( numfullbars < 15 )
numBlanking = 15 - numfullbars - 1;
else
numBlanking = 0;

//erase the array representing the bar by setting custom char 0 (blank)
memset( grBar, 0, sizeof( grBar ) );

//draw in the number of full bars using character 5
for( i=0; i<numfullbars; i++ )
grBar[i] = 5;
//in the last active bar, add the sub-bar value
grBar[i] = (byte)fnumSubBars;

//draw the bar to the LCD
lcd.setCursor( 0, 1 );
for( i=0; i<sizeof( grBar ); i++ )
{
lcd.write( grBar[i] );
//Serial.print( grBar[i] ); //debug/dev

}//for

//Serial.println(); //debug/dev

}//DoBar
``````

Hi, Welcome to the forum.

Please read the first post in any forum entitled how to use this forum. http://forum.arduino.cc/index.php/topic,148850.0.html . Then look down to item #7 about how to post your code. It will be formatted in a scrolling window that makes it easier to read.

Thanks.. Tom.. :)

How to add second channel to have stereo vu meter ?