トラコンヘルパー
トラコンヘルパーハンコンでATS・ETS2で遊ぶときのとても便利なソフトが開発・公開されました!ソフト名:ToraCon-Helper作者 :kuramochia さんここではインストール方法や使い...
Arduino のプログラムを作る
外部スイッチなどを付けて、この入力をUSBを通じてPC(ATSやETS2)に信号を送る方法
Arduino Leonardo を使うことでジョイスティック出力またはキーボードのキー出力にします
ホリのトラックコントローラーのおかげで外付け自作レバーとかスイッチボックスが必要なくなっちゃいましたね
外付けのスイッチボックスなどを自作する場合はジョイスティック出力ではなく「Arduino Leonardo」でキー出力にするのがお勧めです
ジョイスティック接続と違い、ゲーム内での登録・設定が要らなくなります😋
Arduinoにはいくつも種類がありますが、「Arduino Leonardo」はPCにUSB接続した際、自信をゲームパッド(ジョイスティック)やキーボード、マウスとして認識させることができます
キーボードとして認識させキー出力をさせましょう
プログラムバグで暴走した時のために必ず入力を1つ暴走止めに用意すること!
【重要】
スイッチ入力を検知したらそれに該当するキー出力をするわけですが、出力のON時間を100msec(0.1秒)とする場合、この100msecを「Delay」関数で作ってしまうと問題がでてきます
「Delay」関数は他の処理(他のスイッチが押されたかどうかのチェックや、他のキー出力など)もすべて停止してしまうため、他のスイッチを押したのに反応しないとかなにかと厄介です
そこで「Delay」関数を使わずに出力のON時間100msecをどうやって作るかを考えます
以下がそれを実現するひとつの考え方です
物理的スイッチをONするとバネの力で信号がびびり(ON/OFF)を短期間繰り返す現象が出ます
これをチャタリングと呼びます
このチャタリングを無視するためチャタリング除去のプログラムも同時に作ります
ハード的にチャタリングを除去する回路やICもありますが、プログラムで除去する方法を取ります
実際に使っている私のプログラムは以下のようになります
//変数の定義 pint_:public int pulng_:public unsigned long pchr_:public char cint_:Const int cchr_:Const Char
//スイッチ入力調査、それに対応するキー出力に関するデータを全てここの最初に定義として入れておくことで
//定義を設定し直すだけで制御プログラムを触らずに制御内容を変更することを可能とする
#include <Keyboard.h>
const int cint_SwDIN_START = 2; //デジタル入力の最初の番号
//const int cint_SwDIN_END = 13; //デジタル入力の最後の番号 リターダーをアナログ入力する場合
const int cint_SwDIN_END = 19; //デジタル入力の最後の番号 アナログピンも全てデジタル入力にする
int pint_SwPrev[20]; //スイッチの前状態
int pint_SwNow[20]; //スイッチの現在の状態
int pint_SwType[20]; //スイッチの種類
const int cint_SwType_DIN = 0; // デジタル・インプット
const int cint_SwType_DOUT = 1; // デジタル・アウトプット
const int cint_SwType_AIN = 2; // アナログ・インプット
const int cint_SwType_AOUT = 3; // アナログ・アウトプット
const int cint_SwType_STX = 4; // シリアル通信・TX
const int cint_SwType_SRX = 5; // シリアル通信・RX
unsigned long pulng_KeyTime[20]; //キー出力のタイマー
const int cint_KeyTime_Push = 50; //キープッシュの時間 msec
const int cint_KeyTime_Wait = 30; //連続キーインの時、前のキーリリース後、次のプッシュとの間の待ち時間 msec
int pint_SwCheck[20]; //スイッチ状態のチェック 0:しない 1:する
const int cint_SwCheck_NOT = 0;
const int cint_SwCheck_START = 1;
int pint_SwChg[20]; //スイッチ状態 0:OFFで変化なし 1:OFF→ON 2:ONで変化なし 3:ON→OFF
const int cint_SwCtrl_OFFtoOFF = 0; //ON→OFF,OFF→ON状態の解除は制御プログラム内でのみ変更する
const int cint_SwCtrl_OFFtoON = 1;
const int cint_SwCtrl_ONtoON = 2;
const int cint_SwCtrl_ONtoOFF = 3;
//---------- 機能毎の変数・定数 ----------
const int cint_SwNum_ExBrake_A = 2; //右下-押す オルタネート input 2
const int cint_SwNum_ExBrake_M = 3; //右下-引く モーメンタリ input 3
const int cint_SwNum_Light = 4; //右中-押しボタン input 4
const int cint_SwNum_Winker_L = 5; //右上-上げる input 5
const int cint_SwNum_Winker_R = 6; //右上-下げる input 6
const int cint_SwNum_Engene_START = 7; //エンジンキースイッチ スターター input 7
const int cint_SwNum_Engine_ELEC = 8; //エンジンキースイッチ 電気系統 input 8
const int cint_SwNum_Wiper_MINUS = 18; //左上-上げる Analog input 0 = Digital input 18
const int cint_SwNum_Wiper_PLUS = 19; //左上-下げる Analog input 1 = Digital input 19
//アナログピンはデジタル入力として使用する場合に番号が異なるので注意 A0=18,A1=19,A2=20,A3=21,A4=22
//const int cint_SwNum_Retarder = 14; //ロータリースイッチ Analog input 0 = Analog input 14
const int cint_SwNum_RWindow_DOWN = 10; //左ウィンドウ 下げる input 20 (Analog input 2)
const int cint_SwNum_RWindow_UP = 11; //左ウィンドウ 上げる input 21 (Analog input 3)
const int cint_SwNum_LWindow_DOWN = 12; //左ウィンドウ 下げる input 18 (Analog input 0)
const int cint_SwNum_LWindow_UP = 13; //左ウィンドウ 上げる input 19 (Analog input 1)
//const char cchr_Key_ExBrake_A = 'b'; //キー出力 オルタネート出力するとキーを無限に出し続けるのでON&OFF両出力にする
const char cchr_Key_ExBrake_A = 'x';
const char cchr_Key_ExBrake_M = 'x';
const char cchr_Key_Light = 'l';
const char cchr_Key_Winker_L = ',';
const char cchr_Key_Winker_R = '.';
const char cchr_Key_Engene_START = 'e';
const char cchr_Key_Engine_ELEC = 'z';
const char cchr_Key_Wiper_MINUS = 'q';
const char cchr_Key_Wiper_PLUS = 'p';
const char cchr_Key_Retarder_MINUS = '/';
const char cchr_Key_Retarder_PLUS = ';';
const char cchr_Key_LWindow_DOWN = 's';
const char cchr_Key_LWindow_UP = 'w';
const char cchr_Key_RWindow_DOWN = 'd';
const char cchr_Key_RWindow_UP = 'a';
const int cint_KeyKaisuu_ExBrake_A = 1;
const int cint_KeyKaisuu_ExBrake_M = 1;
const int cint_KeyKaisuu_Light = 1;
const int cint_KeyKaisuu_Winker_L = 1;
const int cint_KeyKaisuu_Winker_R = 1;
const int cint_KeyKaisuu_Engene_START = 1;
const int cint_KeyKaisuu_Engine_ELEC = 1;
const int cint_KeyKaisuu_Wiper_MINUS = 1;
const int cint_KeyKaisuu_Wiper_PLUS = 1;
const int cint_KeyKaisuu_EBrake = 5; //リターダー5段階+エンジンブレーキ
const int cint_KeyKaisuu_LWindow_DOWN = 1;
const int cint_KeyKaisuu_LWindow_UP = 1;
const int cint_KeyKaisuu_RWindow_DOWN = 1;
const int cint_KeyKaisuu_RWindow_UP = 1;
const int cint_KeyOut_Type_ONonly = 1; //スイッチ OFF → ON のときのみワンショットキー出力する
const int cint_KeyOut_Type_ONOFF = 2; //スイッチ OFF → ON , ON → OFF の2かいワンショットキー出力する
const int cint_KeyOut_Type_OFFonly = 3; //スイッチ ON → OFF のときのみワンショットキー出力する
const int cint_KeyOut_Type_ALT = 4; //スイッチ ON 中キーPushのまま、OFF になった時にキーReleaseする
int pint_KeyOut_kaisuu[20]; //キー出力何回目 カウンター
int pint_KeyOut_Control[20]; //キー出力コントロール
const int cint_KeyOut_Ctrl_START = 0; // 開始
const int cint_KeyOut_Ctrl_ONcheck = 1; // キープッシュタイマー監視中
const int cint_KeyOut_Ctrl_WAITcheck = 2; // キープッシュ後の待ち時間タイマー監視中
const int cint_KeyOut_Ctrl_ONcheckEBrake = 3; //緊急ブレーキのエンジンブレーキ キープッシュタイマー監視中
const int cint_KeyOut_Ctrl_WAITcheckEBrake = 4; //緊急ブレーキのエンジンブレーキ キープッシュ後の待ち時間タイマー監視中
//アナログ制御
//const int cint_Analog_INPUT = 0;
//int pint_AnalogPrev; //スイッチの前状態
//int pint_AnalogNow; //スイッチの現在の状態
//char pchr_AnalogKey; //出力するキー
//int pint_AnalogKeyOut_kaisuu; //キー出力する回数
//緊急ブレーキ用変数
char pchr_EB_Key;
//*************************************************************************************************************
void setup() {
for (int intNum = cint_SwDIN_START; intNum <= cint_SwDIN_END; intNum++) {
//---------- スイッチの初期化 ----------
pinMode(intNum, INPUT_PULLUP); //ポート全てINPUT_PULLUPに設定
pint_SwCheck[intNum] = cint_SwCheck_NOT; //スイッチの状態チェック しないセット
pint_SwPrev[intNum] = 0; //スイッチの前状態を初期化
pint_SwNow[intNum] = 0; //スイッチの今状態を初期化
pint_SwChg[intNum] = cint_SwCtrl_OFFtoOFF; //スイッチ状態変化を初期化「OFFのまま」セット
//---------- キー出力初期化 ----------
pint_KeyOut_Control[intNum] = cint_KeyOut_Ctrl_START; //各機能のキー出力コントロール 制御開始セット
pulng_KeyTime[intNum] = 0; //キー出力時のプッシュ時間、待ち時間用のタイマーを初期化
pint_KeyOut_kaisuu[intNum] = 0; //出力回数カウンター初期化
}
Serial.begin(9600);
Keyboard.begin();
//---------- 機能ごとに制御開始 ----------
pint_SwCheck[cint_SwNum_ExBrake_A] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_ExBrake_M] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_Light] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_Winker_L] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_Winker_R] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_Engene_START] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_Engine_ELEC] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_Wiper_MINUS] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_Wiper_PLUS] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_LWindow_DOWN] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_LWindow_UP] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_RWindow_DOWN] = cint_SwCheck_START;
pint_SwCheck[cint_SwNum_RWindow_UP] = cint_SwCheck_START;
//アナログ初期化
// pint_SwCheck[cint_SwNum_Retarder] = cint_SwCheck_START;
// pint_AnalogPrev = 0;
// pint_AnalogNow = 0;
// pint_AnalogKeyOut_kaisuu = 0;
}
//*************************************************************************************************************
void loop() {
int intNum;
subInputCheck(); //デジタル・アナログ インプット状態のチェック
//---------- 機能ごとにキー出力制御 (機能、出力するキーコード、キー出力タイプ、キー出力回数) ----------
// subKeyOutControl(cint_SwNum_ExBrake_A, cchr_Key_ExBrake_A, cint_KeyOut_Type_ALT, cint_KeyKaisuu_ExBrake_A); //エンジンブレーキ オルタネート、ALTキー出力
// subKeyOutControl(cint_SwNum_ExBrake_A, cchr_Key_ExBrake_A, cint_KeyOut_Type_ONOFF, cint_KeyKaisuu_ExBrake_A); //エンジンブレーキ オルタネート、ON&OFFキー出力
subKeyOutControl(cint_SwNum_ExBrake_M, cchr_Key_ExBrake_M, cint_KeyOut_Type_ONonly, cint_KeyKaisuu_ExBrake_M); //エンジンブレーキ モーメンタリ、ONのみキー出力
subKeyOutControl(cint_SwNum_Light, cchr_Key_Light, cint_KeyOut_Type_ONonly, cint_KeyKaisuu_Light);
//ライト、ONのみキー出力
subKeyOutControl(cint_SwNum_Winker_L, cchr_Key_Winker_L, cint_KeyOut_Type_ONonly, cint_KeyKaisuu_Winker_L); //ウィンカー左、ON&OFFキー出力
subKeyOutControl(cint_SwNum_Winker_R, cchr_Key_Winker_R, cint_KeyOut_Type_ONonly, cint_KeyKaisuu_Winker_R); //ウィンカー右、ON&OFFキー出力
subKeyOutControl(cint_SwNum_Engene_START, cchr_Key_Engene_START, cint_KeyOut_Type_ONonly, cint_KeyKaisuu_Engene_START); //エンジンスタート、ONのみキー出力
subKeyOutControl(cint_SwNum_Engine_ELEC, cchr_Key_Engine_ELEC, cint_KeyOut_Type_ONOFF, cint_KeyKaisuu_Engine_ELEC); //電気系統 ON&OFFキー出力
subKeyOutControl(cint_SwNum_Wiper_MINUS, cchr_Key_Wiper_MINUS, cint_KeyOut_Type_ONonly, cint_KeyKaisuu_Wiper_MINUS); //ワイパー(+)、ONのみキー出力
subKeyOutControl(cint_SwNum_Wiper_PLUS, cchr_Key_Wiper_PLUS, cint_KeyOut_Type_ONonly, cint_KeyKaisuu_Wiper_PLUS); //ワイパー(-)、ONのみキー出力
subKeyOutControl(cint_SwNum_LWindow_DOWN, cchr_Key_LWindow_DOWN, cint_KeyOut_Type_ALT, cint_KeyKaisuu_LWindow_DOWN); //左ウィンドウ 下げる オルタネート
subKeyOutControl(cint_SwNum_LWindow_UP, cchr_Key_LWindow_UP, cint_KeyOut_Type_ALT, cint_KeyKaisuu_LWindow_UP); //左ウィンドウ 上げる オルタネート
subKeyOutControl(cint_SwNum_RWindow_DOWN, cchr_Key_RWindow_DOWN, cint_KeyOut_Type_ALT, cint_KeyKaisuu_RWindow_DOWN); //右ウィンドウ 下げる オルタネート
subKeyOutControl(cint_SwNum_RWindow_UP, cchr_Key_RWindow_UP, cint_KeyOut_Type_ALT, cint_KeyKaisuu_RWindow_UP); //右ウィンドウ 上げる オルタネート
//リターダー アナログ入力で6段階
// subKeyOutControl(cint_SwNum_Retarder, pchr_AnalogKey, cint_KeyOut_Type_ONonly, pint_AnalogKeyOut_kaisuu); //リターダー スイッチ移動量により出力回数可変
//緊急ブレーキシステム ExBrake_M を使用する
// 1本のレバーを入れるだけで廃棄ブレーキON+リターダーブレーキ最大に入れる、解除も一気に廃棄ブレーキOFF+リターダーブレーキ解除する
subEmergencyBrake(cint_SwNum_ExBrake_A, cchr_Key_ExBrake_A, cint_KeyOut_Type_ONOFF, cint_KeyKaisuu_EBrake);
// String strTmp = String( pint_AnalogKeyOut_kaisuu ) + " kaisuu";
// Serial.println( strTmp );
//制御ルーチンはDelayを使わずに実行しているので全ての制御が取りこぼしなく平行に行われる
//キー出力時間、連続するキー出力間の待ち時間などをDelayでプログラムを止めることなく、次のスイッチ制御に渡っていく
//超簡易的なマルチタスクみたいなもん
delay(10); //信号制御の中でDelay関数を使うと、複数制御では取りこぼしが起こるためここでしか使わない
}
//****** END *******************************************************************************************************
//緊急ブレーキシステム ExBrake_M を使用する
// 1本のレバーを入れるだけで廃棄ブレーキON+リターダーブレーキ最大に入れる、解除も一気に廃棄ブレーキOFF+リターダーブレーキ解除する
void subEmergencyBrake(int intCtrlNum,char chrKey,int intKeyOutType,int intKaisuu) {
String strTmp = "";
//時間監視中なら飛ぶ
if ( pint_KeyOut_Control[intCtrlNum] == cint_KeyOut_Ctrl_ONcheck ) { //キープッシュ時間 調査中?
goto EB_ONcheck_2; // キープッシュ時間 調査へ
} else if ( pint_KeyOut_Control[intCtrlNum] == cint_KeyOut_Ctrl_WAITcheck ) { //キーリリース後の待ち時間 調査中?
goto EB_WAITcheck_2; // キーリリース後の待ち時間 調査へ
} else if ( pint_KeyOut_Control[intCtrlNum] == cint_KeyOut_Ctrl_ONcheckEBrake ) { //キーリリース後の待ち時間 調査中?
goto EB_ONcheck_4; // キーリリース後の待ち時間 調査へ
} else if ( pint_KeyOut_Control[intCtrlNum] == cint_KeyOut_Ctrl_WAITcheckEBrake ) { //キーリリース後の待ち時間 調査中?
goto EB_WAITcheck_4; // キーリリース後の待ち時間 調査へ
}
if ( intKaisuu == 0 ){
return;
}
//スイッチ状態によりキー出力
if ( pint_SwChg[intCtrlNum] == cint_SwCtrl_OFFtoON ) { //スイッチ状態 OFF → ON?
pint_SwChg[intCtrlNum] = cint_SwCtrl_ONtoON; // スイッチ状態を解除(ON → ON にセット)
pchr_EB_Key = cchr_Key_Retarder_PLUS;
// ここで解除しない限り OFF → ON の状態は保持される
// よって取りこぼしは無い
if ( intKeyOutType == cint_KeyOut_Type_ALT ){ // オルタネート動作?
Keyboard.press( pchr_EB_Key ); // キープッシュのまま
// strTmp = String( pchr_EB_Key ) + " push";
// Serial.println( strTmp );
return;
} else if ( intKeyOutType == cint_KeyOut_Type_OFFonly ){ // OFF → ON でキー出力しない?
return; // キー出力しないのでリターン
}
//----- ONonly & ONOFF -----
pint_SwCheck[intCtrlNum] = cint_SwCheck_NOT; // キー出力開始するのでスイッチ状態のチェックをしないようにセット
pint_KeyOut_kaisuu[intCtrlNum] = 1; // キー出力回数を1セット(1回目)
goto EB_ONcheck_1; // キー出力開始(キー出力開始)へ
}
if ( pint_SwChg[intCtrlNum] == cint_SwCtrl_ONtoOFF ){ //スイッチ状態 ON → OFF?
pint_SwChg[intCtrlNum] = cint_SwCtrl_OFFtoOFF; // スイッチ状態を解除(OFF → OFF にセット)
pchr_EB_Key = cchr_Key_Retarder_MINUS;
// ここで解除しない限り ON → OFF の状態は保持される
// よって取りこぼしは無い
if ( intKeyOutType == cint_KeyOut_Type_ALT ){ // オルタネート動作?
Keyboard.release( pchr_EB_Key ); // キーリリース
// strTmp = String( pchr_EB_Key ) + " release";
// Serial.println( strTmp );
return;
} else if ( intKeyOutType == cint_KeyOut_Type_ONonly ){ // ON → OFF でキー出力しない?
return; // キー出力しないのでリターン
}
//----- OFFonly & ONOFF -----
pint_SwCheck[intCtrlNum] = cint_SwCheck_NOT; // キー出力開始するのでスイッチ状態のチェックをしないようにセット
pint_KeyOut_kaisuu[intCtrlNum] = 1; // キー出力回数を1セット(1回目)
goto EB_ONcheck_1; // キー出力開始(キー出力開始)へ
}
return;
EB_ONcheck_1: //キープッシュ開始
Keyboard.press( pchr_EB_Key ); // キープッシュ
// strTmp = String( pchr_EB_Key ) + " push";
// Serial.println( strTmp );
pulng_KeyTime[intCtrlNum] = millis() + cint_KeyTime_Push; // キープッシュ時間セット 現在時間+PushTime(msec)
pint_KeyOut_Control[intCtrlNum] = cint_KeyOut_Ctrl_ONcheck;
EB_ONcheck_2: //キープッシュ時間 調査
if ( pulng_KeyTime[intCtrlNum] < millis() ){ // キープッシュ時間が終了した?
Keyboard.release( pchr_EB_Key ); // キーリリース
// strTmp = String( pchr_EB_Key ) + " Release";
// Serial.println( strTmp );
goto EB_WAITcheck_1; // キーリリース後の待ち時間 開始へ
}
return;
EB_WAITcheck_1: //キーリリース後の待ち時間 開始
pulng_KeyTime[intCtrlNum] = millis() + cint_KeyTime_Wait; // キーリリース後の待ち時間セット 現在時間+WaitTime(msec)
pint_KeyOut_Control[intCtrlNum] = cint_KeyOut_Ctrl_WAITcheck; // キーリリース後の待ち時間の調査中をセット
EB_WAITcheck_2: //キーリリース後の待ち時間 調査
if ( pulng_KeyTime[intCtrlNum] < millis() ){ // キーリリース後の待ち時間が終了した?
pint_KeyOut_kaisuu[intCtrlNum] += 1; // キー出力回数を+1
if ( pint_KeyOut_kaisuu[intCtrlNum] > intKaisuu ) { // キー出力回数が終了した?
pint_KeyOut_Control[intCtrlNum] = cint_KeyOut_Ctrl_START; // Yes → キー出力の制御を最初に戻す
pint_SwCheck[intCtrlNum] = cint_SwCheck_START; // スイッチ状態チェック 再開
pint_SwChg[intCtrlNum] = cint_SwCtrl_OFFtoOFF; // スイッチ状態 OFFで変化なしにセット
} else {
goto EB_ONcheck_1; // No → 次のキー出力開始へ
}
goto EB_ONcheck_3; //リターダー出力が回数終わったら廃棄ブレーキ出力へ
}
return;
//廃棄ブレーキ出力
EB_ONcheck_3: //キープッシュ開始
Keyboard.press( cchr_Key_ExBrake_M ); // キープッシュ
// strTmp = String( cchr_Key_ExBrake_M ) + " push";
// Serial.println( strTmp );
pulng_KeyTime[intCtrlNum] = millis() + cint_KeyTime_Push; // キープッシュ時間セット 現在時間+PushTime(msec)
pint_KeyOut_Control[intCtrlNum] = cint_KeyOut_Ctrl_ONcheckEBrake;
EB_ONcheck_4: //キープッシュ時間 調査
if ( pulng_KeyTime[intCtrlNum] < millis() ){ // キープッシュ時間が終了した?
Keyboard.release( cchr_Key_ExBrake_M ); // キーリリース
// strTmp = String( cchr_Key_ExBrake_M ) + " Release";
// Serial.println( strTmp );
goto EB_WAITcheck_3; // キーリリース後の待ち時間 開始へ
}
return;
EB_WAITcheck_3: //キーリリース後の待ち時間 開始
pulng_KeyTime[intCtrlNum] = millis() + cint_KeyTime_Wait; // キーリリース後の待ち時間セット 現在時間+WaitTime(msec)
pint_KeyOut_Control[intCtrlNum] = cint_KeyOut_Ctrl_WAITcheckEBrake; // キーリリース後の待ち時間の調査中をセット
EB_WAITcheck_4: //キーリリース後の待ち時間 調査
if ( pulng_KeyTime[intCtrlNum] < millis() ){ // キーリリース後の待ち時間が終了した?
pint_KeyOut_Control[intCtrlNum] = cint_KeyOut_Ctrl_START; // Yes → キー出力の制御を最初に戻す
pint_SwCheck[intCtrlNum] = cint_SwCheck_START; // スイッチ状態チェック 再開
pint_SwChg[intCtrlNum] = cint_SwCtrl_OFFtoOFF; // スイッチ状態 OFFで変化なしにセット
}
return;
}
//****** END *******************************************************************************************************
//スイッチ状態の変化調査
void subInputCheck() {
String strTmp = "";
//---------- デジタルインプット チェック ----------
for (int intPin = cint_SwDIN_START; intPin <= cint_SwDIN_END; intPin++) {
if ( pint_SwCheck[intPin] != cint_SwCheck_NOT ){ //制御無しなら次のスイッチへ
pint_SwNow[intPin] = digitalRead(intPin);
if ( pint_SwNow[intPin] == pint_SwPrev[intPin] ) { //ピンの状態に変化なし
if ( pint_SwNow[intPin] == HIGH ) {
pint_SwChg[intPin] = cint_SwCtrl_OFFtoOFF; //スイッチ状態 OFFのまま変化なし
} else {
pint_SwChg[intPin] = cint_SwCtrl_ONtoON; //スイッチ状態 ONのまま変化なし
}
} else {
if ( pint_SwNow[intPin] == HIGH) {
pint_SwChg[intPin] = cint_SwCtrl_ONtoOFF; //スイッチ状態 ON→OFF
// strTmp = String(intPin) + " OFF";
// Serial.println(strTmp);
} else {
pint_SwChg[intPin] = cint_SwCtrl_OFFtoON; //スイッチ状態 OFF→ON
// strTmp = String(intPin) + " ON";
// Serial.println(strTmp);
}
pint_SwPrev[intPin] = pint_SwNow[intPin];
}
}
}
//---------- アナログインプット チェック ----------
// if ( pint_SwCheck[cint_SwNum_Retarder] != cint_SwCheck_NOT ){
// //リターダー アナログ入力
// // 0:0.00v 1:0.40v 2:0.80v 3:1.21v 4:1.62v 5:2.03v
// int intAnalogValue = analogRead( cint_Analog_INPUT );
// float fltAnalogValue = intAnalogValue * 5.0 / 1023.0;
// if ( fltAnalogValue < 0.20 ){
// pint_AnalogNow = 0;
// } else if ( fltAnalogValue < 0.60 ){
// pint_AnalogNow = 1;
// } else if ( fltAnalogValue < 1.00 ){
// pint_AnalogNow = 2;
// } else if ( fltAnalogValue < 1.40 ){
// pint_AnalogNow = 3;
// } else if ( fltAnalogValue < 1.80 ){
// pint_AnalogNow = 4;
// } else {
// pint_AnalogNow = 5;
// }
//// Serial.println( pint_AnalogNow );
//// Serial.println( fltAnalogValue );
//
// if ( pint_AnalogNow > pint_AnalogPrev ){
// //----- PLUS -----
// pint_AnalogKeyOut_kaisuu = pint_AnalogNow - pint_AnalogPrev;
// pchr_AnalogKey = cchr_Key_Retarder_PLUS;
// pint_SwChg[cint_SwNum_Retarder] = cint_SwCtrl_OFFtoON;
// } else if ( pint_AnalogPrev > pint_AnalogNow ){
// //----- MINUS -----
// pint_AnalogKeyOut_kaisuu = pint_AnalogPrev - pint_AnalogNow;
// pchr_AnalogKey = cchr_Key_Retarder_MINUS;
// pint_SwChg[cint_SwNum_Retarder] = cint_SwCtrl_OFFtoON;
// } else {;
// //----- 変化なし -----
// pint_AnalogKeyOut_kaisuu = 0;
// pchr_AnalogKey = cchr_Key_Retarder_MINUS;
// pint_SwChg[cint_SwNum_Retarder] = cint_SwCtrl_OFFtoOFF;
// }
// pint_AnalogPrev = pint_AnalogNow;
// }
}
//****** END *******************************************************************************************************
//キー出力コントロール スイッチON・OFFに変化した時キー出力 intKaisuu 回出力する
// キー出力が開始されると少なくとも1回は Push(msec)+Wait(msec) の間スイッチ状態のチェックをしないので、これがチャタリング除去になる
void subKeyOutControl(int intCtrlNum,char chrKey,int intKeyOutType,int intKaisuu) {
String strTmp = "";
//時間監視中なら飛ぶ
if ( pint_KeyOut_Control[intCtrlNum] == cint_KeyOut_Ctrl_ONcheck ) { //キープッシュ時間 調査中?
goto ONcheck_2; // キープッシュ時間 調査へ
} else if ( pint_KeyOut_Control[intCtrlNum] == cint_KeyOut_Ctrl_WAITcheck ) { //キーリリース後の待ち時間 調査中?
goto WAITcheck_2; // キーリリース後の待ち時間 調査へ
}
if ( intKaisuu == 0 ){
return;
}
//スイッチ状態によりキー出力
if ( pint_SwChg[intCtrlNum] == cint_SwCtrl_OFFtoON ) { //スイッチ状態 OFF → ON?
pint_SwChg[intCtrlNum] = cint_SwCtrl_ONtoON; // スイッチ状態を解除(ON → ON にセット)
// ここで解除しない限り OFF → ON の状態は保持される
// よって取りこぼしは無い
if ( intKeyOutType == cint_KeyOut_Type_ALT ){ // オルタネート動作?
Keyboard.press( chrKey ); // キープッシュのまま
// strTmp = String( chrKey ) + " push";
// Serial.println( strTmp );
return;
} else if ( intKeyOutType == cint_KeyOut_Type_OFFonly ){ // OFF → ON でキー出力しない?
return; // キー出力しないのでリターン
}
//----- ONonly & ONOFF -----
pint_SwCheck[intCtrlNum] = cint_SwCheck_NOT; // キー出力開始するのでスイッチ状態のチェックをしないようにセット
pint_KeyOut_kaisuu[intCtrlNum] = 1; // キー出力回数を1セット(1回目)
goto ONcheck_1; // キー出力開始(キー出力開始)へ
}
if ( pint_SwChg[intCtrlNum] == cint_SwCtrl_ONtoOFF ){ //スイッチ状態 ON → OFF?
pint_SwChg[intCtrlNum] = cint_SwCtrl_OFFtoOFF; // スイッチ状態を解除(OFF → OFF にセット)
// ここで解除しない限り ON → OFF の状態は保持される
// よって取りこぼしは無い
if ( intKeyOutType == cint_KeyOut_Type_ALT ){ // オルタネート動作?
Keyboard.release( chrKey ); // キーリリース
// strTmp = String( chrKey ) + " release";
// Serial.println( strTmp );
return;
} else if ( intKeyOutType == cint_KeyOut_Type_ONonly ){ // ON → OFF でキー出力しない?
return; // キー出力しないのでリターン
}
//----- OFFonly & ONOFF -----
pint_SwCheck[intCtrlNum] = cint_SwCheck_NOT; // キー出力開始するのでスイッチ状態のチェックをしないようにセット
pint_KeyOut_kaisuu[intCtrlNum] = 1; // キー出力回数を1セット(1回目)
goto ONcheck_1; // キー出力開始(キー出力開始)へ
}
return;
ONcheck_1: //キープッシュ開始
Keyboard.press( chrKey ); // キープッシュ
// strTmp = String( chrKey ) + " push";
// Serial.println( strTmp );
pulng_KeyTime[intCtrlNum] = millis() + cint_KeyTime_Push; // キープッシュ時間セット 現在時間+PushTime(msec)
pint_KeyOut_Control[intCtrlNum] = cint_KeyOut_Ctrl_ONcheck;
ONcheck_2: //キープッシュ時間 調査
if ( pulng_KeyTime[intCtrlNum] < millis() ){ // キープッシュ時間が終了した?
Keyboard.release( chrKey ); // キーリリース
// strTmp = String( chrKey ) + " Release";
// Serial.println( strTmp );
goto WAITcheck_1; // キーリリース後の待ち時間 開始へ
}
return;
WAITcheck_1: //キーリリース後の待ち時間 開始
pulng_KeyTime[intCtrlNum] = millis() + cint_KeyTime_Wait; // キーリリース後の待ち時間セット 現在時間+WaitTime(msec)
pint_KeyOut_Control[intCtrlNum] = cint_KeyOut_Ctrl_WAITcheck; // キーリリース後の待ち時間の調査中をセット
WAITcheck_2: //キーリリース後の待ち時間 調査
if ( pulng_KeyTime[intCtrlNum] < millis() ){ // キーリリース後の待ち時間が終了した?
pint_KeyOut_kaisuu[intCtrlNum] += 1; // キー出力回数を+1
if ( pint_KeyOut_kaisuu[intCtrlNum] > intKaisuu ) { // キー出力回数が終了した?
pint_KeyOut_Control[intCtrlNum] = cint_KeyOut_Ctrl_START; // Yes → キー出力の制御を最初に戻す
pint_SwCheck[intCtrlNum] = cint_SwCheck_START; // スイッチ状態チェック 再開
pint_SwChg[intCtrlNum] = cint_SwCtrl_OFFtoOFF; // スイッチ状態 OFFで変化なしにセット
} else {
goto ONcheck_1; // No → 次のキー出力開始へ
}
}
return;
}
//****** END *******************************************************************************************************
シェアボタン: このページをSNSに投稿するのに便利です。
トラコンヘルパーハンコンでATS・ETS2で遊ぶときのとても便利なソフトが開発・公開されました!ソフト名:ToraCon-Helper作者 :kuramochia さんここではインストール方法や使い...
ATS、ETS2 をVRで遊びましょうATS、ETS2のトラックにVRで乗り込むと、その臨場感に圧倒されます。トラックの運転席の高いこと!広いこと!実感して世界の中に入り込んでください。ここではVRで...
MSFS2020 日本語解説Automobilista2解説モンハンVR化解説hideGのVR情報Carrier Command 2Project CARS 2 VRETS2・ATS:VRVTOL V...
HORI トラックコントローラーの取り付け正式名称:HORI FORCE FEEDBACK TRUCK CONTROL SYSTEM for Windows PC2024年(令和6年)6月19日 情報...
ATS、ETS2をVRで遊ぶための設定 2024年07月10日VR機器について現在私は11種類12台のVR機器を所有していました以前は「Varjo Aero」が最適のVRゴーグルとして解説していました...
Arduino のプログラムを作る外部スイッチなどを付けて、この入力をUSBを通じてPC(ATSやETS2)に信号を送る方法Arduino Leonardo を使うことでジョイスティック出力またはキー...
ATS、ETS2をVRで遊ぶための設定●ここの解説は古くなっています。新しいページを作りましたので、そちらをご覧ください。VR機器について現在私は11種類12台のVR機器を所有しています以前は「Var...
ETS2、ATS:公式マルチとVR【VR解説】ETS2、ATS はVRで運転することができます。VRでトラックの運転席に座ると、その広さ高さに驚くことでしょう特に「高さ」はVRじゃないと感じられないの...
【ウィンカーワイパー装置】ウィンカーやワイパーレバーの付いた画期的アイテムを手に入れました。今までは外付けでレバースイッチを付けてウィンカーを作っていたのですが、やっぱり「ハンドルを戻すとウィンカーレ...
●●● ここの記事は過去のものです 新しいページを御覧ください ●●●>VR解説--------- 過去記事 ------------------------------------------...
はじめにここは、雑談・質問・相談など何でも話題にする掲示板です。掲示板についてお知らせコメント・質問等投稿の際はかならず「ハンドルネーム」を入力してください。禁止事項 掲示板の趣旨と関係ない書き込み ...
ベータ1.41 の導入方法【ETS2】ATSに続きETS2でも公式マルチのテストが開始されました。ETS2もATSに続きアクセスコードの必要ない「Public beta」に引き上げられました。STEA...
【クイックリプライ】クイックリプライは運転中も返信ができる文字チャットです。あらかじめ設定しておいた文を選んで返信することができます。日本語も使えますので色々な言葉を登録しておいて活用しましょう。運転...
【マルチのやりかた】コンボイを押すとマルチの一覧が表示されます「コンボイを主催する」をクリックして自分の部屋の作り方はこんな感じセッションを選ぶと右に内容が表示されます部屋ができるとマルチの情報表示が...
右メニューサンプル右メニューはヘッダーメニューの【編集】>【右メニューを編集する】をクリックすると編集できます。 ご自由に編集してください。 ここを編集する...
まずは最初に発信したい文章を自由に入力して保存ボタンを押してみましょう。これで即ページ上に情報発信が可能です。簡単ですね。ちなみに改行したい時は「Shift+Enter(return)」、段落を変える...