Reading the Serial Monitor on an 16x2 LCD screen

Hello, my question is this; how does one take the info that is coming in to the serial monitor via (2 LDR's) and display that to an LCD screen. Forgive my youthful ignorance but I thought it would be as simple as reading from the serial port and having that displayed onto the LCD.

I read up all I could on LCD examples and did some of them to confirm that I have everything hooked up as I should. everything worked fine. However, when I tried to take the info that was coming in from the LDR's it would not display it on the LCD.

I have my code that measures what I want on the serial monitor and will post that a little later if need be but right now I'm just asking how simple is it to send the data from the serial monitor to the LCD screen. I would not think it is that hard being that I was able to write to the serial monitor and have that displayed rather easily.... Thank you in advance for any and all input

Before we start to respond we have to be sure we are thinking about the same thing ....

Acronym Definition
LDR Leader
LDR Land Disposal Restrictions
LDR Long Distance Relationship
LDR Louisiana Department of Revenue
LDR Light Dependent Resistor
LDR Listener Driven Radio (software)
LDR Lutheran Disaster Response
LDR Labor-Delivery-Recovery (room)
LDR Low Data Rate
LDR Loan-to-Deposit Ratio (banking)
LDR Land Development Regulation
LDR Linear Depolarization Ratio
LDR Limited Distribution Release (Microsoft)
LDR Large Deployable Reflector
LDR Long Distance Runner
LDR Long Distance Release (fishing)
LDR Labor Distribution Reporting (US government)
LDR Line Driver/Receiver (Alcatel)
LDR Lucent Digital Radio (Warren, NJ)
LDR Light Detect Resistor
LDR Long Distance Riders (motorcycle certification group)
LDR Last Ditch Racing (Maine-based rally racing team)
LDR Liquid Droplet Radiator
LDR Let Down Ratio (plastics)
LDR Laser Designator Ranger
LDR Logical Design Review
LDR Lapdance Riders (motorcycle club)
LDR Low Definition Radio
LDR Local Dynamic Routing
LDR Labor Distribution Record
LDR Loan-Default Rate (finance/banking)
LDR Local Distribution Radio (Sprint)
LDR Local Dump and Restore
LDR Large Diameter Roll (paper making)
LDR Law of Diminishing Returns (economic theory)
LDR Lana Del Rey (musician)
LDR Land Development Review (various locations)
LDR Low Density Recruiting (US Army National Guard)

Don

LMAO :smiling_imp: ok fair enough "light dependent resistor"

OK, so here is the next question - how does a Light Dependent Resistor - or indeed two of them - have anything to do with a serial killer monitor? :astonished:

I think you have better start explaining just what you are doing. :roll_eyes:

That was also my next question.

Don

The project I have measures the time it takes an object to pass over two LDR's like a race car lap timer. The first (LDR) is on one end and the second (LDR) is on the other end.

(light dependent resistor, for those that are lacking the understanding of that acronym in a forum that only deals with electronics etc.. nothing else)

Moving forward, when I hook everything up to and test my project I open the serial monitor to test my project/code and my lap times are given in the serial monitor.

My question, is this possible to take the lap times that are displayed in the serial monitor and have them displayed on the LCD screen so that I can have my project mobile and not attached to my computer?

If so, I'm curious as to how to get this done.

I thought that would be a simple process as #include<LiquidCrystal.h> and simply including that in my sketch along with the lcd.write(Serial.read());

I'm not expert here, but this doesn't seem like a very hard task being that it was pretty easy to type a message on the serial monitor and have it displayed on the LCD screen via the sketch provided in the library. HELP...

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...