Why do I need to Activate IDE Serial Monitor for LCD To Work?

Hey guys,

I'm curious why I have to open the serial monitor in IDE for my LCD to display the information properly. It shows some garbled information and as soon as IDE is opened, then serial monitor opened, LCD displays properly. The rest of my project/build functions as expected. Just curious if there's something simple I'm missing as I didn't write the program on my Arduino Uno Rev 3.

Thanks,
Dave

Do you have a
while (!Serial)
-in your setup code ?
That may be stopping the program from running further.,,

otherwise post your code here - properly !

Good Question, Swap line 3 with line 20 in your code then change the pink wires to orange. When that does not work post an annotated schematic showing exactly how you wired it. Show all connections, power, ground, power sources and links to any non standard hardwares technical information.

Why not? chatGPT will always fail. Learn to write valid programs.

You must not use pin 1 or pin 0. Find other pins.

Hey guys,

Not sure why there was an assumption of chatGPT. I'm running a program written by someone for a DIY vinyl record cutting lathe that I built. He modified CD burning software to have the transport controls work with a stepper motor.

The Sketch works totally fine, but for the LCD to display some information I'd like to see, I have to open the serial monitor in IDE for it to sort of kick the LCD out of gibberish. Regardless of whether I do this or not, the actual sketch/arduino work 100%. I just wanted to save that step.

Here's the code for the program:

//===========================================================================================
// This program is free software: you can redistribute it and/or modify it under the terms 
// of the GNU General Public License as published by the Free Software Foundation, either 
// version 3 of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
// See the GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License along with this program. 
// If not, see <https://www.gnu.org/licenses/>.
//===========================================================================================
// David Nelson - February 2021
// Controller for disc recorder
// 
//
// Runs on Arduino Uno. Drives horizontal linear rail motor using TMC2208 driver.
// Also required: two photointerrupter circuits, 74HC14 inverter, 74HC595 LCD driver, HD44780 LCD unit,
// optional thermistor circuit.
// 
// The Arduino receives signals via USB from the PC running 'Vinyl Burn' software, moves
// the horizontal stepper as requested, and sends status reports back to the PC for
// display in the Vinyl Burn window.

// This library is required. it is available from https://www.arduino.cc/reference/en/libraries/enableinterrupt/
//#include <EnableInterrupt.h>

#include <SPI.h>
#include <LiquidCrystal.h>


#define TICKS_IN_REPORT_CYCLE 2.000           // Timer 2 ticks are 0.01632 seconds each
#define H_ACCEL_DIVISOR 104857600             // For acceleration/deceleration of H stepper 
#define MIN_H_TICK 32
#define MAX_H_TICK 8160
#define H_STEPPER_WIND_LPCM 5
#define STARTUP_H_TICK_HALF_STEP 2000
#define H_STEPPER_FULL_STEPS_PER_REV 200 //for information only - not used!
#define H_STEPPER_MULTIPLIER 750000   // 60 * 16000000 * 100 / 10 / 400 / 32, i.e.
        // seconds in minute * clock speed in Hz * multiplier for speed (specified via serial as 100 * actual, eg 4500)
        // / stepper revs per linear cm / number of stepper half-steps per rev / number of clock cycles per 'tick'

#define STAT_STOP 0
#define STAT_FORWARD_AT_LPCM 1
#define STAT_BACK_AT_LPCM 2
#define STAT_FORWARD_WIND 3
#define STAT_BACK_WIND 4

#define SER_STAT_IDLE 0
#define SER_STAT_RECD_LT 1
#define SER_STAT_RECD_C 2
#define SER_STAT_RECD_R 3
#define SER_STAT_RECD_T 4

// Arduino pin connections. 
// Pin for thermistor circuit
#define PIN_TEMP_SENSOR 14

// LCD pins. Requires 74HC595 IC.
#define PIN_LCD_CLOCK 13
#define PIN_LCD_DATA 11
#define PIN_LCD_LATCH 10

// Limit switch pins. A limit switch (photointerruptor, e.g HY870P) is required
// at either end of the cutter head carriage travel. The signal from each is 
// cleaned up by passing it through one gate of a 74HC14 Schmitt inverter.
#define PIN_H_STEPPER_LIMIT_HI 9
#define PIN_H_STEPPER_LIMIT_LO 8

