ArduinoとVS-C3コントローラーでリレーを操作 ソフトウェア編

スタジオのストロボ位置調節をワイヤレスでやってしまおうプロジェクト後編、ソフトウェア制御の内容です。回路などのハードウェアはハードウェア編に記事があります。

PS2コントローラーのハンドリングはps2x.libを使っています。
大まかな内容はSPIのピンアサイン他初期設定、マクロ名にピン番号を設定、ピンモードを設定。そのあとはループでボタンの状態を取得、それに応じて条件分岐を繰り返すというものです。

ソースコード

SPIピンアサイン

Arduino MEGAを使用しますので、それに合わせてPS2Xで使用するSPIピンアサインを設定します。

/**
 set pins connected to PS2 controller:
 - 1e column: original 
 - 2e colmun: Stef?
 replace pin numbers by the ones you use
 **/ 
 define PS2_DAT        50  //14 MISO
 define PS2_CMD        51  //15 MOSI
 define PS2_SEL        53  //16 SS
 define PS2_CLK        52  //17 SCK

マクロの設定

各ボタンについてマクロ登録します。将来Arduinoの出力ピン設定を変更する際はこの数字を修正します。

アサインしている名称ですが、例としてTOP_L_UPは2台あるハニカムスポットライト(モデルの後頭部に当てる)の左側を上方向に動かすボタンです。

SKY_FALL_A
モデルの上方にあるスカイライトの左側を降ろすボタン
SKY_FALL_B
モデルの上方にあるスカイライトの右側を下降させるボタン
SKY_RISE_B
モデルの上方にあるスカイライトの右側を上昇させるボタン
TOP_R_RISE
トップライトの右側を上昇させるボタン

といったようにストロボと動かす方向を示す内容になっています。

define TOP_L_RIGHT 30
define TOP_L_UP 31
define SKY_FALL_A 2
define SKY_FALL_B 3
define SKY_RISE_B 4
define TOP_R_RISE 5
define TOP_R_FALL 6
define TOP_R_RIGHT 7
define TOP_R_UP 22
define TOP_L_FALL 23
define TOP_L_LEFT 24
define TOP_L_DOWN 25
define SKY_RISE_A 26
define TOP_R_LEFT 27
define TOP_R_DOWN 28
define TOP_L_RISE 29
define ACC_L_LEFT 32
define ACC_L_UP 33
define SKY_BACK_A 34
define SKY_BACK_B 35
define SKY_FWD_B 36
define ACC_R_RISE 37
define ACC_R_FALL 38
define ACC_R_LEFT 39
define ACC_R_UP 40
define ACC_L_RIGHT 42
define ACC_L_DOWN 43
define SKY_FWD_A 44
define ACC_R_RIGHT 45
define ACC_R_DOWN 46

各ボタンの状態取得

ループを繰り返すごとに値を取得、更新します。

   ps2x.read_gamepad(false, vibrate); 
   L_STICK_X = ps2x.Analog(PSS_LX),DEC;
   L_STICK_Y = ps2x.Analog(PSS_LY),DEC;
   R_STICK_X = ps2x.Analog(PSS_RX),DEC;
   R_STICK_Y = ps2x.Analog(PSS_RY),DEC;

ノイズのフィルタリング

受信機がたまに変な信号を受信して勝手にリレーをカチカチ動かしてしまう症状がありました。取得データを連続表示させていると、無操作時にポツポツと断続的にアナログレバーをいきなり右下びっちりの部分に移動したかのようなデータが現れています。

PS2X.libのサンプルコードでは発生しないのですが、自分のプログラムになると発生します。プログラム自体はサンプルコードに読み取りたいボタンを追加しただけなのですが、原因がわからないのでとりあえずソフトウェアで対処しています。偶発的に発生する特定のデータ(アナログスティック値LX=255,LY=255,RX=255,RY=255)は無視するようにしました。

たまにそれ以外のボタンでも一瞬押されていないボタンが押された状態になる症状が起こるので、所定のループ回数(現在 3回)以上ボタンが押し続けられなければ入力に反応しないようにしています。実質120ms以上ボタンが押し続けられるプチ長押し状態だと操作を受け付ける仕組みです。もたつくような長押しの感覚は全くなく良好な反応です。

//初期設定で突発的な数値(スパイクと呼ぶことにします)カウンタとスパイク認定の閾値を設定
 int LD_SPIKE_COUNT = 0; //突発的な値が生じた回数
 int LR_SPIKE_COUNT = 0;
 int RD_SPIKE_COUNT = 0;
 int RR_SPIKE_COUNT = 0;
 int SPIKE_THRESHOLD = 3; //スパイクの閾値
 bool SPIKE = false;
 int ERROR_COUNT = 0;
