X-Plane コクピットの自作に挑戦!
本物のコクピットと同じように7セグメントで表示する
I2C接続キャラクターLCDモジュールと違って7セグメントで表示するのは、意外と大変です。実際に表示してYouTube等で公開されている方もいらっしゃいますが、実際の作成に関する資料がほとんで世界中を探しても見つかりませんでした。悪戦苦闘しましたが、うまく実際どうりに動作するようになりました。


この7セグでの表示はあくまで、X-Planeからのデータを受信して表示しているだけですが、受信した数値をそれぞれの桁に置き換える作業が難しい、下のスケッチを見てもらえば分かりますがチョット頭を働かせる必要があります。
7セグを表示するために、MAX7219を使用しています。このICは結構高価ですが8桁までを表示出来、配線が楽になるということで使ってみました。配線の苦労など問題ないとう場合は他にも安いICがあると思います。7セグメントはいろんな桁があります、基本はすべて同じですのでどれを使っても問題なく表示できますが、できるだけ必要な桁数に合わせた方が配線等で楽になります。
最初はLEDを点灯させるだけで苦労するかもしれません。6桁全部を繋ぐとLEDが消えてしまって、何で点灯しないのか理解できないのです。これの解決策としてMAX7219のISETピンに繋ぐ抵抗を大きくして流れる電流を制限することです。抵抗が小さいと、大きな電流が流れるため自動的に電流を切断しているようです。
そのため、最初のテストではこの抵抗を100KΩ以上の可変抵抗にして最適な抵抗値を探してから実際の作業に入るのも一つの方法だと思います。私の場合100KΩでうまくいきました。ここの抵抗はLEDの明るさに影響しますが、スケッチでもその明るさを調整できるので、少し明るい位が調整しやすくなります。


6桁7セグ配線図

正の整数だけの7セグメント表示のプログラム(B474-400 Unitedで確認)
これには、teensyの3つのピンが必要になります。MAX7219の DIN、CLK、LOAD をそれぞれ接続します。

以下のプログラム(スケッチ)はB747-400のオートパイロットの高度の例です。

// 5桁の整数のみの場合(頭に - が付かない場合)
#include <LedControl.h>

// 7セグメント表示 5番パネル //////////////////////////////
const int DIN_Pin = 8;    //DINのteensyピン
const int CLK_Pin = 9;    //CLKのteensyピン
const int LOAD_Pin = 10;  //LOADのteensyピン

LedControl Led7seg = LedControl(DIN_Pin, CLK_Pin, LOAD_Pin, 1); //最後の1はMAX7219のチップ数
  
FlightSimInteger AltitudeLed;    //7セグとX-Planeの接続関数


void setup() {

  Led7seg.shutdown(0, false);  // 7せぐディスプレイをオンに(0が最初のチップ)
  Led7seg.setIntensity(0, 15); // 15 = 7セグの明るさ最大
  //mydisplay.setScanLimit(0, 3); // 7セグを表示する桁数の指定(最初は行数、2番めが桁数、0が1桁、1が2桁…)
  pinMode(DIN_Pin, OUTPUT);
  pinMode(CLK_Pin, OUTPUT);
  pinMode(LOAD_Pin, OUTPUT);
  
  AltitudeLed = XPlaneRef("sim/cockpit2/autopilot/altitude_dial_ft");  //alt_actのデータを受信する
    AltitudeLed.onChange(update_alt_act_lcd);  // AltitudeLedが更新されたらLed7segを更新する(上とセットになる)

}

  
void loop() {
  FlightSim.update();
}


