スマホ操作のBluetoothマウス:バーチャルジョイスティックを自作しよう
部品と材料
| 部品 | 数量 |
|---|---|
| Arduino UNO | 1 |
| HC-05 Bluetoothモジュール | 1 |
| ジャンパーワイヤー | 1式 |
アプリとオンラインサービス
- Arduino IDE
- IDLE (Python GUI)
- MIT App Inventor Bluetooth Mouse Control
プロジェクト概要
このプロジェクトは、以前ジョイスティックでPCカーソルを制御した作品に似ていますが、大きな違いはスマートフォンアプリを作成し、2つのバーチャルジョイスティックでカーソル移動、スクロール、左クリック・右クリックを通常のトラックパッドのように操作できる点です。
動作原理
スマートフォンアプリがジョイスティックのX/Y軸データ、スクロール状態、左右クリック状態をBluetooth経由でHC-05モジュール→Arduino Unoへ送信します。Arduinoは受信データを現在のカーソル座標に加減算して新しい座標を算出し、スクロール・ボタン状態とともにシリアル出力します。このデータをPythonスクリプトが読み取り、mouseモジュールでマウス操作を実行します。

アプリケーションについて
スマートフォンアプリはMIT App Inventorで作成しました。ブロックを組み合わせるだけで簡単にアプリが構築できます。Tabletop Roboticsのチュートリアルを参考にしました。メイン画面は以下の通りです。

HC-05モジュールへデータを送信する前に、まず1バイトの「255」を送ってデータ開始を通知します。データ送信シーケンスは以下の通り:
- 「255」送信(開始マーカー)
- ジョイスティックX軸値(1バイト)送信
- ジョイスティックY軸値(1バイト)送信
- 左クリック、右クリック、スクロール状態(1バイト)送信
データは毎20ミリ秒ごとにArduino Unoへ送信されます。
Arduino側の処理
HC-05経由でアプリからのデータバイトを受信します。Arduino内部では現在のカーソル座標を保持し、X座標は0〜1279、Y座標は0〜799の範囲です(これらの極値はPythonのmouse.get_position()で取得)。
受信したジョイスティックデータに基づき、現在座標に加減算して新しい目標座標を計算します。最終的なデータ(X座標、Y座標、クリック/スクロール状態)を以下のシーケンスでシリアル出力し、Pythonプログラムが読み取ります。

Python側で追加モジュール(mouse, pyserial)が必要です。インストール手順は次節を参照してください。
Pythonプログラミング
Python 3がインストール済みである必要があります。未インストールの場合は公式サイトからダウンロードしてください(Windowsの場合)。
インストール後、Python実行ファイルのパスをコピーしておきます。

コマンドプロンプトで以下を実行:
cd <Pythonのパス>
py -m pip install --upgrade pip
py -m pip install mouse
py -m pip install pyserial
mouseモジュールでマウス操作、pyserialでArduinoとのシリアル通信を行います。インストール済みの場合は「Requirement already satisfied」と表示されます。


実行手順
- スマートフォンに「Bluetooth Mouse Control」アプリをインストール
- Arduinoスケッチを書き込み、回路図通りに配線
- Python側:
- Pythonコードをメモ帳にコピーし、ArduinoのCOMポートに変更して
.pyで保存 - IDLEでファイルを開く
- 実行(F5)
- Pythonコードをメモ帳にコピーし、ArduinoのCOMポートに変更して
- スマホアプリを開き、Bluetoothモジュールに接続
- ジョイスティック操作でカーソルが動くことを確認






コード
Arduinoコード
int datareceived[5] = {0,0,0,0,0};
int in_byte = 0;
int array_index = 0;
int l_prev = 0, r_prev = 0;
void setup() {
Serial.begin(9600);
}
int height = 0, width = 0;
void loop() {
int clicks = 0;
int sensitivity = 20; // 感度調整可能
int xpos = 0, ypos = 0;
if (Serial.available() > 0) {
in_byte = Serial.read();
if (in_byte == 255) {
array_index = 0;
}
datareceived[array_index] = in_byte;
array_index++;
// X軸: 右(110-172)→正, 左(60-1)→負
if (datareceived[1] >= 110) xpos = map(datareceived[1], 110, 172, 0, sensitivity);
if (datareceived[1] <= 70) xpos = map(datareceived[1], 60, 1, 0, -sensitivity);
// Y軸: 下(110-255)→正, 上(60-1)→負
if (datareceived[2] >= 110) ypos = map(datareceived[2], 110, 255, 0, sensitivity);
if (datareceived[2] <= 60) ypos = map(datareceived[2], 70, 1, 0, -sensitivity);
// クリック/スクロール判定(エッジ検出)
if (datareceived[3] == 1 && l_prev == 0) clicks = 1; // 左クリック
else if (datareceived[3] == 2 && r_prev == 0) clicks = 2; // 右クリック
else if (datareceived[3] == 3 || datareceived[3] == 4) clicks = datareceived[3]; // スクロール
l_prev = datareceived[3];
r_prev = datareceived[3];
// 何か操作があれば座標更新して出力
if (xpos != 0 || ypos != 0 || clicks != 0) {
height += ypos;
width += xpos;
// 画面範囲内にクランプ
height = constrain(height, 0, 799);
width = constrain(width, 0, 1279);
Serial.print(width);
Serial.print(":");
Serial.print(height);
Serial.print(":");
Serial.println(clicks);
clicks = 0;
}
}
}
Pythonコード
import mouse
import sys
import time
import serial
mouse.FAILSAFE = False
ArduinoSerial = serial.Serial('COM3', 9600) # 正しいCOMポートに変更
time.sleep(1)
while True:
data = str(ArduinoSerial.readline().decode('ascii')).strip()
if not data:
continue
x, y, z = data.split(":")
x, y = int(x), int(y)
mouse.move(x, y)
if '1' in z:
mouse.click(button="left")
elif '2' in z:
mouse.click(button="right")
elif '3' in z:
mouse.wheel(delta=-1) # 下スクロール
elif '4' in z:
mouse.wheel(delta=1) # 上スクロール
回路図

製造プロセス
- Bluetooth 制御 Raspberry Pi ロボットに音声フィードバックを追加して構築
- ジェスチャー制御 RGB テーブルランプ – インタラクティブなハンズフリー照明
- Arduinoとスマホで作るスマート電圧計 – 簡単DIYプロジェクト
- ラズベリーパイとNode-REDでAlexaからLEDを制御する - 簡単ステップバイステップガイド
- 古いラジコンカーをXboxコントローラーで操作可能に - ArduinoとUSBホストシールドで実現
- ArduinoでBluetooth経由でLEDを制御 – シンプルDIYガイド
- Arduinoベースのヌンチャク操作6自由度ロボットアームキット
- Arduino Nanoで音声制御ロボットを自作
- MobBob:Arduino製ロボットをAndroidスマホでシームレスに制御
- 音声で家電を操作:GoogleアシスタントとBluetoothでArduino家電制御
- PiBot:Arduino駆動の精密ピアノ演奏ロボット