// Horizontal cutter head travel. Stepper driver (TMC2208) pins.
#define PIN_H_STEPPER_EN 7
#define PIN_H_STEPPER_MS1 6
#define PIN_H_STEPPER_MS2 5
#define PIN_H_STEPPER_DIR 3
#define PIN_H_STEPPER_PULSE 4

// Constants and variables for Steinhart-Hart equation for thermistor circuit
const float T_A = 2.097030150e-3;
const float T_B = 0.6731423305e-4;
const float T_C = 6.077684946e-7;
const float Rfix = 22000.0; // value of fixed resistor in voltage divider
float logRt;

unsigned long currHStepperTick;
unsigned long desiredHStepperTick;
unsigned long tempHStepperTick;
unsigned int desiredLPcm = 72; // default
unsigned long TTRPMx100 = 3333; // default
unsigned int HStepRShift = 4; // default
volatile long HStepper16thStepsTaken = 0;
long HStepperFullStepsTaken = 0;

int currTickAdj = 0;

unsigned int accelerationRate;
unsigned int accelerationDividend=400;
unsigned int accelerationCounter;

boolean checkHStepperSpeedFlag = false;
boolean checkHLimitSwitchesFlag = false;
boolean checkHStepsTakenFlag = false;
boolean HStepperReturningFlag = false;
//boolean updateLCDFlag = true;

unsigned int serialValue;
volatile boolean toggleHPulse = false;

// Keeps track of what the system is doing
volatile byte currHStepperState = STAT_STOP;
byte currSerialState = SER_STAT_IDLE;

// Variables for serial report
volatile unsigned int ticksThisReportCycle = 0;

// LCD
LiquidCrystal lcd(PIN_LCD_LATCH);

// =============== TIMER SETUP ROUTINE ===================
// Prepare timers.
// Timer 0 ticks once for each microstep (1/2, 1/4, 1/8 or 1/16)
// pulse to drive the H stepper motor.
// Timer 2 ticks as slowly as possible (0.01632 s) and
// this tick is used as the basis for serial reporting.

void initialiseTimers()
{
  cli();                              // Stop any interrupts

  TCCR0A = 0;                         // Clear TCCR0A and TCCR0B registers
  TCCR0B = 0;
  TCNT0  = 0;                         // Clear counter
  TCCR0A |= (1 << WGM01);             // Clear timer on compare match (CTC)
  TCCR0B |= (1 << CS01);              // Set CS01 bit for clock divider of 8
  OCR0A = 255;                        // Default
  TIMSK0 |= (1 << OCIE0A);            // Set timer compare interrupt

  TCCR2A = 0;                         // Clear TCCR2A and TCCR2B registers
  TCCR2B = 0;
  TCNT2  = 0;                         // Clear counter
  TCCR2A |= (1 << WGM21);             // Clear timer on compare match (CTC)
  TCCR2B |= (1 << CS22);              // Set CS22:20 bits for clock divider of 1024
  TCCR2B |= (1 << CS21);
  TCCR2B |= (1 << CS20);
  OCR2A = 255;                        // Default - longest possible delay
  TIMSK2 |= (1 << OCIE2A);            // Set timer compare interrupt
  sei();                              // Allow global interrupts
}

// Called at initialisation and also when accelerating or decelerating the H stepper motor.
void setTimer0()
{
  cli();                                      // Stop any interrupts
  if (currHStepperTick > 8160)                // Each H Stepper 'tick' is defined as a multiple of 32 clock cycles.
  {                                           // Longest delay possible with 8-bit counter is 261120 ( = 1024 * 255)
    currHStepperTick = 8160;                  // - thus longest 'tick' possible is 8160 (= 261120 / 32)
  }
  if (currHStepperTick >= 2016)
  {
    TCCR0B |= (1 << CS02);
    TCCR0B &= ~(1 << CS01);
    TCCR0B |= (1 << CS00);                    // Set CS02:00 bits for clock divider of 1024 ( = 32 * 32)
    OCR0A = (int)(currHStepperTick >> 5);     // Set compare match register to tick specified 1/32 of currHStepperTick
  } else if (currHStepperTick >= 504) {
    TCCR0B |= (1 << CS02);
    TCCR0B &= ~(1 << CS01);
    TCCR0B &= ~(1 << CS00);                   // Set CS02:00 bits for clock divider of 256 ( = 8 * 32)
    OCR0A = (int)(currHStepperTick >> 3);     // Set compare match register to tick specified 1/8 of currHStepperTick
  } else if (currHStepperTick >= 64) {
    TCCR0B &= ~(1 << CS02);
    TCCR0B |= (1 << CS01);
    TCCR0B |= (1 << CS00);                    // Set CS02:00 bits for clock divider of 64 ( = 2 * 32)
    OCR0A = (int)(currHStepperTick >> 1);     // Set compare match register to tick specified 1/2 of currHStepperTick
  } else {
    TCCR0B &= ~(1 << CS02);
    TCCR0B |= (1 << CS01);
    TCCR0B &= ~(1 << CS00);                   // Set CS02:00 bits for clock divider of 8 ( = 1/4 * 32)
    OCR0A = (int)(currHStepperTick << 2);     // Set compare match register to tick specified 4 * currHStepperTick

  }
  sei();                                      // Allow global interrupts
}

