1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Euro Truck Simulator2(ETS2)用の後付けウインカーレバーをAtom liteで作ってみた

Last updated at Posted at 2024-10-07

たまにEuro Truck Simulator2(ETS2)というトラックを運転するゲームをやっているのですが、

使ってるハンコン(Driving Force GT)にウインカーレバーが無くて(普通無い)ボタンを押してウインカーを点灯させていたので不便で仕方なかったんです。

というわけで作りました。

使用するデバイス

Atom lite

image.png

M5Stackシリーズで一番小さいやつ

GPIOが生えてるマイコンなら何でもいいんですけどAtom liteは小さくてケースに入ってるから使いやすいんですよね。
ボタンとLEDもついてるから必要十分だし安いから単機能で使いつぶしても惜しくないのがいいところです。

レバースイッチ

image.png

Amazonでレバースイッチを検索したら出てきたんですけどギター用でした。

image.png

作った後気づいたんですけどこういうトグルスイッチでも良かったですね。
ただ動かしたらセンターに戻らないのでセンターに戻る3極のスイッチあったら教えてください。

ロータリースイッチ

image.png

これもAmazonで適当に探したんですが大きかったです🤣

image.png

こういうロータリーディップスイッチを使った方が良かったと思います。

3Dプリンター

3万円くらいの安物ですがあるとすぐにモノが作れて便利ですね。

ハンコンに机に固定するために回すツマミがあったのでそれにマウントするようにします。

image.png

Atom liteやレバースイッチにノギスを当てながらAutodesk Fusionでゴリゴリとモデリングします。

image.png
image.png

image.png

1時間くらいでこれくらいプリントできるのは凄いことですね。

無いと思いますけど欲しい人がいたらSTLデータをアップします。

配線する

ギタースイッチにケーブルをハンダ付けしてAtom liteのGPIOに接続します。

image.png

真ん中の端子は使わなくなったので2本+GNDだけで良いです。

ロータリースイッチはポジションが12個あるんですが、
どちらに回転したかが分かればよいので2個おきにポリウレタン銅線でショートするようにハンダ付けしました。
GPIOも3個だけでよくなります。

image.png

image.png

ハンダ付けができたらAtom liteのGPIOに接続します。

image.png

レバースイッチ1:19
レバースイッチ2:33
ロータリースイッチ1:25
ロータリースイッチ2:22
ロータリースイッチ3:21

スケッチを書く

