FlickMote:ジェスチャー操作のIRリモコンでスマートホームを制御
必要な部品と材料
- 超音波距離センサ(HC-SR04) × 1
- IR LED(赤外線送信用) × 1
- RGB LED(拡散型・共通カソード) × 1
- Arduino 101(Unoでも可) × 1
使用するアプリとオンラインサービス
- Arduino IDE
プロジェクト概要

はじめに
赤外線リモコンでの家電操作は一般的ですが、手元のリモコンを見てボタンを探す手間があり、特に高齢者には負担です。本プロジェクト「FlickMote」は、手のジェスチャーだけで家電を操作する新しいリモコンシステムを提案します。超音波測距モジュールでユーザーのジェスチャーを検出し、対応するIR信号を出力します。マイコンはArduino 101(Uno互換)を使用。
ハードウェア構成
- Arduino 101またはUno
- HC-SR04 超音波モジュール
- 赤外線LED
- 赤外線LED用抵抗(220Ω)
- RGB LED
- ブレッドボードとジャンパワイヤ
動作原理
超音波測距で手の位置(距離)を検知し、ジェスチャーに応じてIR信号を送信します。距離閾値はコードで調整可能。
- ハイ・スワイプ(> 10インチ) = チャンネルアップ
- ロー・スワイプ(< 10インチ) = チャンネルダウン
- ハイ・ホールド(> 10インチ) = 音量アップ
- ロー・ホールド(< 10インチ) = 音量ダウン
- センサを覆う(< 3インチ) = 電源オン/オフ
回路図(Fritzing)