// Altitudeの7セグ表示 ////////////////////////////////////////
//value これでコクピットの高度の数字を読み込む
void update_alt_act_lcd(long value) {    

  //セグは、面倒だが1桁ずつどの桁の数字を表示するか設定する必要がある。
  //%は割った余り、/は割り算である。
  int alt_act_keta1 = value % 10;          //例えば12345の場合、12345÷10=1234.5の余りの最初の数字「5」が1桁の数字として表示される
  int alt_act_keta2 = value / 10 % 10 ;    //例えば12345の場合、12345÷10=1234.5で、さらに10で割って、123.45で小数点以下の「4」を2桁目の数字として表示
  int alt_act_keta3 = value / 100 % 10;    //例えば12345の場合、12345÷100=123.45で「3」の整数が3桁目の数字として表示
  int alt_act_keta4 = value / 1000 % 10;   //自分では余りのみ意味がよく理解できませんが、とにかくこの設定でうまく動作します。
  int alt_act_keta5 = value / 10000 % 10;  //これが5桁目を表示します。

  //上の設定を使ってそれぞれの桁に数字を表示する。
  Led7seg.setDigit(0, 0, alt_act_keta1, false); //1桁目の値を表示
  Led7seg.setDigit(0, 1, alt_act_keta2, false); //2桁目の値を表示
  Led7seg.setDigit(0, 2, alt_act_keta3, false); //3桁目の値を表示
  Led7seg.setDigit(0, 3, alt_act_keta4, false); //4桁目の値を表示
  Led7seg.setDigit(0, 4, alt_act_keta5, false); //5桁目の値を表示
}

datarif:sim/cockpit2/autopilot/altitude_dial_ft(これはどの機首にも共通で使える)

※B747-400の場合は2桁まで0になるのですが、実際のdatarifでは1桁まで細かく表示しています。従ってそのままだと、実際と違った状態になります。2桁を0にしたい場合、スケッチで
int alt_act_keta1 = value % 10;
int alt_act_keta2 = value / 10 % 10 ;
となっている所を下のようにvalueの値を強引に「0」にしてしまうとうまく表示されます。
int alt_act_keta1 = 0;
int alt_act_keta2 = 0;

🔵その他の7セグメント表示のdataref 例
エアースピードdatarif:
sim/cockpit2/autopilot/airspeed_dial_kts_mach(add-onの機体にも共通で使える)
HDG(heading) datarif:
sim/cockpit2/autopilot/heading_dial_deg_mag_pilot(デフォルトの機体に使える)
バーチカルスピード datarif:
sim/cockpit2/autopilot/vvi_dial_fpm(add-onの機体にも共通で使える)
頭に「 - 」が付く負の整数7セグメント表示のプログラム(B474-400 Unitedで確認)
非常に複雑なスケッチになります。
例としてはオートパイロットのバーチカルスピード(下降率)の表示がそれに当たります。

// 頭に「-」が付く場合の7セグ表示
#include <LedControl.h>

//入力:DINピン、CLK端子、LOAD端子、チップ数(MAX7219の数)
LedControl lc4 = LedControl(8, 9, 10, 1);

FlightSimInteger VSpeed;

FlightSimInteger VsPitchModeEngage;   //規定の高度になったら7セグを消したり、表示したりする設定のためのもの

void setup() {
  lc4.shutdown(0, false);  // ディスプレイをオンに(0が最初のチップ、trueがオフにする)
  lc4.setIntensity(0, 5); // ディスプレイの明るさの調整(0が最初のチップ、後ろの数字は15が最も明るい)
  //lc4.setScanLimit(0, 3); // 表示する桁数の指定(最初は行数、2番めが桁数、0が1桁、1が2桁…)

  pinMode(8, OUTPUT);      //他のピンと差し替え注意!OUTPUTになっている
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);

  VSpeed = XPlaneRef("sim/cockpit2/autopilot/vvi_dial_fpm");  //X-Planeの数値を7セグで表示する
    VSpeed.onChange(update_vs_act_lcd);  // X-Planeが更新されたら7セグを更新する
}

void loop() {
  FlightSim.update();
}

