Lcd.print prints additional random digit

I'm on my first arduino project and don't understand the behaviour of lcd.print().
I declared float ovenTemp and ran the function below.
Serial.println(ovenTemp, 1) results in the temperature beeing printed with one decimal e.g. 27.6
But for the same value of ovenTemp lcd.print(ovenTemp, 1) results in 27.69.

The last digit seems to be random and changes if I put the line somewhere else in the code. It is not an actual digit from the value of ovenTemp. It is static and doesn't change when the function runs again while the other digits update as expected.
If I print with more decimals the random digit is still added to the end.

I switched to an I2C display and this didn't change the behaviour. What am I missing?

void getTemp() {
  static const int numReadings = 10; // determines the size of the readings array
  static int readings[numReadings];  // the readings from the analog input
  static int readIndex = 0;          // the index of the current reading
  static int total = 0;              // the running total

  // initialize all the readings to 0 on the first run
  static bool hasInitialized = false;
  if (hasInitialized == false) {
    for (int i = 0; i < numReadings; i++) {
      readings[i] = 0;
    }
    hasInitialized = true;
  }

  // calculate running average of last sensor readings
  total = total - readings[readIndex];          // subtract the previous reading with the current index
  readings[readIndex] = analogRead(sensorPin0); // read from the sensor
  Serial.print("reading: ");
  Serial.print(readings[readIndex]);
  total = total + readings[readIndex];          // add the reading to the total
  readIndex = readIndex + 1;                    // advance to the next position in the array

  if (readIndex >= numReadings) {               // if at the end of the array...
    readIndex = 0;                              // ...wrap around to the beginning
  }

  int smoothReading = total / numReadings;      // calculate the average
  Serial.print(", smooth reading: ");
  Serial.print(smoothReading);

  float voltage = (smoothReading / 1024.0) * 5.0;
  Serial.print(", V: ");
  Serial.print(voltage);

  ovenTemp = (voltage - .5) * 100;
  Serial.print(", C: ");
  Serial.println(ovenTemp, 1);

  lcd.setCursor(10, 1);
  lcd.print(ovenTemp, 1);
}

you probably forgot to clear characters from the field you are writing to, before writing new data.

1 Like

Overwrite old data with spaces before writing the new data is one way to handle it.

   lcd.setCursor(10, 1);
   lcd.print("      ");  // overwrite old data with spaces
   lcd.setCursor(10, 1); // reset cursor
   lcd.print(ovenTemp, 1); // new data

For a 16x2 display. Your snippet doesn't say the display size.

1 Like

Thanks, both clearing and overwriting before every print does fix the random digit. However I don't quite understand how writing to the display works. Why does this write to a cursor position that should not be affected by the written text?

I use a 20x4 display and wanted to print the temperature unit right behind the value. With both methods the unit get's erased obviously. So do I have to print that everytime, too?
Is it good practice to just update some cursor positions?

Don't know what that means.

No, not if you use the cursor control and print just enough spaces to overwrite the old data and not the units.

This demo will illustrate what I say. Connect a pot to A0 and run this. I use the hd44780 library for I2C LCDs because it is the best available at this time. The library is available via the IDE library manager. I intentionally use 15 (versus 1023) for the divisor to get more significant digits to show how it works with the changing data length.

#include <Wire.h>
#include <hd44780.h>                       // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header

hd44780_I2Cexp lcd; // declare lcd object: auto locate & auto config expander chip

// LCD geometry
const int LCD_COLS = 16;
const int LCD_ROWS = 2;

const byte anaInPin = A0;

void setup()
{
   Serial.begin(115200);
   lcd.begin(LCD_COLS, LCD_ROWS);
   lcd.print("LCD Voltmeter");
   lcd.setCursor(0, 1);
   lcd.print("VOLTS = ");
   lcd.setCursor(14, 1);
   lcd.print("Vdc");
}

void loop()
{
   static unsigned long timer = 0;
   unsigned long interval = 500;
   if (millis() - timer >= interval)
   {
      timer = millis();
      int anaIn = analogRead(anaInPin);
      float volts = anaIn * (5.0 / 15.0); // to give more significant digits
      lcd.setCursor(8, 1);
      lcd.print("      ");  // just enough spaces to overwrite old data (6) and not units.
      lcd.setCursor(8, 1);
      lcd.print(volts, 1);
   }
}

All of the labels are set in setup(). The only thing printed is the changing data.

Yes, I get the idea but it doesn't work for me. I want to print 27.6 so I set the cursor and overwrite 4 characters. But with lcd.print(ovenTemp, 1) it prints the random fifth character and overwrites my unit.

I tested a few more things:

  lcd.print("27.6")

works fine

  int x = 2706;
  lcd.print(x);

works fine

  float x = 27.6;
  lcd.print(x, 1);

works fine, too.

Post a minimal program that reproduces the problem. Then I can load the code and see what is going on. Incomplete snippets, out to context, are not as helpful.

If you work with simple code till you get it working and understand the process you will be better off.

Thanks for your support. While writing the minimal program I found that this works:

//LCD
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

//sensors
const int sensorPin0 = A0;
float ovenTemp;

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.setCursor(14, 0);
  lcd.print(String(char(223)) + String("C"));
}

void loop() {
  while (true) {
    getTemp();
    printTemp();
    delay(100);
  }
}

void getTemp() {
  int readings = analogRead(sensorPin0);
  float voltage = (readings / 1024.0) * 5.0;
  ovenTemp = (voltage - .5) * 100;
}

void printTemp() {
  lcd.setCursor(10, 0);
  lcd.print("    ");
  lcd.setCursor(10, 0);
  lcd.print(ovenTemp, 1);
}

But this produces the fifth random digit which overwrites the unit. So could it be related to the smoothing of the sensor value?

//LCD
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);

//sensors
const int sensorPin0 = A0;
float ovenTemp;

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.setCursor(14, 0);
  lcd.print(String(char(223)) + String("C"));
}

void loop() {
  while (true) {
    getTemp();
    printTemp();
    delay(100);
  }
}

void getTemp() {
  static const int numReadings = 10; // determines the size of the readings array
  static int readings[numReadings];  // the readings from the analog input
  static int readIndex = 0;          // the index of the current reading
  static int total = 0;              // the running total

  // initialize all the readings to 0 on the first run
  static bool hasInitialized = false;
  if (hasInitialized == false) {
    for (int i = 0; i < numReadings; i++) {
      readings[i] = 0;
    }
    hasInitialized = true;
  }

  // calculate running average of last sensor readings
  total = total - readings[readIndex];          // subtract the previous reading with the current index
  readings[readIndex] = analogRead(sensorPin0); // read from the sensor
  total = total + readings[readIndex];          // add the reading to the total
  readIndex = readIndex + 1;                    // advance to the next position in the array

  if (readIndex >= numReadings) {               // if at the end of the array...
    readIndex = 0;                              // ...wrap around to the beginning
  }

  int smoothReading = total / numReadings;      // calculate the average

  float voltage = (smoothReading / 1024.0) * 5.0;

  ovenTemp = (voltage - .5) * 100;
}

void printTemp() {
  lcd.setCursor(10, 0);
  lcd.print("    ");
  lcd.setCursor(10, 0);
  lcd.print(ovenTemp, 1);
}

I found the problem. During the beginning of the smoothing the temperature is negative. This adds a minus which moves all characters one position to the right. After a few readings the temperature turns positive and the mysterious fifth character remains.

Had nothing to do with the display. Thanks for your support anyway. It showed me to break the problem down into smaller increments.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.