🗐 電装工芸日記 - 舞台照明機器の製作とか -

能登半島地震で被災された方々にお見舞い申し上げます。

or 管理画面へ

タグ「Art-Net」を含む投稿[93件](8ページ目)

Icon of admin
 Art-Netは受信したデータのスタックの仕方を変えてうまくいきました。
 約1/100秒毎でスタックし、1/40秒毎で出力しています。
 試験的な処理ですが、Delayもユニバース単位で綺麗に動きます。
 Art-Netの送受信の試験製作はこれにて終了。

 ただ、テストで使っていた中華電器のArt-Netデコーダが不良品でした。
 8アウトの製品ですが、普通に使うとDMXポートが1つしか信号を出さない。
 組み合わせを吟味すると半分の4ポートは出力されますが、マニュアル通りに使って正しく動かないのでは現場じゃ使えません。
 届いた時にMAdot2でテストしてちゃんと動いたような気がするのですが・・・

 Art-Netのデコーダは市販品もありますが、RaspberryPiでここまで出来てしまうと自作した方が圧倒的に安い。市販品の国内価格は7-8万円ですが、材料費だけなら2万もしません。
 レガシーDMXのインターフェースは基板から自作になりますが、PICマイコンでSPIからDMXにプロトコル変換するだけなのでそれほど難しくないハズ。パッチマシンとしてまとめる際には必要ですから作ってしまいましょう。

#RaspberryPi #[Art-Net]
Icon of admin
 Art-Netの入力の扱いについて考えを進めています。

 受信の更新頻度に合わせた処理ではフリッカーが発生することが確定。送られてくる頻度が変化するために起こることですが、根本的に何か変えないと解決しません。
 対策は、十分に早い頻度で入力をサンプリングし、内部処理を整えて値の変化を滑らかにすることです。
 例えば、1/30秒の頻度から1/10秒の頻度を見たとき、更新が1/3回と見るのではなく、3回同じデータが送られているとみるべきなのです。

 DMX512の規格を読み解くと更新頻度は1秒~1/44秒の範囲になりますが、更新頻度の違いによるフリッカーを防止するには1/44秒よりも短い頻度でサンプリングすることが肝のようです。
 短ければ短いほど安定すると思われますが、実際に作って落としどころを見つけましょう。

#[Art-Net]
Icon of admin
 ユニバース単位の試験的な物ですがDelayが出来ました。精度はともかく遅れます。
 ただ、卓の更新頻度による問題発生。
 MAdot2は値が変化しているときの更新頻度が1/30秒くらいですが、値の変化が無いときの更新頻度は1/10秒くらいです。卓としては間違っていない動作ですが、この違いのためにカットチェンジとフェードチェンジではDelayタイムが見た目で違ってしまいます。1/30なら0.033秒、1/10なら0.1秒の潜在的な遅れが処理のキータイムになってしまうからです。
 こうなると入力を遅らせるのではなく出力を遅らせないといけないのかな?スロット単位にDelayをかけたいけど出力側のユニバース単位が現実的かなぁ~。

 ・・・考えを進めてみました。
 今は受信のタイミングでデータをスタックしていますが、一定時間でスタックをしたらどうか。
 DMX512は最大1/44秒毎くらいですが、1/100秒毎くらいで最後に受信したデータをスタックしていくのです。タイミングとピッチが違う情報をサンプリングの頻度を上げることで整えて滑らかにします。また、スタックの時間間隔が一定なら日時情報をスタックせずに済みますし、ソート並みに重い近似値抽出も不要です。
 スタックが多くなっても処理全体が軽くなるならアリかも。

