全年3月9日の投稿[6件]
2025年 この範囲を時系列順で読む この範囲をファイルに出力する
開発や製作は調光ユニットの作り直しもあります。
LitePuterさんのDX1220を2台入れた14Uの物が数台ありますが、しばらく前にパッケージしたのでアナログ信号のコネクタを付けていました。今となっては不用ですし代わりにスプリッターを入れておきたい。
#器具の製作
LitePuterさんのDX1220を2台入れた14Uの物が数台ありますが、しばらく前にパッケージしたのでアナログ信号のコネクタを付けていました。今となっては不用ですし代わりにスプリッターを入れておきたい。
#器具の製作
2023年 この範囲を時系列順で読む この範囲をファイルに出力する
RaspberryPi4BのACT-LEDをGPIOに出力してみました。
/boot/config.txtに設定を追加します。
以下はGPIO24(18番ピン)に出力する設定です。他のピンでも動くと思います。
$ sudo vi /boot/config.txt
# 末尾[all]の後に次を加えます。
dtparam=act_led_gpio=24
再起動すると基板上の緑のLEDの挙動がGPIO24に出ます。
やりたいことはUSB電源の制御で、カーネルが読み込まれたらONにし、カーネルが落ちたらOFFにしたいのです。再起動においてUSBデバイスをリセットするためにUSB電源を一度落とすことが目的です。
更に設定を追加してACT-LEDを常時点灯にすると求める動作を得られるようです。
$ sudo vi /boot/config.txt
dtparam=act_led_gpio=24,act_led_trigger=default-on,act_led=on
起動後にカーネルが読み込まれるとGPIOがHになり、シャットダウンもしくは再起動でカーネルが落ちるとLになります。それぞれのタイミングも良さそうです。
今日はLEDで出力を見ただけですが、実際にリレーを動かすならプルダウンした上にトランジスタ等でバッファする必要があるでしょう。
RaspberryPiのUSB電源はスクリプトで制御可能ですし、リレーを動かすだけならGPIOを操作すればいいのですが、各種モジュールが読み込まれる前に電源を投入し、各種モジュールが落ちてから電源を切りたいので意味が違います。
カーネルが落ちたらUSB電源も落ちればいいのですが、RaspberryPiのUSB電源はPWR-LEDの標準動作と同じ挙動っぽいので、今回はACT-LEDを用いることにします。
#RaspberryPi
/boot/config.txtに設定を追加します。
以下はGPIO24(18番ピン)に出力する設定です。他のピンでも動くと思います。
$ sudo vi /boot/config.txt
# 末尾[all]の後に次を加えます。
dtparam=act_led_gpio=24
再起動すると基板上の緑のLEDの挙動がGPIO24に出ます。
やりたいことはUSB電源の制御で、カーネルが読み込まれたらONにし、カーネルが落ちたらOFFにしたいのです。再起動においてUSBデバイスをリセットするためにUSB電源を一度落とすことが目的です。
更に設定を追加してACT-LEDを常時点灯にすると求める動作を得られるようです。
$ sudo vi /boot/config.txt
dtparam=act_led_gpio=24,act_led_trigger=default-on,act_led=on
起動後にカーネルが読み込まれるとGPIOがHになり、シャットダウンもしくは再起動でカーネルが落ちるとLになります。それぞれのタイミングも良さそうです。
今日はLEDで出力を見ただけですが、実際にリレーを動かすならプルダウンした上にトランジスタ等でバッファする必要があるでしょう。
RaspberryPiのUSB電源はスクリプトで制御可能ですし、リレーを動かすだけならGPIOを操作すればいいのですが、各種モジュールが読み込まれる前に電源を投入し、各種モジュールが落ちてから電源を切りたいので意味が違います。
カーネルが落ちたらUSB電源も落ちればいいのですが、RaspberryPiのUSB電源はPWR-LEDの標準動作と同じ挙動っぽいので、今回はACT-LEDを用いることにします。
#RaspberryPi
インターカムのパワーサプライは3台完成。出来る限り見た目も良くしたのでそれっぽく見えます(自画自賛)。
本業も忙しいのですが、この調子で棚上げ課題を済ませたいところです。
次は「裸族のパイ」です。
HDDケースの「裸族のカプセルホテル」の中にRaspberryPiを入れてサーバー機にするものです。
筐体の改造などは終わっていて、RaspberryPiのACT信号によるUSB電源の制御を残すだけなのでそれほど難しくないハズです。
「裸族のパイ」は自宅サーバーの省電力化のためにも必要なので速やかに進めたいところです。
追記
せっかくなのでパワーサプライの記念撮影

