Reading the Serial Monitor on an 16x2 LCD screen

OK, we are getting a little better. This relates - not surprisingly - to your other thread on the "sensors" discussion so we would need to read through all that to get a better idea, wouldn't we? That is a little inconvenient; it is in general not a good idea - in fact a very bad one - to split discussions over different topics.

We now gather that you have in fact, got a LCD display working with test code and have a program which does your timing and feeds it to the serial monitor. Did you post that code to the other thread? I had a brief look last evening but don't fancy flipping forward and back. How about you post your code here according to the instructions and also the LCD test code you used, and we can look into it.

Note that "printing" stuff to the serial monitor is easy in terms of line length and carriage returns. To use the LCD, you have to be very careful about how you format the data.

/* Object starts a pendulum swing between ldrPin1 and ldrPin2 going from
   right to left. Total recorded time from start to finish
*/

const int THRESHOLD_LOW = 400; // Threshold of amount of light in area, can be adjusted to fit lighting conditions
const int THRESHOLD_HIGH = 630; // Same as above
int ldrPin1 = A0; // object swings right, shadow passes over LDR starting timer
int ldrPin2 = A5; // object swings left, shadow passes over LDR stopping timer
boolean pin1Trigger = false;
boolean pin2Trigger = false;
double totalTime = 0;
double startTime = 0;
double stopTime = 0;

void checkPin(int pin) {
  int pinRead = analogRead(pin);
  if (pinRead < THRESHOLD_HIGH) //an LDR has been triggered
  {
    if (pin == ldrPin1) {
      pin1Trigger = true;
      pin2Trigger = false;
    } else {
      pin1Trigger = false;
      pin2Trigger = true;
    }
  }
}


void setup() {
  Serial.begin (9600);

}

void loop() {
  totalTime = 0; //Reset the timer

  //While both are false, keep checking for a trigger on LDR1.
  while (!pin1Trigger && !pin2Trigger) {
    checkPin(ldrPin1);
    if (pin1Trigger) {
      //start the timer when the shadow FIRST passes over the LDR on ldrPin1
      startTime = millis();
      //pin1Trigger is now true - and therefore will break the while loop.
    }
  }

  //While the LDR1 is true, and LDR2 is false, keep checking for a trigger on LDR2
  while (pin1Trigger && !pin2Trigger) {
    checkPin(ldrPin2);
    if (pin2Trigger) {
      //Stop the timer when the shadow FIRST passes over the LDR on ldrPin2
      stopTime = millis();
      //pinTrigger will now be true - and therefore exit the while loop
    }
  }
  totalTime = (stopTime - startTime) / 1000;
  Serial.print ("time passed: ");
  Serial.print (totalTime);
  Serial.println(" (s)");
  //Reset the triggers for the next cycle
  pin1Trigger = false;
  pin2Trigger = false;
}

No you wouldn't have to flip back and forth to get the idea of what I am trying to get done.
My project has a pendulum on it and it passes over the two LDR's lowering the thresholds, therefore starting and stopping the timer. I am recording the total time from which the pendulum starts its movement, passing over ldrPin1 and when it comes back passing over ldrPin2.
At that point both pins are triggered and the serial monitor displays the "time passed"
It all works pretty good however, when I decided "hey let's put a LCD on here so I do not have to have it displayed on the laptop screen." So I bought an LCD and hooked it up and this is where I am at an impasse.
This is the original code, I did not include all the test sketches I have tried to get the "time passed" that appears on my serial monitor to appear on my LCD screen.

Note that "printing" stuff to the serial monitor is easy in terms of line length and carriage returns. To use the LCD, you have to be very careful about how you format the data.

That includes converting your 'totalTime' to the ASCII code(s) representing that number before sending it to the LCD.

Don

Ok, working with ASCII that is one thing I did not try I just thought it would be simple process as having the lcd.print within the code. Ok then I will try working implementing ASCII into my code and see what I come up with. thanks for the guidance. I will post again if I run into trouble.

The example sketch you posted, all your output uses the Print class on the Serial port to format the output so everything printed to the serial port is already in ASCII.

What isn't clear is what you are really wanting to do.
i.e. are you wanting to:

  • simply add an LCD to what you already have using a single Arduino
  • use one Arduino to print to serial port that is read by a second Arduino which displays the serial data on an LCD

What you need to do varies substantially between the two.

If using a single Arduino, then things are much simpler/easier.
You just wire up the LCD, use the LiquidCrystal library and use lcd.print() instead of Serial print.
However... there would be some changes needed as the LCD doesn't emulate a terminal and does not process line endings so you would have to position the cursor on the LCD each time prior to printing out your information.
Also the LCD display (particularly if you use a 16x2) may have fewer characters than you are currently outputting on the line on the serial port so you would need to alter the output format used on the LCD.