#Python #[Art-Net]
Icon of admin
 Art-Netパッチにはミキサー機能も入れたいような。
 将来的にレガシーDMX512も取り付けるならあると便利ですし、Art-Netはローレベルでミキサーを構成しやすいのがわかったからです。
 見える機能にしないまでも、内部的には可能な様に作っておけばいいのかなと。

 機能の大枠はミキサー、パッチ、ディレイ、カーブプロファイル、リミッタまたはコンプレッション、ライン(固定値・いわゆる直)で検討を進めています。
 設定項目を多くし過ぎると凡ミスの原因になりますので現実的な線で考えたいですが・・・

 用語ですが、DMXの内部系統をラインと呼ぶと混乱するのでルート(route)と呼ぶことにします。

#[Art-Net]
Icon of admin
 先日書いた謎のオレメモ

 np.abs( np_array_dt - ( datetime.datetime.now() - datetime.timedelta(seconds=0.1) ) ).argmin()

 これはDelay機能で重要な処理です。
 日時の配列(np_array_dt)の中から、現在日時から一定の時間を差し引いた日時に最も近い日時を項に持つIndexを得ます。

 Delayを構成するにあたり、受信値に日時を付けて数世代のデータを保存し、少し前の入力値を使います。出力を遅らすのではなく入力を遅らすのです。
 パッチはパッチマップに従って入力スロットの値を出力スロットにコピーしますが、コピー元の入力スロットを探すアドレスに受信世代のインデックスも持たせれば1フェーズでパッチとDelayの処理が完了します。コピー元のアドレスの表現を「何秒前の何番LINEの何番スロット」とするワケです。Titan系からのパクリですが、LINEとはDMXの内部系統のことです。8ユニバースを扱う構想ですから8LINEあります。内部系統に入出力先をパッチするのは言うまでもありません。
 意味合いとして正しいのはパッチが済んだデータの出力を指定時間遅らすことだと思いますが、入力を遅らせてもその様に振る舞うならいいかなと。

 そもそも反応が鈍い劇場の調光装置と反応が鋭い機器をワンボードで操作しても明かりの変化を一斉にさせたいという要望からのDelayです。カットインをカットインにしたいだけで、照明効果を作るエフェクトではありません。
 ですから、厳密に設定時間分遅らせることが目的ではなく、全体が同じタイミングで動いているように「見えれば」いいので、入力の世代を管理する方法で十分だと思うのです。

 「少し前の日時のインデックス」を見つけるのが謎式の正体です。

 ちなみに、時刻を使わず日時を使う理由は、深夜24時、日付が変わる瞬間に必ずエラーが起こるからです。0時0分0秒付近でほんの一瞬ですが、設定可能な最大Delay時間前のデータが出ます。Delay最大値が1秒なら1秒前のデータが出てしまうのです。一瞬のこととはいえ、こんな潜在エラーがあったらカウントダウンの現場では使えません。

#Python #[Art-Net]
Icon of admin
 キーボード、モニタ、ネットワークなど、ハードウェアとのやり取りを先に進めていますが、ボチボチ本丸であるパッチ機能の具体的な作りもまとめ始めています。
 パッチ機能はマッピングファイルに従って入力を出力に置き換える作業なのでアルゴリズムに難しいことはありませんが、十分な速度を得られるかが難しい課題です。
 DMX512は1スロットあたり44usecです。100万分の44秒ってことですが、8ユニバース扱うなら100万分の5.5秒以内に1スロットを確実に処理しなければなりません。RaspberryPi4BのCPUクロックは1GHz以上であり、それが4スレッドありますから間に合うような気もするのですが、確認しながら工夫していく必要があると思われます。
 なんの工夫もなくPythonを動かすとCPUは1スレッドしか使われません。RaspberryPiでは能力の1/4しか使えないってことです。CPUの能力を最大限使おうとするなら、実行ファイルを複数に分けてOSレベルでプロセスを分けるか、Python内でmultiprocessingを定義して複数のCPUスレッドがPythonの処理を請け負うように仕向けないといけません。
 multiprocessingの使い方はThreadingと似ているので難しいことは無さそうですが、こういったちょっと深いところをちゃんと書かないとRaspberryPiでパッチマシンは厳しい感じです。

