ETS2のVer1.37からはパワーウインドウの開閉ができるようになりました。それで、自己満足的にパワーウインドウ・スイッチを作ってみました。ベースにしたのはRX8の運転席側ドアスイッチです。
トレーラ・トラックの窓は運転席側と助手席側の2か所なので普通車用のスイッチではイメージに合いません。軽トラ用だときっとチープでしょうから、右ハンドル用になるのですが、手に入るものはこれしかありません。ヤフオク入手です。
木枠を作って、左ドアスイッチの位置に配置しました。ドアのように乗り降り時に開くことができます。
ついでにスイッチパネルについている他のスイッチにも機能を割り振りました。仕上がりは良好です。
ETS2のパワーウインドウ
スイッチを作る前に試しにキーボードの矢印キーにウインドウの開閉を設定してみたのですが、とても心地よく動きます。ON/OFFのスイッチ2個で一つの窓の開閉を行えることになります。
RX8のウインドウスイッチ
回路図の情報を探せませんでしたので、テスターで探りながら接点の解析を行いました。
調べていくと単なるON/OFFだけではなくスイッチの倒し具合により、一つのスイッチで何通りもの接点が存在します。オートモードがあるので接点がその分増えているのでしょう。不要な接点は飛ばして何とか使おうと色々トライしてみましたが、成立しませんでした。
仕方なく、シーソースイッチの機構だけ使い接点は内部にマイクロスイッチを仕込むことにします。次の写真はシーソースイッチの裏側にある基板です。スイッチの元々の接点部品は取り払い更地にしています。
緑の基板はシーソースイッチのすぐ裏側にあります。この基板は写真下のバスバーに乗っかっています。基板中央部に10個近く並んでいるのが基板とバスバーを繋ぐ端子になります。新たに仕込むマイクロスイッチはこれらの端子に接続します。
上から言えば、シーソースイッチ、基板、バスバーの順で重なっている格好です。コネクタ端子はバスバーから、写真で言うと右側で裏の方へ出ています。
マイクロスイッチの設置
使うマイクロスイッチはこれです。見えないところにマイクロスイッチを配置するので、3D CADでレイアウト検討をします。
基板はマイクロスイッチを固定するためと回路パターンに利用します。基板をシーソースイッチに重ねたときに、シーソースイッチから出ている突起がマイクロスイッチをON/OFFできるように位置決めする必要があります。
十字キーを使う
十字キーは実車と同じくバックミラーの前後左右の傾き調整に使います。
内部のパターンは下写真のようになっています。分かりやすくするため接点とパターンに色付けしました。見てのように、前後左右とも一方向につき2系統の接点の組み合わせにより構成しています。
このまま使うと処理が複雑になるので、一方向1パターンに改造します。白丸3か所でパターンカットし、白フチ青丸の1か所でパターンを繋ぎます。これによって、次のようになります。
- UP: 緑色、 端子④
- DOWN: ピンク、端子新設
- RIGHT: 茶色、 端子⑤
- LEFT: 空色、 端子⑥
6個のミラー
ETS2のゲーム上では、各ミラーが番号付けされています。この番号でミラー選択すればよいので、新たに番号キーになるものをRX8のドアスイッチパネルの前方に追加しました。最初の写真で6個のタクトスイッチが並んでいるものがそれです。1~6の数値KeyBoardとして設定します。
このスイッチはミラーの選択だけでなく、オプションライトやビーコンのON/OFFにも使えます。
その他のスイッチ
他のスイッチにもETS2上のゲーム機能を設定します。
- ウインドウOPEN禁止スイッチ: リーンアウト視点
- ミラー格納スイッチ: グローバルマップ
- L/Rスイッチ: 左右ビュー
- 新設スイッチ: ミラー選択メニュー
スイッチ機能のまとめ
スケッチ
Arduinoではありませんが、Leonardo互換の Pro Microを使います。非常にコンパクトでこういった用途には最適です。Resetボタンがついていなので、写真のようにResetピンから持ってきてタクトスイッチをつけています。
先に説明したバスバーにブレッドボードを貼り付け、そこにPro Microを取り付けました。
これをUSB KeyBoard HIDとして使います。左右のウインドウの開閉には、4つの矢印キーを使い、ミラーの前後左右の動きには、"W"、"S"、"A"、"D"のキーを使います。その他はA3ピンを除いてすべてのdegital input(ON/OFF)で使っています。A3はアナログピンで、VCCとGND間を抵抗分圧して入力しています。
// Leonardoの修飾キーの定義を以下に示します。
// キー 16進値 10進数
// KEY_LEFT_CTRL 0x80 128
// KEY_LEFT_SHIFT 0x81 129
// KEY_LEFT_ALT 0x82 130
// KEY_LEFT_GUI 0x83 131
// KEY_RIGHT_CTRL 0x84 132
// KEY_RIGHT_SHIFT 0x85 133
// KEY_RIGHT_ALT 0x86 134
// KEY_RIGHT_GUI 0x87 135
// KEY_UP_ARROW 0xDA 218
// KEY_DOWN_ARROW 0xD9 217
// KEY_LEFT_ARROW 0xD8 216
// KEY_RIGHT_ARROW 0xD7 215
// KEY_BACKSPACE 0xB2 178
// KEY_TAB 0xB3 179
// KEY_RETURN 0xB0 176
// KEY_ESC 0xB1 177
// KEY_INSERT 0xD1 209
// KEY_DELETE 0xD4 212
// KEY_PAGE_UP 0xD3 211
// KEY_PAGE_DOWN 0xD6 214
// KEY_HOME 0xD2 210
// KEY_END 0xD5 213
// KEY_CAPS_LOCK 0xC1 193
// KEY_F1 0xC2 194
// KEY_F2 0xC3 195
// KEY_F3 0xC4 196
// KEY_F4 0xC5 197
// KEY_F5 0xC6 198
// KEY_F6 0xC7 199
// KEY_F7 0xC8 200
// KEY_F8 0xC9 201
// KEY_F9 0xCA 202
// KEY_F10 0xCB 203
// KEY_F11 0xCC 204
// KEY_F12 0xCD 205
#include <Keyboard.h>
//#include "Mouse.h"
boolean beforeState = false;
int keyWait=20; //keyboardやbuttonを押した後の保持時間(待機時間)
// Last state of the button
int lastButtonState[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
unsigned long prev[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
const int Interval = 10 ; //msec, for prevrnt chattering
int lastAnalogInput = 512; //normalは抵抗分圧の中央で9991/2
const int AnalogInputPin = A3;
void setup(){
//起動時に行う処理
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
pinMode(16, INPUT_PULLUP);
pinMode(18, INPUT_PULLUP);
pinMode(19, INPUT_PULLUP);
pinMode(20, INPUT_PULLUP);
// Serial
Serial.begin (9600);
// Initialize Keyboard Library
Keyboard.begin();
}
void loop(){ //起動後、何度も行う処理
//ウインドウ開閉
if(digitalRead(0) == LOW){
if(!beforeState){
Keyboard.press(KEY_DOWN_ARROW); //open LH
beforeState = true;
}
}
else if(digitalRead(1) == LOW){
if(!beforeState){
Keyboard.press(KEY_UP_ARROW); //close LH
beforeState = true;
}
}
else if(digitalRead(2) == LOW){
if(!beforeState){
Keyboard.press(KEY_RIGHT_ARROW); //open RH
beforeState = true;
}
}
else if(digitalRead(3) == LOW){
if(!beforeState){
Keyboard.press(KEY_LEFT_ARROW); //close RH
beforeState = true;
}
}
else{
if(beforeState){
Keyboard.releaseAll();
beforeState = false;
}
}
// 十字キー
if(digitalRead(10) == LOW){
if(!beforeState){
Serial.println("Ver. UP: W");
Keyboard.write('w');
beforeState = true;
}
}
else if(digitalRead(16) == LOW){
if(!beforeState){
Serial.println("Hor. LEFT: A ");
Keyboard.write('a');
beforeState = true;
}
}
else if(digitalRead(14) == LOW){
if(!beforeState){
Serial.println("Ver. DOWN: S ");
Keyboard.write('s');
beforeState = true;
}
}
else if(digitalRead(15) == LOW){
if(!beforeState){
Serial.println("Ver. RIGHT: D ");
Keyboard.write('d');
beforeState = true;
}
}
else {
if(!beforeState){
//Serial1.println("Ver._Neutral");
Keyboard.releaseAll();
beforeState = false;
}
}
// Read pin values その他のスイッチ設定
for (int index = 4; index < 21; index++) {
int currentButtonState = !digitalRead(index);
if (int changed = (currentButtonState != lastButtonState[index])) {
unsigned long cur = millis();
if (cur - prev[index] > Interval) {
if (index < 10) {
if(!beforeState && currentButtonState){
Serial.println((String)"Key No " + (index - 3));Keyboard.write (48+ index -3 );} //button #1-6
beforeState = true;
} else switch (index) {
case 18: //このスイッチは他と違いnormal on(通電 LOW)
if(!beforeState && !currentButtonState) { //押すとOFF(HIGH), 押した後の状態はHIHG
Serial.println("+"); //Num + リーンアウト視点
Keyboard.write(223);
beforeState = true;
} else if (!beforeState && currentButtonState) {// 離すとき、離した後の状態はLOW
Serial.println("9"); //視点変更 '9'
Keyboard.write('9');delay(keyWait); //視点変更 '9'を4回入れてインテリア視点にする
Keyboard.write('9');delay(keyWait);
Keyboard.write('9');delay(keyWait);
Keyboard.write('9');
beforeState = true;
} break;
case 19:
if(!beforeState ){ //押したとき(HIGH to LOW)と離したときの両方でキーを出す
Serial.println("M"); //ワールドマップ
Keyboard.write('m');
beforeState = true;
} break;
case 20:
if(!beforeState && currentButtonState) { //押したとき(HIGH to LOW)
Serial.println("KEY_F4");
Keyboard.press(KEY_F4);
beforeState = true;
} break;
default:
if(beforeState){
Keyboard.releaseAll();
beforeState = false;
}
}
lastButtonState[index] = currentButtonState;
}
prev[index] = cur;
}
}
// Read analog pin values
int currentAnalogInput = analogRead(AnalogInputPin);
if (currentAnalogInput != lastAnalogInput)
{
if (abs(currentAnalogInput - lastAnalogInput) > 5) {
Serial.print(currentAnalogInput);
if (currentAnalogInput < 512/2 ){Keyboard.write(182);Serial.println(" tenkey ^ : Push LEFT");}// ^ LEFT
else if (currentAnalogInput > (512+1024)/2) {Keyboard.write(221);Serial.println(" ten key * : Push RIGHT");}// * RIGHT
else {Keyboard.write(233);delay(100);Keyboard.releaseAll();Serial.println(" not Push");}
lastAnalogInput = currentAnalogInput;
}
delay(100);
}
}