// =============== MAIN SETUP ROUTINE ===================
// Main initialisation sequence
void setup()
{
  // Thermistor pin (analogue)
  pinMode(PIN_TEMP_SENSOR, INPUT);
  
  // Stepper limit switches
  pinMode(PIN_H_STEPPER_LIMIT_LO, INPUT);
  pinMode(PIN_H_STEPPER_LIMIT_HI, INPUT);

  // LCD outputs
  pinMode(PIN_LCD_LATCH, OUTPUT);
  pinMode(PIN_LCD_CLOCK, OUTPUT);
  pinMode(PIN_LCD_DATA, OUTPUT);

  // H Stepper motor outputs
  pinMode(PIN_H_STEPPER_EN, OUTPUT);
  pinMode(PIN_H_STEPPER_MS1, OUTPUT);
  pinMode(PIN_H_STEPPER_MS2, OUTPUT);
  pinMode(PIN_H_STEPPER_DIR, OUTPUT);
  pinMode(PIN_H_STEPPER_PULSE, OUTPUT);
  // set pulses, dirs off (LOW) & enable off (HIGH), and step size to full (00)
  digitalWrite(PIN_H_STEPPER_DIR, LOW);
  digitalWrite(PIN_H_STEPPER_PULSE, LOW);
  digitalWrite(PIN_H_STEPPER_EN, HIGH);
  digitalWrite(PIN_H_STEPPER_MS1, LOW);
  digitalWrite(PIN_H_STEPPER_MS2, LOW);

  lcd.begin(16, 2);
  initialiseTimers();
  resetHStepperTicks();
  doLPcmCalc();
  // Start serial port
  Serial.begin(115200);

}
// =============== THERMISTOR CALCULATIONS ==============
//float calcTemp(int v0)
//{
//  float TC;
//  logRt = log(Rfix * (1023.0 / (float)v0 - 1));
//  TC = (1.0 / (T_A + T_B * logRt + T_C * logRt * logRt * logRt)) - 273.15;
//  return TC;
//}

int calcTemp(int v0)
{
  float TC;
  logRt = log(Rfix * (1023.0 / (float)v0 - 1));
  TC = (1.0 / (T_A + T_B * logRt + T_C * logRt * logRt * logRt)) - 273.15;
  return TC;
}
// =============== INTERRUPT ROUTINES ===================

// Interrupt routine run when timer 0 compare interrupt fires.
ISR(TIMER0_COMPA_vect)
{
  // Action if stepper is running
  if (currHStepperState != STAT_STOP)
  {
    if (toggleHPulse)
    {
      digitalWrite(PIN_H_STEPPER_PULSE, LOW);
      toggleHPulse = false;
    } else {
      digitalWrite(PIN_H_STEPPER_PULSE, HIGH);
      toggleHPulse = true;
      // Set flag to check limit switches
      checkHLimitSwitchesFlag = true;
      // Adjust number of steps taken
      // If moving forward (towards centre)
      if (currHStepperState == STAT_FORWARD_AT_LPCM || currHStepperState == STAT_FORWARD_WIND) 
      {
        HStepper16thStepsTaken += 1 << (4 - HStepRShift);
        // If 'Homing', and home reached
        if (HStepperReturningFlag && HStepper16thStepsTaken >= 0)
        {}
      }
      // If moving back (away from centre)
      else if (currHStepperState == STAT_BACK_AT_LPCM || currHStepperState == STAT_BACK_WIND) 
       {
        HStepper16thStepsTaken -= 1 << (4 - HStepRShift);
        // If 'Homing', and home reached
        if (HStepperReturningFlag && HStepper16thStepsTaken <= 0)
        {}  
      }
        //checkHStepsTakenFlag = true;
      // Set flag to update LCD
      //updateLCDFlag = true;
      // If the H stepper is accelerating or decelerating
      if (currHStepperTick != desiredHStepperTick)
      {
        // Set flag for speed check in main loop
        checkHStepperSpeedFlag = true;
      }
    }
  }
}


