User input to serial monitor without effecting LCD

Hello,
I’m a complete novice but I’m building a weather monitor that displays humidity, ambient temperature and infrared sky temperature both on the LCD and on the serial monitor. I want to be able to input a sky temperature threshold on the serial monitor only so a bleep is triggered when the reading is above that threshold. I have done this and it works but the problem I am having is that I am prompted for input after every reading and I only want to put in the threshold once without the LCD freezing while the serial waits for input because I want the unit to work both as a stand alone device and as something that displays to the serial monitor when needed. I am unsure where to go from here. Any help would be greatly appreciated. Here is the entire code.

#include "DHT.h"                // includes the DHT11 library for temperature and humidity
#include <LiquidCrystal.h>      // includes the LiquidCrystal Library 
#include <Wire.h>               // includes the Wire library for the IR thermometer
#include <Adafruit_MLX90614.h>  // includes the MLX90614 library for the IR thermometer

#define DHTPIN 8                // Digital pin connected to the DHT sensor (connected to analog pin 8)
                                // Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
                                // Pin 15 can work but DHT must be disconnected during program upload.

#define DHTTYPE DHT11           // Define the type of DHT sensor (in this case the 3 pin version of DHT11)

int tempThresh;  //The temperature thresshold declared as an integer

DHT dht(DHTPIN, DHTTYPE);

LiquidCrystal lcd(12, 2, 4, 5, 6, 7);         // Creates an LCD object. Parameters: (rs, enable, d4, d5, d6, d7)

Adafruit_MLX90614 mlx = Adafruit_MLX90614();  // Sets up the IR thermometer

void setup() {

  lcd.begin(16,2);    // Initializes the interface to the LCD screen, and specifies the dimensions (width and height) of the display } 

  Serial.begin(9600); // Start serial port
  Serial.println("");                                                           // just a blank line as a spacer

  Serial.println("Humidity, Ambient Temperature and Infrared Sky Temperature"); // The title for serial monitor
  Serial.println("");                                                           // just a blank line as a spacer
  Serial.println("");                                                           // just a blank line as a spacer

  lcd.println(F("Humidity and     "));      // The title for lcd monitor
  lcd.setCursor(0,1);                       // Setting the cursor to the second row
  lcd.println(F("Temperature      "));      // The title for lcd monitor

  
  dht.begin();                              // starts the humidity sensor
  mlx.begin();                              // starts the IR thermometer
}

void loop() {
  // Wait a few seconds between measurements.
  delay(2000);

 
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    lcd.clear();                            // Clears the display
    lcd.setCursor(0,0);                     // Sets the location at which subsequent text written to the LCD will be displayed
    lcd.println(F("DHT sensor fail!  "));   // DHT failure warning
    return;
  }

  // Compute heat index in Fahrenheit (the default). This isn't being used due to limitations of LCD screen size but left in anyway.
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);


  lcd.clear();                    // Clears the display
  lcd.setCursor(0,0);             // Sets the location at which subsequent text written to the LCD will be displayed
  lcd.print(F("Humidity: "));     // Just the word "humidity"
  lcd.print(h);                   // Print humidity reading
  lcd.print(F("% "));             // Percentage symbol
  delay(3000);                    // 3 second delay
  
  lcd.clear();                          // Clears the display
  lcd.print("Ambient:");                // the word "ambient"
  lcd.print(mlx.readAmbientTempC());    // display ambient temperature in celsius
  lcd.print((char)223);                 // The symbol for degrees
  lcd.print(F("C "));                   // The letter "C"
  lcd.setCursor(0,1);                   // Setting the cursor to the second row
  lcd.print("Sky:    ");                // the word "sky"
  lcd.print(mlx.readObjectTempC());     // display sky temperature
  lcd.print((char)223);                 // The symbol for degrees
  lcd.print(F("C "));                   // The letter "C"
  
  delay(3000);                          // 3 second delay
  //lcd.clear();                        // Clears the display


  //This section is for user input 
 
  Serial.println("Enter sky temperature thresshold "); //Prompt User for Input
  
  while (Serial.available()==0){ }                     //Wait for User Input
  
  tempThresh = Serial.parseInt();                      //Read User Input
  Serial.print (tempThresh);                           //Print user input
  Serial.println("");                                  // just a blank line as a spacer
  Serial.println("");                                  // just a blank line as a spacer

