質問:
ライブラリLiquidCrystal_I2Cは他のクラスでは機能しません(コンポジション)
Natalia Kelim Thiel
2016-04-16 00:56:03 UTC
view on stackexchange narkive permalink

こんにちは。クラスを使用してLCDへの書き込みを効率化しようとしています。このクラスには、 LiquidCrystal_I2C * _lcd というプライベート属性(ポインターです。どのように呼び出すかわかりません)があります。これまでのところ、コンストラクターでインスタンス化していますが、 _lcd-> begin(20、4)以下のコードは実行されませんが、エラーは表示されません。

Display.h:

 クラスDisplay {public:Display(); ...プライベート:LiquidCrystal_I2C * _lcd; ...}  

Display.cpp:

  ... Display :: Display(){_ lcd = new LiquidCrystal_I2C(0x27、2、1、 0、4、5、6、7、3、ポジティブ); _lcd->begin(20、4);} ...  

Program.ino

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

Serial.println( "test"); が実行されていないことを確認したときに、エラーに気づきました。 _lcd->begin(20、4); すべてが機能することをコメントすると

Program.inoですべてを記述してテストし、機能しましたが、接続などとは関係ありません。このクラスでは作文の概念を適用しないでください。

誰かが私を助けてくれますか?そして、英語で申し訳ありませんが、私はブラジルから来ました。ありがとう。

クラスでの*静的アクセス*の概念を理解していますか?
Javaならわかります
はい、ほとんど同じです。 Display ::を使用してメンバー変数にアクセスすると、その前にあるオブジェクトのローカルメンバーではなく、静的クラスのメンバーにアクセスします。私はそれが実際にそのようにコンパイルされたことに非常に驚いています。
Display ::を削除しましたが、それでも機能しません。
今ですか: `_lcd = new LiquidCrystal_I2C(0x27、2、1、0、4、5、6、7、3、POSITIVE);` `_lcd-> begin(20、4);`
C ++の@Majenko静的変数は静的として宣言する必要があります。 Display ::をそれらの前に置くだけでは、それらをインスタンス変数からクラス変数に変えることはできません。
@JayEyeだからこそ、本当にコンパイルされているのか疑問に思っていました。
とった。ごめんなさい。 //コメントを投稿できるようにもっと多くの文字:)
1 回答:
JayEye
2016-04-18 02:16:58 UTC
view on stackexchange narkive permalink

最も可能性の高い原因

経験豊富なC ++プログラマーでさえ頻繁に見逃している陰湿な問題に直面しています。グローバル変数の初期化の順序です。あなたの場合、 Display lcd main()の前に初期化され(つまりそのコンストラクターが呼び出されます)、その後 setup()が実行されます。ただし、ほぼ確実に、 LiquidCrystal_I2C クラス、おそらく Wire.h などを宣言しているライブラリを #include しているはずです。これらのクラスの多くでは、そのタイプのグローバル変数も定義されており、アクセスしやすくなっています。たとえば、 Serial Serial.println( "foo")のように)は、実際には、特定のコアが使用しているシリアル実装の適切なタイプのグローバル変数です。

あなたが直面している問題は、C ++標準がグローバル変数のコンストラクターの実行順序を保証しないということです。順序は、コンパイラのアーティファクト、オブジェクトファイルがリンクされた順序、そしておそらく月のフェーズです:)

(ほぼ確実に)起こっているのは、のコンストラクターです。クラスDisplay が呼び出され、LCDとi2cバスが初期化されてから、他の何かがLCDコンストラクターまたはi2cコンストラクターのいずれかを呼び出して混乱します。

OK、「これを修正するにはどうすればよいですか?」あなたが尋ねるのを聞きます。シンプル:グローバルlcd変数をポインタにして、次のように begin()でインスタンスを割り当てます。

  #include "Display .h "Display * lcd; void setup(){Serial.begin(9600); lcd = new Display(); // stuff} void loop(){//その他のものlcd->some_method(some_argument); //さらに多くのもの}  

これで、ディスプレイやバスに影響を与える可能性のある初期化コードに最後に触れるコードが保証されます。ポインタを介して class Display メソッドにアクセスし続けるだけです。

原因の可能性は低いです

コンストラクターが正しい順序で実行されている可能性はありますが、ハードウェアは2回初期化されるのが好きではないため(とにかくテストしてください!)、ハードウェアをリセットする方法を理解する必要があります。再度初期化してください。私があなたの投稿を正しく理解している場合、ループは実行されません。つまり、2回目の初期化によって例外が発生する可能性があります(たとえば、ESP8266の場合は、何らかの追加のデバッグチャネルがないと表示されません。出力専用の Serial1 ポートになりますが、それでも、デバッグを明示的にオンにする必要があります。各コアには独自のデバッグ機能があり、実際のArduinoの機能を忘れています。)

これがお役に立てば幸いです。

/ ji

動作します!ありがとう= Dそして遅れてすみません、私はインターネットがありませんでした...
別の満足した顧客:)


このQ&Aは英語から自動的に翻訳されました。オリジナルのコンテンツはstackexchangeで入手できます。これは、配布されているcc by-sa 3.0ライセンスに感謝します。
Loading...