//-------------------------------------------------------------------
// Interrupt routine run when timer 2 compare interrupt fires.
ISR(TIMER2_COMPA_vect)
{
  // Count time to next serial port message
  ticksThisReportCycle++;
}

// =============== LIMIT SWITCH ROUTINES ===================
// Photointerrupters return HIGH if CLEAR, LOW if BLOCKED.
// This is inverted via 74HC14, so input to Arduino is LOW if CLEAR, HIGH if BLOCKED.
// These routines return FALSE if CLEAR, TRUE if BLOCKED.
boolean limitHLo()
{
  return (digitalRead(PIN_H_STEPPER_LIMIT_LO) == LOW) ? false : true;
}
//-------------------------------------------------------------------
boolean limitHHi()
{
  return (digitalRead(PIN_H_STEPPER_LIMIT_HI) == LOW) ? false : true;
}

// =============== HORIZONTAL STEPPER ROUTINES ===================

// Sets angle through which horizontal stepper moves on each pulse. The faster the speed, the fewer
// ticks in a half-step, and the larger the angle required.
void setHStepperMS()
{
  if (HStepRShift == 4)
  {
    // sixteenth step
    // adjust MS1, MS2 HH
    digitalWrite(PIN_H_STEPPER_MS1, HIGH);
    digitalWrite(PIN_H_STEPPER_MS2, HIGH);
  }
  else if (HStepRShift == 3)
  {
    // eighth step
    // adjust MS1, MS2 LL
    digitalWrite(PIN_H_STEPPER_MS1, LOW);
    digitalWrite(PIN_H_STEPPER_MS2, LOW);
  }
  else if (HStepRShift == 2)
  {
    // quarter step
    // adjust MS1, MS2 LH
    digitalWrite(PIN_H_STEPPER_MS1, LOW);
    digitalWrite(PIN_H_STEPPER_MS2, HIGH);
  }
  else
  {
    // half step
    // adjust MS1, MS2 HL
    digitalWrite(PIN_H_STEPPER_MS1, HIGH);
    digitalWrite(PIN_H_STEPPER_MS2, LOW);
  }
}


//-------------------------------------------------------------------
// Set H stepper state and flags
void setHStepperState(byte newState)
{
  currHStepperState = newState;
  //updateLCDFlag = true;
}

//-------------------------------------------------------------------
// Compares current H stepper speed with desired, and accelerates/decelerates smoothly.
// The H stepper varies the length of the tick on timer 0, the pulses
// to the H stepper being made once per tick.
// The tick is lengthened or shortened gradually to avoid jerky acceleration.
void checkHStepperSpeed()
{
  // Reset flag so that this routine is not called more often than necessary
  checkHStepperSpeedFlag = false;

  // Speed is as desired - so just jump out.
  if (currHStepperTick == desiredHStepperTick) return;
  else {
    tempHStepperTick = currHStepperTick;
    // ACCELERATING - need to reduce length of tick per motor step
    if (currHStepperTick > desiredHStepperTick)
    {
      if (accelerationCounter==accelerationRate) 
      {
        accelerationCounter = 0;
        // Reduce currHStepperTick gradually to avoid motor troubles
        currHStepperTick --;
        //if (currHStepperTick == tempHStepperTick) currHStepperTick--; // in case above divisor rounds to 1
  
        // See if a 'gear change' is required
        if (currHStepperTick < MIN_H_TICK)
        {
          if (HStepRShift > 1)
          {
            currHStepperTick <<= 1;
            desiredHStepperTick <<= 1;
            HStepRShift --;
            setHStepperMS();
          } else {
            // Desired tick is too fast: set to allowed minimum tick-duration
            currHStepperTick = MIN_H_TICK;
            desiredHStepperTick = MIN_H_TICK;
          }
        }
        // Avoid 'hunting' if above causes target to be overshot
        if (currHStepperTick < desiredHStepperTick)
        {
          currHStepperTick = desiredHStepperTick;
        }
        // Calculate new acceleration rate to ensure smooth acceleration
        accelerationRate=accelerationDividend / currHStepperTick;
      } else accelerationCounter++; 
      // Call timer set method for new currHStepperTick
      setTimer0();

    } else
      // DECELERATING - need to increase length of tick per motor step
    {
      if (accelerationCounter==accelerationRate) 
      {
        accelerationCounter = 0;
        // Increase currHStepperTick gradually to avoid motor troubles
        currHStepperTick ++;
        //if (currHStepperTick == tempHStepperTick) currHStepperTick++;   // in case above divisor rounds to 1
  
        // See if a 'gear change' is required
        if (currHStepperTick > 2 * MIN_H_TICK)
        {
          if (HStepRShift < 4)
          {
            currHStepperTick >>= 1;
            desiredHStepperTick >>= 1;
            HStepRShift ++;
            setHStepperMS();
          }
        }
        if (currHStepperTick > MAX_H_TICK)
        {
          // Desired tick is too slow: set to allowed maximum tick-duration
          currHStepperTick = MAX_H_TICK;
          desiredHStepperTick = MAX_H_TICK;
        }
        // Avoid 'hunting' if above causes target to be overshot
        if (currHStepperTick > desiredHStepperTick)
        {
          currHStepperTick = desiredHStepperTick;
        }
        // Calculate new acceleration rate to ensure smooth acceleration
        accelerationRate=accelerationDividend / currHStepperTick;
      } else accelerationCounter++;
      // Call timer set method for new currHStepperTick
      setTimer0();
    }
  }
}

