[SOLUCIONADO] Comportamiento raro LCD16x2

Hola a tod@s,

Tengo un comportamiento raro con una pantalla LCD 16x2 conectada con I2C y controlada por la libreria LiquidCrystal_I2C.

El caso es que tengo creados 6 caracteres especiales (posición de memoria del 0 al 5), los cuales puestos en orden (3 en la linea de arriba y 3 en la de abajo) completan un icono más grande.
Si pongo este código:

lcd.clear(); //Borra el LCD
lcd.home(); //Devuelve el cursor a 0,0
lcd.write(0); lcd.write(1); lcd.write(2); //Imprime las 3 partes de arriba
lcd.setCursor(0, 1); // Pone el cursor al principo de la seguna linea del LCD
lcd.write(3); lcd.write(4); lcd.write(5); //Imprime las 3 partes de abajo

Funciona perfectamente.

Pero si pongo este:

lcd.clear(); //Borra el LCD
lcd.home(); //Devuelve el cursor a 0,0
lcd.print(F("\000\001\002"));//Imprime las 3 partes de arriba
lcd.setCursor(0, 1);// Pone el cursor al principo de la seguna linea del LCD
lcd.print(F("\003\004\005")); //Imprime las 3 partes de abajo

Sólo imprime correctamente la linea de abajo.

He probado esto:

lcd.clear();
lcd.home();
lcd.setCursor(0, 1);
lcd.print(F("Compa\356ero"));

Imprimer perfectamente la palabra "Compañero", la "ñ es el caracter 356(octal) del propio set de caracteres del LCD. Si lo imprimo en la linea de arriba del LCD sale "Compa ero".

He probado tambien a quitar la función F, poner lcd.setCursor(0,0); y varias combinaciones más. Incluso a ponerlo en una variable String, pero no, no funciona en la linea de arriba.

¿sabe alguien poque puede estar pasando esto? ¿es alguna limitación de la librería? ¿un bug?...

Ya es sólo por curiosidad porque con el primer código funciona perfectamente. La ventaja (que le veo) es que puedo mandar cadenas a una función que imprima cualquier texto, y así puedo poner el icono grande formado por los caracteres especiales junto a varios textos directamente, sin tener que hacer:

[/code]

lcd.clear();
lcd.home();
lcd.print ("Hola   ";)
lcd.write(0); lcd.write(1); lcd.write(2); //Imprime las 3 partes de arriba
lcd.setCursor(0, 1);
lcd.print(F("2018   "));
lcd.write(3); lcd.write(4); lcd.write(5); //Imprime las 3 partes de abajo

Y así hacer una funcion para cada texto que necesite o una que analice el texto y sepa donde tiene que poner el icono completo.

Muchas gracias por vuestra atención.

Hola

Muchas gracias ArduMyth por la respuesta, pero lo que hay en el video es lo que precisamente hago en el código que funciona, es decir usar lcd.write.

Como se puede ver en el video para cada una de las presentaciones tiene que hacer una función o código exclusivo. Imagina que que los textos que se tienen que presentar son (inventados):

"Tengo 18 años"
"Compañeros"
"Castañas"
"Vino añejo"
"ñoño"

Entonces hay que hacer una función para cada uno de los textos.
Pero con una única función podria presentar en cada momento el que se necesite. Por ejemplo:

...// código del porgrama
String texto;
switch case (texto)
{
case 1:
texto ="Tengo 18 a\356os";
break;
case 2:
texto ="Compa\356eros";
break;
case 3:
texto="Casta\356as";
break;
case 4:
texto="Vino a\356ejo";
break;
case 5:
texto="\356o\356o";
break;
}

imprimetexto(texto);
... //sigue código

void imprimetexto(String texto){
lcd.clear();
lcd.print (texto);
}

En este caso no hay que crear la ñ ya que viene incluida en los caracteres ROM de la LCD y sería hacer lo mismo para cualquier caracter, incluidos los que puedes crear en RAM (0 a 7). Por ejemplo se puede crear una Ñ (la ñ mayúscula no viene en los caracteres ROM) en la posición 2 y los textos se convertirian en:

void creaEgne()
{
//Código para crear la Ñ
byte egne[8]={19,12,17,25,21,19,17,0};
lcd.createChar(2,egne);
}

...
String texto;
switch case (texto)
{
case 1:
texto ="TENGO 18 A\002OS";
break;
case 2:
texto ="COMPA\002EROS";
break;
case 3:
texto="CASTA\002AS";
break;
case 4:
texto="VINO A\002EJO";
break;
case 5:
texto="\002O\002O";
break;
}

De la manera que pone el video, habria que crear cógido para imprimir cada palabra o hacer una función que detecte donde va la ñ y ponga un lcd.write(238); (aquí va el caracter en decimal 356 octal = 238 en decimal).

Bueno, los códigos que puse arriba, funcionan perfectamente.

He investigado un poco y parece ser que al colocar en un literal "\000" el compilador de c++ entiende que es un código null de fin de cadena, por lo que no continua leyendo la cadena y por eso no imprime nada (debía haber probado a ver que pasa si lo pongo en la segunda línea). Entonces no será un problema de la primera linea como pensaba.

Por lo tanto, la solución sería crear los caracteres en las posiciones 1,2,3,4,5,6 de la RAM del LCD e imprimirlas.
Ahora mismo no puedo probarlo, pero cuando llegue a casa lo probaré y comentaré los resultados.

Muchas gracias

Hola de nuevo

Probado, efectivamente no se puede poner en un literal mandado al LCD el código de escape 000 (lcd.print("\000") para que imprima el caracter especial creado en la posición 0.

He pasado los iconos a las posiciones de memoria 1,2,3,4,5 y 6, y

lcd.clear(); //Borra el LCD
lcd.home(); //Devuelve el cursor a 0,0
lcd.print(F("\001\002\003"));//Imprime las 3 partes de arriba
lcd.setCursor(0, 1);// Pone el cursor al principo de la seguna linea del LCD
lcd.print(F("\004\005\006")); //Imprime las 3 partes de abajo

Funciona perfectamente.

Sólo me queda que alguno de los gurús del C++ pueda indicar si hay algún truco para evitar este pequeño incoveniente.

Muchas gracias

Hola de nuevo,

Creo que encontré la solución.

Con lcd.createChar(8), se puede crear el octavo caracter y luego llamarlo con el código de escape "\010", y así no llamar al "\000".

Por lo tanto se pueden crear los caracteres especiales en las posiciones del 1 al 8 y luego imprimirlas con códigos de escape en un literal. Así están disponibles todas las posiciones para hacer iconos de 4x4 e imprimirlos con cadenas literales como un texto.

Muchas gracias por vuestra atención