X-Plane コクピットの自作に挑戦!
X-Plane ロータリーエンコーダコントロール
このページまだ検証が済んでいません。あくまで参考までに!
X-Planeを操作する上で、ノブをドラッグしたり、クリックしたりして回す作業は大変ですよね。そういうときに、ロータリーエンコーダは自作で作成する上でもっとも有用で便利な部品と言えます。これにより、フライトが非常に快適になります。他のは別にしても、是非これだけはオススメします。

このエンコーダを使っての作業で難しいのは、X-Planeの設定でノブを回した時、色んなシチュエーションがあるということです。例えば、回している途中で数字がそれ以上アップしなくなるとか、ある数字になったら 0 に戻るとか、その為、スケッチでちゃんと動くように、その設定を記述しなければならないということです。

X-Plane 10.35r1

このNAV1の周波数をエンコーダで操作してみるとします。
下がTeensy用のスケッチ例題として用意されたものです。私が使っているロータリーエンコーダは1クリックで4つパルスが出ます。
つまり、カチッと1つ回すと4つ数字がアップしたり、ダウンしたりします。

Encder_Nav1_Frequency.ino

#include <Encoder.h>

Encoder wheel = Encoder(35, 36);       // Rotary Encoder 5ピン、6ピン
 
FlightSimInteger NavFrequencyHz;  //X-Planeと通信する関数
 
long encoder_prev=0;    // 回転位置の変化を検出します(0からスタート)
elapsedMillis inactivityTimeout;// 非活動のタイムアウト
 
// セットアップはteensyを起動すると、一度だけ実行されます。
void setup() {
  // すべてのハードウェアを初期化します
  pinMode(5, INPUT_PULLUP);  
  pinMode(6, INPUT_PULLUP); 
 
  // X-Planeの変数を設定します
  NavFrequencyHz = XPlaneRef("sim/cockpit2/radios/actuators/nav1_frequency_hz");
}
 
void loop() {
  // 通常loop()の最初のステップは、X-Planeを更新することです。
  FlightSim.update();
 
  //ロータリーエンコーダを読んで、それが変化した場合、NavFrequencyHzに書き込み
  long enc = wheel.read();       //エンコーダの変化を読み込む(ピンの変化を見ている)
  if (enc != encoder_prev) {     //もし enc と encoder_prev が違ったなら
    NavFrequencyHz = NavFrequencyHz + (enc - encoder_prev); //+ならアップ、-ならダウン。
    encoder_prev = enc;          //回転位置の変化をencに反映させる
 
    inactivityTimeout = 0;       // 無活動タイムアウトをリセット
  }
}

アップ/ダウンが逆になる場合はTeensyのピンを逆にすると正常になります。


メモリを1カウントずつアップダウンするには

それと、問題なのはロータリーエンコーダはカチッと1つ移動すると4つのパルスを発生します。つまり数字が4つ一度に上がるということになり、0だった値が4になります。
これではまずいので、4つのパルスを1つに数えるように変換するため、読み込むエンコーダの値を4で割ります。
方法は下のように、上のプログラムの27行目の最後に「/4」を入れます。
Encder_1count.ino

#include <Encoder.h>

Encoder wheel = Encoder(5, 6);       // Rotary Encoder 5ピン、6ピン

FlightSimInteger NavFrequencyHz;  //X-Planeと通信する関数

long encoder_prev=0;    // 回転位置の変化を検出します
elapsedMillis inactivityTimeout;// 非活動のタイムアウト

// セットアップはteensyを起動すると、一度だけ実行されます。
void setup() {
  // すべてのハードウェアを初期化します
  pinMode(5, INPUT_PULLUP);  // アースのプルアップ抵抗はチップが提供
  pinMode(6, INPUT_PULLUP);  // 

  // X-Planeの変数を設定します
  NavFrequencyHz = XPlaneRef("sim/cockpit2/radios/actuators/nav1_frequency_hz");

}

