Domanda:
La libreria LiquidCrystal_I2C non funziona in un'altra classe (Composizione)
Natalia Kelim Thiel
2016-04-16 00:56:03 UTC
view on stackexchange narkive permalink

Buon pomeriggio, sto cercando di utilizzare una lezione per semplificare la scrittura sul display LCD. In questa classe ho un attributo privato (è un puntatore, non so come lo chiamo) chiamato LiquidCrystal_I2C * _lcd , lo istanzio nel costruttore, finora tutto bene, ma quando chiamo il _lcd-> begin (20, 4) il codice seguente non viene eseguito, ma non viene visualizzato alcun errore.

Display.h:

  classe Display {pubblico: Display (); ... privato: LiquidCrystal_I2C * _lcd; ...}  

Display.cpp:

  ... Display :: Display () {_lcd = new LiquidCrystal_I2C (0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVO); _lcd->begin (20, 4);} ...  

Program.ino

  #include "Display.h" Visualizza lcd; void setup ( ) {Serial.begin (9600);} void loop () {Serial.println ("test"); delay (3000);}  

Ho appena notato l'errore quando ho visto che Serial.println ("test"); non era in esecuzione. Se commento _lcd->begin (20, 4); tutto funziona.

Ho provato a scrivere tutto in Program.ino e ho funzionato, non ha nulla a che fare con le connessioni o qualcosa del genere, semplicemente non applicare il concetto di composizione con questa classe.

Qualcuno può aiutarmi? E mi dispiace per gli inglesi, vengo dal Brasile. Grazie.

Comprendi il concetto di * accesso statico * nelle classi?
Se è come Java, capisco
È più o meno lo stesso, sì. L'accesso alle variabili membro con Display :: davanti a loro accede ai membri della classe statica, non ai membri locali dell'oggetto. Sono piuttosto sorpreso che sia stato compilato in questo modo.
Ho rimosso Display ::, ma ancora non funziona.
È ora: `_lcd = new LiquidCrystal_I2C (0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);` `_lcd-> begin (20, 4);`
Le variabili statiche @Majenko in C ++ devono essere dichiarate statiche. Il semplice fatto di mettere Display :: davanti a loro non li trasformerebbe da variabili di istanza a variabili di classe.
@JayEye Ecco perché mi chiedevo se fosse davvero compilato.
Fatto. Scusate. // più caratteri così posso postare un commento :)
Una risposta:
JayEye
2016-04-18 02:16:58 UTC
view on stackexchange narkive permalink

Causa più probabile

Stai incontrando un problema insidioso che anche i programmatori C ++ esperti spesso perdono: l'ordine di inizializzazione delle variabili globali. Nel tuo caso, Display lcd viene inizializzato ( cioè viene chiamato il suo costruttore) prima di main () e successivamente setup () vengono eseguiti. Tuttavia, quasi certamente stai #include in qualsiasi libreria dichiari la classe LiquidCrystal_I2C , probabilmente Wire.h e così via. In molte di queste classi, viene definita anche una variabile globale di quel tipo per rendere più facile l'accesso alle cose. Ad esempio, Serial (come in Serial.println ("foo") ) è in realtà una variabile globale del tipo appropriato di qualsiasi implementazione seriale utilizzata dal tuo core.

Il problema che stai riscontrando è che lo standard C ++ non garantisce l'ordine di esecuzione dei costruttori di variabili globali. L'ordine è un artefatto del compilatore, l'ordine in cui i file oggetto sono stati collegati e probabilmente la fase della luna :)

Quello che sta accadendo (quasi certamente) è che il costruttore del tuo viene chiamata la classe Display , che inizializza l'LCD e il bus i2c, quindi qualcos'altro chiama il costruttore LCD o il costruttore i2c e confonde le cose.

OK, "come posso risolvere questo problema?" Ti sento chiedere. Semplice: rendi la variabile lcd globale un puntatore e alloca l'istanza in begin () , in questo modo:

  #include "Visualizza .h "Visualizza * lcd; void setup () {Serial.begin (9600); lcd = nuovo display (); // roba} void loop () {// altro materiale lcd->some_method (some_argument); // ancora più cose}  

Ora hai la certezza che il tuo codice sarà l'ultimo a toccare qualsiasi codice di inizializzazione che potrebbe influenzare il display o il bus. Continua ad accedere ai metodi class Display tramite il puntatore.

Una causa meno probabile

È ancora possibile che i tuoi costruttori vengano eseguiti nell'ordine giusto, ma al tuo hardware non piace essere inizializzato due volte (ma provalo comunque!), quindi potresti dover capire come resettare l'hardware in modo da poterlo fare inizializzalo di nuovo. Se comprendo correttamente il tuo messaggio, il ciclo non viene mai eseguito, il che significa che una seconda inizializzazione probabilmente causa un'eccezione (che non vedresti a meno che tu non abbia una sorta di canale di debug aggiuntivo; nel caso dell'ESP8266, ad esempio, quello sarebbe la porta Serial1 di solo output, e anche in questo caso, dovresti attivare esplicitamente il debug. Ogni core ha le sue cose di debug, dimentico cosa fa il vero Arduino.)

Spero che questo aiuti.

/ ji

Funziona! Grazie = D E scusa per il ritardo, ero senza Internet ...
Un altro cliente soddisfatto :)


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...