Gibberish display on LCD

Hello, I'm trying to construct a system that turns on or off(via relay) a heating element by temperature input (from a thermocouple and a max 6675), I have an LCD and buttons for user interface. It worked on breadboard and after soldering but after assembling, there's only gibberish on the LCD. Can you please suggest what could be wrong with my system?
I used the following pins on my Arduino nano :relay -4, buzzer-7, LCD(rs-13, en-12, d4-11, d5-10, d6-9, d7-8), max 6675(so-6, cs-5, sck-4), 5 buttons(A1,A2,A3,A0,3). Thank you for your response.

Use vero/grid board (Fig-1), good soldering iron/solder (Fig-2), good soldering tecniques (Fig-3), and minimum number of good jumpers (Fig-4).



Figure-1:



Figure-2:



Figure-3:


Figure-4:

I have preacticed Fig-1,2, 3, and 4 for 15 years in my professional life, and I am still practicing in my retired life.

We can't see your wiring nor your code. You need to post both.
Post clear pictures of the wiring.
Each connection must be visible. Including the wiring of the LCD pin RW to GND.

#include <max6675.h>
#include <LiquidCrystal.h>
// === LCD and Thermocouple setup ===
const int rs = 13, en = 12, d4 = 11, d5 = 10, d6 = 9, d7 = 8;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int soPin = 6, csPin = 5, sckPin = 4;
MAX6675 thermocouple(sckPin, csPin, soPin);
// === Control pins ===
const int heaterPin = 2;
const int buzzerPin = 7;
const int timerButtonPin = 3; // for reset / confirm / timer setting
const int warmPin = A0;
const int beveragePin = A1;
const int timerPin = A2;
const int autodryPin = A3;
// === Variables ===
float temp = 0, lastTemp = 0;
unsigned long lastReadTime = 0;
const unsigned long sampleInterval = 1000; // 1s for more responsive display
int activeMode = 0;
bool heaterOn = false;
// Button debouncing
unsigned long lastButtonPress = 0;
const unsigned long debounceDelay = 200;
bool warmButtonPressed = false;
bool beverageButtonPressed = false;
bool timerButtonPressed = false;
bool autodryButtonPressed = false;
// Rate calculation for boiling detection
float heatingRate = 0;
unsigned long lastRateTime = 0;
const unsigned long rateInterval = 30000;
float previousHeatingRate = 0;
// === Timer variables ===
int setHours = 0, setMinutes = 0;
bool timerRunning = false;
unsigned long timerStart = 0, timerDuration = 0;
bool timerSettingMode = false;
// === AutoDry variables ===
float stableThreshold = 0.5; // °C/s threshold for stability
const unsigned long stableConfirmationTime = 30000;
bool wasStable = false;
unsigned long stableStart = 0;
float autodryStableTemp = 0.0;
bool autodryStable = false;
unsigned long lastAutodryTempCheck = 0;
// === BASIC FUNCTIONS ===
void heaterOnFunc() {
digitalWrite(heaterPin, HIGH);
heaterOn = true;
}
void heaterOff() {
digitalWrite(heaterPin, LOW);
heaterOn = false;
}
void buzzerAndWaitForReset(unsigned long waitMillis) {
heaterOff(); // Turn off heater immediately
lcd.clear();
lcd.print("Process Complete");
digitalWrite(buzzerPin, HIGH);
delay(2000);
digitalWrite(buzzerPin, LOW);
lcd.clear();
lcd.print("Press Reset...");
lcd.setCursor(0, 1);
lcd.print("Or wait for off");
unsigned long start = millis();
while (millis() - start < waitMillis) {
if (digitalRead(timerButtonPin) == LOW) {
delay(50); // debounce
if (digitalRead(timerButtonPin) == LOW) {
lcd.clear();
lcd.print("Reset Done");
delay(1000);
activeMode = 0; // Return to mode selection
return;
}
}
}
// If not reset within window
lcd.clear();
lcd.print("Auto Reset");
delay(1000);

activeMode = 0; // Return to mode selection
}
// === SELECT MODE WITH PROPER DEBOUNCING ===
void checkModeButtons() {
unsigned long currentTime = millis();
// Only check buttons if enough time has passed (debouncing)
if (currentTime - lastButtonPress < debounceDelay) {
return;
}
// Check each button with INPUT_PULLUP (LOW when pressed)
if (digitalRead(warmPin) == LOW && !warmButtonPressed) {
warmButtonPressed = true;
lastButtonPress = currentTime;
activeMode = 1;
lcd.clear();
}
else if (digitalRead(warmPin) == HIGH) {
warmButtonPressed = false;
}
if (digitalRead(beveragePin) == LOW && !beverageButtonPressed) {
beverageButtonPressed = true;
lastButtonPress = currentTime;
activeMode = 2;
lcd.clear();
}
else if (digitalRead(beveragePin) == HIGH) {
beverageButtonPressed = false;
}
if (digitalRead(timerPin) == LOW && !timerButtonPressed) {
timerButtonPressed = true;
lastButtonPress = currentTime;
activeMode = 3;
timerSettingMode = true;
setHours = 0;
setMinutes = 0;
lcd.clear();
}
else if (digitalRead(timerPin) == HIGH) {
timerButtonPressed = false;
}
if (digitalRead(autodryPin) == LOW && !autodryButtonPressed) {
autodryButtonPressed = true;
lastButtonPress = currentTime;
activeMode = 4;
autodryStable = false;
wasStable = false;
lcd.clear();
}
else if (digitalRead(autodryPin) == HIGH) {
autodryButtonPressed = false;
}
}
void displayMode() {
lcd.setCursor(0, 0);
switch (activeMode) {
case 0:
lcd.print("Select Mode ");
Serial.println("Mode: Off");
break;
case 1:
lcd.print("Mode: Warm ");
Serial.println("Mode: Warm");
break;
case 2:
lcd.print("Mode: Beverage ");
Serial.println("Mode: Beverage");
break;
case 3:
lcd.print("Mode: Timer ");
Serial.println("Mode: Timer");
break;
case 4:
lcd.print("Mode: AutoDry ");
Serial.println("Mode: AutoDry");
break;
default:
lcd.print("Error: Unknown ");
activeMode = 0;
break;
}
}
void displayTemperature() {
lcd.setCursor(0, 1);
lcd.print("Temp: ");
lcd.print(temp, 1);
lcd.print((char)223);
lcd.print("C ");
}
// === TIMER SET ===
void handleTimerSetting() {
if (!timerSettingMode) {
return;
}
lcd.setCursor(0, 0);
lcd.print("Set Timer ");
lcd.setCursor(0, 1);
lcd.print(setHours);
lcd.print("h ");
lcd.print(setMinutes);
lcd.print("m ");
lcd.print("Hold=Start");
if (digitalRead(timerButtonPin) == LOW) {
unsigned long pressStart = millis();
// Wait for release or long hold
while (digitalRead(timerButtonPin) == LOW) {
unsigned long duration = millis() - pressStart;
// If held for 2s or more → confirm and start countdown
if (duration >= 2000) {
lcd.clear();
lcd.print("Timer Starting!");
delay(800);
timerSettingMode = false;
startTimerCountdown();
return;
}
}
unsigned long duration = millis() - pressStart;
if (duration < 500) {
// Short press → add 1 hour
setHours = (setHours + 1) % 6; // limit to 0–5h
}
else if (duration < 1500) {
// Medium press → add 5 minutes
setMinutes = (setMinutes + 5) % 60;
}
delay(200); // debounce
}
}
void startTimerCountdown() {
timerDuration = (setHours * 3600000UL) + (setMinutes * 60000UL);
timerStart = millis();
timerRunning = true;
heaterOnFunc();
lcd.clear();
lcd.print("Timer Running");
}
void updateTimerDisplay() {
if (!timerRunning) return;
unsigned long elapsed = millis() - timerStart;
unsigned long remaining = 0;
if (elapsed < timerDuration) {
remaining = timerDuration - elapsed;
} else {
// Timer completed
buzzerAndWaitForReset(30000);
timerRunning = false;
return;
}
int remainHours = remaining / 3600000;
int remainMinutes = (remaining % 3600000) / 60000;
int remainSeconds = (remaining % 60000) / 1000;
lcd.setCursor(0, 0);
lcd.print("Time Left: ");
lcd.setCursor(0, 1);
lcd.print(remainHours);
lcd.print("h ");
lcd.print(remainMinutes);
lcd.print("m ");
lcd.print(remainSeconds);
lcd.print("s ");
// Check for stop button (hold 2s)
if (digitalRead(timerButtonPin) == LOW) {
unsigned long pressStart = millis();
while (digitalRead(timerButtonPin) == LOW) {
if (millis() - pressStart >= 2000) {
timerRunning = false;
heaterOff();
lcd.clear();
lcd.print("Timer Stopped");
delay(1500);
activeMode = 0;
}
}
}
return;
}