スケッチはこんな感じです。
割り込み使った方がいいんじゃね?とか思わないでもないですが、
実は割り込み使ったこと無いです・・・(´・ω・`)

細かい解説は下でやります。

#include <Arduino.h>
#include <M5Atom.h>
#include <BleKeyboard.h>

BleKeyboard bleKeyboard("AtomWinkerLever");

void setup() {
  M5.begin(true, false, true); // M5Atomの初期化
  bleKeyboard.begin();
  M5.dis.drawpix(0, 0xf0f000); // 初期状態で黄色を表示
  pinMode(19, INPUT_PULLUP);   // ボタン入力ピン19をプルアップ
  pinMode(23, INPUT_PULLUP);   // ボタン入力ピン23をプルアップ
  pinMode(33, INPUT_PULLUP);   // ボタン入力ピン33をプルアップ
  pinMode(25, INPUT_PULLUP);   // ロータリースイッチ1
  pinMode(22, INPUT_PULLUP);   // ロータリースイッチ2
  pinMode(21, INPUT_PULLUP);   // ロータリースイッチ3
}

#define LEVER_UP 0
#define LEVER_MID 1
#define LEVER_DOWN 2
#define ROTARY_1 0
#define ROTARY_2 1
#define ROTARY_3 2

int past = LEVER_MID;
int pastRotary = ROTARY_1;

// BLE Keybordからキーを送る
// 接続チェックもここでやる
void sendKey(char c) {
  if (bleKeyboard.isConnected()) {
    bleKeyboard.print(c);
  }
}

void loop() {
  M5.update();
  if (M5.Btn.wasReleased()) {
    if (bleKeyboard.isConnected()) {
      bleKeyboard.print("Test:Button Pressed");
    }
  }
  if (digitalRead(19) && digitalRead(33)) {
    // レバー上下両方ともHIGHならレバー中央
    M5.dis.drawpix(0, 0xf00000); // 赤色を表示
    // Serial.println("RED");
    past = LEVER_MID;
  }
  else if (!digitalRead(19)) {
    if (bleKeyboard.isConnected()) {
      // Lever UP
      if (past != LEVER_UP) {
        // 読み取り値(レバー位置)が変化してなければ無視
        M5.dis.drawpix(0, 0x00f000); // 緑色を表示
        // Serial.println("GREEN");
        // US配列で[だがJP配列だと@になる
        sendKey('[');
        // bleKeyboard.print("LEVER_UP");
        // bleKeyboard.write(KEY_RETURN);
        past = LEVER_UP;
      }
    }
  }
  else if (!digitalRead(33)) {
    // Lever DOWN
    if (past != LEVER_DOWN) {
      // 読み取り値(レバー位置)が変化してなければ無視
      M5.dis.drawpix(0, 0x0000f0); // 赤色を表示
      Serial.println("BLUE");
      // US配列で]だがJP配列だと[になる
      sendKey(']');
      // bleKeyboard.print("LEVER_DOWN");
      // bleKeyboard.write(KEY_RETURN);
      past = LEVER_DOWN;
    }
  }
  if (!digitalRead(25)) {
    if (pastRotary != ROTARY_1) {
      if (pastRotary == ROTARY_3) {
        // 時計回り
        // Serial.printf("CW:%d\n", ROTARY_1 + 1);
        sendKey('l');
      }
      else {
        // 反時計回り
        // Serial.printf("CCW:%d\n", ROTARY_1 + 1);
        sendKey('l');
      }
      pastRotary = ROTARY_1;
    }
  }
  else if (!digitalRead(22)) {
    if (pastRotary != ROTARY_2) {
      if (pastRotary == ROTARY_1) {
        // 時計回り
        // Serial.printf("CW:%d\n", ROTARY_2 + 1);
        sendKey('l');
      }
      else {
        // 反時計回り
        // Serial.printf("CCW:%d\n", ROTARY_2 + 1);
        sendKey('l');
      }
      pastRotary = ROTARY_2;
    }
  }
  else if (!digitalRead(21)) {
    if (pastRotary != ROTARY_3) {
      if (pastRotary == ROTARY_2) {
        // 時計回り
        // Serial.printf("CW:%d\n", ROTARY_3 + 1);
        sendKey('l');
      }
      else {
        // 反時計回り
        // Serial.printf("CCW:%d\n", ROTARY_3 + 1);
        sendKey('l');
      }
      pastRotary = ROTARY_3;
    }
  }
  delay(100);
}

スイッチの読み取り

  pinMode(19, INPUT_PULLUP);   // ボタン入力ピン19をプルアップ
  pinMode(23, INPUT_PULLUP);   // ボタン入力ピン23をプルアップ
  pinMode(33, INPUT_PULLUP);   // ボタン入力ピン33をプルアップ
  pinMode(25, INPUT_PULLUP);   // ロータリースイッチ1
  pinMode(22, INPUT_PULLUP);   // ロータリースイッチ2
  pinMode(21, INPUT_PULLUP);   // ロータリースイッチ3

スイッチを読み取るときはGPIOのINPUT_PULLUPを使うと便利です。
INPUT_PULLUPを指定してGNDとGPIOの間にスイッチを挟んでdigitalRead()すると
OFFはHIGH(true),ONはLOW(false)が返ってきます。

  if (digitalRead(19) && digitalRead(33)) {
    // レバー上下両方ともHIGHならレバー中央
    M5.dis.drawpix(0, 0xf00000); // 赤色を表示
    // Serial.println("RED");
    past = LEVER_MID;
  }
  else if (!digitalRead(19)) {
  // レバーが上の時

ゲームへコマンドを送る

スイッチの状態が取れるようになったらゲームへワイパーとライトを動かすコマンドを送ります。

実はAtom liteがBLE KeyboardになっててキーストロークをPCに送ってるだけです。

image.png
ウインカーは@と[で左右に動かします。

BLE Keyboardライブラリを使っています。

後はスイッチが動いた時に応じて処理を実装していきます


#include <BleKeyboard.h>

// PCに登録されるときの名前
BleKeyboard bleKeyboard("AtomWinkerLever");


void setup() {
  M5.begin(true, false, true); // M5Atomの初期化
  bleKeyboard.begin();
}

// BLE Keybordからキーを送る
// 接続チェックもここでやる
void sendKey(char c) {
  if (bleKeyboard.isConnected()) {
    bleKeyboard.print(c);
  }
}

void loop() {
  if (digitalRead(19) && digitalRead(33)) {
    // レバー上下両方ともHIGHならレバー中央
    past = LEVER_MID;
  }
  else if (!digitalRead(19)) {
    // Lever UP(ウインカー左)
    if (past != LEVER_UP) {
      // 読み取り値(レバー位置)が変化してなければ無視
      // US配列で[だがJP配列だと@になる
      sendKey('[');
      past = LEVER_UP;
    }
  }
  else if (!digitalRead(33)) {
    // Lever DOWN(ウインカー右)
    if (past != LEVER_DOWN) {
      // 読み取り値(レバー位置)が変化してなければ無視
      // US配列で]だがJP配列だと[になる
      sendKey(']');
      past = LEVER_DOWN;
    }
  }
  if (!digitalRead(25)) {
    if (pastRotary != ROTARY_1) {
      sendKey('l');
      pastRotary = ROTARY_1;
    }
  }
  else if (!digitalRead(22)) {
    if (pastRotary != ROTARY_2) {
      sendKey('l');
      pastRotary = ROTARY_2;
    }
  }
  else if (!digitalRead(21)) {
    if (pastRotary != ROTARY_3) {
      sendKey('l');
      pastRotary = ROTARY_3;
    }
  }
  delay(100);
}

ちなみにETS2にウインカーを逆に動かすコマンドが無かったのでロータリースイッチはGPIO2個で良かったです(´・ω・`)

パッシングとハイビームは・・・?

ゲーム中あんまりやることはないので作ってないです。
ただ、下部を分割してロータリースイッチを仕込めばできないことはないな~と思ってます。

image.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?