LoginSignup
6
1

More than 1 year has passed since last update.

AKBONE2022 で LED パネルを使ったオープンソーストレーニングキットを考える

Last updated at Posted at 2022-10-23

秋葉原ロボット部で(ほぼ)毎年作っているトレーニングキット AKBONE 。

今年版の AKBONE2022 はLEDパネルを扱うものにしようかなと試作しています。

image.png

現在アルファ版を作成して諸々検討中。

この記事は現在検討中の技術課題をオープンソースの流れで共有します。

アルファ版インフォメーション

基板シェイプ

image.png

回路図

image.png

搭載可能モジュール

image.png

機能

  • ESP32 で HUB75 仕様の LED パネルを駆動できる
  • 各種センサーモジュール、ブザー、SDカードスロット、ロータリーエンコーダー、押しボタンスイッチを搭載でき、ESP32で扱える
  • ESP32 と 通信できる Linux ボードを搭載できる
  • ESP32 と Linux ボードは シリアルまたはSPIで通信できる
  • Liux ボードからのオーディオ出力はアンプを経由してスピーカーに接続できる

教育的効果

  • かんたんなはんだづけでサイネージが実現できる
  • サイネージのサンプルプログラムはいくつか用意し、プログラムレスでも楽しめる使える
  • ESP32 をプログラムすることでサイネージの表示を自分で制御できる
  • ブロックプログラミング環境、Arduino IDE、Python 、シェルスクリプトなどレベルに応じたプログラムトレーニングができる
  • LED 点灯数と電源の選定から電圧と電流の概念を掴むことができる
  • 加速度センサを用い、力学の教材として用いることができる
  • ラスターグラフィック表示を通してXY座標系の理解を進めることができる
  • VT-100 化することで Linux ボードのコンソールとして使うことができる
  • バックスクロール可能なスタンドアロンコンソールを用い、一人一台のLinux ブートプロセスの教材とすることができる

などなど

接続確認できたLEDパネル

image.png

P4 64dotx32dot 256mmx128mm

image.png

安くてデカイ 55元ぐらいで調達しています

P3 64dotx32dot 192mmx96mm

image.png

P2 128dotx64dot 256mmx128mm

image.png

128x64 は ちょっとファームを直さないといけないですね。

基本的な動作確認

まずはLEDパネルが光るだけの動作確認をします。

AKBONE2022 は ESP32ボードとして NodeMCU や DevKitC、DevKitv1 などを装着できるようにしています。
利用するESPボードに合わせてソケットを立て、はんだづけします。

image.png

LEDパネル電源コネクタをはんだづけ。」
image.png

HUB75コネクタをはんだづけ。今回はピッタリ合うのがなかったので適当なコネクタを加工しました。

image.png

電源とHUB75を接続します

image.png
LEDパネルに接続

image.png

ファームウェアを書き込みます。

image.png

動作したらOK.

image.png

書き込み時に不安定になるので外部電源コネクタを立てて、ここから電源供給するようにしましょう。

image.png

テスト用ファームウェア

64x32用のLED点灯テスト。
ライブラリも何もなく単にGPIO制御で光らせています。
動作確認は Arduino IDE 1.8.13 上で行っています。
128x64でもとりあえず曲りなりに表示します。


/*
 * 
 * for 64dot x 32 dot RGB LED panel with ICN2037 and ICN2012 using HUB75

 (HUB75 pin layout)
   +-+-+
 R1|o|o|G1
 B1|o|o|GND
 R2|o|o|G2
 B2 o|o|GND/A4
 A0 o|o|A1
 A2|o|o|A3
CLK|o|o|LAT
 OE|o|o|GND
   +-+-+
*/

#include <stdio.h>
#include <string.h>