//-------------------------------------------------------------------
void checkHLimitSwitches()
{
  // Check limit switches before allowing horizontal stepper to proceed.
  switch (currHStepperState)
  {
    case STAT_FORWARD_AT_LPCM:
    case STAT_FORWARD_WIND:
      if (limitHHi())
      {
        // stop stepper
        disableHStepper();
      }
      break;
    case STAT_BACK_AT_LPCM:
    case STAT_BACK_WIND:
      if (limitHLo())
      {
        // stop stepper
        disableHStepper();
      }
      break;
  }
  // No need to call again.
  checkHLimitSwitchesFlag = false;
}

//-------------------------------------------------------------------
//void checkHStepsTaken()
//{
//  if (currHStepperState == STAT_FORWARD_AT_LPCM || currHStepperState == STAT_FORWARD_WIND) 
//    HStepper16thStepsTaken += (16 / HStepRShift);
//  else if (currHStepperState == STAT_BACK_AT_LPCM || currHStepperState == STAT_BACK_WIND) 
//    HStepper16thStepsTaken -= (16 / HStepRShift);
//  checkHStepsTakenFlag = false;
//}


//-------------------------------------------------------------------
// After a full stop of the H stepper, reset to default speeds.
void resetHStepperTicks()
{
  HStepperReturningFlag = false;
  HStepRShift = 4;
  currHStepperTick = STARTUP_H_TICK_HALF_STEP >> 3;
  setHStepperMS();
}

//-------------------------------------------------------------------
// Reset H stepper counter to zero.
void zeroCounter()
{
  HStepper16thStepsTaken = 0;
}

//-------------------------------------------------------------------
// Set or clear PIN_STEPPER_DIR for direction of stepper.
// Clear PIN_STEPPER_EN to enable stepper.
void setDirForward()
{
  if (!limitHHi())
  {
    digitalWrite(PIN_H_STEPPER_EN, LOW);                               // Set enable LOW (ie. enabled)
    digitalWrite(PIN_H_STEPPER_DIR, LOW);                              // Reset direction
  }
}

//-------------------------------------------------------------------
void setDirBack()
{
  if (!limitHLo())
  {
    digitalWrite(PIN_H_STEPPER_EN, LOW);                               // Set enable LOW (ie. enabled)
    digitalWrite(PIN_H_STEPPER_DIR, HIGH);                              // Reset direction
  }
}

//-------------------------------------------------------------------
void disableHStepper()
{
  digitalWrite(PIN_H_STEPPER_PULSE, LOW);                             // Turn off stepper pulse
  digitalWrite(PIN_H_STEPPER_EN, HIGH);                               // Set enable HIGH (ie. disabled)
  digitalWrite(PIN_H_STEPPER_DIR, LOW);                               // Reset direction
  setHStepperState(STAT_STOP);                                        // Set H stepper status
  serialReport();                                                     // Immediately signal via serial port
}