#Python #[Art-Net]
Icon of admin
 Art-Netの受信モニタはイメージ通りに動きました。選択したユニバースをキレイに表示しています。
 当面の習作課題はクリアしましたが、喜ぶというより目の前に新たな壁が見えてきました。

 この後はartnet-coreと名付けている受信と加工を司るサーバー的な部分を作ります。
 ここまでの経験をもとに全体の構造をよく考えてから作る必要があります。

#Python #[Art-Net]
Icon of admin
 画面とArt-Netの送受信を結合させられる段階になりました。Art-Netをスルー出力し特定のユニバースをモニタします。
 簡易ながら実験段階で出来ていることですから、画面を整えたからってなんだよって構成ですが、パッチマシンの一部を先行して作っているので重要な過程です。表示することが目的ではなく、最低限持たなければならない機能を出来るだけ見やすく使いやすく軽く、そして今後の伸びしろを持たせた構成でまとめ上げることが目的です。

#[Art-Net]
Icon of admin
 空き時間が少なかったのですが、Art-Netのエンコードを試してみました。
 受信したバイナリをデコードし、パラメータをそのままにエンコードして送信です。単純な動作ですが、これが出来なきゃパッチマシンなど絶対無理というテストです。
 卓からの8ユニバースをすべて処理したのですが、負荷の増加は2.5%くらいでした。十分に許容範囲で収まったのは良いことです。
 パッチマシンは8in8outくらいを想定していますが、16in16outも可能だったりして。16ユニバース出る卓が無いので試せないし作ってもオーバースペックなので私は不要かな。機能全体を組み込んでから悩むことですが・・・。

 今のところ1日1課題。
 あとどれくらいの課題があるのかわかりませんが、納期はありませんのでノンビリいきましょう。ここまで出来れば、丁寧にclassライブラリにまとめ上げ、コメントに使い方を明記して後々も使える様にしておきましょう。
 そういう意味ではキー操作やモニタ表示もclassライブラリにして汎用性を高めるのがいいですね。

 と言いますか、このまま書き増しを続けるとソースコードがグチャグチャになって後で後悔しそうです。
 私のメインはPICのアセンブラなのでANSI-Cの関数タイプっぽい書き方をしがちですが、Pythonならオブジェクト指向な書き方をしたいものです。最近、クラス、インスタンス、継承を使う意味と感覚がわかってきましたので、出来るだけそういった書き方をしていこうと思います。
 以前は「継承」ってのが感覚的にわからんかったのですが、関数を束ねて新しい関数を作るだけだと簡単に考えればいいみたいです。ただ、関数は実体なのであっちこっちの関数から同じ関数を同時に呼ぶと衝突が起こります。解決には親関数の中で使う関数を親関数にとって専用にすればいいのですが、同じ様な関数を使うだけ書くのは面倒だしやらたとソースが大きくなるので、ひな形であるクラスから実体のインスタンスを作るという発想になったのだと最近ようやく「感覚的に」理解出来ました。
 その筋の解説書を読むと「継承はオブジェクト指向という高貴な峰の頂」みたいな奇妙に美化した記述が多いのですが、その実態は「楽して俺様関数書きてぇ〜」って俗っぽい発想でした。美化した手段を書くだけで目的を書かない解説書が多いので感覚的にわからんかったのです。

#Python #[Art-Net]
Icon of admin
 本業もボチボチ忙しくなってガラクタ週間も終わりを迎えようとしています。

 現場と打ち合わせの合間にArt-Netです。
 受信したバイナリをそのままの送信出来ないようでは先には進めませんが送信できない問題。
 解決はしましたが、正規マニュアルや先達の書き込みに「これはちがう」とある設定で動いてしまいました。

 基本環境:RaspberryPi4 Rasbian_buster Python3.7.3
 ネットワークインターフェース:内臓LANポート(eth0)、USB-LANアダプタ(eth1)
 IPアドレス:eth0もeth1もArt-Net用に設定済み。
 試験環境:MAdot2でArt-Netを送出、RaspberryPiを経由、中華電機のArt-Netデコーダで受信、レガシーDMXをDoctorMXでモニタ。
 処理内容:eth0で受信したArt-Netのバイナリをeth1で送信するだけ(これが出来なきゃ始まらない)。

