problem with lcd.print and char variables on a QAPASS 16x2 I2C-LCD

So here is the new post.

If I print a string directly with lcd.print("somestring");, it works. But if I print a string via a variable, it displays just one character (as shown in the picture).

#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>

float temp;
bool HHein;
int tempPin = 0;
int HHeinPin = 2;
char HHeinOut;

hd44780_I2Cexp lcd;

void setup()
{
  pinMode (2, INPUT);
  lcd.begin(16,2);
  HHein = LOW;
}


void loop()
{
  temp = analogRead(tempPin);
  temp = temp * 0.02;
  //HHein = digitalRead(HHeinPin);
  HHein = LOW;

  if (HHein == HIGH){
    HHeinOut = "ein";
  }
  else {
    HHeinOut = "aus";
  }
 
  lcd.clear();
 
    lcd.setCursor (0,0);
    lcd.print("Boiler: ");
    lcd.print(temp);
    lcd.print(" C");
    lcd.setCursor (0,1);
    lcd.print("Heizung: ");
    lcd.print(HHeinOut);
     
     delay(1000);
}

The result is lcd1.jpg.

lcd2.jpg + lcd3.jpg are showing the lcd module.

If I use the LiquidCystal_I2C library, it shows a "&" with the same code.

If I use this code, it works (lcd4.jpg):

#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>

float temp;
bool HHein;
int tempPin = 0;
int HHeinPin = 2;
char HHeinOut;

hd44780_I2Cexp lcd;

void setup()
{
  pinMode (2, INPUT);
  lcd.begin(16,2);
  HHein = LOW;
}


void loop()
{
  temp = analogRead(tempPin);
  temp = temp * 0.02;
  //HHein = digitalRead(HHeinPin);
  HHein = LOW;
 
  lcd.clear();
 
    lcd.setCursor (0,0);
    lcd.print("Boiler: ");
    lcd.print(temp);
    lcd.print(" C");
    lcd.setCursor (0,1);
    lcd.print("Heizung: ");

    if (HHein == HIGH){
      lcd.print("ein");
    }
    else {
      lcd.print("aus");
    }
    
    //lcd.print(HHeinOut);
     
     delay(1000);
}

Nadine

char HHeinOut;

HHeinOut is declared as a single character. It will not hold more than 1 character. If you want it to hold a string you need to declare it as a character array with enough room for all the characters and a terminating null ('\0').

char HHeinOut[6];  // a string (null terminated character array) with room for 5 characters and a null
HHeinOut = "ein";

Also you cannot use the = to assign the value like that. Use strcpy() instead.

You have a "QAPASS 16x2 I2C-LCD", that's why it works at all; it has QUuality check PASSed.

One of the many reported in this Forum Section. :slight_smile:

david_prentice answered this in the other thread.
https://forum.arduino.cc/index.php?topic=519666.msg4332773#msg4332773

I wouldn't use the solution that groundFungus proposed.
I'd use a pointer as david recommended.

Simply correct the declaration of HHeinOut

char *HHeinOut;

This creates a type of variable that allows it to the desired string.

Did you get a warning about this?
I would recommend that you enable all compiler warnings in the IDE settings.

Alternatively, you could do it inline without variable.
Ex:

    lcd.print(HHein ? "ein" : "aus");

This will print "ein" when HHein is true otherwise "aus"

--- bill

OK, thank you all, I made several stupid mistakes.

The stupidest of all was to not enlarge the message area at the bottom of the IDE. I verified the code every time and there where no errors or warnings in the two lines visible. Only if I enlarge this section, it shows several warnings. The message bar remained green so it looked like there's no problem.

bperrybap:
Did you get a warning about this?
I would recommend that you enable all compiler warnings in the IDE settings.

The compiler warning default setting is 'none'... Changed it to 'all' now.

That was another stupid one:

groundFungus:

char HHeinOut;

HHeinOut is declared as a single character. It will not hold more than 1 character.

Got that, thank you.

bperrybap:
I'd use a pointer as david recommended.

Simply correct the declaration of HHeinOut

char *HHeinOut;

This creates a type of variable that allows it to the desired string.

I did this and it worked, but it prompts this warning:

warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

     HHeinOut = "ein";

                ^~~~~
warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

     HHeinOut = "aus";

                ^~~~~

If I change the variable to

char const *HHeinOut;

there are no warnings. It also works with

String HHeinOut;

Is it correct, that String xxx is the same as char *xxx ?

If so, I don't understand, why it should be wrong to assign a value to a string/char* with the '=':

groundFungus:

HHeinOut = "ein";

Also you cannot use the = to assign the value like that.

In the Examples - 08.Strings it's also assigned like that. Where's the mistake?

david_prentice:
You have several problems with your code.

...

bool HHein;      //true or false
...
char HHeinOut;    //should be a char*
  ...
  //HHein = digitalRead(HHeinPin);
  HHein = LOW;  //LOW happens to have the same value as false

if (HHein == HIGH){  //HIGH happens to have the same value as true
    HHeinOut = "ein";
  }
  else {
    HHeinOut = "aus";
  }
    ...
    lcd.print(HHeinOut);
    ...

I thought because it only can have the value 1 or 0 it's good to use bool (and because it works). It should be

int HHein = 0;

correct?

Nadine

If I change the variable to

char const *HHeinOut;

there are no warnings. It also works with

String HHeinOut;

Is it correct, that String xxx is the same as char *xxx ?

There will be little difference for a const char* or const String
The bytes will be stored in PROGMEM. Probably as a NUL-terminated char array. Probably without the size member. (I have not inspected the generated ASM code)

A regular char* or String implies SRAM. Which is really WASTEFUL for an anonymous constant string. Especially when most Arduino classes will accept strings from PROGMEM.

I suggest that you use const char* instead of String. Your choice depends on whether subsequent calls expect String or char*. The Arduino print() will accept both String or char*

Regarding 0 and 1 versus false or true. C++ is not very strict. C is even less strict. Java would complain.

Personally, I would have chosen:

    lcd.print(HHein ? "ein" : "aus");

David.

Edit. Please do not take the above statements as Gospel. I must check exactly what and where the Compiler handles const char* and const char PROGMEM array[ ]
Not important for your project. But matters when there is a lot of anonymous data.

david_prentice:
Personally, I would have chosen:

    lcd.print(HHein ? "ein" : "aus");

I'd have to go look at the compiler output but I think this requires using the Arduino F() macro to get it not to use RAM on the AVR for holding the string data.

i.e.

lcd.print(HHein ? F("ein") : F("aus"));

I don't use AVRs much anymore so I tend to forget about its limitations.

--- bill

Thanks for your explanation, I haven't considered the memory at all. Now I've changed it to the inline statement, but it was interesting anyway and I learned from it.

Nadine