Questão:
A biblioteca LiquidCrystal_I2C não funciona em outra classe (composição)
Natalia Kelim Thiel
2016-04-16 00:56:03 UTC
view on stackexchange narkive permalink

Boa tarde, estou tentando usar uma aula para agilizar a escrita no LCD. Nesta classe eu tenho um atributo privado (é um ponteiro, não sei como o chamo) chamado LiquidCrystal_I2C * _lcd , eu instancio no construtor, até agora tudo bem, mas quando eu chamo o _lcd-> begin (20, 4) o código abaixo não é executado, mas nenhum erro é exibido.

Display.h:

  classe Display {public: Display (); ... private: 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" Exibir lcd; configuração vazia ( ) {Serial.begin (9600);} void loop () {Serial.println ("teste"); delay (3000);}  

Só notei o erro quando vi que Serial.println ("test"); não estava rodando. Se eu comentar o _lcd->begin (20, 4); tudo funciona.

Testei escrevendo tudo no Program.ino e funcionou, não tem nada a ver com conexões ou algo assim, só não aplico o conceito de composição com essa classe.

Alguém pode me ajudar? E desculpe pelos ingleses, eu sou do Brasil. Obrigado.

Você entende o conceito de * acesso estático * nas classes?
Se for como Java, eu entendo
É praticamente o mesmo, sim. Acessar variáveis ​​de membro com Display :: na frente delas acessa os membros da classe estática, não os membros locais do objeto. Estou bastante surpreso que tenha compilado assim.
Removi o Display ::, mas ainda não funciona.
É agora: `_lcd = new LiquidCrystal_I2C (0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);` `_lcd-> begin (20, 4);`
Variáveis ​​estáticas @Majenko em C ++ devem ser declaradas estáticas. Apenas colocar Display :: na frente deles não os transformaria de variáveis ​​de instância em variáveis ​​de classe.
@JayEye É por isso que eu estava questionando se realmente compilou.
Entendi. Desculpe. // mais caracteres para que eu possa postar um comentário :)
Um responda:
JayEye
2016-04-18 02:16:58 UTC
view on stackexchange narkive permalink

Causa mais provável

Você está se deparando com um problema traiçoeiro que até mesmo programadores experientes em C ++ freqüentemente perdem: a ordem de inicialização das variáveis ​​globais. No seu caso, Display lcd é inicializado ( isto é, seu construtor é chamado) antes de main () e subsequentemente setup () são executados. No entanto, você quase certamente está #include ing qualquer biblioteca que está declarando a classe LiquidCrystal_I2C , provavelmente Wire.h , e assim por diante. Em muitas dessas classes, uma variável global desse tipo também é definida para facilitar o acesso às coisas. Por exemplo, Serial (como em Serial.println ("foo") ) é realmente uma variável global do tipo apropriado de qualquer implementação serial que seu núcleo particular está usando.

O problema que você está enfrentando é que o padrão C ++ não garante a ordem de execução dos construtores de variáveis ​​globais. A ordem é um artefato do compilador, a ordem em que os arquivos de objeto foram vinculados e provavelmente a fase da lua :)

O que (quase certamente) está acontecendo é que o construtor do seu a classe Display está sendo chamada, o que inicializa o LCD e o barramento i2c, e então outra coisa chama o construtor LCD ou o construtor i2c e bagunça as coisas.

OK, "como faço para corrigir isso?" Eu ouço você perguntar. Simples: torne a variável lcd global um ponteiro e aloque a instância em begin () , assim:

  #include "Display .h "Exibir * lcd; void setup () {Serial.begin (9600); lcd = novo display (); // coisas} void loop () {// mais coisas lcd->some_method (some_argument); // ainda mais coisas}  

Agora você tem a garantia de que seu código será o último a tocar em qualquer código de inicialização que possa afetar a tela ou o barramento. Continue acessando os métodos da classe Display por meio do ponteiro.

Uma causa menos provável

Ainda é possível que seus construtores estejam sendo executados na ordem certa, mas seu hardware não gosta de ser inicializado duas vezes (mas teste isso de qualquer maneira!), então você pode ter que descobrir como reiniciar o hardware para que possa inicialize-o novamente. Se entendi sua postagem corretamente, o loop nunca é executado, o que significa que uma segunda inicialização provavelmente causa uma exceção (que você não veria a menos que tivesse algum tipo de canal de depuração adicional; no caso do ESP8266, por exemplo, que seria a porta Serial1 somente de saída e, mesmo assim, você teria que ativar explicitamente a depuração. Cada núcleo tem seu próprio material de depuração, esqueci o que o Arduino real faz.)

Espero que isso ajude.

/ ji

Está funcionando! Obrigada = D E desculpem a demora, fiquei sem internet ...
Outro cliente satisfeito :)


Estas perguntas e respostas foram traduzidas automaticamente do idioma inglês.O conteúdo original está disponível em stackexchange, que agradecemos pela licença cc by-sa 3.0 sob a qual é distribuído.
Loading...