void loop() {
  // 通常はloop()の最初のステップは、X-Planeを更新する必要があります
  FlightSim.update();

  // read the rotary encoder, if it's changed, write to NavFrequencyHz
  // それが変わった場合、NavFrequencyHzに書き込み、ロータリーエンコーダを読みます。
  long enc = wheel.read() /4;       //エンコーダの値を読み込む
  if (enc != encoder_prev) {     //もし enc と encoder_prev が違ったなら
    NavFrequencyHz = NavFrequencyHz + (enc - encoder_prev); //+ならアップ、-ならダウン。
    encoder_prev = enc;          //回転位置の変化をencに反映させる

    inactivityTimeout = 0;       // 無活動タイムアウトをリセット
  }

}


これで、うまく1つずつ数字をカウントするようになります。
ロータリーエンコーダは、必ずしも 1 クリックで 4 パルスとは限らないのでその仕様をよく読んでください。



1クリック5カウントのアップ/ダウンにするには

実際のNAV1の周波数の場合、小数点以下は1クリックで5つ変動して、小数点以上は1つずつになっています。そこで少数点以下の5つを一度に変えるようにしなければいけません。小数点以上は自動的に1つずつ上がります。
Encder_5count.ino

//エンコーダの1クリックで5カウントでアップダウンする
#include <Encoder.h>
  
// Encoder things
Encoder Enc= Encoder(9, 10);

// Heading mode things
FlightSimFloat NavFrequencyHz;
 
void setup() {
  
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);

  NavFrequencyHz = XPlaneRef("sim/cockpit2/radios/actuators/nav1_frequency_hz");
  
}
  
void loop() {
  FlightSim.update();

  // エンコーダの動きを読みます
  short EncDiff = Enc.read()  / 4;  //エンコーダの値を読み込み4で割り、1クリックで1アップにする
  
  if (EncDiff) {  // それらが移動した後のエンコーダをリセット(これを入れないと数字が勝手に動く)
    Enc.write(0);
  }

  int encoderDiff = 20 * EncDiff ;  //20 に EncDiff の値(1)を掛ける。20になる
  
  if (encoderDiff) {
      float tmp = NavFrequencyHz;  //tmpにNavFrequencyHzの値を入れる。float (浮動小数点型)
      //下の最後を1にすると20ずつ、0.5で10、0.1で2、0.25で5ずつアップダウンになる。
      tmp += encoderDiff * 0.25;        //tmp に encoderDiff(20)に0.25を掛けた値をプラスする。つまり5をプラス
      NavFrequencyHz = tmp;              //NavFrequencyHzの値に、5をプラスしたtmpの値に変更する
    }

 } 
これで、うまく5つずつ数字をカウントするようになります。



エンコーダで回すNav1の数値の範囲を限定するには

エンコーダを使った場合、実際に画面をクリックして数値を変更するときと比べると問題があります。X-Planeでの実際のNav1周波数は108〜117の範囲で表示するようになっています。つまり、117になったら108に戻ります。エンコーダでどんどん回していくと117以上でもカウントアップを続けます。やはり、117になったら108に戻したいですね。
while文で範囲を指定します。
NAV1_count108_117set.ino

//エンコーダの1クリックで5カウントでアップダウンする
#include <Encoder.h>
  
// Encoder things
Encoder Enc= Encoder(19, 20);

// Heading mode things
FlightSimFloat NavFrequencyHz;
 
void setup() {
  
  pinMode(19, INPUT_PULLUP);
  pinMode(20, INPUT_PULLUP);

  NavFrequencyHz = XPlaneRef("sim/cockpit2/radios/actuators/nav1_frequency_hz");
  
}
  
