#include <LiquidCrystal.h>

//make 5 custom characters that fill in a character space from left to right
//to give more progressive bar graph
// encodes numbers from 0 to 255
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 = A0; // defines input pin A0
int
    nReading,
    nlastReading;

float V; // this data type allows the analog number with decimal point, V, to be accurately approximated

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


const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; //these values cannot be changed, follows scope rules 
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);   // sets the LCD address display (must be before void setup)

void setup()
{

 // first, set dimensions of LCD, in setup() as lcd.begin(columns, rows) 
    lcd.begin(16, 2);    

    //using 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("Voltage= "); 
    //Serial.begin(9600);   //debug/dev  opens serial port, sets data rate to 9600 bps
    nlastReading = 0; 

}//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;
       
        nReading = analogRead( Vpin ); // reads the input pin, A0
        //only update if current reading not the same as last

        //Compares the variable on the left with the value or variable on the right of the operator. Returns true when the two operands are not equal. 
        if( nReading != nlastReading )
        {
            nlastReading = nReading;
            V = (float)nReading*5.0/1024.0;
            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 3.7V 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
$abcdeabcde151015202530fghijfghij