組み立て手順
- IR LEDをPin 3へ抵抗経由で接続、カソードをGNDへ。
- 超音波センサ:VCC→5V、GND→GND、Trig→Pin 8、Echo→Pin 7(コードで変更可)。
- RGB LED:共通カソードをGND、赤→Pin 11、緑→Pin 10、青→Pin 9(変更可)。
操作詳細
電源
3インチ以内でスワイプするとLEDが紫に点滅し、「電源信号送信準備完了」を通知。誤動作防止のため、5秒以内に再度スワイプすると実際に電源信号を送信します。
チャンネル
3〜10インチでスワイプ=チャンネルダウン、10〜20インチでスワイプ=チャンネルアップ。
音量
3〜10インチで手をかざし続ける=音量ダウン、10〜20インチでかざし続ける=音量アップ。手を離すまで継続。
利点と改善案
- リモコンを見てボタンを探す手間を解消
- 視覚障害者や身体障害者にも操作しやすい
- 同じ仕組みで全家電を制御できるよう拡張可能
Arduinoスケッチ
/* Swipe Remote Control
* 超音波測距でジェスチャー検出し、Sony TV用IR信号を送信
* - High swipe (>10in) = Channel Up
* - Low swipe = Channel Down
* - High hold (>10in) = Volume Up
* - Low hold = Volume Down
* - Cover sensor (<3in) = Power On/Off
* Created by Vignesh Jaishankar
* Uses IRremote library (https://github.com/shirriff/Arduino-IRremote)
*/
#include <IRremote.h>
#define CONTROL_CH 1
#define CONTROL_VOL 2
#define CONTROL_POW 3
#define CONTROL_UP 1
#define CONTROL_DOWN -1
#define DIST_MAX 20
#define DIST_DOWN 10
#define DIST_POW 3
const int irPin = 3; // ライブラリ内で固定
const int pingPin = 8;
const int echoPin = 7;
const int led = 13;
const int ledR = 11;
const int ledG = 10;
const int ledB = 9;
unsigned long timer;
IRsend irsend;
boolean powerConfirmed = false;
void setup() {
Serial.begin(9600);
pinMode(led, OUTPUT);
pinMode(ledR, OUTPUT);
pinMode(ledG, OUTPUT);
pinMode(ledB, OUTPUT);
pinMode(pingPin, OUTPUT);
pinMode(echoPin, INPUT);
timer = millis();
}
void loop() {
long duration = doPing();
if (timer && timer < (millis() - 5000) && (millis() > 5000)) {
Serial.println("timer reset");
timer = false;
}
digitalWrite(led, LOW);
setColor(0, 0, 0);
long inches = microsecondsToInches(duration);
if (inches < DIST_MAX) {
Serial.print(inches); Serial.println("in");
if (inches < DIST_POW) {
if (timer) {
doIR(CONTROL_POW, 0);
timer = false;
delay(2000);
} else {
Serial.println("power flag set");
timer = millis();
setColor(255, 50, 50);
delay(500);
}
} else {
int value = handleDist(inches);
delay(300);
if (microsecondsToInches(doPing()) > DIST_MAX) {
doIR(CONTROL_CH, value); // スワイプ判定
} else {
int d = 500;
while (inches < DIST_MAX) {
value = handleDist(inches);
doIR(CONTROL_VOL, value);
delay(d);
inches = microsecondsToInches(doPing());
d = 100;
}
delay(500);
}
}
}
delay(50);
}
int handleDist(int inches) {
if (inches > DIST_DOWN) {
digitalWrite(led, HIGH);
return CONTROL_UP;
} else {
digitalWrite(led, LOW);
return CONTROL_DOWN;
}
}
void doIR(int control, int val) {
switch (control) {
case CONTROL_POW:
Serial.println("power on/off 0xa90");
for (int i = 0; i < 3; i++) {
setColor(255, 0, 0);
irsend.sendSony(0xa90, 12);
delay(40);
}
break;
case CONTROL_CH:
setColor(0, 255, 0);
if (val == CONTROL_UP) {
digitalWrite(led, HIGH);
for (int i = 0; i < 3; i++) {
irsend.sendSony(0x90, 12);
delay(40);
}
Serial.println("channel up 0xD00A");
} else {
for (int i = 0; i < 3; i++) {
irsend.sendSony(0x890, 12);
delay(40);
}
Serial.println("channel down 0x3002");
}
break;
case CONTROL_VOL:
setColor(0, 0, 255);
if (val == CONTROL_UP) {
digitalWrite(led, HIGH);
for (int i = 0; i < 3; i++) {
irsend.sendSony(0x490, 12);
delay(40);
}
Serial.println("volume up 0x490");
} else {
for (int i = 0; i < 3; i++) {
irsend.sendSony(0xC90, 12);
delay(40);
}
Serial.println("volume down 0xC90");
}
break;
}
}
void setColor(int red, int green, int blue) {
analogWrite(ledR, red);
analogWrite(ledG, green);
analogWrite(ledB, blue);
}
long doPing() {
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
return pulseIn(echoPin, HIGH);
}
long microsecondsToInches(long microseconds) {
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds) {
return microseconds / 29 / 2;
}
回路図

flickmote_9Gx3XNFHEp.fzz(Fritzingファイル)
製造プロセス
- Arduinoで超音波レベーション(浮遊)装置を自作:ステップバイステップガイド
- Bluetooth操作のArduinoスパイボットを自作する
- 自作Arduino TV-B-Gone:全テレビ対応の万能リモコン
- 12メートル先から見える大型LEDマスタークロック(アラーム機能付き)を自作しよう
- ArduinoとBluetoothで作るスマート紛失防止タグ「Find Me」
- Arduinoプロジェクトのための最適化電源ソリューション
- Arduino三目並べ:MAX7219 LEDマトリクスと段ボールケースで自作
- スマートArduino四足歩行ロボットの製作:ステップバイステップガイド
- ゲーム用カスタムArduinoジョイスティックハンドルの製作
- コンパクトなArduinoレーダーシステム – HC-SR04超音波センサー & 1.8インチST7735ディスプレイ搭載
- Arduino Nano R3で本格的なCNCマシンを自作する