エンジニアリング

TouchDesignerからDMXを使ってLEDとモーターをArduinoで制御 – Kinetic Chochin

※2018年7月に制作したものになります。

FUJI ROCK 2017のRED MARQUEEのライブや、サカナクションとSPACE SHOWER TV STATION IDのコラボでも使われていた照明(天井から吊るされた灯体そのものが動く特殊照明)の提灯バージョンです。

イントロダクション

2018/4/7京都メトロで開催されたTouchDesigner Workshop Vol.3.0.0に参加して、インタラクティブ/リアルタイムコンテンツの現場を体験しました。 ほぼプログラミング未経験で初めてのワークショップ参加になりましたが、第一線で活躍されている講師の皆様のレクチャーに、”僕も何かやるぞー!”と感化され、本作の制作に至ります。

TouchDesignerの学習の題材として選定したのは、私がこれまでデザインやムービングヘッドやレーザーなど特殊・舞台照明の現場オペなどの経験してきたので、それらを活かせるよう、現場系DMX制御の特殊舞台照明を扱うことにしました。

TouchDesignerの学習を進めるなかで、e:cueやQLC+などPC上で特殊照明にDMX信号を送って制御する、いわゆるDMXソフトウェアと同等のものは、TouchDesignerにはDMX信号を送るDMX Out CHOPというオペレーターがあるので、簡単に組むことができました。スライダーやボタンなどUIによる人力のオペレーションの他に、OSC通信でセンサーなどと連携し、ムービングヘッドを簡単に制御することができます。

そこで、次なるステップとして、プロダクトとして”モノ作り”を考えました。
ArduinoでDMX信号を受信し、モーターとLEDを使った特殊照明を自作し、TouchDesignerからDMX信号でコントロールする、私にとって初めてのメカトロニクスになります。

コンセプト

京都の街中を歩くと提灯をよく目にします。神社はもちろん、街灯として等間隔に道端に並んでいたり、酒場の店名が書かれている赤提灯など、提灯は日本人にとって(江戸時代からは庶民にとっても)馴染みのある照明器具です。提灯は形や色、大きさ、素材が様々で、模様があったり文字が書いてあり、灯っている個数がひとつだったり、複数のものが規則性を持って並んでいたりしています。

提灯は空間的に面白いアプローチが出来ると考え、動く提灯という、提灯のアップデートというものをテーマに設定しました。プロダクトとして汎用性があり、ナイトクラブなどのイベントや、日本の伝統的な空間でのお茶会など、様々な場面で使用されることを想定しています。

京都の街中で目にする提灯(ロケーション:錦天満宮、祇園花見小路、八坂神社)

ハウツー

灯体設計 Arduino

●要求事項
・DMX受信
・灯体制御
・モーター制御
・電源設計
・ケースデザイン

制御 TouchDesigner

●要求事項
・DMX送信
・LED制御
・モーター制御

メソッド

Arduinoは素晴らしいライブラリがたくさんあります。今回はDMX受信にDMXSerial、LED制御にAdafruit_NeoPixel、モータードライバICであるL6470制御にこちらのライブラリーを使用しました。

DMXのチャンネル数は、以下の通り、LED制御とモーター制御でそれぞれ4チャンネル使い、合計8チャンネルになります。

LED制御

1ch:R
2ch:G
3ch:B
4ch:ロウソクの火エフェクト オンオフ

モーター制御

5ch:停止させるか回転させるか
6ch:初期値からどのポジションにいるか(pos_H)
7ch:6のもと8ビットに加える(pos_L)
8ch:回転スピードはどれぐらいに設定するか

TouchDesignerはDMX Out CHOPというオペレーターがあるので、ConstantやLFOなどのCHOPを組み合わせれば、簡単に灯体を制御できます。

また、灯体が紙の提灯になるので、ケースは熱に強い桐を採用し、木目を生かしたケースにしたり、吊るす紐の太さや金具部分など、細かいテクスチャ含めてしっかりと全体のデザインしました。

回路図&部品

はじめての回路図・・・

主要部品

・Arduino Micro×2※
・最大5WのフルカラーLEDストリップ(NeoPixel) WS2812B
・ステッピングモーター SM-42BYG011
・モータードライブIC L6470
・RS485トランシーバ LTC485CN8(DMX受信IC)
・NEUTRIK NC3MD-LX-B(DMX信号入力用端子)
・NEUTRIK NC3FD-LX-B(DMX信号出力用端子)
・ACアダプター 12V1A
・三端子レギュレーター 5V1A
・電解コンデンサー
・絶縁ラジアルリード型積層セラミックコンデンサー

※Arduinoの完全な並列処理が不可能なためLED制御用とモーター制御用にそれぞれArduinoを2個使用しました。電源はArduino2個とLEDとモーターと空冷ファンをまとめて1つのACアダプターから供給しています。

材料費は全部で1.5万円/1個ぐらいです(今回はほぼ秋月電子通商さんでL6470はストロベリー・リナックスさんになります)。

寸法&概要図

各パーツの説明とスケール。

灯体設計 Arduino

