fc2ブログ

arduinoを使って、DMX経由でモータ制御をしてみた(その1)

こんにちは!
昨日は春一番が吹いてとても暖かく、少し嬉しくなったゆってぃです。
でも、今日からまた寒くなってしまい、ちょっぴりがっかりしています。
なんでこう、春を小出しにするんですかね。

最近はサーバやらAIやらに興味が向いていて、電子工作らしい電子工作はお休みしていたのですが
諸事情により再開いたしました!
作るものは明確になっていて
DMX512という舞台照明用の通信規格を使って、ステッピングモータを動かす装置
です。
「DMXって何?」という人は、タマテックさんのサイトが驚異的に分かりやすいので、是非ご覧になってみてください。

DMXは舞台照明用の規格ですが、物理層はRS485なので、RS485トランシーバを使用すればマイコンで送受信できます。
キャノンケーブルやコネクタも、サウンドハウスさんなどで簡単に手に入るので、回路は簡単に作れそうです。

ただ、DMXのプロトコル自体は公開されているものの、ドライバを書くのは少し骨が折れるのでネットで探したところ、arduino向け拡張ボードarduino向けライブラリを発見しました。
(このライブラリはLGPLv3でライセンスされています。Arduino向けというよりAVRマイコン向けなので、別のプラットフォームへの転用は簡単に出来ますが、商用利用する方はリンクされるコードや開発環境(リバースエンジニアリング環境)も公開対象となる場合があるのでご注意下さい。少なくとも、arduinoで使用する場合は動的リンクではないので、商用利用する場合はリンクされる側のコードも公開対象になります)
今回はプロトタイプなので、ArduinoUnoと、この拡張ボードで、DMXモータ制御装置を作りたいと思います^^

電子工作で使用されるステッピングモータとしてはSM-42BYG011が王道ですが、今回はターゲットが少し大型のものでトルクが不足していたため、高トルクのST-42BYH100にしました。(どなたかこのモータのトルク特性図のありかを知りませんか…涙)
使用するモータードライバ(DRV8835)自体は各相あたり1.5Aを流すことが出来るので、ST-42BYH100(1A/相)でも定格上は問題ありませんが、実際に使用する際は回路にヒートシンクを取り付けるなどして放熱を行ってください。

それでは、さっそく作っていきましょう!!!
まず、簡単な外部仕様から。
DMXのプロトコルにはチャンネルという概念があり、0ch~511chまでの好きなチャンネルを自身に割り当てることが出来ます。
(システムの中で重複してはいけませんが、1つのデバイスで複数のチャンネルを用いることは可能です)
今回はテストですので、開発対象のデバイスでは、0chと1chを使うことにしました。
0chで停止位置を、1chで移動速度を設定することにします。
また、モータは以下の条件で停止します。
(1)停止位置までモータを動かした(従来のstep()と同じ動作)
(2)停止センサが反応した
(3)非常停止スイッチが押下された

arduinoではStepperというステッピングモータ用ライブラリが用意されています。
このライブラリは大変便利なのですが、一度モータを回転させ始めてしまう(回転用API:step()をコールする)と、step()関数が終了するまでモータを停止できないという制約があります。
この制約は、実使用ではそれなりに大きなインパクトを与える場合があります。

通常のモータ制御プログラムでは、停止スイッチが押された場合や、停止センサが反応した場合に、即座にモータを停止したいというシーンが多いです。
例えば、インクジェットプリンタ等でキャリッジをステッピングモータで動かしている場合、キャリッジがガイドシャフトの端まで来たら、モータを停止する必要があります。そうしないと、恐らくプリンタは破損してしまうでしょう。
(余談ですが、ゆってぃは前職ではプリンタの組み込みソフトエンジニアをやっていました)
今回のターゲットはセンサ反応時にモータを停止したいので、この仕様のままではいけません。
そこで、以下の3つの案を検討しました。

(1)step()関数の引数を小さい値にしてループで処理し、ループ毎にセンサ出力ポートを見に行き、停止信号が出ていたらモータを停止する。
(2)Stepperクラスを継承したStepperWithSensorクラスを作り、内部でセンサ出力ポートを見て、センサー反応時にモータを停止する。
(3)Stepperクラスを継承したStoppableStepperクラスを作り、stop()メソッドを新たに実装し、stop()メソッドが呼ばれたらモータを停止する。step()関数は、センサ反応時の割り込みハンドラでコールする。

(1)は最も実装が簡単ですが、設計としてはイマイチです。
センサを見るために定期的にモータを停止するので、モータの励磁タイミングがずれるためスムーズな駆動が難しくなりますし、センサー反応と実際の停止位置にズレが生じる可能性もあります。

(2)も(3)は一長一短ですが、(3)の方が望ましいと言えます。
なぜなら、(2)の場合はモータとセンサが密結合となり、モータ停止の条件がセンサに固定されてしまうからです。(3)はモータ停止の条件がセンサによらないので、例えば緊急停止スイッチを付けた場合などにも対応可能です。
より、今回は(3)で進めることにしました。

※本当にしっかり設計するなら、停止判断クラスを定義し、そのサブクラスのインスタンスをStoppableStepperクラスにコンポジションする、所謂ストラテジパターンにするのが定石です。(2)をより抽象的にした設計ですね。でもあくまでプロトなので、ご勘弁を・・・汗

長くなるので、コードは次の記事で紹介します。
関連記事
スポンサーサイト



コメントの投稿

非公開コメント

プロフィール

ゆってぃ

Author:ゆってぃ
ゴキゲンなおじさまです。

言語:C/C++(C++11)
マイコン/SoC:PIC、SH、R-Car
PoC環境:Arduino、RaspberryPi、Wio LTE、ESP32
OS:OSレス、ITRON、FreeRTOS、Linux(Yocto)
その他:CAN、J1939、MQTT、DMX、Zigbee他

カテゴリ
スポンサードリンク
メールフォーム

名前:
メール:
件名:
本文:

最新記事
スポンサードリンク