ESP32-WROOM-32DでドライバとしてPxMatrixを使用してLED-MATRIX-PANELを駆動しました。
PxMatrix LED MATRIX libraryの中にあるサンプルプログラム「pixetimes」を使用して、学習しました。
使用しているArduino IDEはver1.8.19で、今現在(2023/10/20)はver2.2.1になっていますが、バージョンアップはしていません。
先ずは、ドライバー「PxMatrix」のサンプル「pixeltime」を多少修正して駆動してみました。その完成動画です。
明るすぎてカメラが反応できなく見にくい画像になっています。
最初に「Pixel Time」と表示した後、「Welcome to PxMatrix!」とスクロールして、ウエザーアイコンとカラーバーを
表示しています。その繰返しです。
1.PxMatrix LED MATRIX libraryのインストール
このドライバPxMatrixの特徴として、パネルの入力コネクタ(PI)と出力コネクタ(PO)の間にジャンパ線を接続し、
すべてのシフトレジスタをチェーンして、1つの大きなシフトレジスタとしていることです。
これには、マイクロコントローラに必要なGPIOピンの数を減らすことと、ハードウェアSPIインターフェイスを
使用して駆動できることの2つの利点があります。
(1) Arduino IDEの「スケッチ」⇒「ライブラリをインクルード」⇒「ライブラリの管理」から
「PxMatrix LED MATRIX library」を検索してインストールします。
(2)この「PxMatrix LED MATRIX library」は、「Adafruit GFX Library」を使用していますので、
上記と同様に「Adafruit GFX Library」を検索してインストールしておきます。
(3)上記2つをインストール後、「スケッチ」⇒「ライブラリをインクルード」で、「PxMatrix LED MATRIX library」
と「Adafruit GFX Library」が表示されているか確認してください。
2.ESP32-WROOM-32Dを使用するための設定
(1)「スケッチ」⇒「ボード」⇒「ボードマネージャ」より「esp32」を検索してインストールします。
(2)ESP32-WROOM-32DをUSBコードでPCに接続して、ボードを次のように設定します。
「ツール」⇒「ボード」⇒「ESP32 Aruduino」⇒「ESP32 Dev Module」を選択します。
(3)シリアルポートを「ツール」⇒「シリアルポート」で使用ポートを選択します。
これで、Arduino IDEの設定準備は、OKです。
なお、Arduino IDEでスケッチの書き込みに時間がかかるようでしたら、VSCODEの使用も考えてみてください。
このパネルは、Aliexpressで1000円から2000円程で購入できます。ただ、物によっては入力ピンと
出力ピンのピンアサイン(ピン配置)が表示されていないものがあります。
下図が、私が購入した LEDパネルの裏面ですが入力ピン・出力ピンのピン配置は表示されていませんでした。
1.パネルのピン配置
ピン配置が表示されていなくても大部分がAdafruitのHUB75基準に従って作られたものだと思います。
(心配の場合、購入先で確認してください)
ピン配置が表記されている場合、表記されていない場合でも次のどれかになっていると思います。
なお、入力ピンと出力ピンのピン配置は同じです。
(1)私のパネルは、図1のピン配置を使用しています。
矢印は、パネル裏面に記載されているもので、方向を表しています。
図1
図2
図3
(2)図1と図2の違いは、R、G、Bの添え字が違っているだけで内容は同じです。
図1のR0=図2のR1、 図1のR1=図2のR2・・・・・・等です。
(3)パネルによっては、図3のように8ピン「E」を接続する必要があります。
ピン表示が表記されていない場合、8ピンが「E」か「GND」かの確認は、マルチメーターを使用して、
8ピンと16ピンの導通を調べ、導通していれば図2のように8ピンは「GND」になります。
(4)各ピンの機能は次の通りです。
前述したように、使用するドライバPxMatrixは、パネルの入力コネクタ(PIn)と出力コネクタ(POut)の間に
ジャンパ線を接続し、すべてのシフトレジスタをチェーンして、1つの大きなシフトレジスタとしていますので、
次のように配線します。
1.パネルの入力コネクタと出力コネクタ間の接続
パネルの入力ピンと出力ピンを次のように接続します。
図5
2.パネルの入力コネクタとESP32のGPIO間の接続
図6
このようにR0だけに信号線を接続するだけで済みます。
3.配線図
次図が実際の配線図です。実に簡単な配線になります。
図7
4.実際の配線写真
5.使用した電源は、右図のAliexpressで購入した5V、10A の物を使用しました。
1.このドライバは、追加のコンポーネントなしで、中国製のRGB LEDマトリックスモジュールを制御します。
次の通りこれらのパネルは、大規模なLEDディスプレイで一般的に使用され、さまざまなレイアウトと
解像度で提供されます。
図8
複数のパネルをチェーンして、より大きなパネルを構築することができます。 ドライバーはAdafruit GFXと互換性があり、
現在、ESP8266、ESP32、およびAtmelベースのArduinos(最大64x32のみ)で動作します。
2.表示する構造
パネルは基本的に6つの大きなシフトレジスタで構成されています。 入力コネクタには、シフトレジスタへの
入力(Rx、Gx、Bxの各色に2つ)、2?5ビットのラッチアドレス入力(A、B、C、D、E)、ラッチイネーブル入力(LAT/STB)、
クロック入力(CLK)、出力イネーブル入力(OE)があります。
いくつかの基本的な行スキャンレイアウトがあります。(1/4、1/8、1/16、および1/32行スキャン)
プログラムで display.begin(n) を使用して、ディスプレイの正しいパターンを有効にすることができます。
(n={4,8,16,32} はパターンを定義します)。
このようなLEDマトリックスは通常、大型ディスプレイのサブモジュールとして使用されるため、
デイジーチェーン接続用の出力コネクタを備えています。 出力コネクタには、A、B、C、LAT、CLKが
単にルーティングされ、(R、G、B)ピンがモジュールのシフトレジスタの出力である入力コネクタと同じ
信号があります。
1.「PxMatrix LED MATRIX library」のサンプルプログラム「pixetimes」を使用しました。
Arduino IDEから「ファイル」⇒「スケッチ例」⇒「PxMatrix LED MATRIX library」⇒「pixetimes」と選択し、
サンプルプログラム「pixetimes」を表示します。
2.私のパネルは、P4 RGB LED MATRIX Panel 64x32 を使っていますので、プログラム上で次の点を修正します。
(1)display.begin(n) (n=4,8,16,32)について
私のパネルは、図8から、行スキャンパターンが(1/16)ですので、
display.begin(16) とします。
(2)PxMATRIX display() について
私のパネルは、Eピンを必要としていない(図1のピン配置)ので、次のように
PxMATRIX display(64,32,P_LAT, P_OE,P_A,P_B,P_C,P_D);をコメントアウトします。
//PxMATRIX display(32,16,P_LAT, P_OE,P_A,P_B,P_C);
PxMATRIX display(64,32,P_LAT, P_OE,P_A,P_B,P_C,P_D);
//PxMATRIX display(64,64,P_LAT, P_OE,P_A,P_B,P_C,P_D,P_E);
3.次に、上記2点を修正すれば、そのままで良いのですが、コメントとESP2866関係の部分を全て削除した
プログラムを次に表示します。また、weather_icons[] のデータは、分かり易くするために並び替えています。
ESP32による「pixetimes」のプログラム
#include <PxMatrix.h> // Pins for LED MATRIX #define P_LAT 22 #define P_A 19 #define P_B 23 #define P_C 18 #define P_D 5 #define P_OE 2 hw_timer_t * timer = NULL; portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; #define matrix_width 64 #define matrix_height 32 uint8_t display_draw_time=70; //30-70 is usually fine //PxMATRIX display(32,16,P_LAT, P_OE,P_A,P_B,P_C); PxMATRIX display(64,32,P_LAT, P_OE,P_A,P_B,P_C,P_D); //PxMATRIX display(64,64,P_LAT, P_OE,P_A,P_B,P_C,P_D,P_E); // Some standard colors uint16_t myRED = display.color565(255, 0, 0); uint16_t myGREEN = display.color565(0, 255, 0); uint16_t myBLUE = display.color565(0, 0, 255); uint16_t myWHITE = display.color565(255, 255, 255); uint16_t myYELLOW = display.color565(255, 255, 0); uint16_t myCYAN = display.color565(0, 255, 255); uint16_t myMAGENTA = display.color565(255, 0, 255); uint16_t myBLACK = display.color565(0, 0, 0); uint16_t myCOLORS[8]={myRED,myGREEN,myBLUE,myWHITE,myYELLOW,myCYAN,myMAGENTA,myBLACK}; uint8_t static weather_icons[]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x20,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00 ,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x20,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x07,0xdf,0x07,0xdf,0x07,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x20,0x00,0x20,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x07,0xff,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xdf,0x00,0x00,0x00,0x00,0x07,0xff,0x00,0x00 ,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00 ,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x20 ,0x00,0x00,0x00,0x00,0xff,0xe0,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xdf,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00 ,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00 ,0x00,0x00,0x00,0x20,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00 ,0x00,0x20,0x00,0x00,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0xff,0xe0 ,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xdf,0x07,0xff,0x07,0xdf,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00 ,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00 ,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xdf,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00 ,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xdf,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00 ,0x00,0x00,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00 ,0x00,0x00,0x07,0xff,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x07,0xff,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x07,0xdf,0x07,0xdf,0x07,0xff,0xff,0xe0,0xff,0xe0,0x00,0x00 ,0x00,0x00,0xff,0xe0,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x00 ,0x07,0xff,0x07,0xdf,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0xff,0xe0,0xff,0xe0,0x00,0x20,0x00,0x00 ,0x07,0xdf,0x07,0xdf,0x07,0xdf,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00 ,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00 ,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x07,0xdf,0x07,0xdf,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00 ,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00 ,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0xff,0xff,0x07,0xff,0x07,0xff,0x07,0xdf,0x07,0xff,0x00,0x00 ,0x07,0xff,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xdf,0x00,0x00,0x00,0x00,0x07,0xff,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xdf,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00 ,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00 ,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00 ,0x00,0x20,0x00,0x00,0x07,0xff,0x00,0x20,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x20,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x07,0xdf,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xdf,0x00,0x00,0x07,0xff,0x00,0x00,0x00,0x00 ,0x00,0x00,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xdf,0x00,0x00,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0x07,0xdf,0x07,0xdf,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00 ,0x00,0x00,0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0xff,0xe0 ,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00 ,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00 ,0xff,0xe0,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x07,0xdf,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00 ,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x20,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00 ,0x07,0xff,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xdf,0x07,0xff,0x00,0x00,0x00,0x00,0x07,0xff,0x00,0x00 ,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00 ,0x00,0x00,0xff,0xe0,0xff,0xe0,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xff,0x07,0xff,0x07,0xff,0x00,0x20,0x00,0x00,0x00,0x20 ,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xdf,0x07,0xdf,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x07,0xff,0x07,0xdf,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0xff,0xe0,0xff,0xe0,0x07,0xdf,0x07,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; void IRAM_ATTR display_updater(){ portENTER_CRITICAL_ISR(&timerMux); display.display(display_draw_time); portEXIT_CRITICAL_ISR(&timerMux); } void display_update_enable(bool is_enable){ if (is_enable){ timer = timerBegin(0, 80, true); timerAttachInterrupt(timer, &display_updater, true); timerAlarmWrite(timer, 4000, true); timerAlarmEnable(timer); } else{ timerDetachInterrupt(timer); timerAlarmDisable(timer); } } void setup() { Serial.begin(9600); display.begin(16); display.clearDisplay(); display.setTextColor(myCYAN); display.setCursor(2,0); display.print("Pixel"); display.setTextColor(myMAGENTA); display.setCursor(2,8); display.print("Time"); display_update_enable(true); delay(3000); } union single_double{ uint8_t two[2]; uint16_t one; } this_single_double; void draw_weather_icon (uint8_t icon){ if (icon>10) icon=10; for (int yy=0; yy<10;yy++) { for (int xx=0; xx<10;xx++) { uint16_t byte_pos=(xx+icon*10)*2+yy*220; this_single_double.two[1]=weather_icons[byte_pos]; this_single_double.two[0]=weather_icons[byte_pos+1]; display.drawPixel(1+xx,yy,this_single_double.one); } } } unsigned long last_draw=0; void scroll_text(uint8_t ypos, unsigned long scroll_delay, String text, uint8_t colorR, uint8_t colorG, uint8_t colorB){ uint16_t text_length = text.length(); display.setTextWrap(false); // we don't wrap text so it scrolls nicely display.setTextSize(1); display.setRotation(0); display.setTextColor(display.color565(colorR,colorG,colorB)); for (int xpos=matrix_width; xpos>-(matrix_width+text_length*5); xpos--) { display.setTextColor(display.color565(colorR,colorG,colorB)); display.clearDisplay(); display.setCursor(xpos,ypos); display.println(text); delay(scroll_delay); yield(); } } uint8_t icon_index=0; void loop() { scroll_text(1,50,"Welcome to PxMatrix!",96,96,250); display.clearDisplay(); draw_weather_icon(icon_index); icon_index++; if (icon_index>10) icon_index=0; for (int xx=0; xx<16;xx++) { display.drawLine(xx+16,0,xx+16,5,display.color565(xx*16,0,0)); display.drawLine(xx+16,6,xx+16,10,display.color565(0,xx*16,0)); display.drawLine(xx+16,11,xx+16,15,display.color565(0,0,xx*16)); } delay(1000); for (uint8_t dimm=255; dimm>0; dimm--) { display.setBrightness(dimm); delay(5); } for (uint8_t dimm=0; dimm<255; dimm++) { display.setBrightness(dimm); delay(5); } }
1.ESP32のタイマー割り込みについて
プログラム中の割り込み記述部分は以下の通りです。
#include <PxMatrix.h> ・・・・・・・・・・・・・ hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; ・・・・・・・・・・・・・ ・・・・・・・・・・・・・ void IRAM_ATTR display_updater(){ portENTER_CRITICAL_ISR(&timerMux); display.display(display_draw_time); portEXIT_CRITICAL_ISR(&timerMux); }
void display_update_enable(bool is_enable){ if (is_enable){ timer = timerBegin(0, 80, true); timerAttachInterrupt(timer, &display_updater, true); timerAlarmWrite(timer, 4000, true); timerAlarmEnable(timer); } else{ timerDetachInterrupt(timer); timerAlarmDisable(timer); } }
void setup() {
・・・・・・・・・・・・・ display_update_enable(true); ・・・・・・・・・・・・・ } ・・・・・・・・・・・・・ void scroll_text(・・・・・・・・・・・・・・・・・・){ ・・・・・・・・・・・・・・・・・・・・・・・・ ・・・・・・・・・・・・・・・・・・・・・・・・ yield(); }
(1)hw_timer_t * timer = NULL; について
タイマーを設定するために必要なhw_timer_t型(タイマー管理用の構造体)のポインターを設定します。
これはセットアップ関数で使用します。
(2)portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; について
同期用変数で、portMUX_TYPE型の変数で、メインループとISR(割込処理)で共用変数を変更する時の同期処理に使用します。
(3)void IRAM_ATTR display_updater(){
portENTER_CRITICAL_ISR(&timerMux);
display.display(display_draw_time);
portEXIT_CRITICAL_ISR(&timerMux);
} について
これは、ISR関数の構成を記述しています。
ISR関数のコードを記述するときの注意点:
*ISR関数は引数を伴わないvoid型でなければならない。
*ISRは IRAMに配置するため、IRAM_ATTR属性が必要。
*関数内では割込通知カウンターをインクリメントして、メインループに割り込みの発生を通知する。
*共用変数のインクリメントなので、portENTER_CRITICAL_ISRと portEXIT_CRITICAL_ISRで挟んだ
クリティカルセクション内で行う。
(4)timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &display_updater, true);
timerAlarmWrite(timer, 4000, true);
timerAlarmEnable(timer); について
これはセットアップで行う初期化処理です。
* timer = timerBegin(0, 80, true); 使用タイマーの指定と初期化をします。
timerBegin関数で使用するタイマーの番号などを指定して初期化処理をします。
この関数はesp-hal-timer.h内で次のようにプロトタイプ宣言されています。
hw_timer_t * timerBegin(uint8_t timer, uint16_t divider, bool countUp);
・第1引数: 使用するタイマーの番号(0~3)
・第2引数: プリスケーラー(1マイクロ秒ごとにインクリメントさせたいなら80を指定)
・第3引数: 割込カウンターのインクリメント(カウントアップ)指定
* timerAttachInterrupt(timer, &display_updater, true); 割込処理関数(ISR)の設定です。
ISR関数を割込処理に結びつけます。
この関数もesp-hal-timer.h内で次のようにプロトタイプ宣言されています。
void timerAttachInterrupt (hw_timer_t * timer, void (* fn)(void), bool edge);
・第1引数: 初期化されたタイマー設定用のポインター
・第2引数: ISR関数のアドレス
・第3引数: エッジ割込指定
* timerAlarmWrite(timer, 4000, true); タイマーの動作間隔を指定します。
この関数もesp-hal-timer.h内で次のようにプロトタイプ宣言されています。
void timerAlarmWrite (hw_timer_t * timer, uint64_t alarm_value, bool autoreload);
ただし第2引数の単位は、timerBegin()の第2引数のプリスケーラーで80を指定
、
つまりマイクロ秒指定に基づいていることに注意してください。
・第1引数: タイマーへのポインター
・第2引数: 割込発生までの時間(マイクロ秒)
・第3引数: カウンターのリロード指定(定期的に割り込みを生成させる)
1秒間隔の割込の場合は次のように指定します。
timerAlarmWrite(timer, 1000000, true);
* timerAlarmEnable(timer); タイマー変数を引数として渡してタイマーの有効化を宣言します。
これもesp-hal-timer.h内で次のようにプロトタイプ宣言されています。
void timerAlarmEnable (hw_timer_t * timer);
ここでは次のように指定します。
timerAlarmEnable(timer);
(5)timerDetachInterrupt(timer);
timerAlarmDisable(timer); について
*timerDetachInterrupt(timer);
この関数はタイマーからの割り込みを解除するために使用されます。
* timerAlarmDisable(timer);
この機能は、タイマーアラームイベントの生成を無効にするために使用されます。
(6) yield();
知識不足で良く分からない所がありますが、ESP8266 と同様の扱いで良いかと思います。
loop() の内部に while や for などの長時間実行される部分や入力待ちがある場合は、
ウォッチドッグタイマWDTエラーの発生を回避するために、yield()関数を使用して、タイマを 0 に
戻します。Delay(1)コマンドでも同等に使えます。
2.ディスプレイ関連
(1)display.setTextSize(1); 通常、引数は、1か2です。
「フォントのサイズ」に「1」を指定した場合、1つの文字の高さは「8」、文字の幅は「6」になります。
(2)display.setCursor(posx,posy);
ある文字の真横(ココでは右隣)に、重なることなく別の文字を表示する場合、
第1引数には、「現在のカーソル位置」に「6」以上の値を加えた値を設定する必要があります。
ある文字の真下に、重なることなく別の文字を表示する場合、
第2引数には「現在のカーソル位置」に「8」以上の値を加えた値を設定する必要があります。
(3)display.print("Pixel");
シリアルモニタと似たように、print()、println() が使えます。
(4)display.setTextColor(myCYAN);
表示するテキストのカラー設定です。
3.Weather_icon について
天気用のアイコンが11個描かれるようにしてあります。
(1)11個のアイコンのデータを直列的なデータ構造として、配列にして初期化してあります。
分かり易くするために、データを横20個、縦11行の計220個のデータを1ブロックにして並べ替えて、
uint8_t static weather_icons[] のデータとしています。全部で10ブロックになります。
(2)上記データを以下の共用体の変数に入れて、void draw_weather_icon (uint8_t icon){ }で
アイコンを表示しています。
union single_double{ uint8_t two[2]; uint16_t one; } this_single_double; void draw_weather_icon (uint8_t icon){ ・・・・・・・・・・・・・・・・・・・・・・・・・ for (int yy=0; yy<10;yy++){ for (int xx=0; xx<10;xx++){ uint16_t byte_pos=(xx+icon*10)*2+yy*220; this_single_double.two[1]=weather_icons[byte_pos]; this_single_double.two[0]=weather_icons[byte_pos+1]; display.drawPixel(1+xx,yy,this_single_double.one); } } }
上記、uint8_t static weather_icons[]のデータで10ブロックの各1行目を集めて並べるとアイコンの
データの並びになり、その中の2つのデータがペアで two[1]とtwo[0]に入ります。
例えば、two[1]=0x00、two[0]=0x00の場合、this_single_double.one=0x0000となり,ポイントに黒色を表示します。
また、two[1]=0xff、two[0]=0xe0の場合、this_single_double.one=0xffe0となり、ポイントに黄色を表示します。
uint8_t static weather_icons[] のデータで10ブロックの各1行目を集めて並べたicon=0は次のようになります。
次に、10ブロックのデータの各2行目を集めて並べると次のようになりicon=1 を表示します。
以下、同様にして、icon2~icon10は次のようになります。
3.文字のスクロールについて
文字列のスクロールは、次のscroll_text()関数で行っています。
void scroll_text(ypos, scroll_delay, text, colorR, colorG, colorB){ }
loop() 内で、scroll_text(1,50,"Welcome to PxMatrix!",96,96,250); として、
テキスト「Welcome to PxMatrix!」を表示しスクロールしています。
4.weather_icons とカラーバーの表示
loop() 内で、draw_weather_icon(icon_index); によりweather_iconsを表示し、
3色のカラーバーを表示して、輝度を変化させています。詳細は省略します。