#define R1PIN     33
#define G1PIN     32
#define B1PIN     25
#define R2PIN     18
#define G2PIN     19
#define B2PIN     5
#define A0PIN     12
#define A1PIN     14
#define A2PIN     27
#define A3PIN     26
// #define A4PIN       4 // GND
#define CLKPIN    4
#define LATPIN    17
#define OEPIN     16
#define LEDPANEL_X      64
#define LEDPANEL_Y      32
unsigned long imagedata[ 512 ] = {
  0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  0x10000000,0x00222000,0x70000070,0x50000000,0x33333330,0x20000020,0x44444440,0x10000000,
  0x10000000,0x02000200,0x70000070,0x50000000,0x30000000,0x20000020,0x40000000,0x10000000,
  0x10000000,0x20000020,0x70000070,0x50000000,0x30000000,0x20000020,0x40000000,0x10000000,
  0x10000000,0x20000020,0x70000070,0x50000000,0x30000000,0x20000200,0x40000000,0x10000000,
  0x10000000,0x20000020,0x70000700,0x50000000,0x30000000,0x20000200,0x40000000,0x10000000,
  0x10000000,0x20000020,0x07070700,0x50000000,0x33333330,0x20000200,0x40000000,0x10000000,
  0x10000000,0x20000020,0x07070700,0x50000000,0x30000000,0x02002000,0x44444440,0x10000000,
  0x10000000,0x20000020,0x07070700,0x50000000,0x30000000,0x02002000,0x40000000,0x10000000,
  0x10000000,0x20000020,0x07070700,0x50000000,0x30000000,0x02002000,0x40000000,0x10000000,
  0x10000000,0x20000020,0x07777000,0x50000000,0x30000000,0x02020000,0x40000000,0x10000000,
  0x10000000,0x20000020,0x00707000,0x50000000,0x30000000,0x02020000,0x40000000,0x10000000,
  0x10000000,0x02000200,0x00707000,0x50000000,0x30000000,0x00220000,0x40000000,0x10000000,
  0x11111110,0x00222000,0x00707000,0x55555550,0x33333330,0x00200000,0x44444440,0x11111110,

  0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  0x00030000,0x60000060,0x55555500,0x77777700,0x04444400,0x22222200,0x00111000,0x55555555,
  0x00303000,0x66000600,0x50000050,0x70000070,0x40000040,0x20000020,0x01000100,0x00050000,
  0x00303000,0x66006000,0x50000050,0x70000070,0x40000040,0x20000020,0x10000010,0x00050000,
  0x00303000,0x60660000,0x50000050,0x70000070,0x40000040,0x20000020,0x10000010,0x00050000,
  0x03000300,0x60600000,0x50000050,0x70000070,0x40000040,0x20000020,0x10000010,0x00050000,
  0x03000300,0x60060000,0x55555500,0x70000070,0x40000040,0x20000200,0x10000010,0x00050000,
  0x03000300,0x60060000,0x50000050,0x77777700,0x40000040,0x22222200,0x10000010,0x00050000,
  0x30000030,0x60006000,0x50000050,0x77000000,0x40000040,0x20000200,0x10000010,0x00050000,
  0x30000030,0x60006000,0x50000050,0x70700000,0x40000040,0x20000020,0x10000010,0x00050000,
  0x33333030,0x60000600,0x50000050,0x70070000,0x40000040,0x20000020,0x10000010,0x00050000,
  0x30000030,0x60000600,0x50000050,0x70007000,0x40000040,0x20000020,0x10000010,0x00050000,
  0x30000030,0x60000060,0x50000050,0x70000700,0x40000040,0x20000200,0x01000100,0x00050000,
  0x30000030,0x60000060,0x55555500,0x70000070,0x04444400,0x22222000,0x00111000,0x00050000,
  0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
  0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
};
unsigned long fundata[ 16] = {
  0x12345671,0x23456712,0x34567123,0x45671234,0x56712345,0x67123456,0x71234567,0x00000000,
  0x12345671,0x23456712,0x34567123,0x45671234,0x56712345,0x67123456,0x71234567,0x00000000,
};

void rowselect( int rowaddress )
{
int a,b,c,d,e;
  digitalWrite( OEPIN, HIGH );
  usleep(3);
  digitalWrite( A0PIN, rowaddress & 0x01 );
  digitalWrite( A1PIN, (rowaddress >> 1 ) & 0x01  );
  digitalWrite( A2PIN, (rowaddress >> 2 ) & 0x01 );
  digitalWrite( A3PIN, (rowaddress >> 3 ) & 0x01  );
 // digitalWrite( A4PIN, (rowaddress >> 4 ) & 0x01  );
  usleep(3);
  digitalWrite( LATPIN, HIGH );
  digitalWrite( LATPIN, LOW );
  digitalWrite( OEPIN, LOW );
}
int getcolor( int x, int rowaddress, int bank ){
    int color;
    int imagedataaddress = ((rowaddress+bank*16)*LEDPANEL_X+x)/8;
    if ( 0 == x % 8 ){
        color= (imagedata[ imagedataaddress ] >> 28)& 0x07;
    } else if ( 1 == x % 8 ){
        color= (imagedata[ imagedataaddress ] >> 24)& 0x07;
    } else if ( 2 == x % 8 ){
        color= (imagedata[ imagedataaddress ] >> 20)& 0x07;
    } else if ( 3 == x % 8 ){
        color= (imagedata[ imagedataaddress ] >> 16)& 0x07;
    } else if ( 4 == x % 8 ){
        color= (imagedata[ imagedataaddress ] >> 12)& 0x07;
    } else if ( 5 == x % 8 ){
        color= (imagedata[ imagedataaddress ] >> 8)& 0x07;
    } else if ( 6 == x % 8 ){
        color= (imagedata[ imagedataaddress ] >> 4)& 0x07;
    } else if ( 7 == x % 8 ){
        color= (imagedata[ imagedataaddress ] >> 0)& 0x07;
    }
    return(color);
}
void setup( void )
{
    Serial.begin(115200);
    delay(100);
    pinMode( R1PIN,  OUTPUT );
    pinMode( G1PIN,  OUTPUT );
    pinMode( B1PIN,  OUTPUT );
    pinMode( R2PIN,  OUTPUT );
    pinMode( G2PIN,  OUTPUT );
    pinMode( B2PIN,  OUTPUT );
    pinMode( A0PIN,   OUTPUT );
    pinMode( A1PIN,   OUTPUT );
    pinMode( A2PIN,   OUTPUT );
    pinMode( A3PIN,   OUTPUT );
   // pinMode( A4PIN,   OUTPUT );
    pinMode( CLKPIN, OUTPUT );
    pinMode( LATPIN, OUTPUT );
    pinMode( OEPIN,  OUTPUT );
    digitalWrite( CLKPIN, LOW );
    digitalWrite( LATPIN, LOW );
    digitalWrite( OEPIN, LOW );
}
void loop( void )
{
    int color;
    int x;
    int rowaddress;
    int test1;
    int test2;
    static int counter;
    for( rowaddress=0 ; rowaddress<LEDPANEL_Y/2; rowselect( rowaddress++ ) ) {
        for( x=0 ; x<LEDPANEL_X ; x++ ) {
            color = getcolor( x, rowaddress, 0 );
            digitalWrite( R1PIN,  color        & 0x01  );
            digitalWrite( G1PIN, ((color >> 1 ) & 0x01  ) );
            digitalWrite( B1PIN, ((color >> 2 ) & 0x01  ) );
            color = getcolor( x, rowaddress, 1 );
            digitalWrite( R2PIN,  color       & 0x01  );
            digitalWrite( G2PIN, ((color >> 1 ) & 0x01  ));
            digitalWrite( B2PIN, ((color >> 2 ) & 0x01  ));
            digitalWrite( CLKPIN, HIGH );
            usleep(3);
            digitalWrite( CLKPIN, LOW );    
        }
    }
    counter++;
    for ( int i=0; i<8 ;i++){
      imagedata[255-i] =fundata[counter/100%8+i];
    }
}
    