// === SETUP ===
void setup() {
Serial.begin(9600);
pinMode(heaterPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(timerButtonPin, INPUT_PULLUP);
pinMode(warmPin, INPUT_PULLUP);
pinMode(beveragePin, INPUT_PULLUP);
pinMode(timerPin, INPUT_PULLUP);
pinMode(autodryPin, INPUT_PULLUP);
heaterOff(); // Ensure heater starts off
lcd.begin(16, 2);
lcd.clear();
lcd.print("Hey there!!");
lcd.setCursor(0, 1);
lcd.print("Let's cook!");
delay(2000);
lcd.clear();
lcd.print("Select Mode");
lcd.setCursor(0, 1);
lcd.print("Press a button");
delay(2000);
lcd.clear();
// Initial temperature reading
temp = thermocouple.readCelsius();
lastTemp = temp;
lastRateTime = millis();
}
// === LOOP ===
void loop() {
// Read temperature regularly
if (millis() - lastReadTime >= sampleInterval) {
lastReadTime = millis();
temp = thermocouple.readCelsius();
// Validate reading
if (isnan(temp) || temp < 0 || temp > 500) {
Serial.println("ERROR: Invalid temp reading");
// Keep last valid reading
}
}
// Check mode buttons (only when not in active operation)
if (activeMode == 0 || (!timerRunning && !timerSettingMode)) {
checkModeButtons();
}

// Handle modes
switch (activeMode) {
case 0:
// Idle mode - just display selection prompt
heaterOff();
lcd.setCursor(0, 0);
lcd.print("Select Mode ");
lcd.setCursor(0, 1);
lcd.print(" ");
break;
// --- WARM MODE --
case 1:
displayMode();
displayTemperature();
heaterOnFunc();
if (temp >= 70) {
buzzerAndWaitForReset(30000);
}
break;
// --- BEVERAGE MODE --
case 2:
displayMode();
displayTemperature();
heaterOnFunc();
if (temp >= 100) {
buzzerAndWaitForReset(30000);
}
break;
// --- TIMER MODE --
case 3:
if (timerSettingMode) {
handleTimerSetting();
}
else if (timerRunning) {
updateTimerDisplay();
}
break;
// --- AUTODRY MODE --
case 4:
displayMode();
displayTemperature();
heaterOnFunc();
// Calculate rate of temperature change every second
if (millis() - lastAutodryTempCheck >= 1000) {
lastAutodryTempCheck = millis();
float deltaTemp = temp - lastTemp;
float deltaTime = 1.0; // 1 second
float rateOfChange = deltaTemp / deltaTime; // °C per second
Serial.print("Rate: ");
Serial.print(rateOfChange, 3);
Serial.println(" °C/s");
// Check if temperature rate is stable (near boiling point)
if (abs(rateOfChange) <= stableThreshold && temp >= 90) {
if (!wasStable) {
wasStable = true;
stableStart = millis();
lcd.setCursor(0, 1);
lcd.print("Boiling... ");
Serial.println("Started boiling detection");
}
else if (millis() - stableStart >= stableConfirmationTime) {
if (!autodryStable) {
autodryStableTemp = temp;
autodryStable = true;
Serial.println("Confirmed stable at boiling");
}
}
}
else {
// Temperature is changing - reset or trigger buzzer if was stable
if (autodryStable && temp < autodryStableTemp - 5) {
// Temperature dropped significantly - food is drying
Serial.println("Water evaporated - drying complete");
buzzerAndWaitForReset(30000);
autodryStable = false;
wasStable = false;
}
else if (!autodryStable) {
wasStable = false;
stableStart = 0;
}
}
lastTemp = temp;
}
break;
default:
activeMode = 0;
break;
}
delay(10); // Small delay for stability
}

```Use code tags to format code for the forum

Thank for posting your code. Please could you edit your post and add the CODE tags?
Just select all of the sketch text and click the <CODE/> icon at the top of the editor window and then Save Edit the post. This will format and highlight the code so that it is much easier to read. Thanks.

Thank you...is it better now?

Hi, @terdoo
Welcome to the forum.

Have you tried to load the LCD Example "Hello World" code?

Thanks... Tom.... :smiley: :+1: :coffee: :australia:

Please edit your post to add code tags.

If you want to make your project working on the vero board, you have to start from the very beginning -- a procedure known as SSS Strategy (Start with Small Setp).

1. Unsolder everyting from the vero board excpet the NANO.
2. Put header pins with the LCD and place it on the vero board. Follow post #2 and nicely solder the pins of the LCD with vero board and NANO. Be sure that thee are no cold solder.

3. Upload the followin sketch and check that LCD ready message has appeared on the top-line of the LCD.

#include <LiquidCrystal.h>

const int rs = 13, en = 12, d4 = 11, d5 = 10, d6 = 9, d7 = 8;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup()
{
   lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("LCD ready");
}

void loop()
{

}

4. Connect/solder Butons on the vero board/NANO and check their functionaliies by adding codes withthe sketch of Step-3.

5. Place/solde buzzer with vero board/NANO and check the functionality of buzzer by adding codes witte sketch of Step-4.

6. Connect/solder relay with vero board/NANO and check its functionality by adding codes with the sketch of Step-5.

7. Connect/Solder thermocouple withvero board/NANO by adding codes wit the sketch of Step-6.

8. Now, you can prepare intergrated sketch for the actual functioning of your project.

Please, try this again...

type or paste code here
[sketch_nov11atony.ino.hex|attachment](upload://vZquNbD97RL7PAcGzob8NIyDHNU.hex) (23.3 KB)
#include <max6675.h>
 #include <LiquidCrystal.h>
 // === LCD and Thermocouple setup ===
 const int rs = 13, en = 12, d4 = 11, d5 = 10, d6 = 9, d7 = 8;
 LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
 const int soPin = 6, csPin = 5, sckPin = 4;
 MAX6675 thermocouple(sckPin, csPin, soPin);
 // === Control pins ===
 const int heaterPin = 2;
 const int buzzerPin = 7;
 const int timerButtonPin = 3;  // for reset / confirm / timer setting
 const int warmPin = A0;
 const int beveragePin = A1;
 const int timerPin = A2;
 const int autodryPin = A3;
 // === Variables ===
 float temp = 0, lastTemp = 0;
 unsigned long lastReadTime = 0;
 const unsigned long sampleInterval = 1000; // 1s for more responsive display
 int activeMode = 0;
 bool heaterOn = false;
 // Button debouncing
 unsigned long lastButtonPress = 0;
 const unsigned long debounceDelay = 200;
 bool warmButtonPressed = false;
 bool beverageButtonPressed = false;
 bool timerButtonPressed = false;
 bool autodryButtonPressed = false;
 // Rate calculation for boiling detection
 float heatingRate = 0;
 unsigned long lastRateTime = 0;
 const unsigned long rateInterval = 30000;
 float previousHeatingRate = 0;
 // === Timer variables ===
 int setHours = 0, setMinutes = 0;
 bool timerRunning = false;
 unsigned long timerStart = 0, timerDuration = 0;
 bool timerSettingMode = false;
 // === AutoDry variables ===
 float stableThreshold = 0.5;  // °C/s threshold for stability
 const unsigned long stableConfirmationTime = 30000;     
 bool wasStable = false;
 unsigned long stableStart = 0;
 float autodryStableTemp = 0.0;
 bool autodryStable = false;
 unsigned long lastAutodryTempCheck = 0;
 // === BASIC FUNCTIONS ===
 void heaterOnFunc() { 
  digitalWrite(heaterPin, HIGH); 
  heaterOn = true; 
}
 void heaterOff() { 
  digitalWrite(heaterPin, LOW); 
  heaterOn = false; 
}
 void buzzerAndWaitForReset(unsigned long waitMillis) {
  heaterOff();  // Turn off heater immediately
  lcd.clear();
  lcd.print("Process Complete");
  digitalWrite(buzzerPin, HIGH);
  delay(2000);
  digitalWrite(buzzerPin, LOW);
  lcd.clear();
  lcd.print("Press Reset...");
  lcd.setCursor(0, 1);
  lcd.print("Or wait for off");
  unsigned long start = millis();
  while (millis() - start < waitMillis) {
    if (digitalRead(timerButtonPin) == LOW) {
      delay(50);  // debounce
      if (digitalRead(timerButtonPin) == LOW) {
        lcd.clear();
        lcd.print("Reset Done");
        delay(1000);
        activeMode = 0;  // Return to mode selection
        return;
      }
    }
  }
  // If not reset within window
  lcd.clear();
  lcd.print("Auto Reset");
  delay(1000);

  activeMode = 0;  // Return to mode selection
  }
 // === SELECT MODE WITH PROPER DEBOUNCING ===
 void checkModeButtons() {
  unsigned long currentTime = millis();
  // Only check buttons if enough time has passed (debouncing)
  if (currentTime - lastButtonPress < debounceDelay) {
    return;
  }
  // Check each button with INPUT_PULLUP (LOW when pressed)
  if (digitalRead(warmPin) == LOW && !warmButtonPressed) {
    warmButtonPressed = true;
    lastButtonPress = currentTime;
    activeMode = 1;
    lcd.clear();
  }
  else if (digitalRead(warmPin) == HIGH) {
    warmButtonPressed = false;
  }
  if (digitalRead(beveragePin) == LOW && !beverageButtonPressed) {
    beverageButtonPressed = true;
    lastButtonPress = currentTime;
    activeMode = 2;
    lcd.clear();
  }
  else if (digitalRead(beveragePin) == HIGH) {
    beverageButtonPressed = false;
  }
  if (digitalRead(timerPin) == LOW && !timerButtonPressed) {
    timerButtonPressed = true;
    lastButtonPress = currentTime;
    activeMode = 3;
    timerSettingMode = true;
    setHours = 0;
    setMinutes = 0;
    lcd.clear();
  }
  else if (digitalRead(timerPin) == HIGH) {
    timerButtonPressed = false;
  }
  if (digitalRead(autodryPin) == LOW && !autodryButtonPressed) {
    autodryButtonPressed = true;
    lastButtonPress = currentTime;
    activeMode = 4;
    autodryStable = false;
    wasStable = false;
    lcd.clear();
  }
  else if (digitalRead(autodryPin) == HIGH) {
    autodryButtonPressed = false;
  }
 }
 void displayMode() {
  lcd.setCursor(0, 0);
  switch (activeMode) {
    case 0:
      lcd.print("Select Mode     ");
      Serial.println("Mode: Off");
      break;
    case 1:
      lcd.print("Mode: Warm      ");
      Serial.println("Mode: Warm");
      break;
    case 2:
      lcd.print("Mode: Beverage  ");
      Serial.println("Mode: Beverage");
      break;
    case 3:
      lcd.print("Mode: Timer     ");
      Serial.println("Mode: Timer");
      break;
    case 4:
      lcd.print("Mode: AutoDry   ");
      Serial.println("Mode: AutoDry");
      break;
    default:
      lcd.print("Error: Unknown  ");
      activeMode = 0;
      break;
  }
 }
 void displayTemperature() {
  lcd.setCursor(0, 1);
  lcd.print("Temp: ");
  lcd.print(temp, 1);
  lcd.print((char)223);
  lcd.print("C   ");
}
 // === TIMER SET ===
 void handleTimerSetting() {
  if (!timerSettingMode) {
    return;
  }
  lcd.setCursor(0, 0);
  lcd.print("Set Timer       ");
  lcd.setCursor(0, 1);
  lcd.print(setHours);
  lcd.print("h ");
  lcd.print(setMinutes);
  lcd.print("m  ");
  lcd.print("Hold=Start");
  if (digitalRead(timerButtonPin) == LOW) {
    unsigned long pressStart = millis();
    // Wait for release or long hold
    while (digitalRead(timerButtonPin) == LOW) {
      unsigned long duration = millis() - pressStart;
      // If held for 2s or more → confirm and start countdown
      if (duration >= 2000) {
        lcd.clear();
        lcd.print("Timer Starting!");
        delay(800);
        timerSettingMode = false;
        startTimerCountdown();
        return;
      }
    }
    unsigned long duration = millis() - pressStart;
    if (duration < 500) {
      // Short press → add 1 hour
      setHours = (setHours + 1) % 6;  // limit to 0–5h
    } 
    else if (duration < 1500) {
      // Medium press → add 5 minutes
      setMinutes = (setMinutes + 5) % 60;
    }
    delay(200);  // debounce
  }
 }
void startTimerCountdown() {
  timerDuration = (setHours * 3600000UL) + (setMinutes * 60000UL);
  timerStart = millis();
  timerRunning = true;
  heaterOnFunc();
  lcd.clear();
  lcd.print("Timer Running");
 }
 void updateTimerDisplay() {
  if (!timerRunning) return;
  unsigned long elapsed = millis() - timerStart;
  unsigned long remaining = 0;
  if (elapsed < timerDuration) {
    remaining = timerDuration - elapsed;
  } else {
    // Timer completed
    buzzerAndWaitForReset(30000);
    timerRunning = false;
    return;
  }
  int remainHours = remaining / 3600000;
  int remainMinutes = (remaining % 3600000) / 60000;
  int remainSeconds = (remaining % 60000) / 1000;
  lcd.setCursor(0, 0);
  lcd.print("Time Left:      ");
  lcd.setCursor(0, 1);
  lcd.print(remainHours);
  lcd.print("h ");
  lcd.print(remainMinutes);
  lcd.print("m ");
  lcd.print(remainSeconds);
  lcd.print("s   ");
  // Check for stop button (hold 2s)
  if (digitalRead(timerButtonPin) == LOW) {
    unsigned long pressStart = millis();
    while (digitalRead(timerButtonPin) == LOW) {
      if (millis() - pressStart >= 2000) {
        timerRunning = false;
        heaterOff();
        lcd.clear();
        lcd.print("Timer Stopped");
        delay(1500);
        activeMode = 0;
}
  }
    }
     return;
      }
       

 // === SETUP ===
 void setup() {
  Serial.begin(9600);
  pinMode(heaterPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode(timerButtonPin, INPUT_PULLUP);
  pinMode(warmPin, INPUT_PULLUP);
  pinMode(beveragePin, INPUT_PULLUP);
  pinMode(timerPin, INPUT_PULLUP);
  pinMode(autodryPin, INPUT_PULLUP);
  heaterOff();  // Ensure heater starts off
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("Hey there!!");
  lcd.setCursor(0, 1);
  lcd.print("Let's cook!");
  delay(2000);
  lcd.clear();
  lcd.print("Select Mode");
  lcd.setCursor(0, 1);
  lcd.print("Press a button");
  delay(2000);
  lcd.clear();
  // Initial temperature reading
  temp = thermocouple.readCelsius();
  lastTemp = temp;
  lastRateTime = millis();
 }
 // === LOOP ===
 void loop() {
  // Read temperature regularly
  if (millis() - lastReadTime >= sampleInterval) {
    lastReadTime = millis();
    temp = thermocouple.readCelsius();
    // Validate reading
    if (isnan(temp) || temp < 0 || temp > 500) {
      Serial.println("ERROR: Invalid temp reading");
      // Keep last valid reading
  }
    }
  // Check mode buttons (only when not in active operation)
  if (activeMode == 0 || (!timerRunning && !timerSettingMode)) {
    checkModeButtons();
  }
  
  // Handle modes
  switch (activeMode) {
    case 0:
      // Idle mode - just display selection prompt
      heaterOff();
      lcd.setCursor(0, 0);
      lcd.print("Select Mode     ");
      lcd.setCursor(0, 1);
      lcd.print("                ");
      break;
    // --- WARM MODE --
    case 1:
      displayMode();
      displayTemperature();
      heaterOnFunc();
      if (temp >= 70) {
        buzzerAndWaitForReset(30000);
      }
      break;
    // --- BEVERAGE MODE --
    case 2:
      displayMode();
      displayTemperature();
      heaterOnFunc();
      if (temp >= 100) {
        buzzerAndWaitForReset(30000);
      }
      break;
    // --- TIMER MODE --
    case 3:
      if (timerSettingMode) {
        handleTimerSetting();
      } 
      else if (timerRunning) {
        updateTimerDisplay();
      }
      break;
    // --- AUTODRY MODE --
    case 4:
      displayMode();
      displayTemperature();
      heaterOnFunc();
      // Calculate rate of temperature change every second
      if (millis() - lastAutodryTempCheck >= 1000) {
        lastAutodryTempCheck = millis();
        float deltaTemp = temp - lastTemp;
        float deltaTime = 1.0;  // 1 second
        float rateOfChange = deltaTemp / deltaTime;  // °C per second
        Serial.print("Rate: ");
        Serial.print(rateOfChange, 3);
        Serial.println(" °C/s");
        // Check if temperature rate is stable (near boiling point)
        if (abs(rateOfChange) <= stableThreshold && temp >= 90) {
          if (!wasStable) {
            wasStable = true;
            stableStart = millis();
            lcd.setCursor(0, 1);
            lcd.print("Boiling...      ");
            Serial.println("Started boiling detection");
          } 
          else if (millis() - stableStart >= stableConfirmationTime) {
            if (!autodryStable) {
              autodryStableTemp = temp;
              autodryStable = true;
              Serial.println("Confirmed stable at boiling");
            }
          }
        } 
        else {
          // Temperature is changing - reset or trigger buzzer if was stable
          if (autodryStable && temp < autodryStableTemp - 5) {
            // Temperature dropped significantly - food is drying
            Serial.println("Water evaporated - drying complete");
            buzzerAndWaitForReset(30000);
            autodryStable = false;
            wasStable = false;
          } 
          else if (!autodryStable) {
            wasStable = false;
            stableStart = 0;
          }
        }
        lastTemp = temp;
      }
      break;
    default:
      activeMode = 0;
      break;
  }
  delay(10);  // Small delay for stability
 }

Nice picture but I cannot follow it, please post your annotated schematic with links to technical information on hardware items.

Thank you...i had tried putting together the circuit and soldered on vero board and the LCD worked fine(i added capacitors to the power pins at both ends), but when assembled in the packaging box along with all the other components, it started displaying gibberish.


this was my circuit diagram but not all the components have the specified values

I hope the schematic is wrong and you do not actually have 9V connected to the LCD or the pull-up resistors for the buttons. < edit > now that I have looked at the image at larger scale, the battery may be 5V, looks more like a 9V the way it is drawn.

It would save some parts if you used the internal pull-up resistors.

Nice schematic, I think the gibberish is coming from either an open segment lead or switched segment leads.

It looks like you may have missed the Pull Up resister on B1. I use pull up resistors mainly because of the better noise immunity and switch reliability. I was taught unless the switches were rated for dry switching at least one mA had to flow through them to keep the contacts free of oxidation which would cause them to not switch or switch intermittently.

It is known that mechanical switch contacts suffer from:

  • Oxidation
  • Film buildup
  • Contamination
  • Microscopic corrosion

A small amount of current (called a wetting current) helps “scrub” the oxidation layer every time the switch closes.

Hello, thanks for your input...switch B1 works just fine...or do you think the LCD issue has to do with some sort of interference? Since the relay and max6675 comes in close contact with the LCD when assembled in the box? (The system worked after the breadboard prototyping and soldering).

Hi, @terdoo

What are you using for a power supply, what is the 5V?
You do not show it connected to the Nano on your schematic.

Do you have a DMM? Digital MultiMeter?

Why R1, R2, R4, and R6 when you have the internal pullups activated?
Note that because you have these external resistors connected directly to your power source, you could be phantom powering the Nano when SW1 is turned off, so the Nano may never reset on power up with SW1.

Q1 base circuit needs a series resistor like Q2.

Tom.... :smiley: :+1: :coffee: :australia: