ESP32-DevKitC ( ESP32-WROOM-32 開発ボード ) を使う場合
では今度は、ESP32-DevKitC と LCD ILI9341 モジュールを使う方法を説明したいと思います。
LCD ILI9341 モジュールにピンヘッダ等をハンダ付けしておく
サインスマート販売の物は、SDカード側のピンヘッダはハンダ付けされておりませんでした。
ピンヘッダやピンソケットを別途購入して、ハンダ付けしておいてください。
また、あまりお勧めしませんが、一時的な接続だけならば、以下のようなスルーホール用テストワイヤを使うという手があります。
今回試しに使ってみました。
ピンヘッダのハンダ付け不要でテストすることができます。
ただ、ブレッドボードに挿す時に深く挿し込み過ぎると、抜けなくなる場合があるので注意してください。
本来、ブレッドボードに挿すようには作られていないのですが、ちょっとテストしたいときに便利です。
micro SDHC カードに東雲フォントデータを保存しておく
先ほど、M5Stack 版で述べたように、同じように micro SDHC カードに /font/ フォルダを作成して、3つのフォント関連ファイルを保存しておいてください。
SDカードスロット付き LCD ILI9341 モジュールに SD カードをセットする
先に紹介した、LCD ILI9341 モジュール は 2.2インチのものですが、micro SD カードスロットではなく、標準サイズ SD カードスロットが搭載されています。
これに、micro SDHC カードを使おうとすると、アダプターが必要です。
これは、先に紹介したカードの場合、私が購入した頃には付属していましたが、今は付属されていない場合がありますので、新たに micro SDHCカードを購入する場合は注意してください。
アダプターを使って micro SDHC カードを挿入するとこんな感じになります。
ESP32-DevKitC と LCD ILI9341 モジュールを接続する
下図を参照して、ESP32-DevKitC と LCD ILI9341 モジュールをブレッドボード上で接続してください。
実際の画像ではこんな感じです。
LCD ILI9341 モジュール は様々なものが販売されていますので、場合によっては SD カード用のプルアップ抵抗が接続されていない場合があります。
その場合は接続図にあるように10 kΩ程度のプルアップ抵抗を接続してください。
私の手持ちの物はプルアップ抵抗が接続されていたので、省略しています。
ESP32-DevKitC の場合、今回はタクトスイッチを1つにしました。
M5Stack の場合はボタンスイッチが3つありますが、サンハヤトのブレッドボード SAD-101 1枚の場合、タクトスイッチが一つしか載せられなかったのです。
この回路図のタクトスイッチと同じように GPIO #34, GPIO #25 などに追加すれば、M5Stack と同じように3つのスイッチを作ることができると思います。
タクトスイッチ用のプルアップ抵抗は消費電力を抑えるために 100kΩ以上が良いと思います。
また、LEDバックライトピンには、念のため Max 10mA の定電流ダイオード ( CRD E-103 )を入れました。
ESP32 の GPIO には 12mA 以上の電流を流すと故障する可能性があるため、その保険です。
安価な海外製 ILI9341 モジュールは、詳細な回路図が公開されていなので、しょうがないかなと思っています。
明らかにおかしい? LCD ILI9341 モジュールの画素確認
私の手持ちの LCD ILI9341 モジュールは、 M5Stack と同じ ILI9341 ですが、なぜか最大表示幅が小さくなっていました。
M5Stack と同じ最大ピクセルサイズ 320×240 で図形を表示させると、下図のようになってしまいました。
水平 x = 0 ~ 319 ( 320 pixel )
垂直 y = 0 ~ 239 ( 240 pixel )
上辺と右辺が欠けています。
「なんじゃこりゃ!」
っていう感じです。
原点 ( 0, 0 ) のスタート位置からおかしいです。
これを、
水平 x = 0 ~ 314 ( 315 pixel )
垂直 y = 6 ~ 239 ( 234 pixel )
と変更すると、下図のように正常に表示されました。
これは明らかにおかしいですよね。
液晶板とLED板をはがして調べましたが、よくわかりません。
恐らく、外枠のブラックシートがズレて貼られているものと思われます。
それによって、最大表示幅が小さくなっているものと思われます。
分解してあまり深く追求していないのですが、ソースコードをM5Stack のピクセルサイズで動かしても画面ノイズが出ないので、恐らくそういうことだと思われます。
試しに、以下のスケッチを入力して、Arduino IDE でコンパイル実行させてみてください。
3秒ごとに、ピクセル最大サイズを変えて表示させています。
【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)
#include <mgo_tec_esp32_ili9341_sd.h> const int8_t sck = 18; // SPI clock pin const int8_t miso = -1; // MISO(master input slave output) don't using const int8_t mosi = 23; // MOSI(master output slave input) pin const int8_t cs = 14; // Chip Select pin const int8_t dc = 27; // Data/Command pin const int8_t rst = 33; // Reset pin const int8_t lcd_led_pin = 32; mgo_tec_esp32_bv1::ILI9341Spi LCD; //***********セットアップ**************************** void setup() { Serial.begin(115200); LCD.ILI9341init(sck, miso, mosi, cs, dc, rst, lcd_led_pin, 40000000, false); //microSDを使う場合、必ず false にする LCD.dispRotation(250); //サインスマート ILI9341の場合 LCD.displayClear(); LCD.brightness(255); //LCD LED max brightness 255 } //***********メインループ**************************** void loop() { uint8_t red = 31, green = 63, blue = 31; uint16_t x_min = 0, x_max = 319, y_min = 0, y_max = 239; LCD.drawRectangleLine( x_min, y_min, x_max, y_max, red, green, blue ); LCD.drawLine( x_min, y_min, x_max, y_max, red, green, blue ); LCD.drawLine( x_max, y_min, x_min, y_max, red, green, blue ); delay(3000); LCD.displayClear(); x_min = 0, x_max = 314, y_min = 6, y_max = 239; LCD.drawRectangleLine( x_min, y_min, x_max, y_max, red, green, blue ); LCD.drawLine( x_min, y_min, x_max, y_max, red, green, blue ); LCD.drawLine( x_max, y_min, x_min, y_max, red, green, blue ); delay(3000); LCD.displayClear(); }
これをいろいろ変えてテストしてみてください。
ESP32-DevKitC ( ESP32-WROOM-32 開発ボード )用スケッチの入力
では、以下のスケッチを入力してみてください。
これは、上記の様に、私の手持ちの LCD ILI9341 モジュールのピクセル幅に合わせてあります。
【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)
#include <mgo_tec_esp32_m5stack_firebase.h> const int8_t sck = 18; // SPI clock pin const int8_t miso = -1; // MISO(master input slave output) don't using const int8_t mosi = 23; // MOSI(master output slave input) pin const int8_t cs = 14; // Chip Select pin const int8_t dc = 27; // Data/Command pin const int8_t rst = 33; // Reset pin const int8_t lcd_led_pin = 32; const uint8_t cs_sd = 4; //SD card CS ( Chip Select ) const char* ssid = "xxxxxxxx"; //ご自分のルーターのSSIDに書き換えてください const char* password = "xxxxxxxx"; //ご自分のルーターのパスワードに書き換えてください const char* utf8sjis_file = "/font/Utf8Sjis.tbl"; //UTF8 Shift_JIS 変換テーブルファイル名を記載しておく const char* shino_full_font_file = "/font/shnmk16.bdf"; //オリジナル東雲全角フォントファイル const char* shino_half_font_file = "/font/shnm8x16.bdf"; //半角フォントファイル名を定義 const char* host = "xxxxxxxx.firebaseio.com"; //自分のRealtime database URL const char* firebase_auth = "xxxxxxxxxxxxxxxxxxxx"; //従来のデータベースシークレット String user_path = F("test_user1"); //-------------------------------------- mgo_tec_esp32_bv1::ILI9341Spi LCD; mgo_tec_esp32_bv1::SdShinonomeFont SFR(cs_sd, 40000000); mgo_tec_esp32_bv1::FontParameter font; mgo_tec_esp32_bv1::ScrolleParameter scl_set; mgo_tec_esp32_bv1::DispShinonomeFnt disp_fnt; mgo_tec_esp32_bv1::FirebaseRD firebase; mgo_tec_esp32_bv1::MessageWindow sse_msg, patch_msg; boolean isSSE = false; //Server-Sent Events 通信中かどうかの判定 boolean isRequestSSE = false; //最初にServer-Sent Eventsリクエストする boolean isRequestPatch = false; boolean isNew_firebase_data = false; boolean isNew_firebase_color = false; boolean isNew_firebase_speed = false; boolean isScroll_stop = false; String event_text_str = "?"; String event_color_str = "black"; String event_speed_str = "015"; uint8_t interval = 15; uint8_t red = 0, green = 0, blue = 0; uint16_t max_x = 315; //サインスマート用 ILI9341の場合 //-----ボタンスイッチ 引数初期化-------- mgo_tec_esp32_bv1::ButtonSwitch btnA, btnB, btnC; const uint8_t buttonA_GPIO = 35; //const uint8_t buttonB_GPIO = 34; //const uint8_t buttonC_GPIO = 25; //*****セットアップ****************** void setup() { Serial.begin(115200); pinMode( buttonA_GPIO, INPUT ); //GPIO #39 は内部プルアップ無し // pinMode( buttonB_GPIO, INPUT ); //GPIO #38 は内部プルアップ無し // pinMode( buttonC_GPIO, INPUT ); //GPIO #37 は内部プルアップ無し SFR.init3File(utf8sjis_file, shino_half_font_file, shino_full_font_file); LCD.ILI9341init(sck, miso, mosi, cs, dc, rst, lcd_led_pin, 40000000, false); //microSDを使う場合、必ず false にする LCD.dispRotation(250); LCD.m_max_disp_width = max_x; LCD.displayClear(); LCD.brightness(255); //LCD LED max brightness 255 firebase.init( host, firebase_auth ); initScrolleFont(); initMessage(); //オープニング画面のみのメッセージウィンドウ設定 mgo_tec_esp32_bv1::MessageWindow msg; msg.m_y0 = 140; msg.m_size = 2; msg.m_txt_length = 18; msg.dispMsgWindow( 0, "WiFi connecting..." ); WiFi.begin(ssid, password); Serial.print( F("connecting") ); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); } Serial.println(); Serial.print( F("connected: ") ); Serial.println( WiFi.localIP() ); delay(2000); //Firebaseへ Server-Sent Events(SSE) GETリクエスト firebase.sendGetRequestSSE( user_path ); TaskHandle_t th; //マルチタスクハンドル定義 xTaskCreatePinnedToCore(Task1, "Task1", 8192, NULL, 5, &th, 0); //マルチタスク起動 } //****メインループ******************** void loop() { //文字列を東雲フォントに変換 if( isNew_firebase_data == true ){ disp_fnt.newSetText( scl_set, event_text_str ); isNew_firebase_data = false; } //文字列スクロール if( isScroll_stop == false ){ disp_fnt.scrolleText( font, scl_set ); } //sse connectOK でメッセージウィンドウを消すためには、この位置にすること。 patch_msg.dispWebGetStatusMsgLong( firebase.patch_status, "Patch" ); sse_msg.dispWebGetStatusMsgLong( firebase.sse_status, "SSE" ); if( isNew_firebase_color == true ){ pickUpColorData( event_color_str, red, green, blue ); //ディスプレイの下半分を色で塗りつぶす LCD.drawRectangleFill( 0, 120, 319, 239, red, green, blue ); //スクロール文字色セット font.red = red, font.green = green, font.blue = blue; LCD.scrolleFontColorSet( font ); isNew_firebase_color = false; } } //************ マルチタスクループ ****************** void Task1(void *pvParameters) { while(1){ String sse_str; if( firebase.pickUpStrSSEdataAll( sse_str ) == true ){ isNew_firebase_data = firebase.pickUpStrToTargetStr( sse_str, "text", event_text_str ); event_text_str = event_text_str + " "; //文字スクロールを見やすくするため、全角スペースを追加。 isNew_firebase_color = firebase.pickUpStrToTargetStr( sse_str, "color", event_color_str ); isNew_firebase_speed = firebase.pickUpStrToTargetStr( sse_str, "speed", event_speed_str ); if( isNew_firebase_speed == true ){ pickUpSpeedData( event_speed_str, interval ); scl_set.interval = interval; isNew_firebase_speed = false; } } button_action(); //ボタン操作 delay(1); //マルチタスクの場合、これ絶対必要! } } //**************************************** void initMessage(){ patch_msg.m_x0 = 8; patch_msg.m_y0 = 140; patch_msg.m_size = 2; patch_msg.m_txt_length = 18; patch_msg.m_padding = 4; sse_msg.m_x0 = 8; sse_msg.m_y0 = 180; sse_msg.m_size = 2; sse_msg.m_txt_length = 18; sse_msg.m_padding = 4; } //*************************************************** void pickUpColorData( String color_str, uint8_t &Red, uint8_t &Green, uint8_t &Blue ){ Red = 0, Green = 0, Blue = 0; String red_str = color_str.substring( 1, 3 ); String green_str = color_str.substring( 3, 5 ); String blue_str = color_str.substring( 5, 7 ); uint8_t red_value = strtol( red_str.c_str(), NULL, 16 ); uint8_t green_value = strtol( green_str.c_str(), NULL, 16 ); uint8_t blue_value = strtol( blue_str.c_str(), NULL, 16 ); Red = (uint8_t)floor( (double)red_value / 8.0 ); //0~31範囲に変換 Green = (uint8_t)floor( (double)green_value / 4.0 ); //0~63範囲に変換 Blue = (uint8_t)floor( (double)blue_value / 8.0 ); //0~31範囲に変換 Serial.printf( "red,green,blue = %02X, %02X, %02X\r\n", red_value, green_value, blue_value ); Serial.printf( "red,green,blue = %2d, %2d, %2d\r\n", Red, Green, Blue ); } //*************************************************** void pickUpSpeedData( String speed_str, uint8_t &speed_value ){ String str = speed_str.substring( 0, 3 ); speed_value = strtol( str.c_str(), NULL, 10); if( speed_value == 100 ){ isScroll_stop = true; }else{ isScroll_stop = false; } Serial.printf( "speed = %d\r\n", speed_value ); } //*************************************** void initScrolleFont(){ uint8_t txt_max = 13; scl_set.interval = 15; font.Xsize = 3; font.Ysize = 6; font.y0 = 10; LCD.XscrolleFontArrayInit( font, scl_set, txt_max, font.Xsize, font.Ysize); LCD.scrolleFontSetUp( font, scl_set ); } //**************************************** void button_action(){ btnA.buttonAction( buttonA_GPIO, true, 30, 500 ); //チャタリング対策 30ms, 長押し500ms switch( btnA.ButtonStatus ){ case btnA.MomentPress: //Aボタン瞬時押しの場合 Serial.println( F("Button A Moment Press") ); firebase.patchHTTPrequest( user_path, "text", "ESP32-DevKitC Pushed Button A " ); break; case btnA.ContPress: //Aボタン長押しの場合 Serial.println( F("-------------Button A Cont Press") ); firebase.patchHTTPrequest( user_path, "color", "#FF0000" ); break; default: break; } /* btnB.buttonAction( buttonB_GPIO, true, 30, 500 ); //チャタリング対策 30ms, 長押し500ms switch( btnB.ButtonStatus ){ case btnB.MomentPress: Serial.println( F("Button B Moment Press") ); firebase.patchHTTPrequest( user_path, "text", "ボタンBが押されたよ " ); break; case btnB.ContPress: Serial.println( F("-------------Button B Cont Press") ); firebase.patchHTTPrequest( user_path, "color", "#00FF00" ); break; default: break; } btnC.buttonAction(buttonC_GPIO, true, 30, 500); //チャタリング対策 30ms, 長押し500ms switch( btnC.ButtonStatus ){ case btnC.MomentPress: Serial.println( F("Button C Moment Press") ); firebase.patchHTTPrequest( user_path, "text", "ぼたんCだよ~ん " ); break; case btnC.ContPress: Serial.println( F("-------------Button C Cont Press") ); firebase.patchHTTPrequest( user_path, "color", "#0000FF" ); break; default: break; } */ }
ほとんど M 5スタック版と同じです。
ただ、64行目の dispRotation 関数を、ILI9341init関数のすぐ後に置くことで、様々な ILI9341モジュールに対応できるようにしています。
ここでは、250 としましたが、0~13の値のうちのどれかで良いと思います。
モジュールに合った数値に替えてください。
また、タクトスイッチは1つしか搭載していないので、3つ搭載したい場合はコメントアウトしているところを解除するなりして試してみて下さい。
ESP32-DevKitC ( ESP32-WROOM-32 開発ボード )のコンパイル書き込み実行
では、Arduino IDE でコンパイル書き込み実行させてみてください。
display_bme280_i2c.h: fatal error: bme280.h: No such file or directory
が出る場合、インストールした私の自作ライブラリのSensorフォルダの中のファイルを削除してください。
Windows 10 の場合、以下のパスになります。
C:\Users\__user_name__\Documents\Arduino\libraries\ESP32_mgo_tec-master\src\ESP32_mgo_tec_bV1\Sensor
BME280ライブラリを使っている場合は、Sensorフォルダ内の以下の2つのファイルのみの削除でOKです。
display_bme680_i2c.h
display_bme680_i2c.cpp
また、BME680ライブラリを使っている場合は、以下の2つのファイル削除だけでOKです。
display_bme280_i2c.h
display_bme280_i2c.cpp
両方使わない場合は Sensor フォルダごと削除してからコンパイルしてください。
(2018/09/24)
ボタン操作は M5Stack と同じです。
先に紹介した動画の様に表示されればOKです。
M5Stack だけだと、電子工作している感覚が無くなって来ますが、これならばちょっとは電子工作している感覚になって、自分的にはホッとします。
編集後記
いかがでしたでしょうか。
最初に紹介した動画にはありませんでしたが、これに Windows パソコンも同期させていました。
これだけのデバイスが同時にディスプレイに反映されるのは圧巻ですよね。
改めて Firebase の凄さが身に染みて分かります。
ここまでできれば Google Home や Amazon Echo との連携も比較的やりやすくなると思います。
次回はそれに挑戦してみたいと思います。
今回はここまでです。
ではまた・・・。
コメント
mgo-tec 様
待望の新作発表、早速試させていただきました。
コンパイル書き込みをすると、
未使用 : C:\Users*********\ESP32_mgo_tec-master\src/ESP32_mgo_tec_bV1/Sensor/display_bme680_i2c.h:44:64:fatal error: bme280.h: No such file or directry
となります。
このプログラムでは ESP32_mgo_tec_bV1/Sensor は不要と思い削除し、再コンパイル書き込みをすると、書き込みは可能となりますが、「 WiFi conenecting…」「 SSE Connecting 」の表示のままです。
A ボタンを押すと、「 Patch Connecting 」「 SSE Connecting 」という表示に変わり、その後「 Patch Failed 」「 SSE Connectinng 」となります。
他の方のコメントを参考にと出るのを待っていたのですが、待ちきれず投稿した次第です。
アドバイスの程よろしくお願い致します。
juchangさん
いつも検証いただき、ありがとうございます。
私は、全く気付きませんでした。
BOSCH bme680.h, bme280.h をインストールしていたので、そういうエラーが出なかったのです。
display_bme280_i2c.h ファイル等で、extern していたことが原因です。
応急処置として、juchangさんのやったように、Sensorフォルダごと削除してください。
コンパイルする時に、不要なヘッダファイルまでインクルードされてしまうとは、全然知らずにいました。
とっても勉強になりました。
只今修正中ですので、しばらくそのままご利用ください。
また、「 WiFi conenecting…」「 SSE Connecting 」の表示のままというのは、Firebase Console で事前にデータを入力していないとそういう状態になるかも知れません。
今調査中ですので、分かりましたらお知らせしたいと思います。
度々の不手際、申し訳ございません。
やっぱり、まだまだ素人だなぁと実感しています。
m(_ _)m
juchangさん
お待たせしました。
こちらでいろいろ検証したところ、コンパイルエラーが出た対象ファイルを削除していただくことが最善と思います。
display_bme280_i2c.h エラーが出た場合、
display_bme280_i2c.h
display_bme280_i2c.cpp
の2つのファイルを削除する。
display_bme680_i2c.h エラーが出た場合、
display_bme680_i2c.h
display_bme680_i2c.cpp
を削除していただく。
あるいは、Sensorフォルダごと削除していただくことです。
記事も修正しました。
これは、ホントに気付かなかったです。
当方ではすべてのファイルがインストールされているので、ファイルが無い場合にエラーが出るとは考えも及びませんでした。
コンパイラについて、もっと勉強しなきゃと思いました。
ところで、WiFi conenecting…」「 SSE Connecting 」の表示のままという現象は当方では確認できませんでした。
原因は分からず、申し訳ございません。
m(_ _)m
mgo-tec 様
M5stack で動作確認致しました。
プログラム21行目のデータベースシークレットキーの入力ミスが原因でした。
まだ細かい動作確認はできていませんが取り急ぎご報告まで。
ありがとうございました。
juchangさん
動いて良かったですね。
(^^)
それにしても今回は私自身もとっても勉強になりました。
これからのライブラリ作成に良い教材となりました。
こちらこそ、いつもありがとうございました。
m(_ _)m
mgo-tec 様
LCD ILI9341 モジュールを試してみました。
手持ちの HiLetgo 2.8″TFT LCD では、SD カードスロットが使えず、micro SD カードスロットを別置きとし、A、B、C ボタンも設置しました。
プログラムを実行すると、M5stack と同じ動作をすることを確認致しました。
今回、M5stack と同じPin ナンバーが使えるのが大変ありがたいです。
この、「M5stack もどき」でこれまでの M5stack のプログラムを動かすのが楽しみです。
これからの新作を期待しております。
juchangさん
いつもコメントありがとうございます。
無事動いて良かったです。
2.8″ TFT は画面大きそうで、良さそうですね。
私も、他にESP32開発ボードが数枚あり、わりと重宝しております。
ところで、Yahoo記事を長時間取得し続けていると、取得失敗する新たな原因を本日追記しました。
ESP32 および M5Stack で数時間後に Web 記事取得失敗する問題について
client.connect 関数の使い方を変えれば、殆ど失敗は無くなりました。
自分のライブラリも修正して次回の記事ではバージョンアップします。
ということで、しばらくお待ちくださいませ。
お世話になります。
超初心者的質問なのですが、mgo_tec_esp32_m5stack_firebase.hの
リンク先を教えてください。
隅から隅まで見たつもりでありますが見当たりません。
マッキーさん
お久しぶりです。
記事をご覧いただき、ありがとうございます。
この記事中の以下の項目
自作ライブラリのインストール
に GitHub のリンク先が出ていますが、これではないのでしょうか?
この中に mgo_tec_esp32_m5stack_firebase.h があります。
おはようございます。
githubのリンク先には、ESP32_mgo_tec-masterはあるのですが、mgo_tec_esp32_m5stack_firebase.hがどうしても見つかりません。
ためしに、ESP32_mgo_tec-masterをインクルードしてコンパイルしても
エラーがでます。途方に暮れています。
Firebaseの実験がしたくてうずうずしています。
私も69歳になってぼけてきたのかと自虐しています。
あれ?
おかしいですね。
私の環境では問題無く動いています。
GitHub から ZIPファイルをダウンロードして、ZIP形式のまま Arduino IDE にインストールされていますか?
GitHubにある ZIP形式ライブラリ のインストール方法 ( Arduino IDE )
私の環境は、Windows 10
Arduino IDE 1.8.6
Arduino core for the ESP32 stable 1.0.0
つい先ほど試しても問題ありませんでした。
これでもダメなら、GitHubのページから辿っていくと、srcの中に mgo_tec_esp32_m5stack_firebase.h があります。
そのテキストをコピペして、テキストエディタで保存してみてください。
また、ESP32_mgo_tec beta ver 1.0.40 では、他にもいくつかアップデートしたファイルがありますので、GitHubのページにあるのと同じ構成でテキストエディタでコピペしてファイルを作ってください。
ZIP形式インストールが上手くいっていないのでしょうか?
それとも、ダウンロードした際にウィルスソフトで弾かれている可能性もありますね。
謎ですね。
他のライブラリは問題無くインストールできますか?
お騒がせしました。
見つかりました。w
歳のせいですね。
お!
見つかって良かったですね。
私もホッとしました。(^^)