void update_vs_act_lcd(long value) {    //value これで高度の数字を読み込む
    //プラスの値の処理
    int vs_act_keta1 = value % 10;  //例えば123の数字の場合、123÷10=12.3で小数点以下の3が1桁の数字として表示
    int vs_act_keta2 = value / 10 % 10 ;  //例えば123の数字の場合、、÷10=12.3、さらに10で割って、1.23で小数点以下の2が表示
    int vs_act_keta3 = value / 100 % 10;   //例えば123の数字の場合、123÷100=1.23で1の整数が3桁目の数字として表示
    int vs_act_keta4 = value / 1000 % 10;
    //マイナスの値の処理
    int vs_act_ketaMinus1 = - value % 10;  //例えば123の数字の場合、123÷10=12.3で小数点以下の3が1桁の数字として表示
    int vs_act_ketaMinus2 = - value / 10 % 10 ;  //例えば123の数字の場合、、÷10=12.3、さらに10で割って、1.23で小数点以下の2が表示
    int vs_act_ketaMinus3 = - value / 100 % 10;   //例えば123の数字の場合、123÷100=1.23で1の整数が3桁目の数字として表示
    int vs_act_ketaMinus4 = - value / 1000 % 10;
    
    //プラスの値の処理
    lc4.setDigit(0, 0, vs_act_keta1, false); //1桁目の値を表示
    lc4.setDigit(0, 1, vs_act_keta2, false); //2桁目の値を表示
    lc4.setDigit(0, 2, vs_act_keta3, false); //3桁目の値を表示
    lc4.setDigit(0, 3, vs_act_keta4, false); //4桁目の値を表示
    //マイナスの値の処理
    lc4.setDigit(0, 0, vs_act_ketaMinus1, false); //-の1桁目の値を表示
    lc4.setDigit(0, 1, vs_act_ketaMinus2, false); //-の2桁目の値を表示
    lc4.setDigit(0, 2, vs_act_ketaMinus3, false); //-の3桁目の値を表示
    lc4.setDigit(0, 3, vs_act_ketaMinus4, false); //-の4桁目の値を表示
   
    //表示する桁数を変更する設定(意味不明だが、この並びと設定でうまく動作する)
    if(value == 0 ){             //もし、0と同じなら以下を実行
       lc4.setScanLimit(0, 3);  // 4桁表示にする。(最初は行数、2番めが桁数、0が1桁、1が2桁…)
       lc4.setIntensity(0, 2); // 15 = brightest 明るさを桁数に合わせて個別に指定
    }
    
    else if(value >= 0 && value <= 5000){      //もし、1~99の範囲なら以下を実行
       lc4.setScanLimit(0, 3);  // 4桁表示にする。(最初は行数、2番めが桁数、0が1桁、1が2桁…)
       lc4.setIntensity(0, 2); // 15 = brightest 明るさを桁数に合わせて個別に指定
    }
  
    //この下の「else」は一番下に持っていくと3桁の表示が4桁になってしまう。この位置でうまく動作する。
    else {
       lc4.setScanLimit(0, 5);  //そうでないなら、5桁表示にする
    }
    
   //この下の「if」は上に持って行き「else if」では「-」表示がうまく動作しない
   if(value >= -5000 && value <= -100){     //もし、-999より下で-100より上なら以下を実行
       lc4.setChar(0,4,'-',false);          //5桁目に-を表示
       lc4.setIntensity(0, 10); // 15 = brightest
    }
 
}


小数点が付く7セグメント表示のプログラム(Cessna 172SPで確認)
例としてはNav周波数の表示がそれに当たります。
これは基本的にはスケッチは他とまったく同じ、違うのは指定の位置に7セグ側でドットを点灯させるだけである。
ただし、com周波数など6桁もあるので、その場合は桁数を増やす必要がある。

X-Plane 10.35r1

🔵それぞれのdatarifを以下のとおりです。参考までに
sim/cockpit2/radios/actuators/com1_frequency_hz_833
sim/cockpit2/radios/actuators/nav1_frequency_hz
sim/cockpit2/radios/actuators/com2_frequency_hz_833
sim/cockpit2/radios/actuators/nav2_frequency_hz
sim/cockpit2/radios/actuators/adf1_frequency_hz
sim/cockpit2/radios/actuators/transponder_code
sim/cockpit2/autopilot/altitude_dial_ft(ダイヤルがどこか不明、キーコマンドで上げ下げ可能)
sim/cockpit2/autopilot/heading_dial_deg_mag_pilot

下のスケッチは6桁の周波数用です。

// 周波数の表示、これは7セグで指定の位置のドット(点)を点灯させる
#include <LedControl.h>

