Displaying 2 decimal places on an LCD

I have modified some code posted by DeFex (thank you!) about a year ago, to produce 3 bargraphs on a 4x20 LCD…I’m pleased with the results.

I am using the 4th line of the display to show 3 numerical values calculated from 2 of the values that the bargraphs are monitoring.

The first numerical value I calulated was RF power which involves squaring the value of V2, this displayed as a large interger…I then needed to multiply this by a factor to display the actual RF power…the factor in this case is 0.00153836. I was amazed to see the value expected displayed to two decimal places!

Previous reading led me to think i would need to apply “floating point” or “double” to produce this result…

Even multiplying by 1.0 causes the result to be displayed to 2 decimal places. Excellent!! what sets the number of decimal places? Can i change this? Is this something new? See also SWR and V calculations, last 3 “paragraphs” of code.

// include the library code:
#include <LiquidCrystal.h>

// these constants won't change.  But you can change the size of
// your LCD using them:
const int numRows = 4;
const int numCols = 20;
const int V1pin=0;
const int V2pin=1;
const int V3pin=2;
const int V4pin=3;
int V1;
int V2;
int V3;
int V4;
int val1;
int val2;
int val3;
int val4;
uint8_t custom_0[8] = { 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //blank
uint8_t custom_1[8] = { 
  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00}; //1line
uint8_t custom_2[8] = { 
  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00}; //2line
uint8_t custom_3[8] = { 
  0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00}; //3line
uint8_t custom_4[8] = { 
  0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00}; //4line
uint8_t custom_5[8] = { 
  0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00}; //5line
uint8_t custom_6[8] = { 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //6line redundant.
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //LCD pins on arduino please see liquidcrystal.h and arduino LCD wiring examples

// LiquidCrystal lcd(RS, E, D4, D5, D6, D7)

void setup() {

  lcd.begin(numRows, numCols);
  lcd.createChar(0, custom_0); //send the custom characters to the LCD
  lcd.createChar(1, custom_1);
  lcd.createChar(2, custom_2);
  lcd.createChar(3, custom_3);
  lcd.createChar(4, custom_4);
  lcd.createChar(5, custom_5);
  lcd.createChar(6, custom_6);


void loop() {
  val1 = analogRead(V1pin);//read analog inputs (S)
  val2 = analogRead(V2pin);//                   (Fwd)
  val3 = analogRead(V3pin);//                   (Ref)
  val4 = analogRead(V4pin);//                   (V)
  V1 = (val1/10.5); //change divider depending on how many segments in a meter
  V2 = (val2/6); // changes sensitivity, lower number more sensitive
  V3 = (val3/6);
  V4 = (val4/10.5);

  int vom1 = (V1 / 6);  //divide reading for solid blocks
  int rem1 =  (V1 % 6 ); //get modulo for remainder
  int vom2 = (V2 / 6);   //6 represents no. of horizontal pixels inc the space
  int rem2 =  (V2 % 6 ); //between characters
  int vom3 = (V3 / 6);
  int rem3 =  (V3 % 6 );
  int vom4 = (V4 / 6);
  int rem4 =  (V4 % 6 );

  //static numbers on LCD changes if you change your meter.
  lcd.setCursor(0,0);  //
  lcd.print ("S   ");  // Print title for S meter
  lcd.setCursor(0,1) ; //
  lcd.print ("Fwd ");  // Print title for Forward Power meter
  lcd.setCursor(0,2);  //
  lcd.print ("Ref ");  // Print title for Reflected Power meter

  lcd.setCursor(4,0);       //move cursor to first meter (S)

  for (int i=0; i<vom1;i++) {
    lcd.print(5,BYTE);  //print 3 vertical lines
  lcd.print(rem1,BYTE); //print the remainder which is meter segments within character
  for (int i=(vom1 + 1); i<16; i ++) { // i<17 segments to be written as blank
    lcd.print(" "); //blank spaces after so there is no leftover mess after fast moving meter


  lcd.setCursor(4,1);       //move cursor to second meter (Fwd)

  for (int i=0; i<vom2;i++) {
  for (int i=(vom2 + 1); i<16; i ++) {
    lcd.print(" ");


  lcd.setCursor(4,2);       //move cursor to 3rd meter (Ref)

  for (int i=0; i<vom3;i++) {
  for (int i=(vom3 + 1); i<16; i ++) {
    lcd.print(" ");


  lcd.print((1+((V3*1.0)/(V2*1.0)))/(1-((V3*1.0)/(V2*1.0))));//calculate SWR and print numerical value
  lcd.print("SWR ");

  lcd.print(V4/4.4361);//calculate supply voltage from voltage divider V4 and print numerical value
  lcd.setCursor(14,3);// Calibration factor = 4.4361

  lcd.print((V2*V2)*0.00153836);//calculate Forward Power and print numerical value
  lcd.setCursor(19,3);// Calibration factor = 0.00153836
  lcd.print ("W");

  delay(0);  //delay changed to suit your taste, if using rapid interrupt, then delete.


Previous reading led me to think i would need to apply “floating point” or “double” to produce this result…

Your not wrong here, you do need to use floating point to get decimals.


lcd.print((V2*V2)*0.00153836);//calculate Forward Power and print numerical value

Whats happening here is that the compiler is seeing a floating point number, it knows this because of the . point in the number, it then does floating point math and passes the floating point result to lcd.print(). 2 decimal precision I think is the default precision.

You said it works if you use 1.0, again this is because the . lets the compiler know it’s floating point value. Try it again with 1, and it won’t work.

If you want to find out more, look up type conversion, specifically implicit type conversion in c.

Implicit type conversions are the devils work - well actually I mean to say relying on them is the devils work. The hours spent tracking down weird little bugs because the compiler has done a conversion on your behalf are too numerous. I always try to use explicit conversions, especially with portable code, as rules may change in the future or on another platform - also it's just better practice.

Multiplying a value by 1.0 to force the compiler to give a float result is bad form. Other programmers may look at down the track and ask "wtf?". It's much cleaner if you explicitly cast the values:

lcd.print((1+((float)V3/(float)V2))/(1-((float)V3/(float)V2)));//calculate SWR and print numerical value

Cheers, G.

Yes, 2 decimal places is default. use a comma and a number after your floating point to change it. example: If you want to set 3 decimal places you would write: float PinVoltage = 1.234; lcd.print(PinVoltage,3); // displays voltage value for 3 digits after decimal place command

Hi guys

Thanks very much for the replies..........all very useful, and added to my knowledge bank!

Yes, I did some pretty crude things in this sketch...........like overwriting the second decimal place with the measurement unit i.e. V so that it would look like it was displaying just one decimal place!!

Have modified my code, and although the results look the same as before...........I'm now safe in the knowledge that it is now done properly and will be future proof.

Thanks again