X-Plane コクピットの自作に挑戦!
プッシュスイッチでトグルを実現
プッシュボタンの場合は一度押して離すとOnからOffになる、Offになっっても、そのままスイッチをONにしたい場合、つまりトグル状態はラッチ回路を作成すると実現できるが、その分ICを使って回路を追加する必要が出てくる。
スケッチだけで、ONの状態の保持、OFFの状態の保持、を実現したいのですが、単純な0と1のdetarifなら簡単ですが、0と2とか1以外の数字をコントロール使用とするとやっかいになります。以下に分かっただけのスケッチを記述してみました。

X-Plane10本番.rwsw

X-Plane 10.36r1-1

例えばこのF/Dスイッチ、プッシュボタンではないのですが、状態が分かりやすいのでこれで実験しますが、下のスケッチで手元の自作したプッシュボタンを使うと、スイッチは入るが離すと切れてしまいます。
これがプッシュボタンでの特性です。X-Plane上では実際は放してもONの状態を保持しなければなりません。トグル状態のスケッチが必要になります。(※F/Dスイッチは実際は画像と同じトグルスイッチを使用します)
そのままの(プッシュボタンのON-OFFどうりに動いて状態が保持されない)スケッチ
FD_Switch.ino

#include <Bounce.h>
 
Bounce FDSwitch = Bounce(10, 5);      // Pushbutton on pin 3, 5ms debounce
 
// X-Plane objects, 1 datarefFlightDirector_Switch
 
FlightSimInteger AutoPilotFDSwitch;
 
// variables
 
elapsedMillis inactivityTimeout;// an inactivity timeout
 
 
// setup runs once, when Teensy boots.
//
void setup() {
  // initialize all hardware
  pinMode(10, INPUT_PULLUP);  // input pullup mode allows connecting
  
  AutoPilotFDSwitch = XPlaneRef("sim/cockpit/autopilot/autopilot_mode");
 
}
 
// loop runs repetitively, as long as Teensy is powered up
//
void loop() {
  // normally the first step in loop() should update from X-Plane
  FlightSim.update();
 
  // read the pushbuttons, and send X-Plane commands when they're pressed
  FDSwitch.update();
 
  if (FDSwitch.fallingEdge()) {  //立ち下がりエッジを検出
    AutoPilotFDSwitch = 1;
    inactivityTimeout = 0;
  }
  if (FDSwitch.risingEdge()) {  //立ち上がりエッジを検出
    AutoPilotFDSwitch = 0;
  }
 
}

プッシュボタンでトグル状態を実現するスケッチです。
但し、datarefが0か1かの時(on/off)だけ動作します。0と2とかになると、また違うスケッチが必要です。
FD_Switch_Toggle.ino

const int sw=10;		        //プッシュボタンのピン指定
int currentState, previousState=LOW;	//プッシュボタンのピンを現在と前の状態を、どちれもLOWに初期化

FlightSimInteger AutoPilotFDSwitch;

void setup(){
    pinMode(sw, INPUT);
    AutoPilotFDSwitch = XPlaneRef("sim/cockpit/autopilot/autopilot_mode");
}

void loop(){
  FlightSim.update();
  
  	currentState=digitalRead(sw);                  //swが押された状態を見る
  	if(currentState != previousState){             //エッジ検出(もし、スイッチピンが変化したら)
    	  previousState=currentState;                  //最初の状態を、変化した状態に更新する
           if(currentState == HIGH) {                  //更新した値がHIGHなら
     	      AutoPilotFDSwitch = !AutoPilotFDSwitch;  // トグルアクション(!は否定)
              //つまり、HIGHからLOWになるとき否定してHIGHを保持する
      	      digitalWrite(sw, AutoPilotFDSwitch);
          }
	}
}
上のスケッチは、チャタリングが起きた時はまったく反応しませんが、スイッチを押しなおすと動作したりします。

下にまた別のスケッチを作成しましたが、これはチャタリングが起きても反応はするが元に戻ってしまいます。再度ボタンを押すとううまく動作するという状態になります。
これは、スイッチを押すと何らかの動作をするので、反応が分かるという利点があり、またスケッチが少し短くなるという利点もあります。

どちらもうまく動作しないときもありますが、なんとか動作します。チャタリングの問題をクリアすれば確実に動作するのでしょうが、100%うまく動作せるには、相当いろんなことを勉強しなければならないということが分かります。
FD_Switch_Toggle_2.ino

