ちょっと更新期間が開いてしまいましたが、こういう時は大概プログラム関係やってますw
前回で機体のデモ動作が完成しましました。
次はこの機体を操作するためのリモコンを製作していきます。
リモコンはせっかくなので液晶付きとしたいので、今回は液晶のお話~w
使うのはこちら!なんと丁度Vividさんと同じILI9341の2.8インチw
ただ、私の物はSPI接続となっています^^;
使うライブラリーはもちろん、らびやんさんのLovyanGFX!
もうこれ以外考えられないw
そもそもこの液晶選んだのもLovyanGFXに対応だったからですw
この液晶はタッチパネルも付いていますのでそれも利用です。
こちらのサイトも参考にさせてもらいながら、lovyanGFXのuser_settingを見ながら設定
設定プログラムは後ほど載せて置きます。
こんな感じで動きます。
すげーよ!!LovyanGFX!!なんかよく分からないながらも設定したら普通に動いたwww
いきなりタッチパネル扱えたwwwwちょっと怖いwww!
てなことでプログラムを少し変えてタッチパネルのテスト
指定のエリアをタッチすると対応した動画が再生され、動画再生中は画面を触ると初期画面に戻るようにしてみました。
なんか超簡単に出来たwwwタッチパネルは使えそう。
てなことで、これをリモコンに付けるとして、最大のネックは機体がデモ動作している間だよね~。
画面に「デモ中!!」文字表示しても良いけど、ちょっと手抜き感が凄いwww
やはり理想はコクピットと同じ画面が流れる感じかな。ただ、リモコンでその画面流れたら機体の方のモニター見てもらえない可能性も有るけどねww
まっ、とりあえずコクピットと同じ映像を流す方向でw
プログラムの修正を開始しました。
最初の辺の画面は簡単wただ単に拡大するだけ。
ただ、大きくなった分なんか隙間が目立つww
ちょっと複雑な辺りでは
こんな感じでグチャグチャになりながら整理していきました。
機体に乗っている液晶の表示範囲が約80x60程度。今回の液晶が320x240でそれぞれの辺が4倍になっているので、当然画像とかは全部作り直しw
もしかしてやるかな~?と思って元画像は全部残していましたので大きさの調整だけでよかったのでその辺は比較的簡単でした。
で、進んでいくとついに、パラパラ動画部分の作成となります。この辺も元の動画は保存してありますので、大きさを合わせてパラパラ画像の作成は簡単に。ただ、これが表示となると超悩みましたwww
元が80x60で今回は320x240ピクセルなんですよね・・・・・4倍x4倍=16倍の面積の表示になります・・・・・・・という事は当然表示時間も16倍となりますよね・・・・・・・
で、とりあえず何も考えずに320x240の画像でパラパラ動画やってみました。
これは酷いwwwでも、まっ当然こうなりますわな~~~。
これは相当悩みましたよwww
まず思いついたのが、それぞれのフレームの枚数を減らして読み込む回数を少なくする。
で、1/3のフレームレートになるようにパラパラ画像の枚数を間引いてみました。
カタカタ感むしろ増えたんじゃないwwwwww
そうなんですよw上の動画見ると、1枚の画像を表示するのに時間がかかっているで画像を間引ても、その間が飛んでしまってむしろカタカタ感増える感じなんです。
やはりSPIの限界か・・・・・・・Vividさんの様にパラレルにするべきか・・・・・・・・
(ちなみにVividさんも偶然にも同時期に同じ液晶のパラレルと格闘中。ブログはこちら)
でもパラレルにするとピンが絶対足りなくなる・・・・・・・
最終手段として全画面でデモを表示せずに半分ぐらいの範囲で表示するか・・・・・・・かっちょ悪いな・・・・・・。
と思いながらも試してみると半分ぐらいならまだ見れるスピードに。
全画面だと元の16倍だけど半分なら2x2=4倍だもんね・・・・
でもやはりかっちょ悪いw
3日くらいああでもない、こうでもないと試してみました・・・・・
そこで、ふと、あれっ、これ元の2x2倍のスプライトに表示してそのスプライトを縦横2倍にして全画面に表示したらどうなんだろ?少なくともSPIの通信時間は4倍までで済むし・・・
(スプライトに付いてはこちらをご覧ください。うまく説明されています^^)
てなことで160x120のスプライトをメモリー上に作成してそこに描画して2倍表示で画面に映すようにしてみました。ついでにフレームの枚数も1/2にしたものがこちらです。
うひょー٩(๑>∀<๑)۶ 随分早くなったwww多分元の画面より早いかもw
2倍表示だからちょっと画質落ちるけどこれで行くしかないw
てなことでパラパラ動画の攻略ができました!!
でもね、スプライトで行くのが決まったのですが、そうすると今度はメモリの限界にすぐにぶち当たって、スプライトが描画されない状況にww
例えばこの画面とか
左の大きなマップ、右のレーダー、右下の武器選択画面、ヒカル、マックス、柿崎と全てスプライトで表示しようと思ったのですが、全くメモリーが足りないw
そこでヒカル、マックス、柿崎はスプライトの使いまわしw右下の武器選択画面は表示したらすぐにスプライトの消去と徹底的にスプライトの管理を行って何とか一通り表示出来るようになりました。
ちなみにこの画面
右側はメモリの不足でスプライトが表示されていませんw
結局左部分の表示160x240のスプライトを上下160x120の2つに分けて、下半分の動きが無くなったらすぐに下半分のスプライトを消去してメモリを確保することによって何とか表示出来るようになりました。で、最終的にちょっと画面拡大で隙間が目立つ部分に文字などを足してこんな感じに仕上がりました。
(この画面だけ情報量の密度感高過ぎたかもww)
てな感じで結構苦労しましたw
ちなみに最後のワンコロさんの写真とかせっかく借りたので出来るだけ綺麗な画像でと思ってかなり面倒だったw
最終的にこんな感じに纏めました。途中コクピットと速度を合わせるための編集ポイントとして一瞬止まる時有りますが無視でww
この後同期させていきます^^
あっ、それと一番最初にカッコいい起動画面を追加してみました!!
ちなみに、機体に搭載されている液晶表示はこちら。
なんかおっきな画面で見ちゃった後だとコクピットの画面じゃ辛いねwwwwww
やっぱデモ画面表示やめようかなwwwwww
あっ、そうそう、ILI9341、SPI接続のuser_settingプログラムはこちら。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
// v1.0.0 を有効にします(v0からの移行期間の特別措置です。これを書かない場合は旧v0系で動作します。) #define LGFX_USE_V1 #include <LovyanGFX.hpp> // ESP32でLovyanGFXを独自設定で利用する場合の設定例 /// 独自の設定を行うクラスを、LGFX_Deviceから派生して作成します。 class LGFX : public lgfx::LGFX_Device { /* クラス名は"LGFX"から別の名前に変更しても構いません。 AUTODETECTと併用する場合は"LGFX"は使用されているため、LGFX以外の名前に変更してください。 また、複数枚のパネルを同時使用する場合もそれぞれに異なる名前を付けてください。 ※ クラス名を変更する場合はコンストラクタの名前も併せて同じ名前に変更が必要です。 名前の付け方は自由に決めて構いませんが、設定が増えた場合を想定し、 例えばESP32 DevKit-CでSPI接続のILI9341の設定を行った場合、 LGFX_DevKitC_SPI_ILI9341 のような名前にし、ファイル名とクラス名を一致させておくことで、利用時に迷いにくくなります。 //*/ // 接続するパネルの型にあったインスタンスを用意します。 lgfx::Panel_ILI9341 _panel_instance; // パネルを接続するバスの種類にあったインスタンスを用意します。 lgfx::Bus_SPI _bus_instance; // SPIバスのインスタンス // バックライト制御が可能な場合はインスタンスを用意します。(必要なければ削除) lgfx::Light_PWM _light_instance; // タッチスクリーンの型にあったインスタンスを用意します。(必要なければ削除) lgfx::Touch_XPT2046 _touch_instance; public: // コンストラクタを作成し、ここで各種設定を行います。 // クラス名を変更した場合はコンストラクタも同じ名前を指定してください。 LGFX(void) { { // バス制御の設定を行います。 auto cfg = _bus_instance.config(); // バス設定用の構造体を取得します。 // SPIバスの設定 cfg.spi_host = VSPI_HOST; // 使用するSPIを選択 (VSPI_HOST or HSPI_HOST) cfg.spi_mode = 0; // SPI通信モードを設定 (0 ~ 3) cfg.freq_write = 40000000; // 送信時のSPIクロック (最大80MHz, 80MHzを整数で割った値に丸められます) cfg.freq_read = 16000000; // 受信時のSPIクロック cfg.spi_3wire = true; // 受信をMOSIピンで行う場合はtrueを設定 cfg.use_lock = true; // トランザクションロックを使用する場合はtrueを設定 cfg.dma_channel = 1; // Set the DMA channel (1 or 2. 0=disable) 使用するDMAチャンネルを設定 (0=DMA不使用) cfg.pin_sclk = 18; // SPIのSCLKピン番号を設定 cfg.pin_mosi = 23; // SPIのMOSIピン番号を設定 cfg.pin_miso = 19; // SPIのMISOピン番号を設定 (-1 = disable) cfg.pin_dc = 27; // SPIのD/Cピン番号を設定 (-1 = disable) // SDカードと共通のSPIバスを使う場合、MISOは省略せず必ず設定してください。 _bus_instance.config(cfg); // 設定値をバスに反映します。 _panel_instance.setBus(&_bus_instance); // バスをパネルにセットします。 } { // 表示パネル制御の設定を行います。 auto cfg = _panel_instance.config(); // 表示パネル設定用の構造体を取得します。 cfg.pin_cs = 14; // CSが接続されているピン番号 (-1 = disable) cfg.pin_rst = 33; // RSTが接続されているピン番号 (-1 = disable) cfg.pin_busy = -1; // BUSYが接続されているピン番号 (-1 = disable) // ※ 以下の設定値はパネル毎に一般的な初期値が設定されていますので、不明な項目はコメントアウトして試してみてください。 cfg.memory_width = 240; // ドライバICがサポートしている最大の幅 cfg.memory_height = 320; // ドライバICがサポートしている最大の高さ cfg.panel_width = 240; // 実際に表示可能な幅 cfg.panel_height = 320; // 実際に表示可能な高さ cfg.offset_x = 0; // パネルのX方向オフセット量 cfg.offset_y = 0; // パネルのY方向オフセット量 cfg.offset_rotation = 2; // 回転方向の値のオフセット 0~7 (4~7は上下反転) cfg.dummy_read_pixel = 8; // ピクセル読出し前のダミーリードのビット数 cfg.dummy_read_bits = 1; // ピクセル以外のデータ読出し前のダミーリードのビット数 cfg.readable = false; // データ読出しが可能な場合 trueに設定 cfg.invert = false; // パネルの明暗が反転してしまう場合 trueに設定 cfg.rgb_order = false; // パネルの赤と青が入れ替わってしまう場合 trueに設定 cfg.dlen_16bit = false; // データ長を16bit単位で送信するパネルの場合 trueに設定 cfg.bus_shared = false; // SDカードとバスを共有している場合 trueに設定(drawJpgFile等でバス制御を行います) _panel_instance.config(cfg); } //* { // バックライト制御の設定を行います。(必要なければ削除) auto cfg = _light_instance.config(); // バックライト設定用の構造体を取得します。 cfg.pin_bl = 32; // バックライトが接続されているピン番号 cfg.invert = false; // バックライトの輝度を反転させる場合 true cfg.freq = 44100; // バックライトのPWM周波数 cfg.pwm_channel = 7; // 使用するPWMのチャンネル番号 _light_instance.config(cfg); _panel_instance.setLight(&_light_instance); // バックライトをパネルにセットします。 } //*/ //* { // タッチスクリーン制御の設定を行います。(必要なければ削除) auto cfg = _touch_instance.config(); cfg.x_min = 0; // タッチスクリーンから得られる最小のX値(生の値) cfg.x_max = 239; // タッチスクリーンから得られる最大のX値(生の値) cfg.y_min = 0; // タッチスクリーンから得られる最小のY値(生の値) cfg.y_max = 319; // タッチスクリーンから得られる最大のY値(生の値) cfg.pin_int = -1; // INTが接続されているピン番号 cfg.bus_shared = true; // 画面と共通のバスを使用している場合 trueを設定 cfg.offset_rotation = 0;// 表示とタッチの向きのが一致しない場合の調整 0~7の値で設定 // SPI接続の場合 cfg.spi_host = VSPI_HOST;// 使用するSPIを選択 (HSPI_HOST or VSPI_HOST) cfg.freq = 1000000; // SPIクロックを設定 cfg.pin_sclk = 18; // SCLKが接続されているピン番号 cfg.pin_mosi = 23; // MOSIが接続されているピン番号 cfg.pin_miso = 19; // MISOが接続されているピン番号 cfg.pin_cs = 5; // CSが接続されているピン番号 _touch_instance.config(cfg); _panel_instance.setTouch(&_touch_instance); // タッチスクリーンをパネルにセットします。 } //*/ setPanel(&_panel_instance); // 使用するパネルをセットします。 } }; // 準備したクラスのインスタンスを作成します。 LGFX display; void setup(void) { // SPIバスとパネルの初期化を実行すると使用可能になります。 display.init(); display.setTextSize((std::max(display.width(), display.height()) + 255) >> 8); //* // タッチが使用可能な場合のキャリブレーションを行います。(省略可) if (display.touch()) { if (display.width() < display.height()) display.setRotation(display.getRotation() ^ 1); // 画面に案内文章を描画します。 display.setTextDatum(textdatum_t::middle_center); display.drawString("touch the arrow marker.", display.width()>>1, display.height() >> 1); display.setTextDatum(textdatum_t::top_left); // タッチを使用する場合、キャリブレーションを行います。画面の四隅に表示される矢印の先端を順にタッチしてください。 std::uint16_t fg = TFT_WHITE; std::uint16_t bg = TFT_BLACK; if (display.isEPD()) std::swap(fg, bg); display.calibrateTouch(nullptr, fg, bg, std::max(display.width(), display.height()) >> 3); } display.fillScreen(TFT_BLACK); } uint32_t count = ~0; void loop(void) { display.startWrite(); display.setRotation(++count & 7); display.setColorDepth((count & 8) ? 16 : 24); display.setTextColor(TFT_WHITE); display.drawNumber(display.getRotation(), 16, 0); display.setTextColor(0xFF0000U); display.drawString("R", 30, 16); display.setTextColor(0x00FF00U); display.drawString("G", 40, 16); display.setTextColor(0x0000FFU); display.drawString("B", 50, 16); display.drawRect(30,30,display.width()-60,display.height()-60,count*7); display.drawFastHLine(0, 0, 10); display.endWrite(); int32_t x, y; if (display.getTouch(&x, &y)) { display.fillRect(x-2, y-2, 5, 5, count*7); } } |
関連すると思われる記事:
- None Found
なになに?
なんでwin3.1?
めっちゃなついんですけど!!
そのくらいのマシンパワーってことなのかな?
teznoさん こんばんは!
いやいやwww
冗談でwindows3.1の起動画面入れてみたwww
バルキリーがWindows3.1で動いたいたら面白いじゃないww
こんばんは
6jiroさんと同じ時に同じデバイスでトライしているなんて、びっくりですね!
流石「うっかり教」教祖様と信者です。(笑)
やはり小さなLCDから320×240の大画面は、迫力あって使い心地が良いですよね。
SPIのフレームレートは、ちょっと厳しいですか! でもスプライトを工夫されて、良い感じにスムースに見えます。実は私もスプライトをテストしていて、どうしても画面が欠損して、設定が悪いのかと苦しみました。結果、フル画面のスプライトはメモリオーバーで「物理的に不可能」と気づくまで1週間以上苦しみました。
今のところ、パラレル接続+SD+DAC+4Ch入力まで、何とか行けそうです。
Vividさん こんばんは!
ホントww
示し合わせたように同じデバイスやってたとはwwww
画面大きくなると出来る事増えますが、なかなか大変なことももっと増えますねww
スプライトは画面大きいとメモリとの戦いになりますよねw
画面が大きな場合は3分割して2つのスプライトを使って表示することもされるようです。
https://lang-ship.com/blog/work/lovyangfx-9-time/
音の方はI2Cで別arduinoにしようと思っていましたがDACの方がどのようになるのか楽しみです!
こんばんは
またこんな面白いデバイス持ち出しちゃってw
大画面は迫力ありますね、でも改めて見るとそれよりも、よくあの小さな画面であそこまで情報詰め込んで動かしてたな~という方がインパクトあります(^^)
設定ソースは読みませんでした。もう異次元でついていけませぬ。Vividさんと良い旅を!ww
FGOなおさん こんばんは!
リモコン用にタッチパネル使うことにしてみましたw
ボタン沢山付けると端子足りなくなるので^^;
なおさん良い見方してくれてるねw確かにあの小さな画面に情報詰めるの結構大変だったんですよね~。ただ画面が大きくなると詰める情報なさ過ぎて少し間延びしてますww
うんwあのプログラム部分は実際にLCD使う時来たらやってみてwこれだけ見ても何の事か分からないと思うからww
スプライト、久しぶりに聞きました。
今のPCは描画速度がとてつもなく早くなり、スプライトが不要になったという認識でしたが、こういった環境では、スプライトが有効になるのですね。
それにしてもいろんなハードを使いこなされていて、神の領域ですね~。
パイロットpapaさん こんばんは!
スプライト使いまくっていますよww
流石に今のPCとくらべると使っているマイコン達は全然パワー不足ですからスプライトを有効に使っています^^
ただメモリがきつい~~~~wwwww
この液晶も、もともと今まで使っていたライブラリーで使えることが分かったので選択しました。
慣れたプログラムでやれるのはホント助かります^^