If attempting to use 2 Arduinos and read the serial port using a 2nd Arduino
the key thing to appreciate is what Paul said:

Note that "printing" stuff to the serial monitor is easy in terms of line length and carriage returns. To use the LCD, you have to be very careful about how you format the data.

To appreciate what the means you have to understand how the hd44780 LCD and the LiquidCrystal library works.
The hd44780 LCD is very dumb. While it does have commands to do things like position the cursor, clear the screen, home the cursor and a few others, The display does not understand line endings like and , nor does it understand line wrapping.
The LiquidCrystal library implements and API to talk to the LCD but it only provides API functions that mirror the core functions supported the LCD.
So what the really means is that when using the LiquidCrystal library and Print class, you can't send characters to the LCD the same way you can with the serial monitor.
This is because things like and will not be processed as carriage return or line feed and the characters will not wrap around to the next line on long lines.

So in your case you have this:

 Serial.print ("time passed: ");
  Serial.print (totalTime);
  Serial.println(" (s)");

Which produces output like this on the serial port:

time passed: ### (s)<CR><LF>

The Arduino serial monitor will interpret the character as a carriage return and wrap the cursor, Then interpret the and scroll the screen.
That won't happen on the LCD as neither the LCD nor LiquidCrystal process the and characters that way.
The LiquidCrystal library will send the and characters to the LCD which will interpret them as custom characters which will generally put two unwanted "garbage" characters on the display.

Because of this you can't just read a serial port and send the characters read "as is" to the LiquidCrystal library.
i.e. one Arduino outputs the serial data and another Arduino reading the serial data and sending it to the LiquidCrystal library.

You can simplify things if you can limit the display on the LCD to a single line of output from the serial port.
The reader Arduino could read the data until it sees the line endings and then set the cursor position and send that line (without the line ending characters) to the LCD.
The issue then becomes how to handle the line wrapping for long lines.
If you were to change the serial output to be no larger than your LCD line, then that problem goes away.

If you want to have long line wrapping on the LCD, you could switch to using my hd44780 library as that library will handle line wrapping.
It won't do line scrolling on the LCD but it does support line wrapping.

--- bill

1 Like

Bill, Oh wow what you explained is a lot further than what I thought I needed. To explain my set up yes I only have one Arduino and would like to only use one.

I did just add a 16x2 LCD and tried to have the data that is printed on the serial port, transferred/printed or whatever to the LCD the way you said to just hook it up and use the library and lcd.print(); instead of Serial.print(); or at least I thought I did.

I will check it all out again and run it but to be clear I really do not need the Serial.print ("time passed"); if that will make things a little easier. I just put that in to show what is happening. I also do not need the
(" (s)") on the serial print line, that was just to show the amount of time i.e. "seconds"

If it would be easier I can omit those and just have my time showing.

Right now what is displayed on the serial monitor is exactly this, I'm adding all 0's to the time just to remove any possible confusion but the time does vary from 0.75 all the way to 2.00 and so on. just how I want it to.

time passed: 0.00 (s)
time passed: 0.00 (s)
time passed: 0.00 (s)

Each time I run my project that is what appears on the serial monitor and when I run it again it drops to the second line i.e. Serial.println
Again I do not really need it to say time passed: or have the (s) after the time 0.00 is printed if that will make it easier to get the important info which is just the time sent to the LCD.

I will hook it up again and insert lcd.print in lieu of serial.print and see what I get and try to figure it out. I will post if it works or what happens when I run it. Thanks Bill for all your knowledge which is clearly superior to mine on this issue. hahaha

When printing to the LCD, you won't be able to use println()
When using the LCD, you will want to use setCursor(), then print your output.

--- bill

Ok, took out the serial print and println and inserted set cursor and the lcd print and what I got when I passed over ldr pin 1 was this on the lcd screen 0.00 but the total time was not calculated. each time I passed over ldr pin 1 0.00 appeared.
I do notice the zero's flickering prob due to the fluctuation of the dark resistance. just thought I would note that.
I have included a test sketch below this post hopefully I could get some help to figure this lil sucker out. Thanks in advance for all input.

/* Object starts a pendulum swing between ldrPin1 and ldrPin2 going from
   right to left. Total recorded time from start to finish
*/
#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const int THRESHOLD_LOW = 300; // Threshold of amount of light in area, can be adjusted to fit lighting conditions
const int THRESHOLD_HIGH = 400; // Same as above
int ldrPin1 = A0; // object swings right, shadow passes over LDR starting timer
int ldrPin2 = A5; // object swings left, shadow passes over LDR stopping timer
boolean pin1Trigger = false;
boolean pin2Trigger = false;
double totalTime = 0;
double startTime = 0;
double stopTime = 0;

