Serial.read to display text on LCD

Hello,

I recently got my HD44780-compatible LCD screen. I was able to get it to work in 4-bit mode, and to display static text. I have been searching, however, to figure out a way to push text across the serial port and have it print on the LCD screen. I think that I am getting tripped up in understanding how to convert the string of information i send from the Arduino IDE over serial into the sort of input that lcd.printIn is looking for. As it is, it seems the farthest i have been able to get is having the DEC values of various alphanumeric inputs print on the screen. I have been able to remedy this problem in the case of integers using this formulation :

int val = 12345;
char s[10];
lcd.printIn(itoa(val, s, 10));

however, i am properly stuck at this point on printing out characters dynamically. Any suggestions would be greatly appreciated. Thanks much.

Well I have half answered my question, i can get single letters to print on one cell of the LCD with the following simple code. I didnt realize there was a lcd.print function until i opened up the library, because most of the examples seemed to use lcd.printIn

#include <LCD4Bit.h>
LCD4Bit lcd = LCD4Bit(1);

void setup() {
lcd.init();
Serial.begin(9600);
}

void loop() {

int val = Serial.read();

lcd.clear();
delay(5);
lcd.print(val);
delay(1000);

}

Are you sure it's not supposed to be lcd.println with a small L?

Almost certain, only lcd.printIn (as in i or I) appears in the library and will, consequently compile. I have to figure out now how to push through a string of characters from the serial to display whole words on the screen. The code I posted cycles through each alphanumeric character in a single cell on the LCD so the word "apple" would come across only in the first cell a, then p-p-l-e. Any thoughts on this would be appreciated. I'll be sure to put the code up if I come across it first.

You could read 8 characters from the serial buffer as a string and put it on the lcd with the println function. I don't know what display you have, but anything else as 1x8 characters behaves a bit strange. I have a 1x16 bit display which acts like 2x8 and 4x16 which counts lines top to bottom as 1, 3, 2, 4. I don't know if it is normal this way. But you need to do some coding to get it working aas you want.

I am still playing with this thing and trying to get it to respond. Maybe I am misunderstanding something about the Serial.read function. I am still quite new to all of this, so I appreciate the patience. The display that I am working with is 2 x 16, and my goal is to have the text wrap immediately onto the next line. I suppose to do that I need some way to determine how many bytes are in a certain string of input from the serial.read and to use it to say something like take the first 16 bytes and begin to print them starting from cursor position (1,0), then for bytes 17-32, start from cursor position (2,0). So I have been trying something like this, but I think I am on the wrong track:

#include <LCD4Bit.h>
LCD4Bit lcd = LCD4Bit(2);
int myArray[32];
int serialCount = 0;

void setup()

{
lcd.init();
lcd.clear();
Serial.begin(9600);
}

void loop() {

if (Serial.available() > 0) {

myArray[serialCount] = Serial.read();
serialCount ++;

if (serialCount < 16){
lcd.cursorTo(1,0);
lcd.print(myArray[serialCount]);
}

if (serialCount > 15){
lcd.cursorTo(2,0);
lcd.print(myArray[serialCount]);
}

delay(100);
}

}

I need to look at my own code so this is only a wild guess. First, you can read something from the serial buffer and the characters that you don't read will stay in the buffer. If I am right the buffer is 128 bytes but you can change it (have to look that up too). Second, you can write 1 character to the display at a time. So, after 16 characters you jump to the second line. And don't forget to clear the display when you start at line 1 again.
In your code you start writing to line 2 if you have more than 16 characters, but you should display the first 16 on line 1 and then proceed on line 2.
Just for testing you can print a string of 40 characters to line 1 and check the display. It probably writes to the second line too. Otherwise leftshifting will show what is after the 16th character.
You might also want to catch a return, just in case you receive a sentence that is shorter than 16 characters.
Again, I have to look it up what I did exactly but I just made a line1, line2, line3 etc function to display something on a specific line.

The code wasn't really complicated but had already changed from what I expected. I have a function to put the cursor the the right line:

void GotoLine(int line)
{
    switch (line)
    {
        case 1:
            lcd.cursorTo(1,0);
            break;
        case 2:
            lcd.cursorTo(2,0);
            break;
        case 3:
            lcd.cursorTo(1,20);
            break;
        case 4:
            lcd.cursorTo(2,20);
            break;
    }
}

You don't need this but it makes things easier. I use it in this function:

 switch(j)
    {
        case 0:
        line1("dev: ");
        line1(devStr);
        line1("temp: ");
        line1(tempStr);
        break;
    case 1:
        GotoLine(2);
        line1("dev: ");
        line1(devStr);
        line1("temp: ");
        line1(tempStr);
        break;
    case 2:
        GotoLine(3);
        line1("dev: ");
        line1(devStr);
        line1("temp: ");
        line1(tempStr);
        break;
    case 3:
        GotoLine(4);
        line1("dev: ");
        line1(devStr);
        line1("temp: ");
        line1(tempStr);
        delay(1000);
        lcd.clear();
        break;
    }

Success! :slight_smile:

Thank you so much for your help bigengineer. I have come up with an alternate way of solving the problem which suits my needs quite well, so I will share it here:

#include <LCD4Bit.h>
LCD4Bit lcd = LCD4Bit(2);

void setup()
{
lcd.init();
lcd.clear();
lcd.cursorTo(1, 0);
Serial.begin(9600);

}

void loop ()
{
int data[128]; //allow as many values as the Serial buffer will accept
int idx = 0;
int wait = 250; //control the speed of that the text sent over Serial is printed

while (idx != 33) // this while statement will allow a 2 x 16 lcd display to print 32 characters, then set idx to 0, thus resetting the loop
{
int avail = Serial.available();
if (avail > 0)
{

if (idx != 16) //if idx does not equal 16, or we may still on the first line
{
if (idx != 32) // then check that we are not at the end of the second line
{
data[idx++] = Serial.read(); //if we are not, take the value from the serial and advance the array
lcd.print(data[idx-1]); //print the value from whereever the cursor is
delay(wait);
}

else //otherwise the value equals 32 and we are at the end of the second line
{
lcd.clear(); //clear everything
lcd.cursorTo(1, 0); //move back to the first position
data[idx++] = Serial.read(); // read & print
lcd.print(data[idx-1]);
delay(wait);
}
}

else // it equals 16 and you are at the end of the first line
{
lcd.cursorTo(2, 0); //so go to the second line
data[idx++] = Serial.read(); //read & print
lcd.print(data[idx-1]);
delay(wait);
}
}
} //end while

idx = 0;
}

Just by way of an update, here is the complementary Processing code that I came up with. To recap, the goal of this all was to be able to take a text file and have it print out to an lcd screen continuously, without overwhelming the buffer.

import processing.serial.;
Serial port; // Create object from Serial class
import processing.net.
;
String data;

void setup() {
size(400,200);
background(50);
fill(200);
port = new Serial(this, Serial.list()[0], 9600);
port.buffer(128);
}

void draw() {

String lines[] = loadStrings("prufrock.txt");
for (int i=0; i < lines.length; i++) {
port.write(lines*);*
_ delay(5000); //it seems that you want this delay to equal the speed at which the lcd will print * the characters in the buffer + 10%_
}
}
void serialEvent(Serial port) {
String lines[] = loadStrings("prufrock.txt");
for (int i=0; i < lines.length; i++) {
port.write(lines*);*
* delay(5000);*

*} *
}