編集履歴一覧に戻る
eepooのアイコン画像

eepoo が 2021年02月21日10時33分20秒 に編集

初版

タイトルの変更

+

32x64フルスクラッチライブラリによる内外温湿度表示時計

タグの変更

+

ESP32

+

MatrixPanel

本文の変更

+

LED Matrix PanelのESP32用ライブラリをフルスクラッチで作り、室内用と室外用にATH10を二つ接続。RTC(DS3231)をつないで室内外温湿度表示付き時計を作りました。 時計の操作(時刻合わせなど)はロータリスイッチを使い、暗くなったら表示も暗くするためにCdSを使っています。 フルカラーであることを示すために趣味の悪い色使いになっていますが、実際には落ち着いた色にしています。 ![キャプションを入力できます](https://camo.elchika.com/8e023213652c1bbca85b5ed31fe647566f8a8d78/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f34383434643937372d666533372d343734362d613535612d6566383862393438646166612f33326336663961322d636466382d346664352d613337352d643838646632313339316463/) AHT10はI2Cのカスケード接続です。ケーブルが短い室内はOKでしたが、1m程になる室外はエラーが出て安定しませんでした。フラットケーブルを使って、SDAとSCLの間にGND線を置くようにしたら安定しました。 I2CはRTCとも共有しています。  ソースコードを全て載せると、ソースコードだらけになってしまうので、ポイントのところを抜粋して載せます。  YanelsオブジェクトはMatrix panelの幅x高さ の int16_t バッファint16_t buf[]を持ちます。 ドットの描画は B0RRRRGGGGGBBBBB と各色5bitずつで定義した int16_t を設定します。 バッファプレーンに点を描画する部分です。 ```バッファプレーンに点を描画 void YPanels::drawDot(int16_t x, int16_t y, int16_t color, bool wraproll, bool alpha) { if (x < 0) { if (wraproll) { x = x + PANEL_WIDTH; } else return; } else { if (x >= PANEL_WIDTH) { if (wraproll) { x = x - PANEL_WIDTH; } else return; } else { if (y < 0) { if (wraproll) { y = y + PANEL_HEIGHT; } else return; } else { if (y >= PANEL_HEIGHT) { if (wraproll) { y = y - PANEL_HEIGHT; } else return; } } } if (alpha) { buf[y * PANEL_WIDTH + x] = buf[y * PANEL_WIDTH + x] | color; } else { buf[y * PANEL_WIDTH + x] = color; } } } ``` Matrix Panelにバッファプレーンを転送する描画のキモになる部分、輝度bit毎に上から下までスキャンする。 ``` int ganma[5] = {1, 16, 30, 60, 127}; //輝度bit 各諧調ページの光る時間を定義している //bufの内容を書き出す currRowはスキャンごとの行、 pageは輝度bit void writeColors() { for (byte col = 0; col < PANEL_WIDTH; col++) { bool rr1 = buf[currRow * PANEL_WIDTH + col] & (1 << page + 10); bool rr2 = buf[(currRow + SCAN_COUNT) * PANEL_WIDTH + col] & (1 << page + 10); bool gg1 = buf[currRow * PANEL_WIDTH + col] & (1 << page + 5); bool gg2 = buf[(currRow + SCAN_COUNT) * PANEL_WIDTH + col] & (1 << page + 5); bool bb1 = buf[currRow * PANEL_WIDTH + col] & (1 << page); bool bb2 = buf[(currRow + SCAN_COUNT) * PANEL_WIDTH + col] & (1 << page); //CLKをLOWにする digitalWrite(CLK, LOW); // PB7=CLK digitalWrite(R1, rr1); digitalWrite(R2, rr2); digitalWrite(G1, gg1); digitalWrite(G2, gg2); digitalWrite(B1, bb1); digitalWrite(B2, bb2); digitalWrite(CLK, HIGH); // PB7=CLK } } //page と currRowを順次進める pageは輝度bit 0~4 currRowはスキャン 0~16 void nextSection() { currRow++; if (currRow == SCAN_COUNT) { currRow = 0; page++; if (page == 5) { page = 0; } } } //currRowに従ってABCDをセットする void setScan(byte row) { digitalWrite(AA, row & B00000001); digitalWrite(BB, row & B00000010); digitalWrite(CC, row & B00000100); digitalWrite(DD, row & B00001000); } //page(輝度ビット)毎に光らせて消して次のスキャンを行う void IRAM_ATTR onTimer() { portENTER_CRITICAL_ISR(&timerMux); // Increment the counter and set the time of ISR portEXIT_CRITICAL_ISR(&timerMux); xSemaphoreGiveFromISR(timerSemaphore, NULL); timerAlarmDisable(timer); digitalWrite(OE, HIGH); //出力を消す nextSection(); setScan(currRow); digitalWrite(LAT, LOW); writeColors(); digitalWrite(LAT, HIGH); digitalWrite(OE, LOW); timerAlarmWrite(timer, ganma[page], true); timerAlarmEnable(timer); } ``` インスタンス生成後にタイマーをactivateする部分 ``` void YPanels::begin() //タイマー初期化をコンストラクタに入れるとうまくいかない { timerSemaphore = xSemaphoreCreateBinary(); // Create semaphore to inform us when the timer has fired timer = timerBegin(0, OE_PSCALE, true); // Use 1st timer of 4 (counted from zero). Set 80 divider for prescaler (see ESP32 Technical Reference Manual for more info). timerAttachInterrupt(timer, &onTimer, true); // Attach onTimer function to our timer. timerAlarmWrite(timer, ganma[page], true); // Set alarm to call onTimer function every second (value in microseconds).Repeat the alarm (third parameter) timerAlarmEnable(timer); } ``` ちなみに、ピンアサインは以下の通り ```ESP32 32x64 matrix panelのピンアサイン define R1 25 #define G1 26 #define B1 27 #define R2 21 #define G2 22 #define B2 23 #define AA 12 #define BB 16 #define CC 17 #define DD 18 //8scanなのでいらない 16scan時使用 32 scan向けに増やす必要ありかも #define CLK 15 #define LAT 32 #define OE 33 ```