//スケッチが少し短くなる
const int sw=10;		        //プッシュボタンのピン指定
int currentState, previousState=LOW;	//プッシュボタンのピンを現在と前の状態を、どちれもLOWに初期化

FlightSimInteger AutoPilotFDSwitch;

void setup(){
    pinMode(sw, INPUT);
    AutoPilotFDSwitch = XPlaneRef("sim/cockpit/autopilot/autopilot_mode");
}

void loop(){
  FlightSim.update();
  
  	currentState=digitalRead(sw);                  //swが押された状態を見る
          if(currentState == HIGH) {                  //更新した値がHIGHなら
     	      AutoPilotFDSwitch = !AutoPilotFDSwitch;  // トグルアクション(!は否定)
              //つまり、HIGHからLOWになるとき否定してHIGHを保持する
      	      digitalWrite(sw, AutoPilotFDSwitch);
          }
}
別のパターンでも実現できる。
delay(50); によりチャタリングを軽減できるのかも。

又、以下のようなスケッチもある。
FD_Switch_Toggle_3.ino

/* switch
 //入力ピン(プッシュボタン)がローからハイに行くたびに、出力端子はLOWからHIGH又はHIGHからLOWにトグルになります。  
 //回路はデバウンスするためトグル間の最小の遅延があります。(すなわち、ノイズを無視する)
 *
 */

int inPin = 10;         // the number of the input pin
int outPin = 11;       // the number of the output pin

int state = HIGH;      // 現在の出力ピン状態
int reading;           // 入力ピンからの現在の読み取り
int previous = LOW;    // 入力ピンからの前の読み取り

// the follow variables are long's because the time, measured in miliseconds,
// フォロー変数の、timeはlongのためにあり、ミリ秒で測定されます。
// will quickly become a bigger number than can be stored in an int.
// int型に格納することができる数よりも大きな数になります。
long time = 0;         // 出力ピンがトグルされた最後のtime
long debounce = 200;   // the debounce time, increase if the output flickers
                       // debounce時間は、チャタリングする場合は増やします

void setup()
{
  pinMode(inPin, INPUT);
  pinMode(outPin, OUTPUT);
}

void loop()
{
  reading = digitalRead(inPin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  //入力がちょうどLOWとHIGHから行って、我々は回路上のノイズを無視するために十分な長待っていた場合は、
  //出力ピンをトグルし、時間を覚えて
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

    time = millis();    
  }

  digitalWrite(outPin, state);

  previous = reading;
}
下のスケッチが一番近い状態でdatarefが0と1以外でも動作します。しかし、X-Plane上でこのスイッチのクリックが出来なくなる。
いままでのスケッチでは両方できたので、チョット戸惑っているのだが問題ないのだろうか?それさえ気にしなければこれが今のところベストです。
FD_Switch_Toggle_A.ino

//プッシュボタンを離したあともON・OFFを保持する、トグル状態にする 

#define BUTTON 10 
int val = 0; //入力ピンの状態がこの変数(val)に記憶される 
int old_val = 0; //valの前の値を保存しておく変数 
int state = 0; //LEDの状態(0ならオフ、1ならオン) 

FlightSimInteger FlightDirector;

elapsedMillis inactivityTimeout;// an inactivity timeout

void setup() { 
  //pinMode(LED, OUTPUT); //ArduinoにLEDが出力であると伝える 
  pinMode(BUTTON, INPUT_PULLUP); //BUTTONは入力に設定 
  FlightDirector = XPlaneRef("sim/cockpit/autopilot/autopilot_mode");
} 

void loop() { 
  FlightSim.update();
  val = digitalRead(BUTTON); //入力を読み取りvalに格納 
//入力がHIGH(ボタンが押されている)なら状態(state)を変更 
  if((val == LOW) && (old_val == HIGH)) { //この設定がベスト、LOW、HIGHを逆にするとスイッチの状態が変る
    state = 1 - state; 
    delay(50); //この位がチャタリングが起きない(10だと時々起きる)
  } 
  
  old_val = val; //新しい値に更新する
  if(state ==1){ 
    FlightDirector = 0;    //この設定でスタート時にOFFになる
    inactivityTimeout = 0;
  } 
  else { 
   FlightDirector = 1; 
  } 
}
comments powered by Disqus
Contents