void loop() {
  FlightSim.update();

  // エンコーダの動きを読みます
  short EncDiff = Enc.read()  / 4;  //エンコーダの値を読み込み4で割り、1クリックで1アップにする
  
  if (EncDiff) {  // それらが移動した後のエンコーダをリセット(これを入れないと数字が勝手に動く)
    Enc.write(0);
  }

  int encoderDiff = 20 * EncDiff ;  //20 に EncDiff の値(1)を掛ける。20になる
  
  if (encoderDiff) {
      float tmp = NavFrequencyHz;  //tmpにNavFrequencyHzの値を入れる。float (浮動小数点型)
      
      //下の最後を1にすると20ずつ、0.5で10、0.1で2、0.25で5ずつアップダウンになる。
      tmp += encoderDiff * 0.25;        //tmp に encoderDiff(20)に0.25を掛けた値をプラスする。つまり5をプラス 
     
     // ここで表示する範囲を設定する 
      while (tmp < 10801.0) tmp += 1000.0;  //hdgが0より小さくなった場合、1000をプラスする(つまり11795になる)
      while (tmp >= 11799.0) tmp -= 1000.0;  //hdgが11799以上になった場合、1000を引く(つまり10800になる)

      NavFrequencyHz = tmp;              //NavFrequencyHzの値に、5をプラスしたtmpの値に変更する
    }

 } 

範囲を設定するところがそれになりますが、非常に頭がこんがらかりますね。実際にX-Plane上で確認しながら数値を変更するとよく分かります。
周波数は小数点が入っていますが、それを無視して考えます。108.00は実際のdatarefでは10800となっています。
これでうまく108.00〜117.95までの間で表示できるようになります。




エンコーダをで回す数値の範囲(小数点以下のKhz帯)を限定するには

datarefの「sim/cockpit2/radios/actuators/nav1_frequency_khz」を使えば、小数点以下だけを動かすことが出来ます。
実際のKhz帯は00〜95の範囲で表示するようになっています。つまり、95以上になったら00に戻ります。while文でその範囲を指定します。
NAV1_count_00_95set.ino

#include <Encoder.h>
   
// Encoder things
Encoder Enc= Encoder(14, 15);
 
// Heading mode things
FlightSimFloat NavFrequencyHz;
  