-----

import socket

def artnet_rx_tx():
 """ 基本パラメータセット """
 RECV_HOST_NAME = ''
 SENDTO_HOST_NAME = '255.255.255.255'
 PORT = 6454
 """ socket受信の設定 """
 artnet_rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  #UDPによるソケットを宣言(受信で使う)
 artnet_rx_sock.setsockopt(socket.SOL_SOCKET, 25, str("eth0" + '\0').encode('utf-8'))  #ソケットとNICを関連付け
 artnet_rx_sock.bind((RECV_HOST_NAME, PORT))  #送信元とポートをソケットに関連付け この場合はどこからの送信でも受けるって意味になる
 """ socket送信の設定 """
 artnet_tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  #UDPによるソケットを宣言(送信で使う)
 artnet_tx_sock.setsockopt(socket.SOL_SOCKET, 25, str("eth1" + '\0').encode('utf-8'))  #ソケットとNICを関連付け
 artnet_tx_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)  #ソケットをブロードキャストとして使う宣言
 """ 中継 """
 for i in range(800):  #繰り返し
  artnet_rx_bytes, addr = artnet_rx_sock.recvfrom(1024)  #受信処理
  if len(artnet_rx_bytes) > 18:  #受信データ長が最低長以上かを確認 下行とandで一文にしても意味は同じですがヘッダー長を下回った時にエラーになる
   if artnet_rx_bytes[0:12] == b'Art-Net\x00\x00\x50\x00\x0e': #DMXの値データだけを選別 ヘッダーチェック
    artnet_tx_sock.sendto(artnet_rx_bytes, (SENDTO_HOST_NAME, PORT)) #送信処理 ここがわからんで時間を喰う
 """ 終了操作 """
 artnet_rx_sock.close()  #ソケットの仕舞い
 artnet_tx_sock.close()  #ソケットの仕舞い

※ 行頭の空白と#は全角で書いていますので、このままコピペするとエラーになります。
-----

 for文による繰り返しで800回中継を行うテストソースです。

 ポイントはBroadcastの送信先を指示する「SENDTO_HOST_NAME」です。socket.sendtoのパラメータです。「RECV_HOST_NAME」と同様に空白データを割り付けるベシとされるのが一般的ですが動きません。Broadcastアドレスを示す古い方法の'255.255.255.255'にしたところ稼働したという話です。
 '2.255.255.255'や'10.255.255.255'でも稼働しましたが、'255.255.255.255'はゾーンの末尾アドレスを示すマジックナンバーらしく汎用性が高いと思われます。

 動けばいいのですが、かなりの時間を喰ってしまい課題の残りが明日以降になりました。

 ここまで出来ればパッチマップによる入れ替え処理を作ります。
 壮大な繰り返し処理となりますので、どれだけ簡素に出来るかがカギになります。

#Python #[Art-Net]

■当面の課題

桜のライトアップの季節です。花粉症の季節でもあります。
自分は平気ですが、花粉症の部下は死にそうな顔をしています。

編集

■全文検索:

複合検索窓に切り替える

■複合検索:

  • 投稿者名:
  • 投稿年月:
  • #タグ:
  • カテゴリ:
  • 出力順序:

■日付検索:

■カレンダー:

2022年3月
12345
6789101112
13141516171819
20212223242526
2728293031

■カテゴリ:

■最近の投稿:

最終更新日時:
2024年5月4日(土) 05時49分51秒