LED制御

    #include <DMXSerial.h>
    #include <Adafruit_NeoPixel.h>

    int startCh = 1;//DMXのスタートアドレス(1,9,17,25,33...)
    int chan1 = startCh;                                                                                                                                            
    int chan2 = startCh+1;
    int chan3 = startCh+2;
    int chan4 = startCh+3;

    //WS2812B定義
    #define PIN_LED 6
    #define NUMPIXELS 15
    #define LED_TYPE    NEO_KHZ800
    #define COLOR_ORDER NEO_GRB
    #define COLOR_ORDER NEO_GRB
    Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN_LED, COLOR_ORDER + LED_TYPE);

    void setup(){
    DMXSerial.init(DMXReceiver);

    // LEDストリップ設定
    delay(1000);
    strip.begin();
    strip.show();
    //testPattern(32);
    //delay(1000);
    resetLED(32);
    delay(1000);
    }
    void loop(){
    unsigned long lastPacket = DMXSerial.noDataSince();
    if (lastPacket < 5000) {
        LEDColor(32);
        if(DMXSerial.read(chan4) < 127){
        //何もしない
        }else{
        //揺らめき
        fireWave();
        }
    }else{ //DMX信号が途切れたとき
        resetLED(32);
    }
    }

    //LED設定
    void LEDColor(uint8_t wait){
    int R = DMXSerial.read(chan1), G = DMXSerial.read(chan2), B = DMXSerial.read(chan3);
    for(uint16_t i=0; i<strip.numPixels(); i++) {
        strip.setPixelColor(i, R,G,B);
        strip.show();
        delay(wait);
    }
    }
    void fireWave(){
    for(int i=0; i<strip.numPixels(); i++) {
        int R = DMXSerial.read(chan1), G = DMXSerial.read(chan2), B = DMXSerial.read(chan3);
        int waver = random(0,32);
        int waverR = R-waver;
        int waverG = G-waver;
        int waverB = B-waver;
        if(waver<0) waverR=0;
        if(waverR>256) waverR=255;
        if(waverG<0) waverG=0;
        if(waverG>256) waverG=255;
        if(waverB<0) waverB=0;
        if(waverB>256) waverB=255;
        strip.setPixelColor(i,waverR,waverG, waverB);
    }
    strip.show();
    delay(random(4,400));
    }
    void resetLED(uint8_t wait){
    for(int i=0; i<strip.numPixels(); i++) {
        strip.setPixelColor(i, 0,0,0);
        strip.show();
        delay(wait);
    }
    }
    void testPattern(uint8_t wait){
    for(int i=0; i<strip.numPixels(); i++) {
        strip.setPixelColor(i, 255,255,255);
        strip.show();
        delay(wait);
    }
    }

モーター制御

#include <DMXSerial.h>
    #include "l6470duino.h"
    l6470duino::driver Driver;

    int startCh = 5;//DMXのスタートアドレス(5,13,21,29,37...)
    int chan1 = startCh;                                                                                                                                            
    int chan2 = startCh+1;
    int chan3 = startCh+2;
    int chan4 = startCh+3;

    void setup() {
    DMXSerial.init(DMXReceiver);

    Driver.init(1);
    Driver.voltage_acc  (0xCC);
    Driver.voltage_dec  (0xCC);
    Driver.voltage_run  (0xCC);
    Driver.voltage_hold (0xCC);
    Driver.setMaxSpeed  (0x20);
    Driver.setMinSpeed  (0x00);
    Driver.setStepMode  (0x5);
    delay(1000);
    }
    void loop() {
    unsigned long lastPacket = DMXSerial.noDataSince();
    if (lastPacket < 5000) {
        if(DMXSerial.read(chan1) < 127){
        Driver.SoftStop(); //モーターを停止させるか回転させるか
        }else{
            unsigned short int pos = DMXSerial.read(chan2) << 8; //pos_Hの値を8ビットシフトして格納
            pos += DMXSerial.read(chan3); //pos_Lの値を、pos_Hのもと8ビットに加える
            Driver.Goto(pos); //モーターの初期値からのポジションをモーターに送る
        if(DMXSerial.read(chan4) <= 64){
            motorSpeed1(); //モーターの回転スピード
        }else if(DMXSerial.read(chan4) <= 128){
            motorSpeed2();
        }else if(DMXSerial.read(chan4) <= 192){
            motorSpeed3();
        }else{
            motorSpeed4();
        }
        }
    }else{
        Driver.HardStop();
    }
    }
    //モーターの回転スピードの設定
    void motorSpeed1(){Driver.setMaxSpeed  (0x0A);}
    void motorSpeed2(){Driver.setMaxSpeed  (0x10);}
    void motorSpeed3(){Driver.setMaxSpeed  (0x1A);}
    void motorSpeed4(){Driver.setMaxSpeed  (0x20);}

制御 TouchDesigner

UI部分と全体像。LED制御の4チャンネルとモーター制御の4チャンネルの合計8チャンネル×Kinetic Chochinの個数をマージしてDMX Out CHOPに送ります。