//-------------------------------------------------------------------
void doLPcmCalc()
{
  if (currHStepperState == STAT_FORWARD_AT_LPCM || currHStepperState == STAT_BACK_AT_LPCM) 
    // Calculate tick duration based on desired TT speed
    desiredHStepperTick = (H_STEPPER_MULTIPLIER * desiredLPcm / TTRPMx100) >> HStepRShift;
  else if (currHStepperState == STAT_FORWARD_WIND || currHStepperState == STAT_BACK_WIND)
    desiredHStepperTick = (H_STEPPER_MULTIPLIER * H_STEPPER_WIND_LPCM / 7800) >> HStepRShift;
}

// =============== SERIAL DATA ROUTINES ===================
void processSerial()
{
  byte sb = Serial.read();
  // If the current character is a digit, add it to value so far received.
  if (isdigit(sb))
  {
    serialValue *= 10;
    serialValue += sb - '0';
  }

  // Current character is not a digit: signals change of state
  else
  {
    // Do what we have to with the number just completed
    processPreviousNumber();
    // And set the new state depending on the new character
    switch (sb)
    {
      case 'E': // Emergency stop!
        // Immediately puts H stepper into freewheel, allowing power to be
        // disconnected without danger of back EMF damaging the drivers.
        disableHStepper();
        resetHStepperTicks();
        currSerialState = SER_STAT_IDLE;
        break;
      case 'C':
        currSerialState = SER_STAT_RECD_C;
        break;
      case 'R':
        currSerialState = SER_STAT_RECD_R;
        break;
      case 'T':
        currSerialState = SER_STAT_RECD_T;
        break;
      default:
        currSerialState = SER_STAT_IDLE;
        break;
    }
  }
}


void processPreviousNumber()
{
  switch (currSerialState)
  {
    // A command is coming in
    case SER_STAT_RECD_C:
      switch (serialValue)
      {
        // Stop stepper motor
        case 0:
          resetHStepperTicks();
          disableHStepper();
          break;
        // Start motor moving towards centre at rate specified by LPcm
        case 1:
          resetHStepperTicks();
          setHStepperState(STAT_FORWARD_AT_LPCM);  
          doLPcmCalc();
          setDirForward();
          setTimer0();
          break;
        // Start motor moving away from centre at rate specified by LPcm
        case 2:
          resetHStepperTicks();
          setHStepperState(STAT_BACK_AT_LPCM);  
          doLPcmCalc();
          setDirBack();
          setTimer0();
          break;
        // Start motor winding towards centre at full speed
        case 3:
          resetHStepperTicks();
          setHStepperState(STAT_FORWARD_WIND);  
          doLPcmCalc();
          setDirForward();
          setTimer0();
          break;
        // Start motor winding away from centre at full speed
        case 4:
          resetHStepperTicks();
          setHStepperState(STAT_BACK_WIND);  
          doLPcmCalc();
          setDirBack();
          setTimer0();
          break;
        // return to 'Home' : set direction depending
        // on step counter value, then proceed as for winding
        case 5:
          resetHStepperTicks();
          if (HStepperFullStepsTaken <= 0)
          {
            setHStepperState(STAT_FORWARD_WIND);  
            doLPcmCalc();
            setDirForward();
          } else {
            setHStepperState(STAT_BACK_WIND);  
            doLPcmCalc();
            setDirBack();
          }
          HStepperReturningFlag = true;
          setTimer0();
          break;
        // Zeroise step counter
        case 6:
          resetHStepperTicks();
          disableHStepper();
          zeroCounter();
          break;
      }
      break;
    // A TT RPM value is coming in
    case SER_STAT_RECD_R:
      TTRPMx100 = serialValue;                                     // Value in RPM*100 sent from PC
      doLPcmCalc();
      setTimer0();
      break;

    // An LPcm value is coming in
    case SER_STAT_RECD_T:
      desiredLPcm = serialValue;
      doLPcmCalc();
      setTimer0();
      break;
   }
  serialValue = 0;
}