ピン配置

#define R1PIN     33
#define G1PIN     32
#define B1PIN     25
#define R2PIN     18
#define G2PIN     19
#define B2PIN     5
#define A0PIN     12
#define A1PIN     14
#define A2PIN     27
#define A3PIN     26
// #define A4PIN       4 // GND
#define CLKPIN    4
#define LATPIN    17
#define OEPIN     16
#define LEDPANEL_X      64
#define LEDPANEL_Y      32

その他

ESP32 Linuxボード 信号名 説明
VP(GPIO36) SW_B ロータリーエンコーダーB相
VN(GPIO39) SW_ANALOG ロータリーエンコーダーSWとESCスイッチのマルチプレックス
GPIO34 SW_A ロータリーエンコーダーA相
GPIO35 MOSI/RX SDMISO_SMOSI_RX2 microSDソケットMISO/LinuxボードSPI0_MOSI/ジャンパー選択でLinuxボードRX
GPIO23 MISO/TX SDMOSI_SMISO_TX2 microSDソケットMOSI/LinuxボードSPI0_MISO/ジャンパー選択でLinuxボードTX
GPIO13 SCLK SCLK microSDソケットCLK/LinuxボードSPI0_CLK
GPIO22 I2C_SDA センサやGrove端子のSDA
GPIO21 I2C_SCL センサやGrove端子のSCL
GPIO2 BUZZER 圧電ブザー
GPIO15 CS CS microSDソケットCS/LinuxボードSPI0_CS
TX RX TX ESP32ボード上でUSBシリアルとして接続/ジャンパー選択でLinuxボードRX
RX TX RX ESP32ボード上でUSBシリアルとして接続/ジャンパー選択でLinuxボードTX

SW_ANALOGは、10kでプルアップされていて、ロータリーエンコーダーSWを押すとGND,ESCを押すと電圧が中点となります。両方押すとGND。

拡張モジュール詳細

中華製の市場で安く購入できるものをつなげられるようにしています。

ジャイロ

image.png

RTC
image.png

温湿度気圧センサ
image.png

オーディオアンプ

image.png

スピーカー
image.png
https://detail.tmall.com/item.htm?id=42529253508&spm=a1z09.2.0.0.47fa2e8doTeVkT&_u=n1ieqpng4ede&skuId=4261755627790

技術的検討事項

  • 開発環境
    • ワークショップで使うとなるとポータブル環境が必要
    • Arduino 1.8系?
  • ブロックプログラミング
    • Ardublock?
  • LED ドライバ
    • DMA利用
    • 描画ドライバとしてフォントや簡単な幾何描画を行いたい
    • GFX / g8lib あたり?
    • Laviyan GFX を使うようにできないか?
  • サンプルプログラム
    • 温湿度気圧計
    • RTCを使った時計
    • SDカード連携
  • Linux との連携
    • VT-100互換のESP32のファームウェア
    • 以下が実現できないか?
    • ロータリーエンコーダーでバックスクロール
    • ESCボタンで表示ポーズ

P2LEDは破損しやすい・・・カバーが必要?

image.png

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1