void checkPin(int pin) {
  int pinRead = analogRead(pin);
  if (pinRead < THRESHOLD_HIGH) //an LDR has been triggered
  {
    if (pin == ldrPin1) {
      pin1Trigger = true;
      pin2Trigger = false;
    } else {
      pin1Trigger = false;
      pin2Trigger = true;
    }
  }
}


void setup() {
  Serial.begin (9600);
  lcd.begin(16, 2);

  lcd.setCursor(0, 0); // sets the cursor to collum 0 and row 0
}

void loop() {
  int sensorValue = analogRead (A0);


  totalTime = 0; //Reset the timer

  //While both are false, keep checking for a trigger on LDR1.
  while (!pin1Trigger && !pin2Trigger) {
    checkPin(ldrPin1);
    if (pin1Trigger) {
      //start the timer when the shadow FIRST passes over the LDR on ldrPin1
      startTime = millis();
      //pin1Trigger is now true - and therefore will break the while loop.
    }
  }

  //While the LDR1 is true, and LDR2 is false, keep checking for a trigger on LDR2
  while (pin1Trigger && !pin2Trigger) {
    checkPin(ldrPin2);
    if (pin2Trigger) {
      //Stop the timer when the shadow FIRST passes over the LDR on ldrPin2
      stopTime = millis();
      //pinTrigger will now be true - and therefore exit the while loop
    }
  }


  totalTime = (stopTime - startTime) / 1000;
  lcd.clear();
  lcd.print (totalTime);

  //Reset the triggers for the next cycle
  pin1Trigger = false;
  pin2Trigger = false;
}
double totalTime = 0;
double startTime = 0;
double stopTime = 0;

These are time variables, picking up the value of millis(), and they should be typed as unsigned long instead of floating point numbers(double).

The default lcd print statement of a floating point number is with two places after the dp, and I'm not sure if the .00 for total time isn't an artifact of the improper typing instead of some other problem with the logic of the code.

To test this, I would change the variables to unsigned long, and then remove the /1000 in the print out. What do you see on the display with this.

//totalTime = (stopTime - startTime) / 1000;
  totalTime = (stopTime - startTime);
  lcd.clear();
  lcd.print (totalTime);

The lcd.clear() is slow and is not the proper way to remove old data. You are better to set the cursor and print blank spaces, but that is a refinement, that can be handled when you know that the code is producing the data you want to display.

Ok I will insert that and see what the LCD gives me.

Alright I pulled the double and inserted unsigned long, removed the /1000 at the end of the startTime - stopTime and what I got was a single 0 it fluctuated when I passed over the ldrPin1 meaning went dim (due to dark resistance) but stayed as a 0

I added another totalTime = (stopTime - startTime); after the first one and when I passed over ldrPin1 the reading I get with the first pass is a 0 but on the second pass sometimes I get a 1 as though it is reading digital (on, off) or (high, low)

not sure whats going on here...

Having trouble trying figure out where I am going wrong with my code. To check to see if it can be done I did a sample code to show the numerical values from an LDR that is displayed on the serial monitor and had them transferred to my LCD screen and it works.

It shows the numbers and when I cloak the LDR in a shadow the number changes accordingly just like it would on the serial monitor.

I put the sample code below to show how I got it to work but my question is why am I able to get the readings to display on the LCD with this code, but trying to get the numbers to show from the code I put at the beginning of this thread will not work. I was given some Ideas on how to correct it and make it work but I tried those but got no results. help...

#include <LiquidCrystal.h> // include library code
/* initialize library by associating LCD interface pin
    with the arduino pin number it is connected to
*/
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

int sensorPin = A0; // select the input pin for LDR

int sensorValue = 0; // variable to store the value coming from the sensor

void setup() {
  lcd.begin(16, 2); //sets up LCD's numbe of columns and rows
  Serial.begin (9600); // sets serial port for communication

}

void loop() {
  //when characters arrive over the serial port...
  if (Serial.available()) {
    lcd.setCursor(0, 0);
    lcd.print(0);
    //read all avaialable data
    while (Serial.available() > 0) {
      //display all data to LCD

    }
  }

  sensorValue = analogRead (sensorPin); // read value from sensor
  lcd.clear();
  lcd.print (sensorValue); // prints values coming from serial monitor
  delay(500);
}
sensorValue = analogRead (sensorPin); // read value from sensor
  lcd.clear();
  lcd.print (sensorValue); // prints values coming from serial monitor

Your comment about the lcd printing values coming from the serial monitor is not correct. The lcd is printing the analogRead() value from the sensorPin. The Serial monitor is not involved in any way.

