LCD 16x2 e PCF8574

Volevo visualizzare un simbolo della batteria su un LCD 16x2 in i2C con interfaccia PCF8574, ma mi esce un simbolo strano, non quello che dovrebbe visualizzare.
Il simbolo l'ho creato con il programma "Custom Character Generator".
Lo sketch è il seguente:

#include <Wire.h>
#include <PCF8574_HD44780_I2C.h>

PCF8574_HD44780_I2C lcd(0x27,16,2);

byte batteria[8] = {
  0b00100,
  0b01110,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111
  };

void setup() {
  lcd.createChar(0, batteria);
  lcd.init();
  lcd.home();
  lcd.setBacklight(1);
  lcd.write((uint8_t)0);
  }

void loop(){

  }

Dove sbaglio.

LelloGi

Non vedo cose strane, anche se io uso la LuquidCrystal_I2C non questa.

Prova a fare così (ti ho modificato qualcosina), se non dovesse andare fai una foto (mi raccomando, non sfocata.. ;)) al display per capire cosa intendi con "simbolo strano" e postala qui come allegato così vediamo:

#include <Wire.h>
#include <PCF8574_HD44780_I2C.h>

PCF8574_HD44780_I2C lcd(0x27,16,2);

byte bmpBatteria[8] = {
  0b00100,
  0b01110,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111
  };
// Codice del carattere da programmare
const byte batteria = 1;

void setup() {
  lcd.createChar(batteria, bmpBatteria);
  lcd.init();
  lcd.home();
  lcd.setBacklight(1);
  lcd.write(batteria);
  }

void loop(){

  }

Ho caricato il nuovo sketch ma non è cambiato niente.
Ho allegato la foto del display.
Saluti

LelloGi

>LelloGi: ... porto la tua attenzione su QUESTA mia segnalazione. Per questa volta ho modificato io il post, ma, cortesemente, in futuro, tienne conto. Grazie mille per la collaborazione :slight_smile:

Guglielmo

lcd.write((uint8_t)0);
Non dovrebbe essere:

byte batteria[8] =
{
  0b00100,
  0b01110,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111
};

void setup()
{
  lcd.createChar(0, batteria);
  lcd.write(byte(0));
}

?
L'errore sta in:

lcd.write(uint8_t(0));

Ehhhhh ? ? ? :o :o :o

I cast si fanno mettendo il tipo tra parentesi e la variabile dopo ... lcd.write( (uint8_t) 0 ); ... anche se non ne capisco il senso ... a che servirebbe quel cast ? ? ?

Guglielmo

Infatti non è un cast e probabilmente questa è l'unica forma corretta...

lcd.write(byte(0));

Ma anche NO ... "byte" è un tipo dato ed è una parola riservata !!!

Se deve stampare il carattere memorizzato in locazione 0, deve solo mettere lcd.write( 0 ); ...
... che senso ha scrivere byte(0) ? ? ? :o

Guglielmo

P.S.: ... e magari studiatevli gli esempi delle librerie ... "CustomChars.ino" fa vedere esattamente come si usano i caratteri custom ... :wink:

"byte" è un tipo dato ed è una parola riservata !!!

Però Arduino fornisce anche una funzione (probabilmente una macro) con quel nome, tanto per aggiungere confusione...
Quindi la sintassi byte(x) è lecita.

Ciao, Ale

Qui dice che per il carattere 0 va fatto proprio il cast:

Sono le complicazioni di Arduino... :frowning:

ilguargua:
Quindi la sintassi byte(x) è lecita.

... lecita magari è lecita ... ma è anche del tutto inutile !!! :smiley:

Tra l'altro, come ho avuto già modo di dire, il tipo "byte" è un'invenzione di Arduino ed è semplicemente una typedef che si trova in Arduino.h ...

typedef uint8_t byte;

Guglielmo

Datman:
Qui dice che per il carattere 0 va fatto proprio il cast

... guarda che nelle pagine di spiegazioni di Arduino NON mancano gli errori e le imprecisioni (... e non è la prima volta che si riscontrano) ... invece che tali pagine, come già detto, andatevi a studiare i sorgenti e gli esempi della libreria ... di cast (che comunque NON è quello) non se ne parla proprio, quindi, come detto, la sintassi esatta è lcd.write( 0 );

Estratto dall'esempio che citavo sopra (CustomChars.ino):

...
lcd.print("Hello world...");
lcd.setCursor(0, 1);
lcd.print(" i ");
lcd.write(3); // <<<<<<<<<<<<< vedere qui
lcd.print(" arduinos!");
...

Guglielmo

gpb01:
... lecita magari è lecita ...

... ho fatto un po' di verifiche ... gcc >= 4.6.3 accetta la forma di cast con le parentesi al contrario, ovvero, il tipo senza parentesi e la variabile tra parentesi ... quindi "(int) a" si può scrivere anche "int (a)" (orrore * ) ... detto questo, l'ingannevole riferimento, nel reference, al byte() come fosse una funzione è, in realtà, esattamente un casting che, dato il typedef di cui sopra, sigifica semplicemente un cast con uint8_t , ovvero ...

(uint8_t) variabile <--> uint8_t (variabile) <--> (byte) variabile <--> byte (variabile)

Gira che ti rigira ... sempre di un cast parliamo che, nel caso specifico, è del tutto inutile visto che la "LiquidCrystal_I2C::write(uint8_t value)" comunque accetta solo un uint8_t :slight_smile:

Guglielmo

* : ho messo "orrore" perché NON è conforme al K&R che definische il cast come: "A unary expression preceded by the parenthesized name of a type causes conversion of the value of the expression to the named type" :wink:
Aggiungo che, in oltre 40 anni che programmo microcontrollori, NON ho mai incontrato quella forma di casting, forse perché ... per quanto possibile mi tengo alla larga dal C++ ed uso solo ANSII C :smiling_imp:

LelloGi:
Ho caricato il nuovo sketch ma non è cambiato niente.
Ho allegato la foto del display.

Quello è il classico carattere che compare quando si scrive un carattere non previsto o non stampabile.

Se hai usato esattamente lo sketch che ti ho modificato, posso solo supporre che in qualche modo il tuo LCD abbia qualche problema con la memoria degli 8 caratteri programmabili (spero di no) oppure è la libreria ad avere qualche problema.

Ma scusa una domanda: se è un normale LCD 16x2 e l'interfaccia I2C è la classica schedina, perché stai usando quella libreria invece della ottima e "standard" LiquidCrystal_I2C di Frank de Brabander?

Prova usare quella (che trovi in Gestione Librerie, cerca "liquidcrystal_i2c" e scrolla per trovare quella, versione 1.1.2), sempre sullo sketch che ti ho mandato al quale devi solo adattarlo per quella libreria, e dimmi se funziona.

Datman:
lcd.write((uint8_t)0);
Non dovrebbe essere:

Scusa, ma perché quoti quella istruzione del SUO programma iniziale ossia del primo post (dal quale ho infatti rimosso quel cast, in favore dell'uso di una variabile che evita il cast), tra l'altro facendo partire un thread su come si fa il cast in generale su Arduino, quando poi quel cast non serve? Ti prego, potresti seguire i thread e commentare proseguendo in questo caso il discorso che si faceva con l'OP, e che mostrava l'esito del test che gli ho chiesto (e che non ha nulla a che vedere con il cast)?

Datman:
Qui dice che per il carattere 0 va fatto proprio il cast:

Eh, ma la butto lì: sarà che quella pagina si riferisce magari ad una diversa libreria rispetto a quella dell'OP??? :wink: E magari, se anche fosse, usare una variabile byte come argomento evita tutti sti problemi?

ilguargua:
Però Arduino fornisce anche una funzione (probabilmente una macro) con quel nome, tanto per aggiungere confusione...
Quindi la sintassi byte(x) è lecita.

Ciao, Ale

No, mi spiace ma hai interpretato male quella info. Arduino riporta nella sezione conversion i vari casting, anche ad esempio di int e viene scritto che il casting può essere scritto int(x) oppure (int)x ma quest'ultimo è aderente allo stile C (BK)
Infatti nel core non esiste nessuna funzione byte() o int()

P.S. Guglielmo a me invece non dispiace lo stile int() perché a volte con (int)qualcosa sei poi costretto ad usare delle parentesi tonde in più per specificare meglio fino a che punto deve essere applicato il cast.
K&R a volte li picchierei. Tante cose giuste han scritto sul C ma poi quando hanno esteso al C++ hanno introdotto cose che sono "spaventevoli" quanto a bruttura e difficoltà di lettura del codice. Vedo le nuove specifiche del C++ e... veramente da mal di testa

docdoc:
Eh, ma la butto lì: sarà che quella pagina si riferisce magari ad una diversa libreria rispetto a quella dell'OP??? :wink: E magari, se anche fosse, usare una variabile byte come argomento evita tutti sti problemi?

Sinceramente dubito. Qualsiasi libreria sia, ci sarà o overloading della funzione o un cast fatto dal compilatore in automatico. Se c'e' overloading e 0 viene preso come int, chiami una write(int) che internamente poi chiama la write(byte). Parere mio.

class PCF8574_HD44780_I2C : public Print {

Ok, ma per favore, create un altro post separato dove parlare genericamente del cast in Arduino e come si usa, e lasciamo libero questo per capire e risolvere il problema dell'OP?...

int(x) ricorda la funzione matematica classica intero di x...

non è colpa di Brian e Dennis se il C++ è spaventevole

se fosse stato per loro il C sarebbe rimasto molto più "lineare"

hanno commesso i loro errori, vedasi il break; quasi obbligatorio negli switch

ma hanno evitato e combattuto molti degli obbrobri moderni
tipicamente il modificatore const

Io sono d'accordo con @docdoc, @LelloGi il codice che hai scritto e le modifiche che ha fatto @docdoc con la libreria standard funzionano senza problemi.

Ma da dove hai scaricato quella libreria ? PCF8574_HD44780_I2C.h trovo solo una per ESP
possiamo verificare se ha delle differenze.
Meglio sarebbe usare quella standard indicata da @docdoc

Inoltre, prova a stampare anche una frase normale. Sicuro funziona tutto ?
Se dopo quel carattere scrivi "Ciao" la visualizza ??