Writing data from variable to GLCD. Getting errors

Hi All,

I have a a QY-12864F GLCD panel. Using the example script that comes with the GLCD library works just fine. However any text it writes to the script i.e.

GLCD.Puts("GLCD  version );

Is just text and yes it works fine. When I try to replace this with a variable. I.E.

String glcdVersion = "GLCD version ";
GLCD.Puts(glcdVersion);

I get the following error when I try to compile

error: no matching function for call to 'ks0108::Puts(String&)'

Can anyone provide any advice on how to write a string variable to a GLCD using the GLCD library

Thanks Simon

Try using char instead it compiles without error but i dont have my glcd to hand to test it

char glcdVersion[14] = "GLCD version ";
GLCD.Puts(glcdVersion);

The String class was added after the glcd library Puts() function was written, so the glcd library gText class function Puts() does not support it. However, the Arduino Print class does support the String class and the glcd library supports the Print class.

So you have two choices, you can either not use the String class for your strings or use the Print class function to print String class strings.

The String class has extra overhead, so if you don't intend to manipulate the strings using the String class functions, I would not use the String class to save memory.

So when not using the string class:

char *glcdVersion = "GLCD version ";
GLCD.Puts(glcdVersion);

Currently, if using the String class, you must use the Arduino Print class printing functions instead of directly using the glcd library gText functions like Puts().

String glcdVersion = "GLCD version ";
GLCD.print(glcdVersion);

I'll look into adding String class support to the glcd library gText class printing functions.

--- bill

P18F4550: Try using char instead it compiles without error but i dont have my glcd to hand to test it

char glcdVersion[14] = "GLCD version ";
GLCD.Puts(glcdVersion);

When declaring character arrays for strings, unless you need the storage to be exactly a given size it is best to avoid specifying the array size. Simply let the compiler figure it out because if you make it too small you will get a compile error. Make it too large and unless you need the extra room, you waste memory.

So use either of these two declarations instead. (both are equivalent)

char glcdVersion[] = "GLCD version ";
GLCD.Puts(glcdVersion);
char *glcdVersion = "GLCD version ";
GLCD.Puts(glcdVersion);

--- bill

Thanks for that Bill, i'll keep it mind

Simon, I have updated the glcd library to support the Arduino String class in Printf(), StringWidth(), and Puts() and have created a new RC release for the library.

So if you go grab the RC2 release, it should now work as you wanted it to.

But for simple strings like you have shown, it would use less code and more more importantly RAM if you declared it as a char * instead.

--- bill

Hi Bill,

I very much appreciate your time. I feel a bit bad actually, because after your post I tried the print function and found it did not work, that lead me to realize that I was using the old library. Hope that I have not wasted too much of your time. As soon as I updated with the new GLCD library, I was able to print strings. I was only using char because it was the only option available in the library I had.

One other quick question. Is there any library out there which will allow me to supply a string of text and a maximum character width and have it return a string that is formated with line breaks so that line wraps do not occur in the middle of words?

Again, I (and I think everybody else) appreciates your time and effort on this library!

Simon

Don't feel bad. You did discover that some of the glcd library printing functions didn't support the arduino String class.

As far as smart line/word breaks. Nothing that I've seen (but I've never really looked for it). The problem with modifying one string into another string is that it needs memory in order to do that. RAM is very precious on these small 8 bit micro-controllers. A better way to do it (as far as RAM usage goes) would be to write your own puts() function that handles it on the fly. In other words, it keeps track of the position it is in and then looks ahead after each word break (space character) and if the next word (all characters up to next space character) doesn't fit, then insert a new line and keeps going.

It would be a small routine that sits on top of PutChar().

That way it could even use strings that are only stored in Program memory vs in RAM like strings that declared with String or char *.

If you intend to use alot of strings, you may need to start storing the strings in flash vs RAM. Read up on PSTR() and have a look at the new BigNums example in the RC2 release of the glcd library.

--- bill

Hi Bill,

Just about there with my new project. One thing that I am still struggling with however is getting new lines to be displayed on the GLCD

The following code works just work

GLCD.SetTextMode(SCROLL_UP);
  GLCD.CursorToXY(1,1);
  GLCD.ClearScreen();
  GLCD.println("flkdsjk\nfjdslfjkdfj\ndlfkj\nlsdjf");

A line wrap replaces the \n escape code, however the following code just displays the \n as text

  while (Serial.available()){
    p = Serial.read();
    lcdText += p;
  }
  
  GLCD.SetTextMode(SCROLL_UP);
  GLCD.CursorToXY(1,1);
  GLCD.ClearScreen();
  GLCD.println(lcdText);

Any idea how I can get the escape codes to be recognized when read from serial?

Thanks
Simon

Actually don’t worry about my last post. Not sure why, but the /n escape code works fine when I send it from python via Serial. For some reason it just does not work when I send it from the Arduino Serial monitor

Thanks Anyway

Simon

Hope I am not starting to annoy anyone with all my questions. But…

When I use the GLCD.SetTextMode(SCROLL_UP); (or SCROLL_DOWN) the LCD clears the screen as part of the scroll and starts again from the top. In order for users to read a long string of text, I am writing to the LCD in a teletype fashion that is slow enough to read, as long as the last text written scrolls up the screen, however as I just said it simply clears the screen.

Here is my code

GLCD.CursorToXY(1,1);
  
  GLCD.ClearScreen();
  GLCD.SetTextMode(SCROLL_UP);
  for (int x = 0; x < lcdText.length(); x++)
  {
  delay(50);
  GLCD.print(lcdText.substring(x,x+1));
  }

Is there a way to carry out a true scrolling of text.

Thanks
Simon

I can't tell completely what you have done or were trying to do with that small code fragment. There are other things like what font you have selected, if you have modified the default text area, and how you have initialized your String class object that will affect things.

For example, if you don't select a font for the GLCD object, no text will be displayed when using the GLCD object printing functions.

I have run a simple test using your code fragement, using the system5x7 font, using the default text area in the GLCD object and it works as expected. The text wraps when necessary, and eventually will scroll the text area (up or down, depending on how it is initialized). You will see this slow text area wrapping/scrolling in the GLCDdemo sketch for two different fonts.

If you explained more of what you are trying to do and showed more of the sketch it would be helpful.

The text wrapping/scrolling code does not ever clear the text area or the glcd display screen. (while a text area may exist over the entire display, a text area is different from the entire display screen) The SetTextMode() call does not scroll or clear the text area in any way. It merely sets the text mode. The text mode SCROLL_UP and SCROLL_DOWN sets the direction the text area will be wrapped & scrolled when necessary after a line wrap.(UP scrolling with down wrapping being the default) The only part of the text area that is "cleared" is a small section that is large enough to hold a new row of text after the other text in the text area has been scrolled. This is at the bottom when scrolling up, and at the top when scrolling down.

Normally, when dealing with text areas and wrapping and scrolling you won't want to use CursorToXY(x,y), as that is setting the absolute X & Y pixel offsets within the text area for the character rendering. CursorTo(column, row) sets the character rendering position within the text area based on character positions of the currently selected font. (works best with fixed width fonts).

The reason I bring this up is using a x,y position of 1,1 inside a text area is not a corner of a text area. It is one pixel in. All areas are 0 based. (See the html documentation for details on the text area function calls - it is the gText class)

When scrolling up, the upper left corner would be 0,0 If using an x/y initial position of 1,1 when the scroll finally does happen, the initial scroll may look a bit strange if using something like the system5x7 font because initially there will not be enough room for that 8th row of text to wrap so there will be bit of an extra pixel gap between row7 and row8 of text as the scrolling code makes room for the new row to sit along the bottom edge of the text area.

When dealing with text inside text areas, it is better to use character row/column addressing with CursorTo() and things like ClearArea() when possible rather than absolute x&y positions with CursorToXY() and ClearScreen().

--- bill

Hi Bill, Here is the code I currently have loaded on my Arduino

If the first letter of the code received is a ‘t’ then text is expected next and sent to the LCD. The problem as I mentioned is that any text larger than the display limit for the LCD is not scrolled, the LCD simply clears the screen and starts again from the top.

Can you see what the problem is which my code?

Thank you
Simon

//start GLCD
#include <glcd.h>
#include "fonts/allFonts.h"         // system and arial14 fonts are used
#include "bitmaps/allBitmaps.h"       // all images in the bitmap dir 

String lcdText;
unsigned long startMillis;
unsigned int loops = 0;
unsigned int iter = 0;
//end GLCD

int unreadFlag; //1 = True, 0 = False
int  emailButtonState = 0;
char p;
void setup() {   
  GLCD.Init();   // initialise the library, non inverted writes pixels onto a clear screen  
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  pinMode(8, OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(13,OUTPUT);
  pinMode(12,INPUT);
  Serial.begin(9600);
  
  //Start GLCD
  delay(500);                // allow time for LCD to reset
  GLCD.ClearScreen();  
  
  GLCD.SelectFont(System5x7); // switch to fixed width system font 
  GLCD.print("Welcome to i-Monitor\n\nSimon Carr");
  //End GLCD
}

void loop() {
if (Serial.available()>0)
{
  p = Serial.read();
 
 //p = Serial.read();
}

switch (p){
 case 'x':
  unreadOn();
  break;
 case 'o':
  unreadOff();
  break;
 case 'p':
  flashLED(10,1);
  break;
 case 'a':
  emailAlertOn();
  break;
 case 't':
  delay(100);
  lcdText = "";
  while (Serial.available()){
    p = Serial.read();
    lcdText += p;
  }
  
  
  GLCD.ClearScreen();
  GLCD.CursorToXY(0,0);
  GLCD.SelectFont(System5x7); // switch to fixed width system font 
  GLCD.SetTextMode(SCROLL_UP);

  for (int x = 0; x < lcdText.length(); x++)
  {
  delay(50);
  GLCD.print(lcdText.substring(x,x+1));

  }
  break;

}
p=' ';
emailButtonState = digitalRead(12);
if (emailButtonState == HIGH && unreadFlag == 1){
  beep(1);
  unreadOff();
  emailAlertOf();
 
}
if (emailButtonState == HIGH){
   serialWrite('e'); //Instructs python script to open email program
   delay(2000);
}



}

void unreadOn(){
 if (unreadFlag == 0){
 digitalWrite(8,HIGH); 
 flashBeep(2);
 unreadFlag = 1;
 }
 else{
  flashBeep(1);
 }
 
}

void unreadOff(){
 digitalWrite(8,LOW);
 unreadFlag = 0;
}

int flashLED(int pin, int times){
  for (int a=0;a<times;a++){
  digitalWrite(pin,HIGH);
  delay(250);
  digitalWrite(pin,LOW);
  delay(250);
  }  
}


int beep(int times){
for (int a=0;a<times;a++){
 digitalWrite(11, HIGH);
 delay(250); 
 digitalWrite(11,LOW);
 delay(250);
}
}

int flashBeep(int times){
for (int a=0;a<times;a++){
 digitalWrite(9, HIGH);
 digitalWrite(11,HIGH);
 delay(250); 
 digitalWrite(9,LOW);
 digitalWrite(11,LOW);
 delay(250);
}
}

char serialWrite(char data){
 Serial.write(data);
}

void emailAlertOn()
{
 digitalWrite(13,HIGH);
 flashBeep(3); 
}

void emailAlertOf()
{
 digitalWrite(13,LOW); 
}

I still not understanding what you you seeing/experiencing or expecting. I don't understand what you mean by: "Any text larger than the display limit for the LCD is not scrolled, the LCD simply clears the screen and starts again from the top".

Text areas simply display characters at the next available location inside the text area and if there is not room on a line, the line is wrapped within the text area. If there is not room to wrap, the entire text area is scrolled to make room for the new line. The direction of wrap and scroll is determined by the scroll mode. One thing to keep in mind is that since there is no other buffering or memory for text or graphics anywhere else other than the glcd display memory itself, once text is scrolled off the text area that text is gone & lost forever.

Likewise, because there is no other memory other than the glcd display memory itself, All the text areas and the graphic area of the display share the same memory. So if you do a ClearScreen() the entire glcd display is cleared and so all the text inside all text areas will also be cleared. If you create a text area that is smaller than the full display you can clear that text area using ClearArea() and only that portion of the display will be cleared and the other portions of the display will be untouched.

I took your exact sketch and ran it on my Teensy++ board. (I had to remove your digitalWrite() and pinMode() calls as they conflicted with the Teensy glcd pins)

When I sent a very long string from the serial monitor starting with a 't', it worked as expected. The text printed slowly, wrapped and when it reached the right edge of the text area it started to scroll the text up as needed.

The serial buffering in the serial code varies depending on which AVR processor you have. Some get 128 bytes and some get only 32 bytes. I don't know how much text data you are sending and what the inter character timing is. Keep in mind that if you send more than 100 characters, you may have issues as you only wait 100 ms after receiving the 't'. And if you send more than 128 characters the additional characters will be lost as the buffer will overflow while you are waiting.

A few other comments: ClearScreen() really isn't for text areas. It clears the entire display. ClearArea() is for text areas. (When using the default text area in GLCD, since it is the full display, it is a bit difficult to them apart) ClearArea() will home the cursor when the area is cleared. ClearScreen() will not alter the text location because it is not tied to a text area. There is no need to select the font and set the sroll direction over and over again. Once you set those, they will be remembered until you change them.

See the included html documentation for the full list of functions available for text areas and information on how they work. Text areas use the gText class funtions.

--- bill

The only way I can describe the symptom is that text starts from the top left of the display and fills all the way down to the bottom. If there is more text to come, I would expect the top line to be removed and all other lines move up one line to fill it's place and new text appear on the now empty bottom line.

Instead, when the text fills the screen down to the bottom right hand corner, the display clears it's self and the remaining text starts to be printed from the top left of the screen again.

I have tried to make a bit of graphic example below (LCD is bigger than this of course).

Imagine I am sending this text to the LCD "This is some text that I have written to show what I have tried to put in words above. A picture is better than words."

Here is what I would expect screen 1 |-----------------------------------| |This is some text that I have | |written to show what i have | |tried to put in words above | |-----------------------------------| screen 2 |-----------------------------------| |written to show what i have | |tried to put in words above | |A picture is better than words | |-----------------------------------|

Here is what I actually get

screen 1 |-----------------------------------| |This is some text that I have | |written to show what i have | |tried to put in words above | |-----------------------------------| screen 2 |-----------------------------------| |A picture is better than words | | | | | |-----------------------------------|

Hope this makes it clearer what the problem is. As you can imagine, it makes it much harder to read the message when all the relevant text on previous lines (especially if it is mid sentence) has been removed.

Thanks Simon

OK, I seem to have sorted it. I was not defining a text area. I assumed that by not defining an area, the GLCD would use the full area as the default text area. Once I defined

gText  textTop = gText(textAreaFULL);

and pre-pended all my other calls such as print with textTop I found the scrolling now works

Thanks Simon

I think I understand what you were seeing. I'm not convinced yet that using a separate text area solved the problem. (Post note: I believe it is a sketch problem - see below)

There is no reason for a user declared gText object to work any different than the gText area inside the GLCD object. A user defined text area will work exactly the same as the GLCD object.

Sounds like you have changed multiple things at once, which is not good practice when trying to debug or track down an issue.

I'm not sure what you mean by:

pre-pended all my other calls such as print with textTop

The library code does not have anything inside it that works by clearing the screen instead of scrolling. So something abnormal/unexpected is going on.

The GLCD object contains a gText object inside it. The internal gText object is initialized to be the full display during the Init() function. The when using the GLCD object for printing the text area (that covers the full display) will behave as you expected. It wraps, if not enough room it scrolls all the other lines, it erases the line that will contain the text after the wrap, and then it draws the character that wouldn't fit prior to the wrap.

I ran the sketch you posted earlier and it wrapped and scrolled as expected. I don't know what AVR you are using but I used a AT90USB1286 (teensy++ board) which has built in real USB support so unread virtual serial port data is buffered inside the AVR chip. This actually was a bit misleading. A real Arduino board or clone which uses an FTDI chip or the newer Uno Arduino designs will send data much slower (9600 baud as your sketch requested) and potentially lose any unread serial port data if the serial RX buffer overflows.

Since I didn't know what messages you were sending over the serial port or how long they were I couldn't totally replicate what you were doing.

The only way the display can be cleared and the text position homed, is if either the sketch code did it itself, or perhaps the processor is crashing and starting over due to a coding error (perhaps in a library) or memory corruption.

My guess at this point is that you are getting some unexpected behaviors from your sketch.

There are some things to consider with the sketch code you have. (Or at least the code that was posted a few entries back)

For example. After you receive a 't', you wait 100 ms before starting to build your String object. So that means if you are using a real serial port on the AVR at 9600 baud, I will never "see" more than 100 characters a time (it may be less depending on start & stop bits and which AVR chip you have) Additional characters may be buffered in the serial RX buffer, but this 't' command won't see it because it only waited 100 ms. Also, each time you "detect" a string by seeing a 't' command, you build the String object up and then clear the entire glcd display, and set the text position to (0,0), and re-select the system font before you output the text. So each time you receive a 't' command, you clear the screen and home the cursor. The problem with this is that when the text area is the entire display using the system font, the display will be 21x8 characters. That is more than 100 characters.

So with your code, using a real serial port on the AVR at 9600 baud, there really is no way that you can send enough characters to fill the screen and scroll. It worked for me because I'm not using a real serial port, the AVR chip I used has built in real USB support so my characters come in USB packets at USB speeds. "As is" when using a real serial port on the AVR at 9600 baud, you will end up clearing the display every 100 hundred characters or less.

Also, if you send the AVR more than 100 characters, since the code won't see more than 100 characters, the remaining characters are then interpreted as further commands. If you happen to see another 't' in the data stream, you will clear the screen and then print the remaining characters after waiting 100ms.

You also have to keep in mind that the RX serial buffer is a maximum of 128 characters. So if you send more than 128 characters you run the risk that some might be lost depending on the timing of your the String object building code (which drains the RX buffer). It will depend on the baud rate you use vs the delay you are waiting, how many characters you send and the speed at which they are displayed on the GLCD.

POST NOTE: Assuming you are using a real serial port on the AVR, it is definitely your sketch. I just ran your sketch on a Mega328 AVR which uses a real serial port and used a FTDI USB to TTL converter (this will be like official Arduino boards) and it does not work properly. If you send it more than about 100 characters, things go wonky and you don't get the scroll. This is caused by the issues noted above.

So you definitely have a sketch logic problem. You will have to figure out how you want to handle sending "large-ish" text data. As is, the sketch clears the display on each 't' command and a 't' command cannot receive more than 100 characters.

There are many ways to handle this, but if it were up to me, I wouldn't try to buffer entire text messages.

--- bill

bperrybap: Simon, I have updated the glcd library to support the Arduino String class in Printf(), StringWidth(), and Puts() and have created a new RC release for the library.

So if you go grab the RC2 release, it should now work as you wanted it to.

--- bill

Bill, where do I find the RC2 release? I am running version 22 at the moment and it doesn't work with that.

I've been out of town. Did you resolve this? The glcd v3 RC2 library release can be found on google code: http://code.google.com/p/glcd-arduino/downloads/list

--- bill