Basic(?) lcd.setCursor Question

I'm writing to a standard 16x2 LCD display and can't understand why a portion of the text is being "blanked" out (removed from display). Can anyone explain this to me, please?

in setup(), I display introductory text in both rows of the LCD.
in loop(), I call Function #1...
in Function #1, I call Function #2 where I perform:

// Clear the LCD and position cursor @ top-left
lcd.clear();
// Print a message to the LCD.
// top row message
lcd.print("Leaning: Mtr FWD");

Function #2 ends, and returns to Function #1, where I print additional info in the bottom row:

lcd.setCursor(0, 1);
// bottom row formatting: Temp=xxx
// bottom row message
lcd.print("Temp=");
lcd.setCursor(5,1);
lcd.print(val, DEC);

SO FAR SO GOOD...

Function #1 ends and returns to loop()
This is followed by printing additional text in the bottom row (at least this was the intent):

// print peakValue to LCD
// bottom row formatting: Temp=xxx Pk=xxx
// set the cursor to bottom row (column 9, line 1)
lcd.setCursor(9, 1);
// bottom row message
lcd.print("Pk=");
lcd.setCursor(12,1);
lcd.print(peakValue, DEC);

HERE'S WHERE THE PROBLEM LIES...

It actually DOES print the "Pk=xxx" text, in the expected position too... BUT... the previously-displayed "Temp=xxx" (on the same bottom row, to the left) has been removed from display.

Why?

Thanks for your help.

There appears to be a lot of code we are not seeing. I'm guessing that the problem lies in code we don't get to see.

Can you post all of your code?

I tried to trim it down to the relevant area... but here it is:

// include the library code
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(4, 5, 6, 7, 8, 10);
// LCD RS pin to digital pin 4
// LCD EN pin to digital pin 5
// LCD D4 pin to digital pin 6
// LCD D5 pin to digital pin 7
// LCD D6 pin to digital pin 8
// LCD D7 pin to digital pin 10

// select the input pin for the pot
const int potPin = 0;

// select the pin from which to output to the four H-Bridge transistor Base legs
const int r1PinYellow = 9; // a PWM output pin
const int r2PinBlue = 2;
const int r3PinOrange = 11; // a PWM output pin
const int r4PinWhite = 3;
// H-Bridge Motor Control
// COMMAND          Q1       Q2      Q3      Q4
// -----------------------------------------------
// coast/roll/off   LOW      LOW     LOW     LOW
// forward          LOW      *HI*    *HI*    LOW
// brake/slow down  *HI*     LOW     *HI*    LOW
// reverse          *HI*     LOW     LOW     *HI*

// select the pin for the pushbutton switch
const int s1Pin = 12;
// variable for reading the pushbutton status
int buttonState = 0;
// previous state of the button
int lastButtonState = 0;

// variable to store peak value in loop() function
int peakValue = 0;

void setup()
{
  // initialize the pushbutton pin as an input:
  pinMode(s1Pin, INPUT);
  // turns on the pullup resistor
  digitalWrite(s1Pin, HIGH);
  // declare pins driving the transistor Base legs as OUTPUT
  pinMode(r1PinYellow, OUTPUT);
  pinMode(r2PinBlue, OUTPUT);
  pinMode(r3PinOrange, OUTPUT);
  pinMode(r4PinWhite, OUTPUT);
  
  // Begin by turning the motor OFF
  analogWrite(r1PinYellow, 0);
  digitalWrite(r2PinBlue, LOW);
  analogWrite(r3PinOrange, 0);
  digitalWrite(r4PinWhite, LOW);
  
  // set up the LCD's number of columns and rows 
  lcd.begin(16, 2);
  // display intro message #1
  // center text -- Column 4, Row 0 (top row)
  lcd.setCursor(4,0);
  lcd.print("TAKAIR");
  // center text -- Column 2, Row 1 (bottom row)
  lcd.setCursor(2, 1);
  lcd.print("Electronics");
  delay(3000);
  
  // print intro message #2
  // clear the LCD and position cursor @ top-left
  lcd.clear();
  // top row message
  lcd.print("Press Switch To");
  // set the cursor to bottm row (column 0, line 1)
  lcd.setCursor(0, 1);
  // bottom row message
  lcd.print("Start");
}

void loop()
{
  // read the pushbutton input pin
  buttonState = digitalRead(s1Pin);
    
  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == LOW) {
      // if the current state is HIGH then the button
      // went from off to on:
      // call the findPeak() function and store result
      peakValue = findPeak();
      // print peakValue to LCD
      // bottom row formatting: Temp=xxx Pk=xxx
      // set the cursor to bottom row (column 9, line 1)
      lcd.setCursor(9, 1);
      // bottom row message
      lcd.print("Pk=");
      lcd.setCursor(12,1);
      lcd.print(peakValue, DEC);
      delay(1000);
      
      // call the turnMotorReverse() function
      turnMotorReverse(peakValue);
    } 
    else 
    {
      // if the current state is LOW then the button
      // went from on to off:  DO NOTHING
    }
    // save the current state as the last state, 
    //for next time through the loop
    lastButtonState = buttonState;
  }
}

void turnMotorForward()
{
  // MOTOR FORWARD
  // Clear the LCD and position cursor @ top-left
  lcd.clear();
  // Print a message to the LCD.
  // top row message
  lcd.print("Leaning: Mtr FWD");
      
  digitalWrite(r4PinWhite, LOW);
  analogWrite(r1PinYellow, 0);
  digitalWrite(r2PinBlue, HIGH);
  analogWrite(r3PinOrange, 200); // 127 for small motor
}

