寝る前に電気を消すのは面倒ですね、立ち上がりたくないですね。面倒くさい!
我が家では悲しいことにリモコンで操作できる系のシーリングライトが取り付けできない感じのお部屋です。
リモコンでスイッチを操作できる仕組みを作りましょう!
材料
- Arduino Uno
- サーボモーター(SG92R)
- 赤外線リモコン受信モジュール(PL-IRM2121)
- リモコン(RU-DM114)
ちょうど壊れてしまったディスプレイに付いていた、使い道のなくなったリモコン(RU-DM114)があったのでこれを使います。
サーボモーターを動かす
サーボモーターにはそれぞれ5V、GND、5番PINを接続
#include<Servo.h>
#define SERVO_PIN 5
Servo servo;
void setup(){
servo.attach(SERVO_PIN);
}
void loop() {
servo.write(0);
delay(500);
servo.write(100);
delay(500);
}
赤外線を受信する
#define READ_PIN 7
#define LOW_STATE 0
#define HIGH_STATE 1
void setup(){
Serial.begin(9600);
pinMode(READ_PIN, INPUT);
}
int waitHigh() {
unsigned long start = micros();
while (digitalRead(READ_PIN) == HIGH) {
if (micros() - start > 5000000) {
return 1;
}
}
return 0;
}
unsigned long now = micros();
unsigned long lastStateChangedMicros = micros();
int state = HIGH_STATE;
void loop() {
if (state == LOW_STATE) {
while (digitalRead(IR_READ_PIN) == LOW);
} else {
int ret = waitHigh();
if (ret == 1) {
Serial.print("\n");
return;
}
}
now = micros();
Serial.print((now - lastStateChangedMicros) / 10, DEC);
Serial.print(",");
lastStateChangedMicros = now;
if (state == HIGH_STATE) {
state = LOW_STATE;
} else {
state = HIGH_STATE;
}
}
赤外線センサーが反応したらLEDが光るようにしています。
受信した赤外線を識別する
このままではすべての赤外線に反応してしまうため、テレビのリモコンでもエアコンのリモコンでもセンサーが反応してしまいます。
対応させるリモコンの電源ボタンの信号にのみに反応させるため、受信したときの信号を調べます。
電源ボタンの赤外線を受信するとシリアルモニタでこんな感じの数値の羅列が取得できました。
2028,803,384,54,46,56,44,60,136,59,40,60,41,60,135,60,136,59,135,60,384,59,136,59,136,59,41,56,43,60,41,59,41,60,41,59,40,59,2026,803,387,54,46,59,41,59,136,59,41,59,41,59,136,59,136,60,135,60,384,59,136,59,136,60,40,60,41,57,44,59,41,59,40,58,43,59,2026,803,387,56,44,59,41,59,136,56,44,59,41,59,136,59,136,59,135,60,384,59,136,59,136,59,41,60,41,59,41,60,41,59,41,59,40,59,2026,803,387,54,46,59,41,60,136,59,41,59,41,59,136,56,138,60,134,57,387,59,136,60,136,59,41,60,41,59,41,60,41,59,41,59,40,60,2026,805,384,54,46,60,41,59,136,59,41,59,41,59,136,59,136,59,135,60,384,57,138,59,136,59,41,60,41,59,41,59,41,60,42,58,40,60
アナログなので数値は多少前後しますが、
よく観察すると、2026,803,384,54,・・・
というパターンが何度もでてくるのが観測できます。
これをパターン毎に分解して、Excelに突っ込みます。
MODE関数で最頻値が取得できますので、この値が電源ボタンの信号だと推測できます。
この2つをくっ付けて完成!
問題いろいろ
問題その1 あまり赤外線を検知しない
完全な信号はなかなか来ないので、数値の揺らぎはある程度許容する
if (abs(value - pattern[number]) < 10) {
// OK
}
問題その2 サーボモーターがうるさい
待機音がうるさいので
普段はdetachしておく
servo.detach(SERVO_PIN);
servo.attach(SERVO_PIN);
雑ですが最終的にこんなコードになりました
#include<Servo.h>
#define IR_READ_PIN 7
#define SERVO_PIN 5
#define LOW_STATE 0
#define HIGH_STATE 1
Servo servo;
void setup(){
Serial.begin(9600);
pinMode(IR_READ_PIN, INPUT);
}
int waitHigh() {
unsigned long start = micros();
while (digitalRead(IR_READ_PIN) == HIGH) {
if (micros() - start > 5000000) {
return 1;
}
}
return 0;
}
unsigned long now = micros();
unsigned long lastStateChangedMicros = micros();
int state = HIGH_STATE;
int number = 0;
int pattern[38] = {2026, 805,384,54,46,59,41,59,136,59,41,59,41,59,136,59,136,59,135,60,384,59,136,59,136,59,41,60,41,59,41,59,41,59,41,59,40,60};
void loop() {
if (state == LOW_STATE) {
while (digitalRead(IR_READ_PIN) == LOW);
} else {
if (1 == waitHigh()) {
if (servo.attached()) {
servo.detach();
}
Serial.println("off");
return;
}
}
now = micros();
long value = (now - lastStateChangedMicros) / 10;
Serial.print(value);
Serial.print(", ");
number++;
if (value > 2000 || number >= 38) {
number = 0;
} else {
if (abs(value - pattern[number]) > 10) {
number = 0;
}
if (number == 38) {
push();
number = 0;
}
}
if (state == HIGH_STATE) {
state = LOW_STATE;
} else {
state = HIGH_STATE;
}
lastStateChangedMicros = now;
}
void push() {
Serial.println("");
Serial.println("push!");
if (!servo.attached()) {
servo.attach(SERVO_PIN);
delay(5000);
}
servo.write(170);
delay(1000);
servo.write(90);
delay(500);
}
問題その3 どうやって固定しよう・・・
ダンボールとビニタイで固定した
とりあえずできた!
good night 🌙
こうやって人類は退化していくのでした。💤
参考