2022年の投稿(時系列順)[394件](11ページ目)
2022年3月 この範囲を新しい順で読む この範囲をファイルに出力する
レガシーDMX512の出力インターフェースを作るには少し工夫が必要です。
RaspberryPiでもPICでも使えるインターフェースで十分な速度を持つのはSPIです。I2Cは便利ですがPICが最大400kbpsなので1ユニバースしか扱えません。
かといって、高速のSPIで複数のPICで扱うのはかなり難しい。解決するにはロジックICを用いた分岐回路を用いるのが良さそうですが、ICが5個くらい必要なので実装面積に問題があります。
ならばGALを使うのはどうかと。FPGAやCPLDの祖先であり、今回の構成に丁度良いスペックです。何と言っても安い。
ただし、GALはすでに過去の物で開発は終わっています。決して多くないニーズに応えて生産されているだけですし、開発ソフトウェアも正規対応がWindowsXP止まり。
されど、10個未満のTTL-ICで組む様な事を1個で組めるのは便利ですし、数十MHzまで対応するので、RaspberryPiなどのLinux系小型マイコンの外付け回路を組むには丁度良いと思います。
便利そうですが微妙なので導入を控えていましたが、改めて調べたところ書き込み装置などの開発用品が安くなっていたので、この際環境を整えてみましょう。
RaspberryPiとPICとGALを組み合わせれば製品が作りやすくなるような気がします。
#電子工作
RaspberryPiでもPICでも使えるインターフェースで十分な速度を持つのはSPIです。I2Cは便利ですがPICが最大400kbpsなので1ユニバースしか扱えません。
かといって、高速のSPIで複数のPICで扱うのはかなり難しい。解決するにはロジックICを用いた分岐回路を用いるのが良さそうですが、ICが5個くらい必要なので実装面積に問題があります。
ならばGALを使うのはどうかと。FPGAやCPLDの祖先であり、今回の構成に丁度良いスペックです。何と言っても安い。
ただし、GALはすでに過去の物で開発は終わっています。決して多くないニーズに応えて生産されているだけですし、開発ソフトウェアも正規対応がWindowsXP止まり。
されど、10個未満のTTL-ICで組む様な事を1個で組めるのは便利ですし、数十MHzまで対応するので、RaspberryPiなどのLinux系小型マイコンの外付け回路を組むには丁度良いと思います。
便利そうですが微妙なので導入を控えていましたが、改めて調べたところ書き込み装置などの開発用品が安くなっていたので、この際環境を整えてみましょう。
RaspberryPiとPICとGALを組み合わせれば製品が作りやすくなるような気がします。
#電子工作
本日は久しぶりの現地照明。現場って感じでホッとします。
実機での研究や試験は出来ませんが、アイデアが出てきたら整理しています。今日出てきたアイデアはArt-Netの受信に関するものです。
Art-Netは複数の送信機を同じネットワークに接続することが出来ます。正しくはないけど間違ってもいない使い方ですが、期待してない挙動が起こっても面白くないので対応しといた方が良さそう。
socketによる受信からはデータと送信元アドレスを取り出せますから、送信元アドレスをキーにデータを仕分けます。採用するデータは送信元を一つに限るのが道理な気もしますが、同じユニバース・スロットの最大値を採用したらHTPのミキサーになってしまいます。
ミキサーは欲しい機能ですが、バカよけを施した副産物でミキサーになりそう。
#[Art-Net]
実機での研究や試験は出来ませんが、アイデアが出てきたら整理しています。今日出てきたアイデアはArt-Netの受信に関するものです。
Art-Netは複数の送信機を同じネットワークに接続することが出来ます。正しくはないけど間違ってもいない使い方ですが、期待してない挙動が起こっても面白くないので対応しといた方が良さそう。
socketによる受信からはデータと送信元アドレスを取り出せますから、送信元アドレスをキーにデータを仕分けます。採用するデータは送信元を一つに限るのが道理な気もしますが、同じユニバース・スロットの最大値を採用したらHTPのミキサーになってしまいます。
ミキサーは欲しい機能ですが、バカよけを施した副産物でミキサーになりそう。
#[Art-Net]
オレメモ
Pythonのsocket.recvfromでタイムアウト処理をする。
socketのインスタンスをsockとした場合、sock.recvfromの前に
sock.settimeout(<タイムアウトの秒数>)
とする。
sock.recvfrom(<バッファ数>) を try: で実行し、except socket.timeout: でタイムアウトエラーを拾う。
#Python
Pythonのsocket.recvfromでタイムアウト処理をする。
socketのインスタンスをsockとした場合、sock.recvfromの前に
sock.settimeout(<タイムアウトの秒数>)
とする。
sock.recvfrom(<バッファ数>) を try: で実行し、except socket.timeout: でタイムアウトエラーを拾う。
#Python
実機を離れて考えを進めると抜けが見えてきます。
一つ前のオレメモはArt-Netを受信していないときの対策です。タイムアウトを設定しませんと延々と待つだけの無限ループになり、適切な終了すら出来なくなります。一定時間受信が無いならそれをユーザーに伝えることも大切な処理です。
その前の送信元が複数になった時の対策もそうです。ミキサー機能が無いと謳っても複数の接続をする人が居ないとも限りませんし、そんな人に限って勝手な想像通りに動かないと作った奴が悪いとかダメな製品だとかレッテルを貼ってくるものです。この件については副産物としてミキサー機能に至れそうな可能性が見えましたので「災い転じて何とやら」ですが、先入観を排除して可能性を熟慮することの大切さを改めて痛感です。
受信処理は試行錯誤しながらディレイを可能にしたことでソースコードが読みにくくなってきましたので、タイムアウトと複数の送信元への対応を加えながら読みやすく書き直しです。
パラメータが増えてくると変数の命名に配慮するだけでも読みやすさが違ってきますので、この辺りも含めてよく考えていきます。
ここまでやってきて、思った以上に受信処理が大切なことに驚いています。
ミキサーしかり、ディレイしかり、思い描いている機能の大半が受信直後の処理にかかっていたとは当初は全く思いもしませんでした。
この辺りは所詮アマチュアの所業でありますが、まだまだ修行です。
#Python #[Art-Net]
一つ前のオレメモはArt-Netを受信していないときの対策です。タイムアウトを設定しませんと延々と待つだけの無限ループになり、適切な終了すら出来なくなります。一定時間受信が無いならそれをユーザーに伝えることも大切な処理です。
その前の送信元が複数になった時の対策もそうです。ミキサー機能が無いと謳っても複数の接続をする人が居ないとも限りませんし、そんな人に限って勝手な想像通りに動かないと作った奴が悪いとかダメな製品だとかレッテルを貼ってくるものです。この件については副産物としてミキサー機能に至れそうな可能性が見えましたので「災い転じて何とやら」ですが、先入観を排除して可能性を熟慮することの大切さを改めて痛感です。
受信処理は試行錯誤しながらディレイを可能にしたことでソースコードが読みにくくなってきましたので、タイムアウトと複数の送信元への対応を加えながら読みやすく書き直しです。
パラメータが増えてくると変数の命名に配慮するだけでも読みやすさが違ってきますので、この辺りも含めてよく考えていきます。
ここまでやってきて、思った以上に受信処理が大切なことに驚いています。
ミキサーしかり、ディレイしかり、思い描いている機能の大半が受信直後の処理にかかっていたとは当初は全く思いもしませんでした。
この辺りは所詮アマチュアの所業でありますが、まだまだ修行です。
#Python #[Art-Net]
オレメモ
● Art-Netの受信の準備でするべきこと。
・受信のタイムアウトを定義し、タイムアウトを例外としてキチンと処理する。
● Art-Netを受信したらするべきこと。
・受信した「Art-Netのバイナリデータ」に「いつ」「どこからか(送信元)」を絡めて受信データとする。
・ユニバースと内部ルートの対照データを基に、データの参照キーを「ユニバース」から「ルート」に変換してキャッシュする。
・「いつ」をキーに送信元からの送信が無くなったと見なせるならキャッシュも含め送信元情報を消去する。
・「いつ」をキーにキャッシュの有効期限が切れたならキャッシュのレベル値をすべてゼロにする。
・送信元ごとのキャッシュをルートで丸めて一意のキャッシュにする。
#[Art-Net]
● Art-Netの受信の準備でするべきこと。
・受信のタイムアウトを定義し、タイムアウトを例外としてキチンと処理する。
● Art-Netを受信したらするべきこと。
・受信した「Art-Netのバイナリデータ」に「いつ」「どこからか(送信元)」を絡めて受信データとする。
・ユニバースと内部ルートの対照データを基に、データの参照キーを「ユニバース」から「ルート」に変換してキャッシュする。
・「いつ」をキーに送信元からの送信が無くなったと見なせるならキャッシュも含め送信元情報を消去する。
・「いつ」をキーにキャッシュの有効期限が切れたならキャッシュのレベル値をすべてゼロにする。
・送信元ごとのキャッシュをルートで丸めて一意のキャッシュにする。
#[Art-Net]
オレメモ
受信時に得られるArt-Netの情報
・Art-Netパケットのバイナリデータ
・送信元IPv4アドレス
・受信日時
指示データ
・ユニバースとルートの対照マップ
受信処理のアウトプット
・ルートで仕訳けた直近の受信値(直近値)
処理の第一段階
・バイナリデータのデコード
・インデックスをユニバースからルートへ変換
処理の第二段階
・送信元を有効期限でフィルタ出来るキャッシュ
・送信元ごとに、デコードしたデータを有効期限でフィルタ出来るキャッシュ
処理の第三段階
・送信元を有効期限でフィルタ(送信元が期限切れなら受信データもクリア)
・受信データを有効期限でフィルタ
処理の第四段階
・送信元ごとの受信データを一つにまとめ、ルート単位の直近値とする(実質ミックス処理)
処理の第五段階
・直近値を次に渡す
#[Art-Net]
受信時に得られるArt-Netの情報
・Art-Netパケットのバイナリデータ
・送信元IPv4アドレス
・受信日時
指示データ
・ユニバースとルートの対照マップ
受信処理のアウトプット
・ルートで仕訳けた直近の受信値(直近値)
処理の第一段階
・バイナリデータのデコード
・インデックスをユニバースからルートへ変換
処理の第二段階
・送信元を有効期限でフィルタ出来るキャッシュ
・送信元ごとに、デコードしたデータを有効期限でフィルタ出来るキャッシュ
処理の第三段階
・送信元を有効期限でフィルタ(送信元が期限切れなら受信データもクリア)
・受信データを有効期限でフィルタ
処理の第四段階
・送信元ごとの受信データを一つにまとめ、ルート単位の直近値とする(実質ミックス処理)
処理の第五段階
・直近値を次に渡す
#[Art-Net]
RaspberryPiからレガシーDMXを出力する方法を妄想しています。
直接出すのは無理があります。UARTはありますが、2系統出すのが関の山。BreakTimeも出しにくい。
ならば、RaspberryPiからはSPIで出力し、PICで250kbpsのUARTに変換するのがいいかなと。
RaspberryPiからCS(チップセレクト)を使ってPICを選択するのがノーマルな方法ですが、レガシーDMXを出来る限り数多くだすには効率が悪い。SPIを休みなく送りつけたらPICは処理しきれませんので1ワード毎に休み時間を入れないといけない。また、PIC1個毎に一気にデータを送り付けるにはPICがデータをキャッシュ出来なければなりませんが、512バイト以上のメモリを持ったPICは選択肢が少なくピン数も多い。
しかるに、SPIを普通に使ったら2系統扱うのが限界だと思われます。
で、考えた方法が、複数のPIC(レガシーDMX1系統に付き1個使用)がRaspberryPiから1個に見える方法です。
RaspberryPiからは複数のユニバースのデータを適切に並べ替えて一気に送出します。RaspberryPiにとっては一番ストレスが無い方法です。
もちろんPICはこれを捌くことが出来ませんから、RaspberryPiとPICの間に仕掛けを入れます。
SPIはクロック同期型の送信方法ですからデータ線の他にクロック線があります。受信はクロックによって実行されますので、CSがアクティブでも、データ線に変化があっても、クロックが伴わなければ何も起こりません。通常ならCSを用いて受信先を決定しますが、クロックの出力先を仕分けても同じことです。
送信が始まって1から8カウントの間は1番目のPICへSPIのクロックを送り、9から16カウントの間は2番目のPICへSPIのクロックを送り・・・以下末番のPICまで繰り返します。RaspberryPiから送信があっても、クロックが行かない受信器にとってはワードとワードの間の休み時間でしかありません。
これなら、送信するRaspberryPiからはPIC達が1個に見え、受信するPIC達には自分宛のデータがだけが届きます。RaspberryPiが休みなく送信してもPIC側は他が受信している間に処理を進められますし、RaspberryPiの送信タイミングが適切であれば受信したSPIのデータをUARTに渡すだけでPIC内でのスタックは不要です。ピン数が少ないPIC12F1822でも対応可能ということ。
これを実現するクロックの仕分けは汎用ロジックICで行います。
バイナリカウンタ74HC4040
3to8 ラインデコーダ TC74HC138
この二つです。
数日前はGALを使おうかと思ったのですが、16ピンの汎用ロジック2個で可能ならこちらの方がいいかと。ファームウェア書かなくていいし、安いし、30年以上確実に動くし。
バイナリカウンタはクロックをカウントして2進数相当の出力をするICです。これにSPIクロックを入力し、下から4~6bit目の出力を使います。SPIクロックの8倍周期でカウントされる3bitのバイナリと見なせます。
8倍周期の3bitのバイナリをラインデコーダに入れます。ラインデコーダは入力された3bitのバイナリに相当するピンだけ出力します。このデコーダにSPIのクロックも入れれば8カウント毎に送り先が切り替わるクロックが出力されます。
SPIのモードは74HC4040の特性に合わせてmode3がよいと思われます。
文章で伝わりにくいのは承知していますが、アイデアがまとまってスッキリした。
オレメモってことで。
整理しきらないとモヤモヤして本業が手に付かなかったので回路図を描いてみました。気分スッキリ。
折角なので揚げてみました。
クリックして表示されるモノはぼやけてしまいますので、回路を追いたい方はサムネのリンク先の画像本体をダウンロードして見てください。
追記
回路図に間違い発見!
74HC4040のCLKにはSPI_CLKが入らないといけません。
74HC4040から74HC138のA,B,Cに行くのもQ4,Q5,Q6です。なら74HC4020でもいいな。
データは手直ししましたが、ここに再アップするのは面倒。まぁいいか。
さらに追記
クロックカウントの考え方が根本的に間違っているような気が・・・74HC4040(4020)のカウントの進み方がズレてね?最初のビットをサンプリングする前に1カウントされてしまうぞ。
ならばSPIをmode0で使えばいいか?mode0ならアイドル・ローだから74HC138ではなく74HC238か?
考え直し。
#電子工作 #RaspberryPi
直接出すのは無理があります。UARTはありますが、2系統出すのが関の山。BreakTimeも出しにくい。
ならば、RaspberryPiからはSPIで出力し、PICで250kbpsのUARTに変換するのがいいかなと。
RaspberryPiからCS(チップセレクト)を使ってPICを選択するのがノーマルな方法ですが、レガシーDMXを出来る限り数多くだすには効率が悪い。SPIを休みなく送りつけたらPICは処理しきれませんので1ワード毎に休み時間を入れないといけない。また、PIC1個毎に一気にデータを送り付けるにはPICがデータをキャッシュ出来なければなりませんが、512バイト以上のメモリを持ったPICは選択肢が少なくピン数も多い。
しかるに、SPIを普通に使ったら2系統扱うのが限界だと思われます。
で、考えた方法が、複数のPIC(レガシーDMX1系統に付き1個使用)がRaspberryPiから1個に見える方法です。
RaspberryPiからは複数のユニバースのデータを適切に並べ替えて一気に送出します。RaspberryPiにとっては一番ストレスが無い方法です。
もちろんPICはこれを捌くことが出来ませんから、RaspberryPiとPICの間に仕掛けを入れます。
SPIはクロック同期型の送信方法ですからデータ線の他にクロック線があります。受信はクロックによって実行されますので、CSがアクティブでも、データ線に変化があっても、クロックが伴わなければ何も起こりません。通常ならCSを用いて受信先を決定しますが、クロックの出力先を仕分けても同じことです。
送信が始まって1から8カウントの間は1番目のPICへSPIのクロックを送り、9から16カウントの間は2番目のPICへSPIのクロックを送り・・・以下末番のPICまで繰り返します。RaspberryPiから送信があっても、クロックが行かない受信器にとってはワードとワードの間の休み時間でしかありません。
これなら、送信するRaspberryPiからはPIC達が1個に見え、受信するPIC達には自分宛のデータがだけが届きます。RaspberryPiが休みなく送信してもPIC側は他が受信している間に処理を進められますし、RaspberryPiの送信タイミングが適切であれば受信したSPIのデータをUARTに渡すだけでPIC内でのスタックは不要です。ピン数が少ないPIC12F1822でも対応可能ということ。
これを実現するクロックの仕分けは汎用ロジックICで行います。
バイナリカウンタ74HC4040
3to8 ラインデコーダ TC74HC138
この二つです。
数日前はGALを使おうかと思ったのですが、16ピンの汎用ロジック2個で可能ならこちらの方がいいかと。ファームウェア書かなくていいし、安いし、30年以上確実に動くし。
バイナリカウンタはクロックをカウントして2進数相当の出力をするICです。これにSPIクロックを入力し、下から4~6bit目の出力を使います。SPIクロックの8倍周期でカウントされる3bitのバイナリと見なせます。
8倍周期の3bitのバイナリをラインデコーダに入れます。ラインデコーダは入力された3bitのバイナリに相当するピンだけ出力します。このデコーダにSPIのクロックも入れれば8カウント毎に送り先が切り替わるクロックが出力されます。
SPIのモードは74HC4040の特性に合わせてmode3がよいと思われます。
文章で伝わりにくいのは承知していますが、アイデアがまとまってスッキリした。
オレメモってことで。
整理しきらないとモヤモヤして本業が手に付かなかったので回路図を描いてみました。気分スッキリ。
折角なので揚げてみました。
クリックして表示されるモノはぼやけてしまいますので、回路を追いたい方はサムネのリンク先の画像本体をダウンロードして見てください。
追記
回路図に間違い発見!
74HC4040のCLKにはSPI_CLKが入らないといけません。
74HC4040から74HC138のA,B,Cに行くのもQ4,Q5,Q6です。なら74HC4020でもいいな。
データは手直ししましたが、ここに再アップするのは面倒。まぁいいか。
さらに追記
クロックカウントの考え方が根本的に間違っているような気が・・・74HC4040(4020)のカウントの進み方がズレてね?最初のビットをサンプリングする前に1カウントされてしまうぞ。
ならばSPIをmode0で使えばいいか?mode0ならアイドル・ローだから74HC138ではなく74HC238か?
考え直し。
#電子工作 #RaspberryPi
妄想は続けておりますが、本業がそれなりに忙しくなってきました。
現場の日程はそうでもないのですが、「やっぱり開催しよう」的な話が多く準備期間が短い。時間が無いだけならまだいいですが、主催者も混乱しているのが必要が情報がなかなか来ない。知らないウチに話が変わっているなんてこともザラ。前もって大枠はまとめておくとしても、直前に手直しやり直しになるならギリギリまで寝かせても同じこと。「夏休みの宿題は始業式の前の日から」状態です。
そんな渦中の気分転換が工作ってのもおかしな人だと思いますが、趣味趣向は人それぞれってことで。
反動でアイデアが出まくるのは嬉しいやら困るやら・・・
#日常
現場の日程はそうでもないのですが、「やっぱり開催しよう」的な話が多く準備期間が短い。時間が無いだけならまだいいですが、主催者も混乱しているのが必要が情報がなかなか来ない。知らないウチに話が変わっているなんてこともザラ。前もって大枠はまとめておくとしても、直前に手直しやり直しになるならギリギリまで寝かせても同じこと。「夏休みの宿題は始業式の前の日から」状態です。
そんな渦中の気分転換が工作ってのもおかしな人だと思いますが、趣味趣向は人それぞれってことで。
反動でアイデアが出まくるのは嬉しいやら困るやら・・・
#日常
RaspberryPiでレガシーDMXを送出する装置のクロック切替器の回路図を訂正しました。
細かい誤植の訂正とロジックICの変更です。
#電子工作
細かい誤植の訂正とロジックICの変更です。
#電子工作
オレメモ
RaspberryPiのSPIバッファサイズ
※出展:「RasPi 3B+ で最新の spidev_test を使う」
--------
現在の最大転送サイズを確認
$ cat /sys/module/spidev/parameters/bufsiz
4096 (byte)
これが固定値で変更不可といった書き込みが少なくありませんが変更可能です。
変更するには、/boot/cmdline.txt に下記変数を追加。
spidev.bufsiz=<サイズ数値>
拡大可能なサイズ
4096: OK (デフォルト)
16384: OK
65536: OK
1048576: OK (1MB)
4194304: OK (4MB) ⇒ 最大値 (これ以上を設定しても拡大しない)
--------
RaspberryPi4Bも同様だと思いますが、実機で確認してみましょう。
DMX512を8系統出そうと思っていますが、StartCodeやBreakTimeもSPIで送出するので4096バイトでは不足です。
試したところOKでした。
変更するファイルは/boot/cmdline.txtであって/boot/config.txtではありません。
開くと1行にいろいろなコマンドが書いてあります。このコマンド列の末尾に空白を入れてspidev.bufsiz=<サイズ数値>を記述します。
#RaspberryPi
RaspberryPiのSPIバッファサイズ
※出展:「RasPi 3B+ で最新の spidev_test を使う」
--------
現在の最大転送サイズを確認
$ cat /sys/module/spidev/parameters/bufsiz
4096 (byte)
これが固定値で変更不可といった書き込みが少なくありませんが変更可能です。
変更するには、/boot/cmdline.txt に下記変数を追加。
spidev.bufsiz=<サイズ数値>
拡大可能なサイズ
4096: OK (デフォルト)
16384: OK
65536: OK
1048576: OK (1MB)
4194304: OK (4MB) ⇒ 最大値 (これ以上を設定しても拡大しない)
--------
RaspberryPi4Bも同様だと思いますが、実機で確認してみましょう。
DMX512を8系統出そうと思っていますが、StartCodeやBreakTimeもSPIで送出するので4096バイトでは不足です。
試したところOKでした。
変更するファイルは/boot/cmdline.txtであって/boot/config.txtではありません。
開くと1行にいろいろなコマンドが書いてあります。このコマンド列の末尾に空白を入れてspidev.bufsiz=<サイズ数値>を記述します。
#RaspberryPi