ケーブルに隠れていますが、3枚目の写真の右側にターミネーターを実装した分岐基板があります。
以前から使っているパワーサプライはXLRコネクタの内側端子にターミネータの部品を直接ハンダ付けしていますが、見た目も悪いし機械強度も不安なので、この基板に換装しようと思います。
#電子工作
本業も忙しいのですが、この調子で棚上げ課題を済ませたいところです。
次は「裸族のパイ」です。
HDDケースの「裸族のカプセルホテル」の中にRaspberryPiを入れてサーバー機にするものです。
筐体の改造などは終わっていて、RaspberryPiのACT信号によるUSB電源の制御を残すだけなのでそれほど難しくないハズです。
「裸族のパイ」は自宅サーバーの省電力化のためにも必要なので速やかに進めたいところです。
追記
せっかくなのでパワーサプライの記念撮影



ケーブルに隠れていますが、3枚目の写真の右側にターミネーターを実装した分岐基板があります。
以前から使っているパワーサプライはXLRコネクタの内側端子にターミネータの部品を直接ハンダ付けしていますが、見た目も悪いし機械強度も不安なので、この基板に換装しようと思います。
#電子工作
2022年 この範囲を時系列順で読む この範囲をファイルに出力する
Art-Netを受信した後、送信元別だった受信値をミックス(HTP)する方法。
numpy.maxを用いれば簡単
受信値を3次元のnumpy.arrayで保存します。
3次元のnumpy.arrayはエクセルでイメージするとわかりやすいかなと。
1スロットの受信値は0-255の数値で、これが横方向(行)に512個並んだ状態をユニバースとします。
これをルート別に縦方向(列)で並べます。ここまでは縦横の1枚のシートです。
この1枚を送信元別のシートとし、レイヤーとして重ねます。もちろん、スロットアドレスとルートは同様にします。
あとはレイヤーを串刺しで最大値を得ればHTPでミックスしたルートとスロットの2次元のnumpu.arrayを得られます。
numpyをnpの名前でimportし、3次元のnumpy.arrayをan_cache_senders_route、最大値の2次元のnumpy.arrayをan_cache_htpとすると次の様になります。
an_cache_htp = np.max( an_cache_senders_route, axis=0 )
こんな感じの1行で計算出来ます。axis=0は最大値を得る次元方向の指示です。3次元なら、axis=2は横で、axis=1は縦で、axis=0は奥行という指示です。
以下、ちょいとオレメモ
受信値、付随するデータ
an_bytes 受信したArt-Netパケットのデータ(type=bytes、別途デコード必要)
an_sender_ipaddress 受信したArt-Netパケットの送信元IPアドレス(type=string、4つのドット切り10進数 IPv4の一般的な表記)
an_received_datetime 受信された時点でdatetime.datetime.now()により取得した日時(type=datetime.datetime)
処理の処理を指示するデータ
an_universes2route 対象ユニバースの1次元配列 ( Net, Subnet, Universe )[ ルート ]
受信値を処理、管理するデータ
an_ipaddress_senders 送信元のIPアドレスの1次元配列 IPアドレス [ 送信元 ]
an_datetime_senders 送信元ごとの最終受信日時の1次元配列 最終受信日時 [ 送信元 ]
an_datetime_senders_route 送信元ごとにルートの最終受信日時の2次元配列 最終受信日時 [ 送信元, ルート ]
an_cache_senders_route 送信元とルートごとに受信値を保存する3次元配列 受信値 [ 送信元, ルート, スロットアドレス ]
an_cache_htp 次の処理へ渡す処理済み受信値の2次元配列 受信値 [ ルート, スロットアドレス ]
※ [ ]内はインデックスの要素([3次元目,2次元目,1次元目])
※ 同名のindexは同じ値になるように設定
#an_ipaddress_senders から an_sender_ipaddress と同じIPアドレスを持つ[ 送信元 ]のindex配列を得る
list( zip( *np.where( an_ipaddress_senders == an_sender_ipaddress ) ) )
※ 受信した際に重複しない様に送信元情報を保存してインデックスを発行し、送信元別に日時と受信値を保存するために使う。
※ ただし、対象のユニバースを送って来ない送信元は無いものとする。早い段階でフィルタしないと後が面倒。
#an_datetime_senders から現在日時より1秒以上前の日時を持つ[ 送信元 ]のindexの配列を得る
list( zip( *np.where( an_datetime_senders < ( datetime.datetime.now() - datetime.timedelta( seconds=1 ) ) ) ) )
※ 送信元の存在を確認するために使う。1秒間受信が無い送信元は無いものとする。
#an_datetime_senders_route から現在日時より1秒以上前の日時を持つ[ 送信元, ルート ]のindexの配列を得る
list( zip( *np.where( an_datetime_senders_route < ( datetime.datetime.now() - datetime.timedelta( seconds=1 ) ) ) ) )
※ ユニバースの存在を確認するために使う。1秒間受信が無いユニバース(=送信元,ルート)はゼロデータにする。
#Python #[Art-Net]
numpy.maxを用いれば簡単
受信値を3次元のnumpy.arrayで保存します。
3次元のnumpy.arrayはエクセルでイメージするとわかりやすいかなと。
1スロットの受信値は0-255の数値で、これが横方向(行)に512個並んだ状態をユニバースとします。
これをルート別に縦方向(列)で並べます。ここまでは縦横の1枚のシートです。
この1枚を送信元別のシートとし、レイヤーとして重ねます。もちろん、スロットアドレスとルートは同様にします。
あとはレイヤーを串刺しで最大値を得ればHTPでミックスしたルートとスロットの2次元のnumpu.arrayを得られます。
numpyをnpの名前でimportし、3次元のnumpy.arrayをan_cache_senders_route、最大値の2次元のnumpy.arrayをan_cache_htpとすると次の様になります。
an_cache_htp = np.max( an_cache_senders_route, axis=0 )
こんな感じの1行で計算出来ます。axis=0は最大値を得る次元方向の指示です。3次元なら、axis=2は横で、axis=1は縦で、axis=0は奥行という指示です。
以下、ちょいとオレメモ
受信値、付随するデータ
an_bytes 受信したArt-Netパケットのデータ(type=bytes、別途デコード必要)
an_sender_ipaddress 受信したArt-Netパケットの送信元IPアドレス(type=string、4つのドット切り10進数 IPv4の一般的な表記)
an_received_datetime 受信された時点でdatetime.datetime.now()により取得した日時(type=datetime.datetime)
処理の処理を指示するデータ
an_universes2route 対象ユニバースの1次元配列 ( Net, Subnet, Universe )[ ルート ]
受信値を処理、管理するデータ
an_ipaddress_senders 送信元のIPアドレスの1次元配列 IPアドレス [ 送信元 ]
an_datetime_senders 送信元ごとの最終受信日時の1次元配列 最終受信日時 [ 送信元 ]
an_datetime_senders_route 送信元ごとにルートの最終受信日時の2次元配列 最終受信日時 [ 送信元, ルート ]
an_cache_senders_route 送信元とルートごとに受信値を保存する3次元配列 受信値 [ 送信元, ルート, スロットアドレス ]
an_cache_htp 次の処理へ渡す処理済み受信値の2次元配列 受信値 [ ルート, スロットアドレス ]
※ [ ]内はインデックスの要素([3次元目,2次元目,1次元目])
※ 同名のindexは同じ値になるように設定
#an_ipaddress_senders から an_sender_ipaddress と同じIPアドレスを持つ[ 送信元 ]のindex配列を得る
list( zip( *np.where( an_ipaddress_senders == an_sender_ipaddress ) ) )
※ 受信した際に重複しない様に送信元情報を保存してインデックスを発行し、送信元別に日時と受信値を保存するために使う。
※ ただし、対象のユニバースを送って来ない送信元は無いものとする。早い段階でフィルタしないと後が面倒。
#an_datetime_senders から現在日時より1秒以上前の日時を持つ[ 送信元 ]のindexの配列を得る
list( zip( *np.where( an_datetime_senders < ( datetime.datetime.now() - datetime.timedelta( seconds=1 ) ) ) ) )
※ 送信元の存在を確認するために使う。1秒間受信が無い送信元は無いものとする。
#an_datetime_senders_route から現在日時より1秒以上前の日時を持つ[ 送信元, ルート ]のindexの配列を得る
list( zip( *np.where( an_datetime_senders_route < ( datetime.datetime.now() - datetime.timedelta( seconds=1 ) ) ) ) )
※ ユニバースの存在を確認するために使う。1秒間受信が無いユニバース(=送信元,ルート)はゼロデータにする。
#Python #[Art-Net]
PICでDMX512を出力する際、面倒なのがBreakTimeです。
一般的なUARTでDMX512の様に長いBreakTimeが使われることは無いためか、PICにはそのような機能がありません。何らかのチカラ技で作らないといけません。
私が最終的にたどり着いた方法は、
1)USARTが出力されるI/Oピンをプルダウンしてアイドル・ローにしておく。
2)BreakTimeは0x00の空送信で作る。ただし、0x00送信でもStopBit(H)が発生するので、以下(3)の方法で消す。
3)BreakTimeの空送信が始まってからStopBitが始まるまでの間(Lが続く間)にTRIS(I/Oピンの入出力方向を決めるフラグ)を入力に切り替える。入力にするとI/Oピンがハイインピーダンス(Z)になり、プルダウンされているためRS485ドライバに届く信号はLを維持する。
4)BreakTimeの時間に相当する空送信する。
5)BreakTimeの終わりというか次のフレームの送信開始前に0x00を送信してTRISを出力に切り替える。0x00送信のStopBitがMarkAfterBreakとなる。ただ、MarkAfterBreakは少し長い方が安定するので、0xCO(b11000000)などのMSB詰めの数値を使ってMarkAfterBreakを長くしてもいい。
といった内容です。
これならタイマー処理をせずにBreakTimeを作れます。
BreakTimeを表すデータをBreakTimeZero、BreakTimeZeroの始まりのバイトをBreakTimeNose、最後をBreakTimeTailと勝手に呼んでますが、RaspberryPiからのSPIデータをBreakTimeTailから始まるモノにしておけばPIC側の処理は凄く簡単です。
0)RaspberryPiからRESET信号(実際にはCSを用いる)をPICに送り、PICはこれを見て送信カウンタをクリアしてUSART.TXピンのTRISを入力に切り替えておく。アイドル・ロー。
1)SPIの最初のバイト(BreakTimeTail)を受信したら、USARTに渡して送信し、3bit分待ってからUSART.TXピンのTRISを出力に切り替える。以下、受信値を1バイト送信するごとに送信カウンタをインクリメントする。
2)512スロットを送信した後のバイトはBreakTimeNoseになる。ただ、PICのUSARTは1ワード分のキャッシュを持っているので、BreakTimeZeroの2バイト目をUSARTに渡した後(BreakTimeNoseが送信開始された後)、3bit分待ってからTRISを入力に切り替えてBrakTimeとする。送信制御は送信カウンタを用いる。
3)以下、SPIのデータが終了(RaspberryPiからのCSで確認)したら、送信カウンタをクリアしてSPIを受信待機にする。=>(1)に戻る。
4)BreakTimeZeroを送信する前にSPIが終わってしまったらエラー。TRISを入力に切り替えてBrakTimeにしておくなど、エラー処理を行う。
5)TRISの切り替えの前に3bit分待つのは、次の送信バイトの受け入れがStopBit中に可能になるからです。
こんな感じかな。
#電子工作
一般的なUARTでDMX512の様に長いBreakTimeが使われることは無いためか、PICにはそのような機能がありません。何らかのチカラ技で作らないといけません。
私が最終的にたどり着いた方法は、
1)USARTが出力されるI/Oピンをプルダウンしてアイドル・ローにしておく。
2)BreakTimeは0x00の空送信で作る。ただし、0x00送信でもStopBit(H)が発生するので、以下(3)の方法で消す。
3)BreakTimeの空送信が始まってからStopBitが始まるまでの間(Lが続く間)にTRIS(I/Oピンの入出力方向を決めるフラグ)を入力に切り替える。入力にするとI/Oピンがハイインピーダンス(Z)になり、プルダウンされているためRS485ドライバに届く信号はLを維持する。
4)BreakTimeの時間に相当する空送信する。
5)BreakTimeの終わりというか次のフレームの送信開始前に0x00を送信してTRISを出力に切り替える。0x00送信のStopBitがMarkAfterBreakとなる。ただ、MarkAfterBreakは少し長い方が安定するので、0xCO(b11000000)などのMSB詰めの数値を使ってMarkAfterBreakを長くしてもいい。
といった内容です。
これならタイマー処理をせずにBreakTimeを作れます。
BreakTimeを表すデータをBreakTimeZero、BreakTimeZeroの始まりのバイトをBreakTimeNose、最後をBreakTimeTailと勝手に呼んでますが、RaspberryPiからのSPIデータをBreakTimeTailから始まるモノにしておけばPIC側の処理は凄く簡単です。
0)RaspberryPiからRESET信号(実際にはCSを用いる)をPICに送り、PICはこれを見て送信カウンタをクリアしてUSART.TXピンのTRISを入力に切り替えておく。アイドル・ロー。
1)SPIの最初のバイト(BreakTimeTail)を受信したら、USARTに渡して送信し、3bit分待ってからUSART.TXピンのTRISを出力に切り替える。以下、受信値を1バイト送信するごとに送信カウンタをインクリメントする。
2)512スロットを送信した後のバイトはBreakTimeNoseになる。ただ、PICのUSARTは1ワード分のキャッシュを持っているので、BreakTimeZeroの2バイト目をUSARTに渡した後(BreakTimeNoseが送信開始された後)、3bit分待ってからTRISを入力に切り替えてBrakTimeとする。送信制御は送信カウンタを用いる。
3)以下、SPIのデータが終了(RaspberryPiからのCSで確認)したら、送信カウンタをクリアしてSPIを受信待機にする。=>(1)に戻る。
4)BreakTimeZeroを送信する前にSPIが終わってしまったらエラー。TRISを入力に切り替えてBrakTimeにしておくなど、エラー処理を行う。
5)TRISの切り替えの前に3bit分待つのは、次の送信バイトの受け入れがStopBit中に可能になるからです。
こんな感じかな。
#電子工作
SPIでレガシーDMXを出力する回路の基本要素は揃いました。PICをプログラムして実験する段階です。
本業が忙しくなってしまったので棚上げですが、PICの基本設計は進めましょう。
PICは12F1822を使います。PIC12とありますが、PIC16系の8ピン版と思っていい製品です。
ピンアサインは次の通りです。
拡張ミッドレンジPICにはモジュールのアサインピンをある程度切り替えられる機能があります。
TRISとはI/Oピンの入出力方向を設定する要素です。
VDD
VSS(GND)
RA0 TX_Pilot_LED TRIS-OUTPUT(汎用I/Oとして使い、送信が行われるとLEDを点灯させます)
RA1 SPI.SCK TRIS-INPUT
RA2 SPI.SDI TRIS-INPUT
RA3 DMX.RESET TRIS-INPUT
RA4 USART.TX TRIS-OUTPUT(ただし、BreakTimeを作るためにINPUTにすることがあります)
RA5 CSC1 TRIS-INPUT(クロックの設定は優先順位が高いので、TRISはどちらでも機能します)
これには隠れたコツがあります。
SPIを使うならSPI.SDOがあります。使わないI/Oですがどこかにアサインしなければなりませんので、USART.TXと同じRA4にアサインします。被って出力がおかしくなりそうですが、SPIよりも優先順位が高いUSART.TXが出力されますから大丈夫。逆だったら困りましたけどね。
クロック発信子にはクリスタルオシレータ(8MHz)SG-8002DC(3.3V)を使います。普段はPIC1個に対し水晶発振子を1個使うのですが、今回は同じクロックレートで動く複数のPICを1枚の基板に載せますので、部品点数を減らす意味も含めてこれを使います。PICのI/Oピンも減るし。
#電子工作
本業が忙しくなってしまったので棚上げですが、PICの基本設計は進めましょう。
PICは12F1822を使います。PIC12とありますが、PIC16系の8ピン版と思っていい製品です。
ピンアサインは次の通りです。
拡張ミッドレンジPICにはモジュールのアサインピンをある程度切り替えられる機能があります。
TRISとはI/Oピンの入出力方向を設定する要素です。
VDD
VSS(GND)
RA0 TX_Pilot_LED TRIS-OUTPUT(汎用I/Oとして使い、送信が行われるとLEDを点灯させます)
RA1 SPI.SCK TRIS-INPUT
RA2 SPI.SDI TRIS-INPUT
RA3 DMX.RESET TRIS-INPUT
RA4 USART.TX TRIS-OUTPUT(ただし、BreakTimeを作るためにINPUTにすることがあります)
RA5 CSC1 TRIS-INPUT(クロックの設定は優先順位が高いので、TRISはどちらでも機能します)
これには隠れたコツがあります。
SPIを使うならSPI.SDOがあります。使わないI/Oですがどこかにアサインしなければなりませんので、USART.TXと同じRA4にアサインします。被って出力がおかしくなりそうですが、SPIよりも優先順位が高いUSART.TXが出力されますから大丈夫。逆だったら困りましたけどね。
クロック発信子にはクリスタルオシレータ(8MHz)SG-8002DC(3.3V)を使います。普段はPIC1個に対し水晶発振子を1個使うのですが、今回は同じクロックレートで動く複数のPICを1枚の基板に載せますので、部品点数を減らす意味も含めてこれを使います。PICのI/Oピンも減るし。
#電子工作