kon104のアイコン画像

iPadやPC問わずフィットネスバイクとストリートビューを連動するアダプター製作

kon104 2021年03月28日に作成  (2021年03月28日に更新)
iPadやPC問わずフィットネスバイクとストリートビューを連動するアダプター製作

はじめに

リモートワークや外出自粛で巣ごもり生活が多くなったので
運動不足解消にフィットネスバイク(エアロバイク)を買ってみましたが、
ご多分に漏れず長続きしなかったので、ArduinoでGoogleストリートビューと連動するアダプターを作ってみました。

先駆者「【フィットネスバイク】のインターネットを作る!!」の事例等では、
ペダルのフィードバックをインターネット経由でストリートビューの進行に反映しているが、
今回作ったアダプターはUSBキーボードとして機能するため、ダイレクトにデバイスに伝わるので、
Windows PCやMacはモチロンのこと、iPadやAndroidのデバイスでも動作し、
エアロバイクとデバイスに繋ぐだけの簡単セットアップで、気軽にエクササイズを開始できます。

ハンドルの舵取りはジョイスティックで操作します。

なお、USBデバイスとして動作させるにはATmega32u4搭載のArduinoを利用するのが手っ取り早いので、
今回の製作では該当コントローラーを搭載しているArduino Microを使っています。

イメージ

利用イメージ

ここに動画が表示されます

アダプター

ダイソーの500円コインケースを加工して、Arduino Microとジョイスティックを組み込みました

キャプションを入力できます

加工したコインケースに配線前のArduinoを組み込んだ状態(左)と、iPadとフィットネスバイクに実際に繋いだ状態(右)

キャプションを入力できます

構成

システム全体の構成図です

キャプションを入力できます

  • 利用しているフィットネスバイクは「ALINCO クロスバイク4417
    • ペダルの回転判定のメーターへの連動は、オーディオケーブルが使われている
  • メーターへの接続直前にオーディオ分配ケーブルを割り込ませ、アダプターを接続できるようにする
  • アダプターがストリートビューの進行を制御する
    • ペダルの回転でストリートビューを前進する
    • ハンドルの舵取りはジョイスティックで左右転回する
  • Lightning端子のiOSデバイスは「Lightning - USBカメラアダプタ」を使いUSBケーブルへ接続する
  • アプリ版のGoogleマップはキーボード移動に対応していないので、iPad/iPhone、Androidの場合でもブラウザ版を利用する

材料

部品 型番 個数
マイコンボード Arduino Micro ピンヘッダ無し 1個
オーディオジャック ステレオジャック 3.5mm 1個
オーディオケーブル ステレオ分配ケーブル 3.5mm (メス⇔オス×2) 0.2m 1本
ジョイスティック ジョイスティック モジュール 1個
ケーブル(オーディオジャック接続) ジャンパワイヤ(オス~オス) 2本
ケーブル(ジョイスティック接続) ジャンパワイヤ(オス~メス) 5本
スペーサー 絶縁POM(ポム)スペーサー 六角 M3×15mm [RoHS] 4個
ネジ EV型導通ビス M3×5mm 8本
ケース コインケース 500円玉 1個

回路図

キャプションを入力できます

部品 部品ソケット Arduinoピン ケーブル色
オーディオジャック RIGHT(RING) GND
LEFT(TIP) D4
ジョイスティック VCC D7 水色
VERT A3 オレンジ
HORZ A0 黄緑
SEL 5V
GND GND

ソースコード

link-pedal2key.ino

