problem displaying floating point number with 'LCD3wire'

Hi All, I hope you can help me with something. please forgive me if I don't explain things very well, I'm very much an arduino newbie. I am using Arduino 0022

I have a project that reads three temperature sensors ( ds18b20) and among other things displays the temperatures on a 20x4 LCD.

I was using the liquidcrystal.h library and all was working well. I then decided to use LCD3wire.h library with a shift register to free up some pins. I eventually figured out the LCD addressing ( third row being lcd.cursorTo(1,20); etc)

The problem I have is that I can't get the temperatures to display on the LCD. stored as Float point numbers eg. (T1). I can serial print fine so I know they are working.

Making a few changes from liquidcrystal.h I thought this should work.

lcd.cursorTo(2,0); lcd.printIn("Collection :"); lcd.print(T1);

hope you can point me in the right direction.

Cheers

C++ has the concept of overloaded functions, and presumably liquidcrystal.h defines an overloaded function which takes a floating point type, and prints out the number. It sounds like LCD3wire.h doesn’t have such a function.

If your floating point values are not very large or very small, you can do something like:

void print_float (double T1)
{
    double T1_pos = (T1 < 0) ? -T1 : T1; 
    int T1_int = (int) T1_pos;
    int T1_frac = (int) (100.0 * (T1_pos - (double)T1_int));
    int i;

    if (T1 < 0) {
       lcd.print ("-");

    lcd.print (T1_int);
    lcd.print (".");
    for (i = 100; i > 0; i /= 10) {
        int digit = T1_frac % i;
        lcd.print (digit);
        T1_frac -= digit * i;
    }
}

HI Michael, thanks for taking the time to try and find a solution.

the values I'm working with are between about 20.00 and 100.00

I have to admit I don't really understand your code :) but I have tried it on my project and unfortunately with no change.

I'm thinking I may try a different 3 wire LCD library. and upgrade to IDE 1.0

watertrade: HI Michael, thanks for taking the time to try and find a solution.

the values I'm working with are between about 20.00 and 100.00

I have to admit I don't really understand your code :) but I have tried it on my project and unfortunately with no change.

Being a compiler developer and language lawyer, I tend to be a little high level, in terms of programming.

If you can switch libraries to one with floating point support, that would probably be simplest.

If you just need the integer part and don't need the fractional part, then you can do:

lcd.print ((int) T1);

What this does is convert T1 from floating point to integer.

The other parts of my code was to print the fractional part.

Do you really need to be calculating in floating point? Since the ATmega is an 8 bit processor, with no floating point, each floating point operation probably takes thousands of instructions, and the floating point emulation routines do take up a lot of space in your flash memory. If you need to do calculations in floating point, you need to, but the ATmega isn't an optimal processor for such calculations.

As an aside, I got a DFRobot lcd shield and it uses either liquid crystal or a LCD4bit_mod library, and the LCD4bit_mod isn't as polished as the liquid crystal library. It may be the same thing for the LCD3wire library.

Making a few changes from liquidcrystal.h I thought this should work.

lcd.cursorTo(2,0); lcd.printIn("Collection :"); lcd.print(T1);

hope you can point me in the right direction.

I'm not sure if these points are relative to your problem or not, but here they are anyway!

(1) The regular LiquidCrystal library does not include println as one of it's functions. The code still compiles because println is legitimate further down the food chain but LiquidCrystal does not handle the result the way you might expect. I do not know about LCD3wire.

(2) When you display this code:

cd.cursorTo(2,0); lcd.printIn("Collection :"); lcd.print(T1);

in a 'Code' box, like this ...

cd.cursorTo(2,0); 
lcd.printIn("Collection :");
lcd.print(T1);

... it is easier to see that you are not even invoking the 'print line' function as I think you had intended.

Don

floresta: (1) The regular LiquidCrystal library does not include println as one of it's functions. The code still compiles because println is legitimate further down the food chain but LiquidCrystal does not handle the result the way you might expect. I do not know about LCD3wire.

While the lcd libraries don't actually implement the functions like println() and print(), technically they do "include" println() print() etc.. by inheriting the Print class which is where the code for those functions is implemented.

It is the Print class that actually implements the "print" code.

But from an API perspective, the sketch can't tell the difference where the code is actually implemented.


As far as libraries go, I'm not sure which library you are using so I can't really comment as to why it isn't working. If the Print class is inherited by the lcd library then it should work.

I'd switch over to fm's library. It has much more testing and run time on it and includes support for backlight control. It should fix up your cursor addressing issues on the 20x4 lcd. https://bitbucket.org/fmalpartida/new-liquidcrystal/overview

It can easily be configured for your current 3 wire shift register hardware. Or if you want to save another pin you can re-wire things with a few extra components using the 2 wire shift register support. I included some ascii art in the SR2W class header to help with the wiring for 2 wire mode.

--- bill

But from an API perspective, the sketch can’t tell the difference where the code is actually implemented.

Bill, we have discussed this before so correct me if I am wrong about the following:

When println is ultimately implemented the compiler tacks the ASCII codes for ‘carriage return’ and a ‘line feed’ (I’m not sure of the order) on to the end of the string. These codes are 0x0D and 0x0A and will be interpreted as expected by many devices but not by the LCD Controller chip. When the LCD Controller is sent one of these codes that code will be interpreted as an address in the CGROM and the character stored at the corresponding address will be displayed on the LCD screen. Address 0x0D is a foldback (extra) address for 0x05 and 0x0A is a foldback address for 0x02. These are both addresses in the area for the eight custom characters that you can create. I am not sure what information is present at those addresses by default but it is not documented and therefore it may not even be the same between different manufacturers of the chip or between different runs by the same manufacturer.

The net result is that the compiled output of the println function is not interpreted as expected by the LCD controller and that is most likely why it is not included in the documentation for the library.

If the Print class is inherited by the lcd library then it should work.

If my assumption about the tacking on of a pair above is correct then I don’t think that this statement is correct as it applies to println.

Don

Don,
Yes, end of line character processing is an issue when using nearly all the Arduino LCD libraries.
(I have seen newline character processing implemented in 1 LCD library)

But in general there is no single correct answer as to how to handle new line processing
as sometimes you want new line processing and some times you don’t.
That is why most real systems have tty disciplines that can be set by the
application so it can control whether or not new line processing is wanted.

I think I was a bit unclear by what watertrade meant by

I can’t get the temperatures to display on the LCD

I assumed he meant exactly what he said: He didn’t see any of the temperature digits.
With the small example provided, I would have thought that the temperature should have printed but then be followed by two
unpredictable characters after the final digit of the temperature because of using println() vs print().
Not seeing any of the the temperature digits
is a different problem than getting extra garbage characters on the end of the temperature.
But then many things about the issue are still unclear including which library is being used.
Maybe one of the LCD3wire libraries referenced here: http://www.arduino.cc/playground/Code/LCD3wires ???

The compiler doesn’t play a role in this. It is all up to the libraries and/or the device receiving the character data.
The Print class sends and characters to the underlying library whenever println() is called.

println(xxx);

is implemented as:

print(xxx);
println();

In the case of the serial port, if your terminal monitoring “device” processes end of line characters
(which the Arduino serial monitor does), the and characters are interpreted by the terminal
monitor and do what is expected (wrap, and drop the next line or scroll when necessary).

In the case of an LCD, like you said, the LCD does not interpret and as end of line characters
but rather as printable characters that map into the custom characters.
While it it possible to implement end of line processing for and characters in the LCD library,
out of more than a dozen Arduino LCD libraries I’ve seen, only one has implemented newline processing
to provide wrapping (but no scrolling) capability.

So yes, I do agree that println() shouldn’t really be used when using a LCD as it won’t do what is expected since
neither the LCD or the LCD library are processing the end of line characters.


watertrade,
what is needed to really comment on how to resolve your issue is all the information needed to replicate the issue.

  • a full description of what you are seeing vs what you expected to see
  • a pointer to the exact library you are using
    (This is very important as there are many SR libraries out there that have issues)
  • example sketch that demonstrates the issue

Anything less, and we are all guessing about what is happening and how to solve it.


Taking another guess, from looking at 2 different versions of LCD3wire on the link referenced above, both have issues.
The early one doesn’t support the Print class so print() won’t work as expected.
Both the early one and the more recent one will have issues with cursor positioning on certain
lcd geometries.
And neither will work with Arduino 1.x
I’d recommend switching to fm’s library as it doesn’t have these issues
and works with pre or post 1.x Arduino.

— bill

So yes, I do agree that println() shouldn’t really be used when using a LCD as it won’t do what is expected since
neither the LCD or the LCD library are processing the end of line characters.

Agreed:
(1) The LCD controller does not handle or as expected.
(2) This could be handled in software but none of the libraries do so.
(3) The compiler does not issue an error message when it encounters lcd.prntln because that function is inherited from the Print class (my terminology is probably not totally accurate but I think you get the idea).

Questions:
(1) Is this a feature or a bug?
(2) Should this anomaly be mentioned in the documentation since the mere absence of the function description doesn’t seem to prevent people from trying to use it?
(3) Why didn’t the compiler barf when he used lcd.printIn?

Don

floresta:

So yes, I do agree that println() shouldn’t really be used when using a LCD as it won’t do what is expected since
neither the LCD or the LCD library are processing the end of line characters.

Agreed:

(3) The compiler does not issue an error message when it encounters lcd.prntln because that function is inherited from the Print class (my terminology is probably not totally accurate but I think you get the idea).

Questions:
(1) Is this a feature or a bug?
[/quote]
I’d call it a limitation. The real problem is that the wimpy Arduino environment didn’t deal with line disciplines
so there is no way to properly handle the new line characters for all situations.
Sometimes the application may want new line processing (when using println()) and sometimes not, like if you really
want to print the character stored at location 0xa or 0xd in the font. - This is true with the glcd library that I support
In my case I decided to always support newline processing. A potential issue in glcd is now you can never
print the character represented by 0xa or 0xd in the font.

Smart OS’s like Unix figured this out decades ago and provided a way to have “cooked” mode (where you support line disciplines)
and “raw” where everything goes straight through.
The Arduino environment doesn’t have this capability.

(2) Should this anomaly be mentioned in the documentation since the mere absence of the function description doesn’t seem to prevent people from trying to use it?

Perhaps it is worth a mention in the LiquidCrystal library since it is limitation / “bug” in the LiquidCrystal library.
LiquidCrystal pulls in the Print Class API and functionality but does not really support all of it.
While it never says println() is actually supported, it might be useful to mention in the LiquidCrystal library documentation
that while the library uses the Print class it does not support the println() function since people do occasionally call it.
(I’d simplify it down to saying that because the LCD does not support line wrapping and scrolling
that println() is not supported for the LCD)

(3) Why didn’t the compiler barf when he used lcd.print

Because it is not a compiler error. The code is syntacticly correct. This is an implementation/functional error.
The compiler has no way of knowing that the Print class defined some functionality that LiquidCrystal pulled in
but does have the necessary code to properly support.
It is kind of like writing an infinite loop. The code is correct code, it just doesn’t do anything useful
or at least not what was intended.
The problem in this case is the Print class API definition & interface is too weak.
The way it is defined, the lower level can’t tell
when a user is sending down and from a println() call or is intentionally explicitly sending them down
using a write() call.

— bill

A potential issue in glcd is now you can never print the character represented by 0xa or 0xd in the font.

That is not a limitation in the case of the HD44780 controllers since these are foldback addresses. The accepted method to deal with foldback memory is to use the lowest address that works and this is how it is documented for the HD44780 controller.

(I'd simplify it down to saying that because the LCD does not support line wrapping and scrolling that println() is not supported for the LCD)

I agree with some minor editing. You should refer to the 'LCD controller' not just the LCD. You should also avoid the word 'scrolling' since they have already misused that term to refer to the horizontal 'shifting' that the controller does inherently support. You might get away with using the term 'vertical scrolling'.

(3) Why didn't the compiler barf when he used lcd.print

That's not what I asked. I asked about lcd.printIn. The next to last letter is a capital 'I' as in INPUT.

Don

floresta:

(3) Why didn't the compiler barf when he used lcd.print

That's not what I asked. I asked about lcd.printIn. The next to last letter is a capital 'I' as in INPUT.

Don

Good question. I think my 50 yo eyes missed that. On the font used on my terminal it is only a single pixel difference in height between capital I - as in INPUT and lower case l as in lower.

If it was an eye instead of an ell then that would cause a compiler error. My guess is typo in the original post.

--- bill

floresta:

A potential issue in glcd is now you can never print the character represented by 0xa or 0xd in the font.

That is not a limitation in the case of the HD44780 controllers since these are foldback addresses. The accepted method to deal with foldback memory is to use the lowest address that works and this is how it is documented for the HD44780 controller.

Nice. So since an application should never be sending or to the hd44780 display since there really
isn’t a valid glyph at those locations, I guess the LCD library could choose to always support and as end of line characters
with no loss of functionality.

This is not the case for a GLCD where all character values potentially have a glyph.
With the cp437 font you lose an inverted “cross” for and 1/4 note musical symbol for

bperrybap: Good question. I think my 50 yo eyes missed that. On the font used on my terminal it is only a single pixel difference in height between capital I - as in INPUT and lower case l as in lower.

I believe the original version of the LCD3wire (and LCD4Bit_mod library that I downloaded) used print to print a character array, and printIn to print an integer. It did not have the overloading that the versions based off of the Print base class have, and so you wouldn't be able to print a floating point number. LCD3wire was rewritten with version 1.0 of the Arduino software came out to use Print, and you would be able to use print to print just about anything, and println to print anything and go to the next line.

bperrybap: Good question. I think my 50 yo eyes missed that. On the font used on my terminal it is only a single pixel difference in height between capital I - as in INPUT and lower case l as in lower.

I believe the original version of the LCD3wire (and LCD4Bit_mod library that I downloaded) used print to print a character array, and printIn to print an integer. It did not have the overloading that the versions based off of the Print base class have, and so you wouldn't be able to print a floating point number. LCD3wire was rewritten with version 1.0 of the Arduino software came out to use Print, and you would be able to use print to print just about anything, and println to print anything and go to the next line.

Given \n is part of the ISO C and C++ standard, the Print library really should support it if it doesn't already. Ditto for \f to clear the screen.

Hi everyone, Thanks for your replies and input.

I used float instead of int as I would wanted to make the most of the accuracy of the ds18b20. For my project 1 degree (C )change could make a difference. I didn’t realise it was so memory heavy!

This is going to sound crazy but I tried to find the source of the 3LCDwire library - and I can’t remember where I found it. But I the code I started with was example 24.3 from here. http://tronixstuff.wordpress.com/2011/01/08/tutorial-arduino-and-monochrome-lcds/

the printIn (); issue. The code from the example above uses PrintIn(); which was confusing for me as I was happily using println(); from the original liquidcrystal library. I think this has been cleared up now.

Rather than dig myself deeper into a problem I will try the fm’s new-liquidcrystal library -

I notice the shift registers used in the ‘3 wire Shift register schematic’ the shift register is 74hc595n - I am using a ’ 4094 8-bit Tri-state Shift Register Latch CMOS IC’ will this work the same? 74hc595n?

I will try and find some time to try it out tomorrow night and report back - hopefully with success ;)

Thanks again, Jim

I believe the original version of the LCD3wire (and LCD4Bit_mod library that I downloaded) used print to print a character array, and printIn to print an integer.

Why didn't you clarify the print IN versus print LN difference right after I brought it up in reply #4.

Don

This is not the case for a GLCD where all character values potentially have a glyph.
With the cp437 font you lose an inverted “cross” for and 1/4 note musical symbol for

Could you get around this limitation by using some sort of ‘escape’ sequence the way they do with most serial backpack implementations for the character mode LCDs?

Don

floresta:

This is not the case for a GLCD where all character values potentially have a glyph.
With the cp437 font you lose an inverted “cross” for and 1/4 note musical symbol for

Could you get around this limitation by using some sort of ‘escape’ sequence the way they do with most serial backpack implementations for the character mode LCDs?

Don

Kind of. But in my view it would be a bit awkward.
With the glcd library there are better ways to handle it that i’m looking at going forward.
Since glcd supports text areas, and each text area has its own attribute modes,
I’ll simply extend the modes to include wrapping options and a way to disable scrolling.
If you don’t want wrapping or scrolling you can disable them and then every character prints.

In reality I don’t think it is much of a problem as in over 2 years no one has complained about
not being able to print the glyphs under \r and \n.

— bill

watertrade: I notice the shift registers used in the ‘3 wire Shift register schematic’ the shift register is 74hc595n - I am using a ’ 4094 8-bit Tri-state Shift Register Latch CMOS IC’ will this work the same? 74hc595n?

the 3 wire code in fm's library doesn't care what shift register part is used as long as it has - clock - data - latch/strobe input pins.

It also doesn't care which arduino pins control those 3 input pins or which output bits on the SR are used for which lcd function. All of that can be specified in the constructor so you can wire it up any way you want. Just make sure to match the constructor to the way you have wired it up. d,clk, and strb are arduino pin numbers all the other parameters are shift register data bit numbers.

If you happened to have used this page as a wiring guide: http://arduino.cc/playground/Code/LCD3wires

Then your 3wire constructor would be:

                 //     d,clk,strb, en,rw,rs,d4,d5,d6,d7 
LiquidCrystal_SR3W lcd(11, 10, 12,  3, 2, 1, 7, 6, 5, 4);

While you can use any shift register, I've found that the 595's seem to be cheaper and easier to find. You can get them in small quantities for 20 cents from these guys: http://www.taydaelectronics.com/catalogsearch/result/?q=74hc595

--- bill