void turnMotorReverse(int peak)
{
  int potVal = 0;
  int targetVal = peak - 50;
  
  // print targetVal
  // Serial.print("targetVal is ");
  // Serial.println(targetVal, DEC);
  
  // Position cursor @ top-left
  lcd.setCursor(0,0);
  // Print a message to the LCD.
  // top row message
  lcd.print("Stby to Enrich..");
  
  // Position cursor to overwrite Pk=xxx
  // Display Tv=xxx instead (Target Value)
  // bottom row formatting: Temp=xxx Tv=xxx
  // set the cursor to bottom row (column 9, line 1)
  lcd.setCursor(9, 1);
  // bottom row message
  lcd.print("Tv=");
  lcd.setCursor(12,1);
  lcd.print(targetVal, DEC);
  
  delay(1000);
  
  // stop the motor first
  
  // Position cursor @ top-left
  lcd.setCursor(0,0);
  // Print a message to the LCD.
  // top row message
  lcd.print("Riching: Mtr OFF");
  
  analogWrite(r1PinYellow, 0);
  digitalWrite(r2PinBlue, LOW);
  analogWrite(r3PinOrange, 0);
  digitalWrite(r4PinWhite, LOW);
  // wait half a second
  delay(500);
  
  // begin motor reversal
  // Position cursor @ top-left
  lcd.setCursor(0,0);
  // Print a message to the LCD.
  // top row message
  lcd.print("Riching: Mtr REV");
  
  analogWrite(r3PinOrange, 0);
  digitalWrite(r2PinBlue, LOW);
  delay(50);
  analogWrite(r1PinYellow, 140); // 60 for small motor
  digitalWrite(r4PinWhite, HIGH);
  // read potVal [while turning motor] until it equals targetVal
  while (potVal != targetVal)
  {
    // read pot value
    potVal = analogRead(potPin);
    // remap to a 0 to 255 range
    potVal = map(potVal, 0, 1023, 0, 255);
    // print out the value to LCD
    // set the cursor to bottm row (column 0, line 1)
    lcd.setCursor(0, 1);
    // bottom row formatting: Temp=xxx
    // bottom row message
    lcd.print("Temp=");
    lcd.setCursor(5,1);
    lcd.print(potVal, DEC);
    
    // small delay
    delay(10);
  }
  // stop motor  
  // Position cursor @ top-left
  lcd.setCursor(0,0);
  // Print a message to the LCD.
  // top row message
  lcd.print("Riching: Mtr OFF");
  analogWrite(r1PinYellow, 0);
  digitalWrite(r2PinBlue, LOW);
  analogWrite(r3PinOrange, 0);
  digitalWrite(r4PinWhite, LOW);
  
  // Clear the LCD and position cursor @ top-left
  lcd.clear();
  // top row message
  lcd.print("Press Switch To");
  // set the cursor to bottm row (column 0, line 1)
  lcd.setCursor(0, 1);
  // bottom row message
  lcd.print("Set Fuel Mixture");
}

int findPeak()
{
  // variable to store whether the peak has been detected
  int peakNotFound = 1;
  // variable to store new values from the pot
  int newVal = 0;
  // variable to store current values from the pot
  int val = 0;
  // variable to store the peak value
  int peak = 0;
  
  while (peakNotFound)
  {
    // call the turnMotorForward() function
    turnMotorForward();
    
    if (newVal >= val || (val-newVal) < 3)
    {
      // keep on reading the potentiometer...
      val = analogRead(potPin);
      // remap to a 0 to 255 range
      val = map(val, 0, 1023, 0, 255);
      // print out the value to LCD
      // LCD was cleared in turnMotorForward()
      // set the cursor to bottm row (column 0, line 1)
      lcd.setCursor(0, 1);
      // bottom row formatting: Temp=xxx
      // bottom row message
      lcd.print("Temp=");
      lcd.setCursor(5,1);
      lcd.print(val, DEC);
      // small delay
      delay(1000);
      // read the analog input into the "newval" variable
      newVal = analogRead(potPin);
      // remap to a 0 to 255 range
      newVal = map(newVal, 0, 1023, 0, 255);
      delay(10);
      // print out the value to Serial Monitor
      // Serial.print("     newVal is ");
      // Serial.println(newVal, DEC);
    }
    else  // peak has been detected...  exit "while" loop
    {
      // store the latest val into peak
      peak = val;
      // peakNotFound is now false
      peakNotFound = 0;
    }
  }
    // return the value of peak to main program
    return peak;
}

What happens if you omit the lcd.setCursor call in loop? Just print a couple of spaces, instead.

Good thought, I'll try that tonight and report back. It's still a mystery to me why it doesn't work the way the code is written now...

Thanks, PaulS.

In case you're still interested... The last suggestion didn't work, BUT...

I do know where it all breaks down (although I have no explanation why), and I wrote a work-around.

  1. It appears that the entire bottom row on the LCD is cleared in the findPeak() function... immediately after exiting the IF statement, but prior to entering the ELSE loop. Don't know why.

  2. My work-around is to redisplay the desired text ("Temp=xxx") in the ELSE statement as well.

If anyone figures out why the bottom row blanks out in the first place, let me know. Thanks for looking into this.

It might be a matter of which LCD you are using, or more precisely which LCD controller.

Things like "set cursor", "clear screen", etc, are often done by escape codes.

It may be that the "setCursor" provided in the library you are using uses different escape codes than your controller requires.

Happily, it is usually simple enough to create your own "setCursor" (with a different name) to send what your controller needs.

Tell us which LCD and controller you are using... someone will probably jump in either with "the standard one worked for me with that" or "here's how I did it with that".