今まで球体ディスプレイなど、いわゆる”2.5D”ディスプレイを作ってきたわけですが、やっと真の3次元ディスプレイ(Volumetric Display)を作れる公算ができました。
今回は本当に立体に見えるかの検証になります。
こういうの作りたいんだよってのはこちらを見て下さい↓
部品
64×64 LEDマトリクスディスプレイ
今回のディスプレイのメインになる部品。フルカラーLEDが密に並んでいるディスプレイで液晶よりもドット密度は低いですが、たくさん並べて大型のディスプレイにするために使用します。HUB75というディスプレイ規格で制御します。このHUB75はシンプルな通信ながら常に信号を送り続けないと表示が止まってしまうというもので、制御にクセがありますがその代わりリフレッシュレートが高いという特徴もあります。一昔前はp4~p6(LEDが4~6mm間隔で並んでいる)のが普通でしたが今回p2というものがあり、64個並んでいても一辺128mmという小ささ!
ちなみにこれは正確にはHUB75Eという規格で列指定のABCDピン(4bit)にEを加えて5bit(=32列)で制御するタイプのものです。(仕様表に1/32 Scanって書いてあるのがそれね)
ESP32マイコン
ある程度高性能でGPIOがたくさん(OUT:14個、IN:1個)あるやつが必要です。OUTの14ピンはLEDディスプレイ用で、INの1ピンは回転速度検出のためのホールセンサ用(今回は使いませんが)です。今回は家に転がっていたESP32-WROOM-32D搭載のSparkFun Thing Plusというマイコンボードを使用しましたがもっと安いやつがあると思います。
モーター
今回は実験も兼ねてブラシレスモーターを使いました。大きさの割に高いトルクと消費電力の小ささはありましたが、今回のはまだトルク不足だったので次回はもっと高トルクのものにしようと思います。
フレーム
今回は実験なので剛性があって、簡単に組み立てできる20x20mmのアルミフレームを組み合わせて使用
無線送電モジュール
回転物に電力を送るため、市販の無線送電モジュールを使用します。ずっと回転させておかないならバッテリーでも良いと思いますが、回転部分が重くなるとブレやすくなります。
組み立て
3Dプリンタで、部品を作ります。LEDマトリクスとモーター軸を直結させて、モーターはアルミフレームに固定します。回転軸がぶれないように上側もベアリングで保持します。
回転テスト②
— やまたい@ものつくり⚙️ (@yamatai_mk) October 6, 2024
カウンターウェイト(ネジ)を入れることで振動をある程度抑えることに成功
モーターの始動時トルク向上が課題#バーサライタ pic.twitter.com/xvqBciGZvv
プログラム
Arduino IDEで書き込みます。LEDマトリクスの制御にはHUB75-LED-Matrixライブラリを使用しています。ESP32で使えるピンの配置などもあるので、ライブラリのデフォルトのピン設定からいくつかを変更して、きちんとデモサンプルが動くことを確認してから回転表示を試します。
本来はホールセンサで回転時間を測って、それに合わせてLEDの表示タイミングを変えるのですが、今回は簡略化して表示タイミングは固定し、モーターの速度を調整することにします。(delayMicroseconds(500)を入れているので、一列表示が0.5ms、一周240列なので、一周240×0.5=120ms=8.3回転/秒で回すと綺麗に表示できるはずです。)
表示する立体映像は立方体のフレームを計算で表示することにします。イメージとしては立方体を回転軸で積分する感じです。
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 |
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h> // ピン配置 /* #define R1_PIN 25/A1 #define G1_PIN 26/A0 #define B1_PIN 27 #define R2_PIN 14->13 #define G2_PIN 12 #define B2_PIN 13->14 #define A_PIN 23/SDA->33 #define B_PIN 19/MISO->21 #define C_PIN 5/SCK->22 #define D_PIN 17 #define E_PIN -1->32 // required for 1/32 scan panels, like 64x64px. Any available pin would do, i.e. IO32 #define LAT_PIN 4/A5 #define OE_PIN 15 #define CLK_PIN 16 */ #define RES_X 64 // 使用するLEDパネルの横方向のピクセル数 #define RES_Y 64 // 縦方向のピクセル数 #define RES_C 240 // 円周方向のピクセル数 #define CHAIN 1 // 使用するLEDパネルの横方向の連結数 #define A_PIN 33 // remap esp32 library default from 23 to 33 #define B_PIN 21 // remap esp32 library default from 19 to 21 #define C_PIN 22 // remap esp32 library defaultfrom 5 to 22 #define E_PIN 32 // HUB75のE端子の定義:規定値がないので必要に応じて定義する必要がある #define R1_PIN 27 #define B1_PIN 25 #define R2_PIN 13 #define B2_PIN 14 uint16_t White; uint16_t Red; uint16_t Blue; uint16_t Green; uint16_t Yellow; uint16_t Cyan; uint16_t Magenta; //描画用メモリを確保 byte imgByte[RES_X][RES_Y][RES_C]; uint16_t vCount; MatrixPanel_I2S_DMA *dma_display = nullptr; //フォトリフレクタの設定 float nowRPS; float tgtRPS; unsigned long drawTime; unsigned long preTime; unsigned long nowTime; unsigned long cycleTime; unsigned long rawCycleTime; unsigned long cycleTimeTh = 20000; //誤検知防止用のしきい値[us] bool drawFlag; void setup() { Serial.begin(115200); HUB75_I2S_CFG mxconfig(RES_X, RES_Y, CHAIN); if (RES_Y == 64){ mxconfig.gpio.a = A_PIN; mxconfig.gpio.b = B_PIN; mxconfig.gpio.c = C_PIN; mxconfig.gpio.e = E_PIN; // 縦が64ピクセルで1/32スキャンのパネルを使用する場合 mxconfig.gpio.r1 = R1_PIN; mxconfig.gpio.b1 = B1_PIN; mxconfig.gpio.r2 = R2_PIN; mxconfig.gpio.b2 = B2_PIN; } mxconfig.clkphase = false; // 表示された城枠の左端が表示されない場合にはこの行を有効にする mxconfig.setPixelColorDepthBits(2); // Display Setup dma_display = new MatrixPanel_I2S_DMA(mxconfig); dma_display->begin(); dma_display->setBrightness8(128); //0-255 vCount = 0; White = dma_display->color444(15, 15, 15); Red = dma_display->color444(15, 0, 0); Blue = dma_display->color444(0, 0, 15); Green = dma_display->color444(0, 15, 0); Yellow = dma_display->color444(15, 15, 0); Cyan = dma_display->color444(0, 15, 15); Magenta = dma_display->color444(15, 0, 15); } void loop() { /* if(vCount%15==0){ dma_display->drawRect(0,0,64,64,dma_display->color444(15, 8, 4)); } else{ dma_display->clearScreen(); }*/ //dma_display->drawRect(0,0,64,64,dma_display->color444(15, 15, 15));//白枠 //dma_display->fillScreenRGB888(255, 255, 255);//白全埋め uint16_t Color, Color2; if(vCount<60){ Color = Red; Color2 = Green; } else if(vCount<120){ Color = Blue; Color2 = Yellow; } else if(vCount<180){ Color = Green; Color2 = Red; } else{ Color = Yellow; Color2 = Blue; } //白いフレームを描画 int square = 32-floor(abs(22.68/cos(PI*(30-vCount%60)/120))); int square2 = dma_display->height()-1-square; dma_display->drawPixel(square, 9, White); dma_display->drawPixel(square, 54, White); dma_display->drawPixel(square2, 9, White); dma_display->drawPixel(square2, 54, White); /* //面を描画 dma_display->drawLine(10, square, 53, square, Color); dma_display->drawLine(10, square2, 53, square2, Color2); dma_display->drawLine(9, square+1, 9, square2-1, Magenta); dma_display->drawLine(54, square+1, 54, square2-1, Cyan); */ //4辺の白いフレームを描画 if(vCount%60==0){ dma_display->drawLine(0, 9, 0, 54, White); dma_display->drawLine(dma_display->height()-1, 9, dma_display->height()-1, 54, White); } vCount++; if(vCount== RES_C)vCount = 0; delayMicroseconds(500); dma_display->clearScreen(); } |
LEDディスプレイ表示テスト
64x64LEDマトリクスの点灯テスト
— やまたい@ものつくり⚙️ (@yamatai_mk) September 29, 2024
ピッチ2mmの1辺128mmという小型サイズ pic.twitter.com/RlziEgeVt7
表示実験
回転数が同期できていないので立方体が回転してしまっていますが、十分3Dに見えます。
立体ディスプレイ試作1号機できました#バーサライタ #POV #VolumetricDisplay pic.twitter.com/5vqFvd6T9A
— やまたい@ものつくり⚙️ (@yamatai_mk) October 8, 2024
ちなみにLEDディスプレイを全点灯して回転するとこんな感じ↓これはこれで円柱が綺麗。
回転テスト②
— やまたい@ものつくり⚙️ (@yamatai_mk) October 6, 2024
カウンターウェイト(ネジ)を入れることで振動をある程度抑えることに成功
モーターの始動時トルク向上が課題#バーサライタ pic.twitter.com/xvqBciGZvv
これから
とりあえずLEDディスプレイを回転させれば3Dに見えることが分かったし、LEDディスプレイのリフレッシュスピードも3Dディスプレイに耐えられるということが今回わかりました。
これからの計画としては、
・任意の3Dデータを表示する
・3Dデータを動画表示する
・RaspberryPiで実現可能かの実証(ESP32ではやや処理能力不足なので)
・モーターや構造の検討
・無線送電モジュールではなく、スリップリングに変更する(RaspberryPi使うと無線送電では電力不足なので)
・カッコいいデザイン(重要)
市販でVoxonってのが発表されてしまったので、個人でも(比較的安価に)作れるよ!ということと、純粋に3Dディスプレイを作ってみたいの思いでプロジェクトを進めていきます。
コメント