LED制御部分。Ramp TOPで色を選択し、TOP to CHOPでRGBを数値化し、Table DATでそのRGBの値をそれぞれの灯体に割り振ります。
Ramp TOPのPhaseにabsTimeを設定し、冒頭タイトルにある動画0:19〜0:34のように流れる灯体の光のパターンを作ります。

モーター制御にはAnimation COMPを使います。時間軸で制御できるので、複数でパターンを作るときに便利です。

モーターの制御は2ch=2バイトでポジションの設定ができるように、scriptCHOPでビット演算をしています。以下のように、Arduino側でもこれをパースしています。

unsigned short int pos = DMXSerial.read(chan2) << 8; //pos_Hの値を8ビットシフトして格納
pos += DMXSerial.read(chan3); //pos_Lの値を、pos_Hのもと8ビットに加える
Driver.Goto(pos); //モーターの初期値からのポジションをモーターに送る

ディテール

ケース内部。各部品の配置。モーターと三端子レギュレーターの排熱のため、右側の電源部分に空冷ファンを取り付けてあります。モーターの巻き上げ機構には空洞の筒状のヒノキ材を使用し、捻って結線(巻き上げで捻れるので初期値で逆向きに捻っています)しています。
本体は2箇所のヒートンを結束バンドで吊るします。中心のヒートンが本体のへそ、ど真ん中になり、提灯を吊るす紐の位置になります。

Arduino MicroとL6470は12Vの入力電圧、LEDストリップは5Vの入力電圧になるので、三端子レギュレータで12Vから5Vに変換します。
安定した電圧で出力するため、コンデンサを接続し、放熱板を取り付けました。
WS2812Bへの信号線には330Ωの抵抗を接続しています。

提灯内のLEDストリップ。土台となる木材とLEDストリップ間は排熱フィルムを貼り、熱伝導の両面テープで固定しています。これに提灯を引っ掛けると灯体部分になります。

複数をDMX信号線で結線した様子。DMX信号線の長さによって、提灯の様々な設置が可能です。
本体と灯体はマイクXLR3pinコネクタで脱着可能なので切り離しができます。よって、バラシ・運搬が楽になり、灯体の付け替え・変更が容易にできます。

完成

冒頭タイトルにある動画のように、フルカラーで光る提灯が上下に動いてくれました。 単体でも綺麗なのですが、複数あるからこその動き方や光のパターンがあるので、作り込むことで表現が広がります。材料費が15,000円/個なので、非常に安価でKinetic Lightが実現できます。

課題としては、モーターの回転でケース内部の結線がどうしても捻れるために断線が起こり、動画撮影の際、1個LEDが点灯しなくなってしまったため、捻れないような仕組み、または、それ以外の吊るす方法を考案する必要がありました。市販されている特殊照明でも同様のことが言えますが、ごくわずかでも個体差が出てくるので、品質管理を詰めていくことが課題でした。

今後としては、実際にどこかの現場でお披露目したいです。また、いまのところ人力オペで制御していますが、入力装置をセンサーやカメラなどを使ってインタラクティブ/リアルタイムコンテンツとして扱ったり、出力装置をArduinoが扱えるようになったのでLEDの他に灯体部分を裸電球などに変えてAC100V機器のオンオフのコントロールでパターンを作ったりしたいです。

伝統的な提灯の工房とのコラボや、広告媒体として企業のロゴを提灯に印刷して空間演出をしたり、幼稚園児など提灯に自由にお絵かきをしてもらいそれを吊るして発表会をするワークショップを企画したり、商業や教育領域で色々と広がりを見せられたらと考えています。

最後に…

2018年4月にTouchDesignerに初めて触れ、5月にArduinoに初めて触れ、6・7月でKinetic Chochinを制作しました。

現場系の照明をやっていたので使える”機材として成立する”っていうのはもちろんですが、インタラクティブ/リアルタイムコンテンツに興味を持ち、みんなが”あっ!”となるようなものを作りたいという一心で、思い切ってインスタレーション・クリエイティブの世界に飛び込んでみました。

たった1人で、誰からの支援を得ることなく、知識がまったく無い状態からはじめました。手始めにArduinoはLEDとモーターの入門キットをそれぞれ購入し、ブレッドボードでFirmataを使ってTouchDesignerから制御するというような基礎的なものからスタートし、はんだごてでの結線やインパクトで木工作業など実際に”作りながら作っていく”というプロトタイピングを経験をしました。エラー出ても泣かない!失敗しても凹まない!

分からなくてもいいから”とにかく手を動かす”を実践しましたが、TouchDesignerとArduinoはとにかく学習コストが非常に良いです。先人の皆様にリスペクトを送りつつ、トライ&エラーを繰り返しながらではありますが、ひとつの到達点に達することができました。

この記事がどなたかのお役に立つことを祈ります!

参考文献

書籍 – Visual Thinking with TouchDesigner プロが選ぶリアルタイムレンダリング&プロトタイピングの極意 書籍 – Prototyping Lab 第2版「作りながら考える」ためのArduino実践レシピ (Make: PROJECTS) 書籍 – Arduinoをはじめよう 第3版 (Make:PROJECTS)