#define DEBUGLOG 0 #if DEBUGLOG // definitions to log for debug when not to use 'keyboard.h'. #define KEY_UP_ARROW 'U' #define KEY_DOWN_ARROW 'D' #define KEY_LEFT_ARROW 'L' #define KEY_RIGHT_ARROW 'R' #else #include "Keyboard.h" #endif #define BIKE_PIN 4 #define LED_PIN 13 #define SW_PIN 7 #define X_PIN A0 #define Y_PIN A3 #define WAITING_MSEC 125 #define MAX_ROTATION 3 int rotation = 0; boolean stat_p = false; #define MAX_POS 1024 boolean stat_l = false; boolean stat_r = false; boolean stat_u = false; boolean stat_d = false; void printNumberOfRotation(int now, int max) { Serial.print("The pedal has rotated "); Serial.print(rotation); Serial.print("/"); Serial.print(MAX_ROTATION); Serial.println(" times."); } void printKeyboardEvent(String event, char key) { Serial.print(event); Serial.print(" keyboard ["); Serial.print(key); Serial.println("]"); } boolean ctrlStick2KeySmall(int pos, boolean stat, char key) { if (pos < (MAX_POS / 5)) { if (!stat) { Keyboard.press(key); stat = true; printKeyboardEvent("Pressed", key); } } else { if (stat) { Keyboard.release(key); stat = false; printKeyboardEvent("Released", key); } } return stat; } boolean ctrlStick2KeyLarge(int pos, boolean stat, char key) { if (pos > (MAX_POS - MAX_POS / 5)) { if (!stat) { Keyboard.press(key); stat = true; printKeyboardEvent("Pressed", key); } } else { if (stat) { Keyboard.release(key); stat = false; printKeyboardEvent("Released", key); } } return stat; } void setup() { // put your setup code here, to run once: Serial.begin(9600); Keyboard.begin(); pinMode(BIKE_PIN, INPUT_PULLUP); pinMode(LED_PIN, OUTPUT); pinMode(X_PIN, INPUT); pinMode(Y_PIN, INPUT); pinMode(SW_PIN, INPUT_PULLUP); } void loop() { // put your main code here, to run repeatedly: int pedal = digitalRead(BIKE_PIN); if (pedal == LOW) { if (!stat_p) { rotation++; printNumberOfRotation(rotation, MAX_ROTATION); if (rotation >= MAX_ROTATION) { Keyboard.press(KEY_UP_ARROW); Keyboard.release(KEY_UP_ARROW); digitalWrite(LED_PIN, HIGH); delay(WAITING_MSEC); digitalWrite(LED_PIN, LOW); rotation = 0; } stat_p = true; } } else { stat_p = false; } int x_pos = analogRead(X_PIN); int y_pos = analogRead(Y_PIN); stat_d = ctrlStick2KeySmall(x_pos, stat_d, KEY_DOWN_ARROW); stat_u = ctrlStick2KeyLarge(x_pos, stat_u, KEY_UP_ARROW); stat_l = ctrlStick2KeySmall(y_pos, stat_l, KEY_LEFT_ARROW); stat_r = ctrlStick2KeyLarge(y_pos, stat_r, KEY_RIGHT_ARROW); }
2
kon104 さんが 2021/03/28 に 編集 をしました。 (メッセージ: 初版)
kon104 さんが 2021/03/28 に 編集 をしました。
kon104 さんが 2021/03/28 に 編集 をしました。
kon104 さんが 2021/03/28 に 編集 をしました。
Opening
wiのアイコン画像 wi 前の月曜日の15:14

こんにちはwiです。
興味があり質問させて頂きます。
クロスバイクの回転数(距離)とマップの距離はある程度シンクロされるのでしょうか?
よろしくおねがいします。

kon104のアイコン画像 kon104 前の火曜日の16:41

こんにちは、興味持っていただきありがとうございます。

正直言うとシステム的に厳密なシンクロはできておりません。

3kmを走るのに必要としたペダル回転数とストリートビューの遷移数を、
全国いくつかの箇所でサンプルを取ったところ、だいたい3ペダル漕ぐとストリートビューが一つ遷移の状況でした。

その統計より、ペダル3回転すると一つストリートビューを遷移する様にプログラムを実装しており、
ソースコードでは「#define MAX_ROTATION 3」の定数がストリートビューを遷移させるペダル回転数の閾値となっております。
(将来的には、MAX_ROTATIONの定数も、ダイヤルなどで可変的にできると汎用性が増すな。とか、ふと思いつきました)

1 件の返信が折りたたまれています
ログインしてコメントを投稿する