//読み込んだスティックが突発的な値でない場合に以降の処理を続ける
  ps2x.read_gamepad(false, vibrate);
  if( (ps2x.Analog(PSS_LX) == 255) && (ps2x.Analog(PSS_LY) == 255) && ( ps2x.Analog(PSS_RX) == 255) && (ps2x.Analog(PSS_RY) == 255 )){
  }else{
//ボタンが押し続けられるたらカウンタをインクリメント   
 if(ps2x.Button(PSB_START)) START_SC++; else START_SC = 0;
    if(ps2x.Button(PSB_SELECT)) SELECT_SC++; else SELECT_SC = 0;
    if(ps2x.Button(PSB_GREEN)) TRIANGLE_SC++; else TRIANGLE_SC = 0;
    if(ps2x.Button(PSB_BLUE)) CROSS_SC++; else CROSS_SC = 0;
    if(ps2x.Button(PSB_PINK)) SQUARE_SC++; else SQUARE_SC = 0;
    if(ps2x.Button(PSB_RED)) CIRCLE_SC++; else CIRCLE_SC = 0;
.
.(中略)
.
//閾値(ループ3回分 = 120ms)以上ボタンが押され続けた時に所定の動作を実行
    // RISE
    if( SKY_RISE_SC > SPIKE_THRESHOLD ){
      Serial.println("SKY Rise up"); 
      digitalWrite(SKY_RISE_A,HIGH);
      digitalWrite(SKY_RISE_B,HIGH);
    }else{
      digitalWrite(SKY_RISE_A,LOW);
      digitalWrite(SKY_RISE_B,LOW);
    }
  
    // FALL
    if( SKY_FALL_SC > SPIKE_THRESHOLD ){
      Serial.println("SKY Fall down"); 
      digitalWrite(SKY_FALL_A,HIGH);
      digitalWrite(SKY_FALL_B,HIGH);
    }else{
      digitalWrite(SKY_FALL_A,LOW);
      digitalWrite(SKY_FALL_B,LOW);
    }
  
    // BACKWARD
    if( SKY_BACK_SC > SPIKE_THRESHOLD ){
      Serial.println("SKY Backward"); 
      digitalWrite(SKY_BACK_A,HIGH);
      digitalWrite(SKY_BACK_B,HIGH);
    }else{
      digitalWrite(SKY_BACK_A,LOW);
      digitalWrite(SKY_BACK_B,LOW);
    }
  
    // FORWARD
    if( SKY_FWD_SC > SPIKE_THRESHOLD ){
      Serial.println("SKY Forward"); 
      digitalWrite(SKY_FWD_A,HIGH);
      digitalWrite(SKY_FWD_B,HIGH);
    }else{
      digitalWrite(SKY_FWD_A,LOW);
      digitalWrite(SKY_FWD_B,LOW);
    }
  }

ボタンのアサイン

コントローラーの操作をきちんと受信できるようになったところで各ボタンの役割このようにしました

L1,L2
左トップストロボ上昇、下降
R1,R2
右トップストロボ上昇、下降
左スティック
左トップストロボ上下左右
右スティック
右トップストロボ上下左右
L3(or R3)+L1,L2
左アクセントライト上昇、下降
L3(or R3)+左スティック
左アクセント上下左右
L3(or R3)+右スティック
右アクセント上下左右
十字キー
スカイライト上下前後
十字キー + ○
スカイライト右個別モーター上下前後
十字キー + □
スカイライト左個別モーター上下前後

アナログスティックでトップストロボの前後左右を動かしますが、スティックを押し込む(L3,R3)状態だとアクセントライトの操作に切り替わります。なおループ制御の都合上ボタンの複数押しにもきちんと対応できます。二つのストロボを同時にコントロールできますね。

これらのアサインはプログラム上でいつでも変更可能なので、使い勝手がよくなければ後で簡単に変更できます。

組み込み・設置

ケースの中身
あまり物のHENケースに組み込んでいます
フロントパネル
フロントパネルはアクリル製にして電波を通します
スイッチが入った状態の内部
スイッチONの状態。

D-subケーブルの刺さった状態
ケーブルはヤフオクで落札したDsub25ピンプリンタケーブル

一通りデバッグとテストが終わったのでケースに組み入れます。写真はタカチのHENシリーズです。コントローラーはワイヤレスなので、電波を遮断しないように全面パネルをアクリルにしています。
ついでに USBの口とペアリング、リセットボタンをフロントに設置しました。プログラムの変更が必要になったとき等でもケースを分解せずにPCに接続できます。

完成

自由な立ち位置でストロボのモデリングランプを見ながら位置を決められるようになりました。
一つ気を付けたいのは雑にコントローラーを床に置くとL2/R2ボタンが押しっぱなしになることがあることです。モーターが回り続けますのでその点についての対策をする必要があるかもしれません。
ノイズの件もありますので、完全に自己責任といいますか色々リスクは想定しながらの運用になっています。ワイヤレス部分のトラブルの際はこれまでの操作盤を差し戻せば緊急時の対応も可能とはしています。