void serialReport()
{
  
    Serial.print("<");
    Serial.print(HStepperFullStepsTaken);
    Serial.print("L");
    Serial.print(limitHLo());
    Serial.print("H");
    Serial.print(limitHHi());
    Serial.print(">");
  
  /*
    Serial.print("HS Status: ");
    Serial.print(currHStepperState);
    Serial.print(" RPM100: ");
    Serial.print(desiredTTRPMx100);
    Serial.print(" desLPcm: ");
    Serial.print(desiredLPcm);
    Serial.print(" HStRt: ");
    Serial.print(HStepRShift);
    Serial.print(" currHStTick: ");
    Serial.print(currHStepperTick);
    Serial.print(" desHStTick: ");
    Serial.println(desiredHStepperTick);
  
  Serial.print("H: ");
  Serial.print(currHStepperState);
  Serial.print("  Des/Curr: ");
  Serial.print(desiredHStepperTick);
  Serial.print("/");
  Serial.print(currHStepperTick);
  Serial.print(" RShift: ");
  Serial.print(HStepRShift);
  Serial.print(" 16ths: ");
  Serial.print(HStepper16thStepsTaken);
  Serial.print(" Full: ");
  Serial.print(HStepperFullStepsTaken);
  Serial.print(" L:");
  Serial.print(limitHLo());
  Serial.print(" H:");
  Serial.println(limitHHi());
  */
  ticksThisReportCycle = 0;
}
// =============== DISPLAY ROUTINES ===================

void showLCD()
{
  // Display messages depending on current state and settings.
  lcd.setCursor(0, 0);
  switch (currHStepperState)
  {
    case STAT_STOP:
      lcd.print("IDLE ");
      break;
    case STAT_FORWARD_AT_LPCM:
      lcd.print("FWD  ");
      break;
    case STAT_BACK_AT_LPCM:
      lcd.print("BACK ");
    case STAT_FORWARD_WIND:
      lcd.print(">>   ");
    case STAT_BACK_WIND:
      lcd.print("<<   ");
      break;
  }
  // Show number of H Stepper steps taken
  lcd.setCursor(5, 0);
  lcd.print(HStepperFullStepsTaken);
  lcd.print("     ");

  // Display home indicator
  lcd.setCursor(0, 1);
  if (HStepperFullStepsTaken == 0) {
    lcd.print("HOME "); 
  } else {
    lcd.print("     ");
  }
  // Display temperature
  lcd.print(calcTemp(analogRead(PIN_TEMP_SENSOR)));
  lcd.print((char)223);
  //updateLCDFlag = false;

}
// =============== MAIN ITERATION ===================

void loop()
{
  // Calculate number of FULL steps taken.
  HStepperFullStepsTaken = HStepper16thStepsTaken >> 4;
  // If returning to zero position, check whether zero position
  // found, guarding against overshoot.
  if (
    HStepperReturningFlag &&
    (((currHStepperState == STAT_BACK_WIND) && (HStepperFullStepsTaken <= 0))
     || ((currHStepperState == STAT_FORWARD_WIND) && (HStepperFullStepsTaken >= 0)))
  )
  {
    // Stop motor and cancel "returning" flag.
    HStepperReturningFlag = false;
    resetHStepperTicks();
    disableHStepper();
  }


  while (Serial.available()) processSerial();
  if (checkHStepperSpeedFlag) checkHStepperSpeed();
  //if (checkHStepsTakenFlag) checkHStepsTaken();
  if (checkHLimitSwitchesFlag) checkHLimitSwitches();


  // Serial report back to PC
  if (ticksThisReportCycle >= TICKS_IN_REPORT_CYCLE) 
  {
    showLCD();
    serialReport();
  }
  //if (updateLCDFlag) showLCD();
}

Pins 1 & 0 are not in use

Perhaps something in one of these sections?

 while (Serial.available()) processSerial();
  if (checkHStepperSpeedFlag) checkHStepperSpeed();
  //if (checkHStepsTakenFlag) checkHStepsTaken();
  if (checkHLimitSwitchesFlag) checkHLimitSwitches();


  // Serial report back to PC
  if (ticksThisReportCycle >= TICKS_IN_REPORT_CYCLE) 
  {
    showLCD();
    serialReport();
  }
  //if (updateLCDFlag) showLCD();
}
// Start serial port
  Serial.begin(115200);

Because you did not describe the author in your original post. Garbage input results in garbage output.

This looks strange to me. I would expect something like this... if your LCD has four wires...

#define I2C_ADDR    0x27
#define LCD_COLUMNS 16
#define LCD_LINES   2
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);

Or something like this if your LCD uses six wires (plus a few brightness wires)

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

Would you show a picture of the LCD wiring?