// 7セグメント表示 5番パネル //////////////////////////////
const int DIN_Pin = 8;    //DINのteensyピン
const int CLK_Pin = 9;    //CLKのteensyピン
const int LOAD_Pin = 10;  //LOADのteensyピン

LedControl Led7seg = LedControl(DIN_Pin, CLK_Pin, LOAD_Pin, 1); //最後の1はMAX7219のチップ数
  
FlightSimInteger Nav1Frequency;    //7セグとX-Planeの接続関数


void setup() {

  Led7seg.shutdown(0, false);  // 7せぐディスプレイをオンに(0が最初のチップ)
  Led7seg.setIntensity(0, 15); // 15 = 7セグの明るさ最大
  //mydisplay.setScanLimit(0, 3); // 7セグを表示する桁数の指定(最初は行数、2番めが桁数、0が1桁、1が2桁…)
  pinMode(DIN_Pin, OUTPUT);
  pinMode(CLK_Pin, OUTPUT);
  pinMode(LOAD_Pin, OUTPUT);
  
  Nav1Frequency = XPlaneRef("sim/cockpit2/radios/actuators/nav1_frequency_hz");  //alt_actのデータを受信する
    Nav1Frequency.onChange(update_nav1_frequency);  // AltitudeLedが更新されたらLed7segを更新する(上とセットになる)

}

  
void loop() {
  FlightSim.update();
}


// Altitudeの7セグ表示 ////////////////////////////////////////
void update_nav1_frequency(long value) {    //value これでコクピットの高度の数字を読み込む

  //7セグは以下の設定をしないとはvalueの値を1桁しか読み込まない。
  //従って、面倒だが1桁ずつどの桁の数字を表示するか設定する必要がある。
  //%は割った余り、/は割り算である。
  int nav1_frequency_keta1 = value % 10;          //例えば12345の場合、12345÷10=1234.5の余りの最初の数字「5」が1桁の数字として表示される
  int nav1_frequency_keta2 = value / 10 % 10 ;    //例えば12345の場合、12345÷10=1234.5で、さらに10で割って、123.45で小数点以下の「4」を2桁目の数字として表示
  int nav1_frequency_keta3 = value / 100 % 10;    //例えば12345の場合、12345÷100=123.45で「3」の整数が3桁目の数字として表示
  int nav1_frequency_keta4 = value / 1000 % 10;   //自分では余りのみ意味がよく理解できませんが、とにかくこの設定でうまく動作します。
  int nav1_frequency_keta5 = value / 10000 % 10;  //これが5桁目を表示します。
  int nav1_frequency_keta6 = value / 100000 % 10;

  //上の設定を使ってそれぞれの桁に数字を表示する。
  Led7seg.setDigit(0, 0, nav1_frequency_keta1, false); //1桁目の値を表示
  Led7seg.setDigit(0, 1, nav1_frequency_keta2, false); //2桁目の値を表示
  Led7seg.setDigit(0, 2, nav1_frequency_keta3, false); //3桁目の値を表示
  Led7seg.setDigit(0, 3, nav1_frequency_keta4, false); //4桁目の値を表示
  Led7seg.setDigit(0, 4, nav1_frequency_keta5, false); //5桁目の値を表示
  Led7seg.setDigit(0, 5, nav1_frequency_keta6, false); 
}
以下は7セグメントにおける特徴的な関数です。(#include <LedControl.h>が必要です)
●7セグを表示したり、非表示にしたりできます。
lc.
shutdown(0, false); // 7せぐディスプレイをオンに(0が最初のチップ)
●7セグのLEDの明るさを調整できます。
lc.
setIntensity(0, 15); // 15 = 7セグの明るさ最大
●7セグの表示する桁数を指定できます。
lc.
setScanLimit(0, 3); // 0が1行または桁、1が2行または桁…最初の数字は行数、2番めが桁数を指定)
●単純に7セグに数字を表示するには以下を使用する
lc.
setDigit(0, 0, 8, false); //1番目は?、2番目の数値は表示する桁、3番目の数値は表示する数字、false(非表示)true(表示)
●7セグの画面クリア
lc.
clearDisplay(0);
comments powered by Disqus
Contents