void setup() {
   
  pinMode(14, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
 
  NavFrequencyHz = XPlaneRef("sim/cockpit2/radios/actuators/nav1_frequency_khz");
   
}
   
void loop() {
  FlightSim.update();
 
  // エンコーダの動きを読みます
  short EncDiff = Enc.read()  / 4;  //エンコーダの値を読み込み4で割り、1クリックで1アップにする
   
  if (EncDiff) {  // それらが移動した後のエンコーダをリセット(これを入れないと数字が勝手に動く)
    Enc.write(0);
  }
 
  int encoderDiff = 20 * EncDiff ;  //20 に EncDiff の値(1)を掛ける。20になる
   
  if (encoderDiff) {
      float tmp = NavFrequencyHz;  //tmpにNavFrequencyHzの値を入れる。float (浮動小数点型)
      //下の最後を1にすると20ずつ、0.5で10、0.1で2、0.25で5ずつアップダウンになる。
      tmp += encoderDiff * 0.25;        //tmp に encoderDiff(20)に0.25を掛けた値をプラスする。つまり5をプラス
       
     // ここで表示する範囲を設定する 
      while (tmp < 00.0) tmp += 100.0;  //0より小さくなった場合、100をプラスする(つまり95になる)
      while (tmp >= 99.0) tmp -= 100.0;  //99以上になった場合、100を引く(つまり00になる)
      
      NavFrequencyHz = tmp;              //NavFrequencyHzの値に、5をプラスしたtmpの値に変更する
    }
 
 } 

小数点以上も、このようにして作成できます。datarefは「sim/cockpit2/radios/actuators/nav1_frequency_Mhz」になります。



COM1と2も同じように設定できます。

datarif:
sim/cockpit2/radios/actuators/com1_frequency_hz_833
小数点以下は000〜990で、5ずつのカウントですが、040からは045にならず050になり、090からは095にならずに100になります。非常に複雑。私にはまだそのコードの処理はまだ勉強不足でもあるし、そんなに気にする必要も無いということで、ここは省きます。
全体では118.000〜136.990となっている。

しかし、その前にもう一つ、この少数点以下3桁の数値を1つのエンコーダで上げ下げするのは非現実的である。小数点以上を1つずつ上げるのには時間がかかり大変である。
X-Planeの画面のように、小数点以上と以下を分けるのがベストだと思う。方法として2つのエンコーダを使うか,1つのエンコーダを切り替えて行う方法がある。



エンコーダを2つ使って切り替える

小数点以上のdatarefを
sim/cockpit2/radios/actuators/com1_frequency_Mhz
小数点以下のdatarefを
sim/cockpit2/radios/actuators/com1_frequency_khz(注意:上はMhzが大文字だが、これはkhzは小文字で始まっている)
この2つ分をスケッチに記述すればOKでしょう。



エンコーダ 1つで切り替える

方法は少しスケッチが複雑になる、スイッチで切り替えます。以下がそのビデオ



針路バグ&エレベータトリム図面

これはロータリーエンコーダのプッシュスイッチ付きを使っていますが、代わりに右のようにプッシュボタンを使用することでも実現できます。

プログラムは以下のとうりです。

Com1_Switchi118-136.ino

#include <Encoder.h>
#include <Bounce.h>
  
enum pins {
  MyEnc_A = 19,
  MyEnc_B = 20,
  ModeSwitchPin = 18,
  MhzModeLED = 11,
  KhzModeLED = 13
};
  
Encoder myEnc(MyEnc_A, MyEnc_B);
short myEncPrev = 0;
Bounce modeSwitch = Bounce (ModeSwitchPin, 5);
enum Modes {
  Mode_com1FrequencyMhz, // automatically = 0
  Mode_com1FrequencyKhz, // automatically = 1
  Mode_Count // automagically = 2、2つのモードを持っている、それは便利です!
};
int mode = 0;
  
FlightSimFloat com1FrequencyMhz;
FlightSimFloat com1FrequencyKhz;

  
void setup() {
  pinMode(ModeSwitchPin, INPUT_PULLUP);
  pinMode(MhzModeLED, OUTPUT);
  pinMode(KhzModeLED, OUTPUT);
  
  com1FrequencyMhz = XPlaneRef("sim/cockpit2/radios/actuators/com1_frequency_Mhz");
  com1FrequencyKhz = XPlaneRef("sim/cockpit2/radios/actuators/com1_frequency_khz");

}
  
void loop() {
  FlightSim.update();
  modeSwitch.update();
  
  // スイッチが押されたときにモードを変更
  if(modeSwitch.fallingEdge()) {
    ++mode;
    if(mode >= Mode_Count)
      mode = 0;
  }
  
  //光のステータスLED
  digitalWrite(MhzModeLED, (mode == Mode_com1FrequencyMhz));
  digitalWrite(KhzModeLED, (mode == Mode_com1FrequencyKhz));
  
  short myEncDiff = (myEnc.read() - myEncPrev) / 4;
  
  if (myEncDiff) {
    myEncPrev = 0;
    myEnc.write(0);
  
    //118~136の範囲
    if (mode == Mode_com1FrequencyMhz) {
      float tmp = com1FrequencyMhz;
      tmp += myEncDiff;
      while (tmp < 117.9) tmp += 19.0;  //tmpが117.9以下になった場合、19をプラス(つまり136になる)
      while (tmp >= 136.1) tmp -= 19.0;  //tmpが136.1以上になった場合、19を引く(つまり118になる)
      com1FrequencyMhz = tmp;
    }
    
    int encoderDiff = 20 * myEncDiff ;  //20 に EncDiff の値(1)を掛ける。20になる
     if (mode == Mode_com1FrequencyKhz) {
      float tmp = com1FrequencyKhz;  //tmpにcom1FrequencyKhzの値を入れる。float (浮動小数点型)
      //下の最後を1にすると20ずつ、0.5で10、0.1で2、0.25で5ずつアップダウンになる。
      tmp += encoderDiff * 0.25;        //tmp に encoderDiff(20)に0.25を掛けた値をプラスする。つまり5をプラス
      
      //ここまでだと、小数点は3桁以上になるので900以上になったら、000に戻す必要がある
      while (tmp < 0.0) tmp += 1000.0;  //tmpが0より小さくなった場合、100をプラスする(つまり990になる)
      while (tmp >= 999.0) tmp -= 1000.0;  //tmpが990以上になった場合、100を引く(つまり000になる)
      while (tmp == 00) tmp -= 1000.0;
      
      com1FrequencyKhz = tmp;              //NavFrequencyHzの値に、5をプラスしたtmpの値に変更する
    }
 
  }
}

X-Plane 10.35r1-1

ADF受信機の周波数は3桁ともそれぞれ別々に0から9までで動作します。しかしロータリーエンコーダでは別々に3桁をアップダウンさせることはできません。3桁を1つのdatarefで動作させているからで、1から999までグリグリ回しかないのです。大変です。
仕方がないので、方法としては粗いと微細の切替でやるしかありません。

1つは2つのエンコーダを使って粗いと微細を切り替える。もう一つは1つのエンコーダで桁を1つのスイッチでそれぞれ切り替えて設定するという方法があります。オススメは後の桁ごと設定するX-Planeのやり方がいいと思います。

取り敢えず最初に2つのエンコーダで、微細は1カウントずつ、粗いは10カウントにします。これだと大まかな動きは、粗いの10カウントで、1桁は1カウントで微調整して周波数を合わせることが出来ます。



2つのエンコーダで1カウントと10カウントを切り変える(ADF周波数例)

以下のプログラムが2つのエンコーダを使った場合
ADF_1countEnc_10countEnc.ino

//1カウントと10カウントのエンコーダを使用
#include <Encoder.h>

Encoder coount1enc = Encoder(7, 8); 
Encoder coount10enc = Encoder(9, 10);        // Rotary Encoder on pin 20 and 21

FlightSimInteger AdfFrequency;   //Nav1の周波数


// variables(変数)
long encoder_prev1=0.25;    // encoder_prev1の回転位置の変化を検出する
long encoder_prev2=0;
elapsedMillis inactivityTimeout;// 無活動のタイムアウト

void setup() {

  AdfFrequency = XPlaneRef("sim/cockpit2/radios/actuators/adf1_frequency_hz");

}

// Teensyが実行されている間、ループは繰り返し実行される、
void loop() {
  // 通常 loop() の最初のステップは X-Planeから更新する必要がある
  FlightSim.update();

 // 1カウントエンコーダ
 // ロータリーエンコーダを読む, それが変化した場合, AdfFrequencyに書き込み
  long enc1 = coount1enc.read() /4;	//4、ここで1カウントにしている
  if (enc1 != encoder_prev1) {
    AdfFrequency = AdfFrequency + (enc1 - encoder_prev1);
    encoder_prev1 = enc1;
    inactivityTimeout = 0;   // 無活動タイムアウトをリセット
  }

 // 10カウントエンコーダ
  // ロータリーエンコーダを読む, それが変化した場合, AdfFrequencyに書き込み
  long enc2 = coount10enc.read() /0.4;	//0.4、ここで10カウントにしている
  if (enc2 != encoder_prev2) {
    AdfFrequency = AdfFrequency + (enc2 - encoder_prev2);
    encoder_prev2 = enc2;
    inactivityTimeout = 0;   // 無活動タイムアウトをリセット
  }
}


1つのエンコーダと1つのスイッチで3桁をそれぞれ切り変える(ADF周波数例)
X-Plane 10.35r1

以下のプログラムです
ADF_1Enc1switch_Chenge.ino

//1つのエンコーダと1つのスイッチで3桁を切り替える
#include <Encoder.h>
#include <Bounce.h>

// Encoder things
Encoder myEnc(9, 10);
short myEncPrev = 0;

// Mode things
Bounce modeSwitch = Bounce (20, 5);
   
enum LEDpins {
  digit1_ModeLED = 11,
  digit2_ModeLED = 12,
  digit3_ModeLED = 13,
};
   
enum Modes {
  Mode_digit1, // 1桁モード
  Mode_digit2, // 2桁モード
  Mode_digit3, // 3桁モード
  Mode_Count // automagically = 4, 4モードで切替
};
int mode = 0;
 
FlightSimFloat adf1frequency;
   
void setup() {
  pinMode(20, INPUT_PULLUP);
  pinMode(digit1_ModeLED, OUTPUT);
  pinMode(digit2_ModeLED, OUTPUT);
  pinMode(digit3_ModeLED, OUTPUT);
 
  adf1frequency = XPlaneRef("sim/cockpit2/radios/actuators/adf1_frequency_hz");
}
   
void loop() {
  FlightSim.update();
  modeSwitch.update();
   
  // スイッチが押されたときにモードを変更
  if(modeSwitch.fallingEdge()) {
    ++mode;
    if(mode >= Mode_Count)
      mode = 0;
  }
   
  // LED点灯選択
  digitalWrite(digit1_ModeLED, (mode == Mode_digit1));
  digitalWrite(digit2_ModeLED, (mode == Mode_digit2));
  digitalWrite(digit3_ModeLED, (mode == Mode_digit3));
   
  // エンコーダの動きを見る
  short myEncDiff = myEnc.read() /4;  //粗いの変更したエンコーダを読む- 変更前のエンコーダの値
   
  // それらが移動した後のエンコーダをリセット
  if (myEncDiff) {
    myEncPrev = 0;
    myEnc.write(0);
  }
   
  // 1カウントと10カウントの切替設定(モード切替で同じadf1frequencyを書き換える)
  int encDiff = 20 * myEncDiff;  //20 ✕ 1 で encDiff は20
   
  if (encDiff) {
    //1桁モードが選択されたら
    if (mode == Mode_digit1) {
      float tmp = adf1frequency;  //tmpはX-Planeからの周波数の値を取得
      tmp += encDiff * 0.05;  // encDiffは20だから ✕ 0.05で1カウント、その値を周波数にプラスする
      while (tmp < 0) tmp += 10;  //tmpが0より小さくなった場合、10をプラスする(つまり9になる)
      while (tmp >= 10) tmp -= 10;  //tmpが10以上になった場合、10を引く(つまり0になる)     
      adf1frequency = tmp;
    }
  //2桁モードが選択されたら
    if (mode == Mode_digit2) {
      float tmp = adf1frequency;
      tmp += encDiff * 0.5;   //10カウント、その値を周波数にプラスする
      while (tmp < 0) tmp += 100;  //tmpが0より小さくなった場合、100をプラスする(つまり90になる、2桁目が有効になっている)
      while (tmp >= 100) tmp -= 100;  //tmpが100以上になった場合、100を引く(つまり00になる)
      adf1frequency = tmp;
    }
    //3桁モードが選択されたら
    if (mode == Mode_digit3) {
      float tmp = adf1frequency;
      tmp += encDiff * 5;   //10カウント、その値を周波数にプラスする     
      while (tmp < 0) tmp += 1000;  //tmpが0より小さくなった場合、1000をプラスする(つまり900になる、3桁目が有効になっている)
      while (tmp >= 1000) tmp -= 1000;  //tmpが1000以上になった場合、1000を引く(つまり000になる)
      adf1frequency = tmp;
    }
    
  }
} 

上のプログラムは、後半が少し理解できていないところがあるのですが、動作しています。



トランスポンダの4桁を別々にアップ/ダウンする

X-Plane 10.35r1

この受信機/送信機は、航空管制のレーダースクリーンであなたの航空機を見ることができます。トランスポンダは、地上レーダから「あなたは誰?」と尋ねてくる信号を受信、そして、標準の視界飛行規則コードの4桁コード、この場合1200で返信するとか。私自身もイマイチ理解していませんが。X-Planeで普段の飛行にはあんまり使用しませんが一応、この動作も検証してみます。

動きはどの桁も0〜7までです。それを過ぎると0にもどります。
datarif:sim/cockpit/radios/transponder_code
これも1つしかありません。しかし、これがうまくいきます。スイッチ切替でやるといいのかもしれません。アップダウンも8になると0に飛びます。
Transponder_4digit_ChengeSwitch.ino

//1つのエンコーダと1つのスイッチで1カウントと10カウントを切り替える
#include <Encoder.h>
#include <Bounce.h>

// Encoder things
Encoder myEnc(9, 10);
short myEncPrev = 0;

// Mode things
Bounce modeSwitch = Bounce (20, 5);
   
enum LEDpins {
  digit1_ModeLED = 11,
  digit2_ModeLED = 12,
  digit3_ModeLED = 13,
  digit4_ModeLED = 14,
};
   
enum Modes {
  Mode_digit1, // 1桁モード
  Mode_digit2, // 2桁モード
  Mode_digit3, // 3桁モード
  Mode_digit4, // 4桁モード
  Mode_Count // automagically = 4, 4モードで切替
};
int mode = 0;
 
FlightSimFloat adf1frequency;
   
void setup() {
  pinMode(20, INPUT_PULLUP);
  pinMode(digit1_ModeLED, OUTPUT);
  pinMode(digit2_ModeLED, OUTPUT);
  pinMode(digit3_ModeLED, OUTPUT);
  pinMode(digit4_ModeLED, OUTPUT);
 
  adf1frequency = XPlaneRef("sim/cockpit/radios/transponder_code");
}
   
void loop() {
  FlightSim.update();
  modeSwitch.update();
   
  // スイッチが押されたときにモードを変更
  if(modeSwitch.fallingEdge()) {
    ++mode;
    if(mode >= Mode_Count)
      mode = 0;
  }
   
  // LED点灯選択
  digitalWrite(digit1_ModeLED, (mode == Mode_digit1));
  digitalWrite(digit2_ModeLED, (mode == Mode_digit2));
  digitalWrite(digit3_ModeLED, (mode == Mode_digit3));
  digitalWrite(digit4_ModeLED, (mode == Mode_digit4));
   
  // エンコーダの動きを見る
  short myEncDiff = myEnc.read() /4;  //粗いの変更したエンコーダを読む- 変更前のエンコーダの値
   
  // それらが移動した後のエンコーダをリセット
  if (myEncDiff) {
    myEncPrev = 0;
    myEnc.write(0);
  }
   
  // 1カウントと10カウントの切替設定(モード切替で同じadf1frequencyを書き換える)
  int encDiff = 20 * myEncDiff;  //20 ✕ 1 で encDiff は20
   
  if (encDiff) {
    //1桁モードが選択されたら
    if (mode == Mode_digit1) {
      float tmp = adf1frequency;  //tmpはX-Planeからの周波数の値を取得
      tmp += encDiff * 0.05;  // encDiffは20だから ✕ 0.05で1カウント、その値を周波数にプラスする

      while (tmp < 0) tmp += 8;  //tmpが0より小さくなった場合、8をプラスする(つまり7になる)
      while (tmp >= 8) tmp -= 8;  //tmpが8以上になった場合、8を引く(つまり0になる)
      
      adf1frequency = tmp;
    }
  //2桁モードが選択されたら
    if (mode == Mode_digit2) {
      float tmp = adf1frequency;
      tmp += encDiff * 0.5;   //10カウント、その値を周波数にプラスする
      while (tmp < 0) tmp += 80;  //tmpが0より小さくなった場合、80をプラスする(つまり7になる)
      while (tmp >= 80) tmp -= 80;  //tmpが80以上になった場合、80を引く(つまり00になる)
      adf1frequency = tmp;
    }
    //3桁モードが選択されたら
    if (mode == Mode_digit3) {
      float tmp = adf1frequency;
      tmp += encDiff * 5;   //10カウント、その値を周波数にプラスする     
      while (tmp < 0) tmp += 800;  //tmpが0より小さくなった場合、80をプラスする(つまり7になる)
      while (tmp >= 800) tmp -= 800;  //tmpが80以上になった場合、80を引く(つまり00になる)
      adf1frequency = tmp;
    }
    //4桁モードが選択されたら
    if (mode == Mode_digit4) {
      float tmp = adf1frequency;
      tmp += encDiff * 50;   //10カウント、その値を周波数にプラスする    
      while (tmp < 0) tmp += 8000;  //tmpが0より小さくなった場合、80をプラスする(つまり7になる)
      while (tmp >= 8000) tmp -= 8000;  //tmpが80以上になった場合、80を引く(つまり00になる)
      adf1frequency = tmp;
    }
  }
} 

後は高度と方位の設定が残っています。
X-Plane 10.35r1-2

この高度の設定はどこで回すのか不明です。FLIGHT DIRをAUTOにしてALTを押すと、現在飛んでいる高度がここに読み込まれるようですね。その高度を維持するようになっているようだ。
これはジョイスティック&機器でキーコマンドを設定しても数字を変更できるようだ。autopilot/altitude_upとautopilot/altitude_downがそれに当たるようです。しかし、これで高度を設定してもその高度にならないのでこの数字をアップダウンする意味がないのかな?

その下の方位は、下の計器の右下のノブを回せば方向を変えることができます。
X-Plane 10.35r1-3

000359の範囲です。これのやり方はこのページを見て下さい。



小数点以下の数値をコントロールするには(動作する桁を決めることが出来る)
エンコーダで普通に回すと小数点以上の数値がアップダウンして、以下の数値は動きません。
そこで上の例で桁ごとに回す方法で、小数点以下も回します。
例題はB747-400のスピードのノットとマッハの切り替えでマッハは0.01というように表示されます。エンコーダでそのままのスケッチでは小数点以上の数値しか変化しないので変な動きになってしまいます。小数点以下2桁からアップダウン出来るようにすると良いということになります。
data ref:sim/cockpit/autopilot/airspeed

//エンコーダで小数点以下からカウントアップ/ダウンする
#include <Encoder.h>

Encoder myEnc(35, 36);      //エンコーダピン
short myEncPrev = 0;
    
int mode = 0;
FlightSimFloat adf1frequency;
    
void setup() {
  pinMode(38, INPUT_PULLUP);
  adf1frequency = XPlaneRef("sim/cockpit/autopilot/airspeed");
}
    
void loop() {
  FlightSim.update();

  // エンコーダの動きを見る
  short myEncDiff = myEnc.read() /4;  //粗いの変更したエンコーダを読む- 変更前のエンコーダの値
    
  // それらが移動した後のエンコーダをリセット
  if (myEncDiff) {
    myEncPrev = 0;
    myEnc.write(0);
  }
    
  // encDiffは20にmyEncDiffの値(1カウント)を掛ける値になる
  int encDiff = 20 * myEncDiff;  //20 ✕ 1 で encDiff は20になる
  
  //小数点以下2桁からカウントアップ/ダウンを行う  
  if (encDiff) {      //もし20なら  
      float tmp = adf1frequency;  //tmpはX-Planeからの周波数の値を取得
      tmp += encDiff * 0.0005;  // encDiffは20だから ✕ 0.00005で0.01ずつカウントとおなり、その値を周波数にプラスする
      
      //後はX-Plane側で処理してくれるので以下の範囲設定はしなくても良い
      //while (tmp < 0) tmp += 8;  //tmpが0より小さくなった場合、8をプラスする(つまり7になる)
      //while (tmp >= 8) tmp -= 8;  //tmpが8以上になった場合、8を引く(つまり0になる)
       
      adf1frequency = tmp;
  }
} 

comments powered by Disqus
Contents