but trying to get the numbers to show from the code I put at the beginning of this thread will not work. I was given some Ideas on how to correct it and make it work but I tried those but got no results. help...

Please post your latest code, and describe what it does and does not do.

This is the updated code that I have ran, all that is displayed on the LCD screen is 0.00

There is no calculation of time when I run my object over the ldrpin1 or ldrpin2 the 0.00 is just static.
what I am wanting for the LCD screen to display is the same thing that I see when I print to the serial monitor, which is the time it takes for my object to pass over both ldr's.

project: - Object passes over ldrpin1 (A0) triggering the timer to start counting

  • Object makes 180* turn passing over ldrpin1 (A0) second time; timer still counting.
  • Object passes over ldrpin2 (A5) triggering the timer to stop counting.
  • Time is calculated recorded and displayed on serial monitor, i.e. 1.50, 1.75, 1.00 sec etc...
    dependent on how fast the object is moving.

what I need to happen is the LCD screen display the same recorded data that is on the serial monitor
so that my project is mobile and not attached to my laptop. below is the updated code.

/* Object starts a pendulum swing between ldrPin1 and ldrPin2 going from
   right to left. Total recorded time from start to finish
*/
#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const int THRESHOLD_LOW = 250; // Threshold of amount of light in area, can be adjusted to fit lighting conditions
const int THRESHOLD_HIGH = 550; // Same as above
int ldrPin1 = A0; // object swings right, shadow passes over LDR starting timer
int ldrPin2 = A5; // object swings left, shadow passes over LDR stopping timer
boolean pin1Trigger = false;
boolean pin2Trigger = false;
double totalTime = 0;
double startTime = 0;
double stopTime = 0;

void checkPin(int pin) {
  int pinRead = analogRead(pin);
  if (pinRead < THRESHOLD_HIGH) //an LDR has been triggered
  {
    if (pin == ldrPin1) {
      pin1Trigger = true;
      pin2Trigger = false;
    } else {
      pin1Trigger = false;
      pin2Trigger = true;
    }
  }
}


void setup() {
  lcd.begin(16, 2);
  Serial.begin (9600);

}

void loop() {
  int sensorValue = analogRead (A0);
  if (Serial.available()) {
    lcd.setCursor(0, 0); // sets the cursor to collum 0 and row 0
    lcd.print(0);
    totalTime = 0; //Reset the timer
    while (Serial.available() > 0) {
    }
  }
  //While both are false, keep checking for a trigger on LDR1.
  while (!pin1Trigger && !pin2Trigger) {
    checkPin(ldrPin1);
    if (pin1Trigger) {
      //start the timer when the shadow FIRST passes over the LDR on ldrPin1
      startTime = millis();
      //pin1Trigger is now true - and therefore will break the while loop.
    }
  }

  //While the LDR1 is true, and LDR2 is false, keep checking for a trigger on LDR2
  while (pin1Trigger && !pin2Trigger) {
    checkPin(ldrPin2);
    if (pin2Trigger) {
      //Stop the timer when the shadow FIRST passes over the LDR on ldrPin2
      stopTime = millis();
      //pinTrigger will now be true - and therefore exit the while loop
    }
  }


  totalTime = (stopTime - startTime) / 1000; {
    lcd.clear();
    lcd.print (totalTime);
  }//Reset the triggers for the next cycle
  pin1Trigger = false;
  pin2Trigger = false;
}
if (Serial.available()) {
    lcd.setCursor(0, 0); // sets the cursor to collum 0 and row 0
    lcd.print(0);
    totalTime = 0; //Reset the timer
    while (Serial.available() > 0) {
    }
  }

Please explain what you are trying to do here. Are you entering anything in the Serial Monitor?

If you actually are entering a value, the program will hang here because you never perform a Serial.read() to empty the serial input buffer and the code will hang in the while loop because Serial.available>0 is true.

If you are trying to enter a character to start the measurement process, make sure the Serial monitor is set to no line ending and try

if (Serial.available()) {
    Serial.read();
    lcd.clear();
    //lcd.setCursor(0, 0); // sets the cursor to collum 0 and row 0
    lcd.print(0);
    totalTime = 0; //Reset the timer
   // while (Serial.available() > 0) {
   // }
  }

No, point of fact everything that is displayed on the serial monitor is from the when the two ldr's are triggered, when their threshold has been breached. Thus starting the timer when ldrPin1 threshold is breached by the shadow of the object and once the ldrPin2 threshold has been breached the timer stops. And the time is displayed on the serial monitor, displayed in seconds such as 1.63 secconds or 2.45 seconds for the object to pass over both ldrs however long it takes.

Maybe I should make another video showing what happens and what is displayed on the serial monitor with out the LCD and what happens when I use the code with the liquid crystal library.

It will make much more sense I just haven't had time to do that.