会社に放置されていた作りかけのキネティックディスプレイを動かす
TL;DR
こんなキネティックディスプレイを制御できるようにした。🙌
↑ちょっと判りにくいが、手を振るのに合わせてブロックが動いている
インスタレーションの夢のあと
会社の倉庫の2階の奥に幅1m、重さ30kgくらいユニットが17基ほど置いてある。経緯はここに詳しくは書けないが、僕が入社する前のあるプロジェクトで「完成しなかった」インスタレーションだという。ほとんど産業廃棄物扱いをされていたが、実際に動かせたら面白いだろうと思い、今回いちからシステムを設計しなおして動かすことにした。
とはいえ現状を調査しようと思ってもユニット1基で30kgもあり、駆動ユニットのついた背面側は保護カバーもなく破損しやすい状態、しかも取っ手などついていないので移動するのも骨が折れるのだが、ある日ハンドキャリーに載せて気合で会社まで持ってきてしまった。通行人からしたらエアキャップに包まれ、ところどころケーブルがのぞいている梱包物を重そうに運んでいる様子は怪しいこと極まりなかっただろう。駅員さんもよくそのまま電車に乗せてくれたものである。
この梱包されてる奴らがそれ
既存のシステムの調査
そのインスタレーションでは発泡スチロールのブロック1024個を横64×縦16のグリッドに並べて制御し、キネクトで取得したユーザーの形状をブロックの凹凸で表現するインタラクティブなインスタレーションだった(のはずだった)。ブロックは64個(横16縦4)のユニット16基に分割されており、ユニットごとにArduino Due1台で制御する構成となっていた。
当時制作にかかわったメンバーの話を聞く限り動かなかった理由は諸説あり、ブロックを駆動するユニットのトルクが足りなかった、ユニットとPCの通信がうまくいっていなかった、ブロックの位置測定用アナログ入力にノイズが載っていた、などである。そもそも諸説あるということは体系的なトラブルシューティングができていなかったということだろう。
下に再現したシステム構成図を示す。手書きで申し訳ないのだが、どれだけの規模のものか見てほしい。まず、明らかにマイコン(Arduino Due)あたりの制御ユニット数が多すぎる印象を受ける。また、PCからUSBシリアル経由で16台マイコンに制御用のパケットストリームを流さなければいけないのもできればやりたくない構成だ。特にUSBシリアルだとポート番号が変わってしまったり混乱のもとにもなりそうだ。
コントロールボード1枚の大体の構成
これが4セットでユニット1基を構成
実際のユニット背面はこんな感じで緑のコントロールボードが見える
ユニット16基でインスタレーションを構成 Insane...
制御回路側はArduino Dueにアクチュエーターであるモーター付きのスライドボリューム(ムービングスライダー)の位置信号をアナログマルチプレクサで切り替えてマイコンのアナログ入力で読んでいた。またIOエキスパンダを使ってモータードライバのドライブ入力を制御し、別途16chのPWMモジュールからPWM制御信号を入れる構成になっていた。この制御ボードが1ユニット当たり4枚あり、それを1台のArduino Dueで制御していた。当初はブロックの位置制御を構想していたようが、制作時間の制約のために結局単純なOn/Off制御にしたということだ。これくらいのモーター制御システムならアップデートレート50Hzくらいは確保したいが、Arduino Dueがいくら高速動作するとはいえ、64台のアクチュエータの位置制御をしつつPCからの制御パケットも待っていたりしたら仮にコードが正常に動作していたとしてもちょっと間に合わなかったのではないだろうか。
当時On/Off制御だけにすると決めたのだったらアナログ入力によるフィードバックループも構成せずにディジタル出力だけでフィードフォワード制御にしてしまって、なんならPWM制御も切ったほうがシステムが圧倒的に簡素化されてデバッグしやすかったのではないだろうか。今更言っても仕方ないことではあるが。
観察する限り、既存のシステムの課題は以下のように思われた。
・マイコン1CPUあたりの制御デバイスが多すぎる
・シリアルパケット構成をみていないが、取りこぼし対策などが出来ていたか疑問
・USBシリアル経由で16台のデバイスに安定してデータストリームが送れていたか疑問
・アナログ入力、ディジタル出力、I2CとSPIが混在。しかもケーブル長が長い
・モーターのノイズ対策、瞬時電圧低下対策がない
新システムの設計
観察してみる限り、既存のシステムの問題は通信周りとモーター制御系の複雑な回路構成であり、潜在的な課題が複数あることから一つ一つ問題をつぶすより、根本的にシステムの設計思想から作り直す必要があると思われた。
新システムの設計の方針は以下の通り
・ノイズに強いRS−422 / 485を使用
・1ユニットごとにEthernet-RS485ブリッジを経由して接続する構成をとることでUSBシリアルのデバイスが増えることを回避。ユニット増設時もUDP通信を増やすだけなので対応しやすい
・アナログ入力をマルチプレクサでスイッチングせずに直接CPUに入力
・1CPUあたりの制御アクチュエータ数を低減
・ノイズの影響が考えられたのでI2CやSPIを使用しない
・制御基板の製作量が多くなるためカスタム基板を設計
・アクチュエータ、モータードライバは既存のものを使用
また、制御ユニット16基を全て稼働させることは目標とせず、1ユニットのみを稼働させることとした。
モーター制御
モータードライバTB6612によるアクチュエータ制御は容易にできた。TB6612は1ユニットあたり2モータ(またはステッピングモータ1台)の制御が可能な高性能HブリッジICである。最終的にOn/Off制御しかしていなかったのが実にもったいない。
フリーでアクチュエータを動かして見たところ、アクチュエータのベルトドライブによるバネ特性と比較的高い初動抵抗、順方向と逆方向で摩擦抵抗が違うなど、少し制御しにくい特性がみられた。位置制御だけではなく速度制御の実装も検討したが、実際に組み上がった状態で発泡スチロールブロックを動かして見たところいい感じに摩擦抵抗がありバネ特性をダンピングしてくれたのでそのままにしてしまった。初動抵抗が比較的大きいのはこのアクチュエータが実際はスライドボリュームで、規定の位置で止まっている必要があるためだと思われるが、そのせいで厳密な位置制御をしようとすると:すぐ動かない→大きなパワーをかける→いきなり抵抗が軽くなる→目標値を通り過ぎてオーバーシュート、となって振動を引き起こしてしまうため不感帯を設けた。
位置制御特性
コントローラCPU選定
当初 ATtiny85あたりを使って回路フットプリントを小さくしようと思っていたが、なにぶん8ピンしかないICなのでIOの数が少なすぎた。Arduino Unoでアクチュエータ4個を制御するとちょうどIOを全て使い切り、PWM出力の数もちょうど良かったため、ATmega328PにArduinoのブートローダを焼いて使うこととした。FTDI経由でファームを焼き直せるようにしたので実質ArduinoProMiniのクローンである。アクチュエータ4台/CPUとなるため、制御ユニット1基あたり16枚の制御ボードが必要な構成となる。
ATmega328Pにしたのはよいが、DIP28版だとどうしてもサイズが大きくなってしまうため、QFP32版(ATmega328P-AU)にした。QFP32ピンなら手でもはんだ付けできるし、今回はクリームはんだを使ってみたかったのだ。プログラマブルソケットに入れてArduinoファームウェアを焼いてからはんだ付けするようにしたのだが、amazonで安く買ったQFP32のプログラマブルソケットが2か所もはんだ付け不良でショートしており、問題特定に2,3日かかってしまった。でも定価でちゃんとしたやつを買うと数万するので、入手してよかったと思う。プログラマにはArduino UNOでISPスケッチを書き込んで使用した。この記事あたりが参考になる。
なお、ATmega328Pの内部クロック(CR発振8MHz)を当初使おうとしたが、周波数の精度が悪くRS-485通信のパケットを大幅に落としたため、村田製作所のセラロック16MHzでクロックを作ることにした。クリスタルよりはクロック精度が落ちるはずだが、今回の通信ボーレートだと特に問題もなく、部品点数および基板フットプリントも小さくなったので良い選択だったと思う(それに圧倒的に安かった)。
通信設計
RS485通信を使うのは初めてだったが、都合よく会社にDFRoboticsのRS-485シールドが2個転がっていたため簡単にテストできた。
実際に難しいことは特になく、普通にUARTで通信できた。通信ラインにノイズが乗る可能性があったため、配線はオーディオ用シールド線とし、3.5mmスレテオジャックで基板同士を市販のオーディオケーブルで数珠繋ぎできるようにした。RS-485についてはこのビデオやテキサスインスツルメンツのRS485アプリケーションガイドを一読するとよい。
デバイスIDを指定して通信、デバイス側からAckを返したりしているとどうしても遅くなるため通信はストリームにした。プロトコルはヘッダ、チェックサム、フッタを入れて各アクチュエータの制御値を1バイトとし、計67バイトのパケット長とした。受信したデータは67バイトのリングバッファに格納し、チェックサムを確認したら1パケット分すべて受信したとみなして自分の担当範囲のアクチュエータ制御値4台分を返すようにした。最低でも10FPSくらいで制御データを受信したかったため、67Bytes x 8bits x 10FPS = 5360bps、通信速度は9600bpsでも問題なさそうだったが、もし少し上げて20FPSにした場合10720bpsで通信速度を超えてしまうため、通信速度は余裕をみて19200bpsにしておいた。
また、上り方向の通信が不要だったたためRS-485トランシーバICからは受信ラインだけCPUにつないでいる。
パケット構成はこんな感じ
デバイスID設定方法
ここまで来てデバイスIDを設定する方法に悩んだのだが、IDをプログラムに焼いてしまうと、デバイス毎にIDを変更しなければならず毎回コンパイルが走って時間がかかるため、デバイス側でIDを設定することとした。DigitalIOピンをすでに使い切ってしまったため、安い家電基板でよく見かけるアナログ入力レベルを抵抗で規定電圧に固定しておいてID設定に使用することにした。下図のような構成をとることで1入力あたり5レベル設定できるようにし、2入力で最大25パターンIDが設定できるようにした。ただし、のちに起動時に一斉にモーターが動いて突入電流が流れ電源電圧が低下する現象が確認されたため、このID設定方式だと起動タイミングが悪いと間違ったIDが設定される恐れがある。モーターを動作させる時間をID順に従ってずらしたりすれば解決すると思われるが、そもそも間違ったIDが設定されてしまう現象があまりみられなかったため、結局まだプログラムはまだそのままにしてある。
ID設定回路
プロトタイピング
プロトタイプとして作った基板はこんな感じである。
基板設計
CPUが表面実装だったためほかの部品もできるだけ表面実装にしようと思ったのだが、社内でなぜか大量に余っていた電解コンを使ったり、秋月で入手したミニスライドスイッチがスルーホールだったりして、結局中途半端に表面実装とスルーホール部品が混ざった状態になってしまった。ただ、後述のCPUはんだ付けリワークの時に背の高い部品を取り外す必要があり、その時はCPU周囲のスルーホール部品が取り外しやすくて助かった。
表面実装で半量産が初めてだったのでチップ抵抗、コンデンサは比較的大きい3216にした。それらは特に問題もなくはんだ付けできたのだが、前述のID設定用に選定した抵抗アレイのサイズが、1005x4、つまり1.0mm x 0.5mmの極小チップ抵抗が4個連なっているくせもので、ここでのはんだ付け不良がとても多くて困った。
プログラムを焼くときのFTDIモジュールとの接続にはピンを立てるより、コンスルーピン(スプリングヘッダピン)を想定して0.7mmのスルーホールを開けておいた。この部品は抜き差し回数に制限があるようだが、基板側の部品点数が減るので一時的に接続するだけのプログラミングポートには最適だと思う。
(コンスルーピンは自作キーボードの遊舎工房やマックエイトで買える。マックエイトはほかにもマニアックな部品があっておすすめ)
後付けの基板のため、ユニット上に基板を固定する場所は無く、結局基板の上部を伸ばしてインシュロックで鉄製のフレームに固定できるようにした。
フレームに一度固定してそれでおしまいだったら良かったのだが、固定した基板を外さないといけない状況が2,3度あり、そのたびにインシュロックを切って外さなければいけないのは不便だった。基板と一体化しているので破損の危険もあるし、もう少し良い固定方式を考えればよかったと思う。
前述のID設定には通常ディップスイッチが使われることが多いと思うが、部品点数も多くなるし一度設定したら切り替えることはない(と思っていた)のではんだブリッジを複数個所用意して、ブリッジした箇所のパターンにてIDが設定ができるようにした。現実には、組み立てた後で勘違いが発覚しID設定をし直さないといけない状況になったのだが、組み込んだ状態で狭く配線が集中している箇所をはんだブリッジし直すのは困難で、結局取り外してはんだブリッジをし直していた。この瞬間だけはディップスイッチにすればよかったと思った。
作成した基板はこんな感じ
電源は基板同士をカスケード接続して配線の簡素化を図った。そのため電源コネクタ間のパターン上にかなり電流が流れるため、パータン上にはんだを盛っておいて導電率を稼ぐことにした。これは家電基板でもよく見られる手法でそれなりにうまくいっていたと思う。
電源電圧はもともとの設計で9Vにされており、それでモーターを駆動するとともにステップダウンレギュレータで5Vを作ってCPUに供給することにした。電源電圧をマイナーな9Vにした理由はアクチュエータの定格最大電圧が10Vだったためだということだ。当時製作のために買ったのか、社内には9Vの大電流を供給できるステップダウンコンバータモジュールが大量にあり、中途半端な9Vという電圧のために誰も使われないままでいる。
製作作業
今回は16台マイコン基板を生産しなければいけなかったため、初めてクリームはんだを使って基板制作を行った。意外なことに秋月、千石ではクリームはんだの取り扱いが無く、結局モノタロウから購入した。
もちろんリフローオーブンなどないので、同僚の使っていないパン焼きトースターにK型熱電対を置いて温度を確認しつつ、懐中電灯で中をのぞいてはんだの溶け加減を見ながらリフローはんだ付けをした。
こんな感じでリフローオーブンの真似事。ちなみに作っているのは別の基板
結果としては多数のはんだ付けをこなすには最適の方法だったのだが、前述の極小抵抗アレイの端子をほぼ全数リワークしなければいけないなど、手直しが多かった。これはもう少しサイズが大きくてパッドが大きくできる部品を選定すべきだった。極めつけはCPUで、端子が見えないところでショートしていたり熱で故障してしまい、故障率33%という実に不名誉な数字をたたき出してしまった。そのためマイコン基板4枚分のQFP32パッケージをリワーク、交換することになった、作業時間だけで考えるとすべて手はんだで済ませたほうがよかったかもしれない。または鉛フリーではなく有鉛タイプのクリームはんだだったらもっと温度を下げられたのでコンポーネントへのダメージは少なかったと思う。
改造前のキネティックディスプレイ背面
改造後の背面。どっちもカオスじゃん!とか言わないでくれ
制御
PCではTouchDesignerにてカメラ入力から16 x 4 ドットのモノクロパターンを作り、ExecuteDAT内でパケットを成形して、USB-RS485ブリッジを介して通信をするようにした。この辺は超簡単なので割愛。
今後の課題
・基板上のコンポーネントサイズを適正化し、はんだ付けしやすくする
・たまに通信が拾えなくなって固まるノードがあり、そのたびにリセットしないといけないので受信ファンクションにバグが残っている可能性がある
・RS485の通信ラインにオーディオジャックを使っているが、オーディオジャックは抜き差しの瞬間ショートするためほかのタイプのコネクタが良い
・ID設定は起動時の瞬時電圧低下に影響されないようにすべき
・発泡スチロールのブロックがアクチュエータと直接接着されており、任意に外せない。また時々接着がはがれてしまう。ただしこれは僕のせいではない。
まとめ
正直なところ、技術難易度はさほど高くなかった。ただしそれは過去の失敗を知ったうえで第三者視点で製作に取り掛かれたためであることは言うまでもない。また、プロジェクト初期段階でのシステム設計が非常に重要であることを再認識する機会ともなった。
キネティックディスプレイはMITMediaLabの石井教授をはじめ様々なところで製作されているが、今回製作したシステムはモータースライダーを流用したシステムなのでコンプライアンス特性を持たせることができるのが面白いと思う。つまり、バネが入っているかのようにブロックを触ったら引っ込み、元に戻るような特性をもたせられる。また、かなり反応スピードが速いので、人が通った時の動きでもレスポンスよく追随してくれる。その反面、耐久性は保証されておらず、長期運用はすべきではない。
今回は付属品が少ないという単純な理由で最終的にはUSB-RS485ブリッジから制御パケットを流していたが、Ethernet経由でRS-485の制御パケットを流せることも確認している。Ethernet経由の場合、ユニット増設数に大きな制約がない点も当初構想していたシステムより有利である。
倉庫にはあと16基ほどユニットが転がっているため、あと1~3ユニットつくってどこかで展示してみたい。どなたか場所貸していただけましたら幸いです。
この記事が気に入ったらサポートをしてみませんか?