//end of user input section

  
  Serial.print(F("Humidity:  "));       // Just the word "humidity"
  Serial.print(h);                      // The humidity
  Serial.print(F("%"));                 // percent symbol
  //Serial.println("");                 // just a blank line as a spacer


  Serial.print("   Ambient:    ");            // the word 'ambient'
  Serial.print(mlx.readAmbientTempC());       // display ambient temperature in celsius
  Serial.print(F("°C "  ));                   // The degrees symbol and the letter "C"
  //Serial.println("");                       // just a blank line as a spacer
  
  Serial.print("   Sky:    ");               // the word "sky"
  Serial.print(mlx.readObjectTempC());       // sky temperature
  Serial.print("°C");                        // The degrees symbol and the letter "C"


//if statement to ring bell (currently a text warning).

  if (mlx.readObjectTempC() > tempThresh) {Serial.print ("   -   Cloud");}; //Print 'Cloud' if sky temperature is above an input thresshold
  if (mlx.readObjectTempC() > tempThresh) {Serial.print ( "\a" );};         //Bleep if sky temperature is above an input thresshold

  Serial.println("");      // just a blank line as a spacer

} //End of loop

Nice job using code tags on your first post.

and as something that displays to the serial monitor when needed

How will you know that you want serial input? Perhaps if you enter an ‘S’ from serial monitor. Then you could have the user input section look like this.

 if (Serial.available() > 0)
  {
    char input = Serial.read();
    //if you can guarantee no line endings from monitor
    //the next lines are not required
    delay(10);//let line endings arrive
    while (Serial.available() > 0)
    {
      Serial.read();//throw away any terminating character
      delay(5);//see if there's another
    }

    if (input == 'S')
    {
      Serial.println("Enter sky temperature thresshold "); //Prompt User for Input
      while (Serial.available() == 0) { }
      int tempThresh = Serial.parseInt();//Read User Input
      Serial.print (tempThresh);                           //Print user input
      Serial.println("");                                  // just a blank line as a spacer
      Serial.println(""); // just a blank line as a spacer
    }
  }
}

//end of user input section

Using Serial.parseInt() is not an optimal approach and you should review the methods in the Serial input basics tutorial by Robin2.

Ah, thank you so much for that Cattledog. I tried your suggestion and it does exactly what I wanted it to do...I was going round in circles trying to find a solution (and failing). To answer your question, I'm an amateur astronomer and sometimes I go out without a computer (just the telescope) and at other times I sit indoors with the computer and cables running outside...but I always need to keep an eye on what the weather is up to so I'm hoping this little device will work in both circumstances. I have bookmarked the Serial input basics tutorial you provided and will read it (I certainly need that knowledge). Thanks again :slight_smile:

    if (input == 'S')
    {
      Serial.println("Enter sky temperature thresshold "); //Prompt User for Input
      while (Serial.available() == 0) { }
      int tempThresh = Serial.parseInt();//Read User Input
      Serial.print (tempThresh);                           //Print user input
      Serial.println("");                                  // just a blank line as a spacer
      Serial.println(""); // just a blank line as a spacer
    }

Making tempThresh a local variable is probably not a good idea.

Thanks Paul, the code seems to work pretty well now and does what I wanted it to do. The only thing I changed was to make "int tempThresh = Serial.parseInt();" into "tempThresh = Serial.parseInt();" because it was giving me the cloud alert no matter what threshold I entered. That adjustment made the sketch work as I hoped. I am currently reading the Serial input basics tutorial by Robin2 that Cattledog recommended so I can try and find out why using Serial.parseInt() and making tempThresh a local variable aren't good ideas, so hopefully future versions of this and other projects will be better as I learn more.

  if (input == 'S')
    {
      Serial.println("");                                  // Just a blank line as a spacer
      Serial.println("Enter sky temperature threshold ");  // Prompt User for Input
      while (Serial.available() == 0) { }                    // Wait for serial port
      tempThresh = Serial.parseInt();                      // Read User Input
      Serial.println("");                                   // Just a blank line as a spacer
      Serial.print (tempThresh);                      // Print user input
      Serial.println("");                                  // just a blank line as a spacer
      Serial.println("");                                  // just a blank line as a spacer 
    }

so I can try and find out why using Serial.parseInt() and making tempThresh a local variable aren't good ideas

When tempThreshold was a local variable, its scope was limited to within the { } of the if conditional block. This was fine for printing from within the block, but if you wanted to use the variable somewhere else in the program it would not be valid.

https://www.arduino.cc/reference/en/language/variables/variable-scope--qualifiers/scope/

The problem with Serial.parseInt() is that it is a "blocking" function, and the Arduino can do nothing else while it is waiting for input. Depending on what else is going in your program it may not be an issue, but it is good programming practice to write non blocking code.

parseInt() also tries to parse line endings from the Serial monitor, returns 0, and sometimes confuses beginners who don't understand its behavior.

Thank you for that, I think I understand now. I'll need to do some more experimenting to drive the lesson home. It's best to learn good practice at this early stage before bad habits form :slight_smile: