Wierd characters on display

I have combined several example sketches for a real time clock and the result is that the LCD displays two wierd characters at the end of the lines.
I used the example sketches from several libraries, DS1302, LiquidCrystal_I2C.
What am I doing wrong here?

Here is the code:

// include the library code:
#include <stdio.h>
#include <string.h>
#include <DS1302.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
 
/* Set the appropriate digital I/O pin connections */
uint8_t CE_PIN   = 2;
uint8_t IO_PIN   = 3;
uint8_t SCLK_PIN = 11;

/* Create buffers */
char buf1[20];
char buf2[20];
char buf3[20];
//char buf4[25];
char day[10];

/* Create a DS1302 object */
DS1302 rtc(CE_PIN, IO_PIN, SCLK_PIN);

// initialize the LCD library
LiquidCrystal_I2C lcd2(0x20,20,4);  // set the LCD address of the first lcd to 0x20 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd1(0x21,16,2);  // set the LCD address of the second lcd to 0x21 for a 16 chars and 2 line display

void print_time()
{
  /* Get the current time and date from the chip */
  Time t = rtc.time();

  /* Name the day of the week */
  memset(day, 0, sizeof(day));  /* clear day buffer */
  switch (t.day) {
    case 1:
      strcpy(day, "Zo");
      break;
    case 2:
      strcpy(day, "Ma");
      break;
    case 3:
      strcpy(day, "Di");
      break;
    case 4:
      strcpy(day, "Wo");
      break;
    case 5:
      strcpy(day, "Do");
      break;
    case 6:
      strcpy(day, "Vr");
      break;
    case 7:
      strcpy(day, "Za");
      break;
  }

  /* Format the time and date and insert into the temporary buffer */
  snprintf(buf1, sizeof(buf1), "%s %02d-%02d-%04d   ",
            day,
            t.date, t.mon, t.yr);
  snprintf(buf2, sizeof(buf2), "%02d:%02d:%02d        ",
           t.hr, t.min, t.sec);

  /* Print the formatted string to LCD so we can see the time */
  lcd1.clear();
//  lcd1.setCursor(5, 0);
  lcd1.println(buf1);
  lcd1.setCursor(0, 1);
  lcd1.println(buf2);
//  lcd1.setCursor(4, 2);
//  lcd1.println(buf3);
}

void setup() {
  lcd1.init();                      // initialize the first lcd 
  lcd2.init();                      // initialize the second lcd 
 
  // Print a message on the first LCD.
  lcd1.backlight();
  lcd1.print("Hello, #1 world!");
 
  // Print a message on the second LCD.
  lcd2.backlight();
  lcd2.setCursor(0, 0);
  lcd2.print("Hello, #2 world!");
  delay(1000);
}

void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd1.setCursor(0, 0);
//  // print the number of seconds since reset:
//  lcd.print(millis()/1000);
  print_time();
  delay(1000);

}

Please post code with the code block:

Search and replacing all your println with print in your code.

Thanks, that did the trick.

But can someone explain me the difference between print and println?

dwattel:
Thanks, that did the trick.

But can someone explain me the difference between print and println?

"print" just sends what it's told to send. "println" sends the content, plus a newline (i.e. CR/LF).

To clarify, if you are sending the string "123" to an LCD, "print" (or "write") will send, in hex:

31, 32, 33

If you use "println", it sends this:

31, 32, 33, 0D, 0A

The last two characters make a serial terminal move to the next new line, but to an LCD, they are just gibberish.

Make sense?

If you do println on serial port, then the next output will start on a new line in the serial monitor. Serial monitor understands those two characters. It makes reading the output so much easier. On the other hand, the LCD controller doesn't understand the new line characters so it just prints out some random stuff. If you need to start a new line on an LCD, you will have to do it with setCursor to a new line.

Another major difference between LCD and the serial monitor is serial monitor scrolls the information when there is too much to be displayed on the monitor. LCD will not. There is no scroll mechanism in either the LCD controller or the liquidcrystal library.

To implement both scroll and new line is quite time consuming. On the other hand, my phi-panels can process all that and a whole lot more like rendering menus etc. I do sell them so take my recommendation with your own discretion. I am, anyway, pretty proud of what I designed :slight_smile:

All of the above is absolutely correct when explaining the action of the LiquidCrystal library that is included with the Arduino when it is driving a 14 (or 16) pin LCD module directly through a parallel interface. That is why you will find no mention of println in the LiquidCrystal documentation.

In this case we are dealing with a serial interface and an unspecified library. The OP was unlucky in that his particular library did not intercept the 0x0D and 0x0A characters and make those codes do what he expected. The responders were lucky in that their explanation was correct for this particular library.

By the way the reason that the resulting characters are weird and possibly random is because they are accessing two of the eight available custom characters (the ones that you can create using createChar) via their 'foldback' addresses. These characters are associated with ASCII codes 0x00 - 0x07, but the same eight characters are also accessible by using 0x08 - 0x0F.

Don

Thank you all, I have learned a lot from you.

It is the first time I do any programming (besides some BASIC in the past).

Don, the liquidCrystal_I2C library came from the playground and is for the PCF8474 IO expander.

The responders were lucky in that their explanation was correct for this particular library.

If the println compiles at all, and two random characters show up with println, I am not lucky. It's inheritance.

liudr:

The responders were lucky in that their explanation was correct for this particular library.

If the println compiles at all, and two random characters show up with println, I am not lucky. It's inheritance.

I understand that 'inheritance' is what causes the standard LiquidCrystal library to display the weird characters instead of barfing when it encounters the undocumented (for that library) println. I thought that it was luck that the other libraries reacted the same way. So I have some questions: Does inheritance always work? Are there some cases where it will and others where it won't?

Don

Don,

There used to be no such thing as LCD.println before Arduino 1.0 (or around that version). In Arduino 1.0 (or around that version), the LiquidCrystal library was modified with this line:

class LiquidCrystal : public Print

This essentially makes LiquidCrystal object inherit Print class, which has all the print and println with different types of arguments (byte, int, char, char * etc.).

LiquidCrystal class thus no longer implements print or println and just implements write, the writing single byte to LCD. The print and println are implemented in the parent class, the Print. They are very simple implementations where write is called repeatedly until all that needs to be printed is sent out byte per byte with write.

The newer libraries with I2C LCDs probably just takes the Arduino 1.0 LiquidCrystal library and rewrites the begin and write4bytes etc. methods and keep the rest unchanged, slap on a new library name. I don't think the I2C library writers are all eager beavers to write out their println method to OVERRIDE the parent ones. The mere fact that println works and with 2 strange characters covers maybe 90% of the logic leading to my conclusion, not 100%.

There used to be no such thing as LCD.println before Arduino 1.0 (or around that version).

Well there still is 'no such thing' if you look at the documentation for the LiquidCrystal library.

So if I understand correctly, in older Arduini IDE versions the use of LCD.println would have resulted in an error of some kind but now there is none since there really is no error, just some unusual behavior due to the characteristics of the LCD controller that I explained in reply #5.

By not mentioning println in the LiquidCrystal documentation the powers that be are essentially absolving themselves of responsibility for this strange (to the uninitiated) behavior. It seems to me that it would be more responsible to mention why println was omitted from the documentation.

Don

floresta:

There used to be no such thing as LCD.println before Arduino 1.0 (or around that version).

Well there still is 'no such thing' if you look at the documentation for the LiquidCrystal library.

So if I understand correctly, in older Arduini IDE versions the use of LCD.println would have resulted in an error of some kind but now there is none since there really is no error, just some unusual behavior due to the characteristics of the LCD controller that I explained in reply #5.

By not mentioning println in the LiquidCrystal documentation the powers that be are essentially absolving themselves of responsibility for this strange (to the uninitiated) behavior. It seems to me that it would be more responsible to mention why println was omitted from the documentation.

Don

Right, undocumented but exists through inheritance. The potential problem of inheritance is showing its color here with LCD lib. You make a bunch of these functions in your base class and your child class inherits these functions but not all are working with the child class. The base class does nothing special other than printing 0D and 0A, assuming the receiving device understands it. But the child class hardware (LCD) is not exactly a super set of the base class hardware (computer serial monitor). A child should have all base plus extra but this case it is not. The base class should probably declare println as virtual so a child class has to define it to use it. We have a bunch of newbies that don't know these subtleties and think they can use println anywhere it won't complain. In an extreme case, say a base class defines .kill_self() and the child class commits suicide with .kill_self() but finds the method doesn't really apply to the child due to different hardware, maybe the child is a cylon and inherits from human parents, the child may become zombie or something LOL

liudr:
Don,

There used to be no such thing as LCD.println before Arduino 1.0 (or around that version). In Arduino 1.0 (or around that version), the LiquidCrystal library was modified with this line:

class LiquidCrystal : public Print

This is incorrect. I just went back and looked. The LiquidCrystal library was added in IDE 0012 (Sept of 2008)
and from its very beginning until today's 1.0.1,
the Print class was always inherited. (I just looked at every single IDE release since 0012)

The issue is that the LiquidCrystal library inherited the Print class but failed to implement everything that the
Print class supports and can attempt to use. As a result, things like lcd.println() don't provide the expected/desired behavior.

Don, with C++ inheritance, if you choose to inherit a class ALL the public
functions and members in that class get dragged in.
Think of it like pulling in a gigantic set of Assembler macros.

The way the Print class works, the layer below it really does not know anything about println() or that
println() is being called by the sketch. The lower layer, LiquidCrystal in this case, only sees calls to write()
as that is the interface between Print and LiquidCrystal.
Print implements println() and then converts it to a series of write() calls.
So from LiquidCrystal's point of view, it cannot tell the difference between a sketch doing:

lcd.println("hello");

and

lcd.write('h');
lcd.write('e');
lcd.write('l');
lcd.write('l');
lcd.write('o');
lcd.write('\r');
lcd.write('\n');

Because in both cases LiquidCrystal only sees the calls to write().

Rather than write the needed code in LiquidCrystal to fully support all the inherited functions in the Print class,
(which meant writing code to handle newline processing and line wrapping)
the developers took the easy way out and chose to simply say that println() isn't supported.
They also took a short cut by simply not documenting println().
What they should have done instead is to explicitly document that LiquidCrystal supports all the functions in the Print class (with a reference to the Print class documentation) but, state that println() is not implemented in LiquidCrystal and therefore
is not supported and if used will create undesired results.

When they chose to not write the additional code to support println() (new line processing), they could have added
a tiny amount of code to swallow the and characters to at least avoid the junk characters
but then there would never be a way to send 0x0d and 0x0a to the display, which might be desirable in
some cases.

There are some Arduino hd44780 libraries out there like this one:
http://www.pjrc.com/teensy/td_libs_LiquidCrystal.html
that have the code to support newline processing and line wrapping.
When using those libraries that support newline processing, println() will work as expected.

--- bill

... but then there would never be a way to send 0x0d and 0x0a to the display, which might be desirable in
some cases.

They don't even get this as an excuse. As I said in reply #5 these two codes are included in the eight foldback addresses for the eight documented addresses used to access the 'custom characters'. The ability to use 0x0D and 0x0A will not get you any added capability.

Don

Don, with C++ inheritance, if you choose to inherit a class ALL the public

Nah. Inheritance gets you all public and protected functions from parent. But one needs to know the difference between public keyword of members and public inheritance. This case is public inheritance, a standard way to inherit. You can also inherit privately, in which case the public members become private members so they can't be accessed from outside. I hate this fact that they just can't invent words but instead use public in different places for different meanings, like public members, public static variables, public inheritance. It's madness.

IMHO, this should be done: println should instead of calling print then print(0d, 0a), call print then cursor(home), cursor(next line). This way lcd library needs to define cursor(home) to be setcursor(0,current row), and cursor(next line) as setcursor(column,current row+1). Since lcd library is not making use of cursor position, it can't be implemented. Then serial can define cursor(home) as write(od) etc.

liudr:
IMHO, this should be done: println should instead of calling print then print(0d, 0a), call print then cursor(home), cursor(next line). This way lcd library needs to define cursor(home) to be setcursor(0,current row), and cursor(next line) as setcursor(column,current row+1). Since lcd library is not making use of cursor position, it can't be implemented. Then serial can define cursor(home) as write(od) etc.

It is an interesting idea/concept, but newline processing isn't that simple.
For example, there is also how to handle the display and cursor position
when the characters hit the edge of the line on the display (right side, when using a left to right orientation)
before a newline is sent.
Things like do you wrap and drop down a line when the edge is reached on a line or do you wrap to the beginning
of the same line or do you start dropping the characters.
Then there is what to do on the bottom line. Do you wrap back to the top line or start dropping characters or
do you scroll the existing text on the display and then wrap back to column 0 and erase any characters on the line.
In order to scroll the text up/down on a device like a hd44780,
you have to have a shadow buffer of all the characters on the display and re-write the data "scrolled"
to the display.

In the grand scheme of things, would support for these new cursor functions that Print could use
really be any different than simply using write(0xd) and write(0xa)?
It seems to be inventing a new way of doing the same functionality that could be handled with the existing
0xd and 0xa characters.
(other devices and libraries including other lcd & glcd libraries are handling newlines ok without the need for these new functions)

In order to handle line wrapping of long lines and scrolling I believe it would be too much of a burden
and start to get messy to have to communicate
the display dimensions to the Print class as well as have to configure it for newline, wrapping, and scrolling behaviors.
I think Print is ok as it is.
Print is fairly clean and simple as it lets the lower layer deal with any/all the newline, wrapping, and scrolling issues
of the device.


As a Quick & Dirty ugly but effective hack to prevent println() from being used,
the LiquidCrystal.h header file could add this line after the #include "Print.h"

#define println println_IS_NOT_SUPPORTED

While, it will create a little bit of a strange compiler error about the redefined function
not existing in the LiquidCrystal class, it will prevent the code from compiling.
Depending on the sketch code, the IDE will jump to the line with the println() showing it as an error.
(Often it positions to the wrong line because the IDE is not handling the line numbers correctly when
it converts the .pde/.ino files to .cpp files)
(This seems to have finally been fixed in IDE 1.5)

--- bill

That's right Bill. All these new line features of line wraps are handled by the arduino serial monitor. By the way, my phi-panel serial Lcd keypad panel proudly handles all these with options you mentioned, such as scroll or back to beginning etc. You are right, all those features took a whole summer to develop, plus all the other features. I would recommend arduino serial monitor to support snail escape codes.

There's another way to look at all of this. The LiquidCrystal library is essentially tied to the HD44780 controller and it's instruction set. The displays that are driven by this type of controller are intended to display short messages, typically the status of a device such as a printer. They are not designed to be used as a computer terminal, that is, to display large amounts of text on multiple lines. I'm not saying that no one uses them this way, but it's not what they were intended to do.

I feel that perhaps the LiquidCrystal library itself should be limited to implementing the HD44780 instruction set, one for one, with no embellishments. There could be a separate library or libraries designed handle other cases such as terminal emulation and similar yet different controllers such as those used by New Haven Displays.

There can be limitations imposed by the addition of some of these features to the basic instruction set. For example, the implementation of automatic line wrapping at the end of a line on a 16x2 or 20x2 character wide display means that you can't easily take advantage of storing a long string that includes the 'hidden' character locations for later display by means of shifting.

Don