tokumi_robo が 2021年02月25日16時18分03秒 に編集
初版
タイトルの変更
某インク銃型水鉄砲の赤外線リモコン化
タグの変更
秋葉原2021
Arduino
赤外線リモコン
リモコン
メイン画像の変更
本文の変更
1.**はじめに** - たしかフリマサイトの2000円引きクーポンで買った某インク銃の水鉄砲です。 かなり前に作りかけて、家の隅の方でガラクタになっていた赤外線リモコン銃を今回完成させました。 2.**仕様** - ArduinoのIRremoteライブラリで、テレビのリモコン信号や扇風機、リビングの電気などの赤外線信号を解析し、ArduinoのAVR328pマイコンに保存、基板に実装して家電ごとにDIPスイッチで切り替え、トリガーのところにあるタクトスイッチを押すと赤外線を送信し同時に光線銃の音が鳴る仕組みです。 3.**使用したもの** - - 某インク銃型水鉄砲 - マイクロスピーカー 赤/黒リード付 8Ω - DFPlayer min(MP3プレーヤー) - AVR328p - フルカラーLED - タクトスイッチ - トグルスイッチ - 赤外線LED - トランジスタ 2SC1815 - 006Pアルカリ電池 (積層電池) 9V - バッテリースナップ - 各種抵抗 4.**配線** - ![キャプションを入力できます](https://camo.elchika.com/3c9064215a0b8f0276b241d576fb7a711ace4b57/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33343561666135612d613764612d346566322d626335372d3430363062346266363634352f33626462306137352d336233662d346231632d393238332d396537656638623834633465/) 実験段階 ![キャプションを入力できます](https://camo.elchika.com/bb6c13d1d1dd83934900b83715f7a74399fa7ab2/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33343561666135612d613764612d346566322d626335372d3430363062346266363634352f64373832323430632d306530312d343432312d616630322d336530333631653336336234/) 回路実装後 電子工作を始めたての時に配線したものですので配線は汚くなっております。 すみません配線図は書いていません。 プログラムはあったのでポート番号から察してください。 5.**プログラム** - ```arduino:赤外線リモコン銃 //赤外線リモコン銃プログラム #include "Arduino.h" #include "SoftwareSerial.h" #include "DFRobotDFPlayerMini.h" #include <IRremote.h> //赤外線はArduinoのGPIO3で送信できる //ピン指定 #define BUSY_PINNO 9 #define trigerSW 8 #define sw1 7 #define sw2 6 #define sw3 5 #define sw4 4 #define RLED 13 #define GLED A1 #define BLED 12 SoftwareSerial mySoftwareSerial(10, 11); // (TX, RX) DFRobotDFPlayerMini myDFPlayer; void printDetail(uint8_t type, int value); IRsend irsend; void setup(){ Serial.begin(115200); // software serial init mySoftwareSerial.begin(9600); if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3. Serial.println(F("Unable to begin:")); Serial.println(F("1.Please recheck the connection!")); Serial.println(F("2.Please insert the SD card!")); while (true); } // BUSY_PINNO init pinMode(BUSY_PINNO, INPUT); //switch pinMode(trigerSW, INPUT_PULLUP); pinMode(sw1, INPUT_PULLUP); pinMode(sw2, INPUT_PULLUP); pinMode(sw3, INPUT_PULLUP); pinMode(sw4, INPUT_PULLUP); //LED pinMode(RLED, OUTPUT); pinMode(GLED, OUTPUT); pinMode(BLED, OUTPUT); // DFPlayer Init myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms myDFPlayer.setTimeOut(10000000); myDFPlayer.volume(30); //Set volume value (0~30) myDFPlayer.EQ(DFPLAYER_EQ_NORMAL); myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD); } void PLAYBACK_MP3_MUSIC1(void) {//レーザー銃音 int isBusy = digitalRead(BUSY_PINNO); // 0:playing, 1:not playing (refer website) if (isBusy == 1) { myDFPlayer.play(1); //Play next mp3 every 3 second. } } void PLAYBACK_MP3_MUSIC2(void) {//機関銃音 int isBusy = digitalRead(BUSY_PINNO); // 0:playing, 1:not playing (refer website) if (isBusy == 1) { myDFPlayer.play(2); //Play next mp3 every 3 second. } } void PLAYBACK_MP3_MUSIC3(void) {//操作音 int isBusy = digitalRead(BUSY_PINNO); // 0:playing, 1:not playing (refer website) if (isBusy == 1) { myDFPlayer.play(3); //Play next mp3 every 3 second. } } void Stop(void) {//操作音ストップ int isBusy = digitalRead(BUSY_PINNO); // 0:playing, 1:not playing (refer website) if (isBusy == 1) { myDFPlayer.setTimeOut(100000); } } /*テレビ*/ void TVON(void) { //テレビON信号 //赤外線データコード int khz = 38;//搬送波38kHz unsigned int irSignal[] = {3450, 1500, 550, 300, 550, 1100, 550, 300, 500, 1150, 500, 350, 500, 1150, 500, 350, 500, 1150, 500, 350, 450, 1200, 500, 300, 500, 1200, 450, 1200, 450, 350, 500, 1200, 450, 350, 500, 1150, 500, 1200, 450, 1200, 450, 1200, 500, 350, 450, 350, 500, 350, 450, 1200, 500, 350, 450, 1200, 450, 350, 500, 350, 500, 1150, 500, 350, 450, 350, 500, 400, 450, 350, 450, 1200, 450, 1200, 500, 350, 450, 1200, 450, 400, 450, 350, 500, 350, 450, 1200, 450, 400, 450, 350, 500, 350, 450, 1200, 500, 350, 450, 1200, 450, 1200, 500 }; irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); } void Channel_menu(void) {//番組表ボタン int khz = 38;//搬送波38kHz unsigned int irSignal[] = {3450, 1550, 550, 300, 500, 1150, 550, 300, 500, 1150, 500, 350, 500, 1150, 500, 300, 550, 1150, 500, 300, 500, 1150, 550, 300, 500, 1150, 500, 1150, 500, 350, 500, 1150, 500, 350, 500, 1150, 500, 1150, 500, 1200, 450, 1200, 500, 300, 500, 350, 500, 350, 450, 1200, 450, 350, 500, 1200, 450, 350, 500, 350, 450, 1200, 500, 350, 450, 350, 500, 350, 450, 350, 500, 350, 500, 350, 450, 350, 500, 350, 450, 1200, 500, 1150, 500, 350, 450, 400, 450, 1200, 450, 400, 450, 350, 450, 1200, 500, 1150, 500, 1150, 500, 1200, 450 }; irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); } void Right(void) {//リモコンの右ボタン int khz = 38;//搬送波38kHz unsigned int irSignal[] = {3450, 1500, 550, 350, 500, 1150, 500, 300, 550, 1100, 550, 300, 500, 1150, 550, 300, 500, 1150, 500, 350, 500, 1150, 500, 350, 500, 1150, 500, 1150, 500, 350, 500, 1150, 500, 300, 500, 1200, 450, 1200, 500, 1150, 500, 1150, 500, 350, 500, 300, 500, 350, 500, 1150, 500, 350, 500, 1150, 500, 350, 450, 350, 500, 1200, 450, 350, 500, 350, 450, 350, 500, 350, 450, 400, 450, 350, 500, 1150, 500, 1200, 450, 350, 500, 1150, 500, 1200, 450, 1200, 450, 400, 450, 350, 500, 350, 450, 1200, 450, 1200, 500, 1150, 500, 1150, 500 }; irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); } void Left(void) {//リモコンの左ボタン int khz = 38;//搬送波38kHz unsigned int irSignal[] = {3450, 1500, 550, 350, 500, 1150, 500, 300, 550, 1150, 500, 300, 500, 1150, 550, 300, 500, 1150, 500, 350, 500, 1150, 500, 350, 500, 1150, 500, 1150, 500, 350, 500, 1150, 500, 300, 500, 1200, 450, 1200, 500, 1150, 500, 1150, 500, 350, 500, 300, 500, 350, 500, 1150, 500, 350, 500, 1150, 500, 350, 450, 350, 500, 1200, 450, 350, 500, 350, 450, 350, 500, 1200, 450, 1200, 450, 1200, 500, 350, 450, 1200, 450, 350, 500, 1200, 450, 1200, 450, 1200, 500, 350, 450, 350, 500, 350, 450, 400, 450, 350, 500, 350, 450, 400, 450 }; irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); } void Enter(void) {//決定ボタン int khz = 38;//搬送波38kHz unsigned int irSignal[] = {3500, 1500, 600, 250, 550, 1100, 600, 250, 550, 1100, 550, 300, 550, 1100, 550, 300, 500, 1150, 550, 300, 500, 1150, 500, 300, 550, 1100, 550, 1150, 500, 300, 550, 1150, 500, 350, 500, 1100, 550, 1150, 500, 1150, 500, 1150, 500, 350, 500, 350, 450, 350, 500, 1150, 500, 350, 500, 1150, 500, 350, 500, 300, 500, 1200, 450, 350, 500, 350, 500, 350, 450, 350, 500, 1150, 500, 350, 500, 350, 450, 1150, 500, 350, 500, 1150, 500, 350, 500, 1150, 500, 350, 500, 350, 450, 350, 500, 1150, 500, 350, 450, 1200, 500, 1150, 500 }; irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); } /*扇風機*/ void Fan(void) {//扇風機のリモコン信号 int khz = 38;//搬送波38kHz unsigned int irSignal[] = {9050, 4400, 650, 1550, 650, 1600, 650, 450, 650, 500, 600, 500, 650, 1600, 600, 1600, 650, 500, 600, 500, 650, 450, 650, 1600, 650, 1600, 600, 1600, 650, 450, 650, 500, 650, 1600, 600, 500, 650, 1600, 600, 500, 650, 450, 650, 1600, 650, 450, 650, 500, 600, 500, 650, 1600, 600, 500, 650, 1600, 600, 1600, 650, 500, 600, 1600, 650, 1600, 600, 1600, 650 }; irsend.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), khz); } void loop() { int value; value = digitalRead(trigerSW); //変数 int mode1; int mode2; int mode3; int mode4; //ディップスイッチ判定 if (digitalRead(sw1) == HIGH) { mode1 = 1; } else { mode1 = 0; } if (digitalRead(sw2) == HIGH) { mode2 = 1; } else { mode2 = 0; } if (digitalRead(sw3) == HIGH) { mode3 = 1; } else { mode3 = 0; } if (digitalRead(sw4) == HIGH) { mode4 = 1; } else { mode4 = 0; } //TVON_赤 if (mode1 == 0 && mode2 == 0 && mode3 == 0 && mode4 == 0) { digitalWrite(RLED, HIGH); //赤 delay(100); digitalWrite(RLED, LOW); if ( value == LOW ) {//トリガーの判断 digitalWrite(RLED, LOW); PLAYBACK_MP3_MUSIC1(); delay(100); TVON(); delay(500); } else { Stop(); } } //番組表mode_青 if (mode1 == 1 && mode2 == 0 && mode3 == 0 && mode4 == 0) { digitalWrite(BLED, HIGH); //青 delay(100); digitalWrite(BLED, LOW); if ( value == LOW ) {//トリガーの判断 digitalWrite(BLED, LOW); PLAYBACK_MP3_MUSIC3(); delay(100); Channel_menu(); delay(500); } else { Stop(); } } //右_mode_黄 if (mode1 == 0 && mode2 == 1 && mode3 == 0 && mode4 == 0) { digitalWrite(GLED, HIGH); //黄 digitalWrite(RLED, HIGH); delay(100); digitalWrite(GLED, LOW); digitalWrite(RLED, LOW); if ( value == LOW ) {//トリガーの判断 digitalWrite(GLED, LOW); digitalWrite(RLED, LOW); PLAYBACK_MP3_MUSIC3(); delay(100); Right(); delay(500); } else { Stop(); } } //左_mode_緑 if (mode1 == 1 && mode2 == 1 && mode3 == 0 && mode4 == 0) { digitalWrite(GLED, HIGH); //緑 delay(100); digitalWrite(GLED, LOW); if ( value == LOW ) {//トリガーの判断 digitalWrite(GLED, LOW); PLAYBACK_MP3_MUSIC3(); delay(100); Left(); delay(500); } else { Stop(); } } //決定_mode_シアン if (mode1 == 0 && mode2 == 1 && mode3 == 1 && mode4 == 0) { digitalWrite(GLED, HIGH); //シアン digitalWrite(BLED, HIGH); delay(100); digitalWrite(GLED, LOW); digitalWrite(BLED, LOW); if ( value == LOW ) {//トリガーの判断 digitalWrite(GLED, LOW); digitalWrite(BLED, LOW); PLAYBACK_MP3_MUSIC3(); delay(100); Enter(); delay(500); } else { Stop(); } } //扇風機&Gan_mode_マゼンタ if (mode1 == 1 && mode2 == 1 && mode3 == 1 && mode4 == 1) { //Light_mode digitalWrite(RLED, HIGH); //マゼンタ digitalWrite(BLED, HIGH); delay(100); digitalWrite(RLED, LOW); digitalWrite(BLED, LOW); if ( value == LOW ) {//トリガーの判断 digitalWrite(RLED, LOW); digitalWrite(BLED, LOW); PLAYBACK_MP3_MUSIC2(); delay(100); Fan(); delay(100); } else { Stop(); } } } ``` DIPスイッチを切り替えてトリガースイッチを押すことで TVのオンオフ、番組表、決定、方向キー、扇風機など切り替えれるようにしてある。 ++扇風機.....っていつの夏に作ったんだよ++ 6.**動作確認** [](https://twitter.com/Zr6cXz/status/1364794717561528324?s=20) twitter上に動作の様子をアップしました。 7.**課題と問題点** - ++IRremoteライブラリで赤外線のデータを解析したのですが、Arduinoに書き込む際にrawデータで書き込んだことにより、長い赤外線コードを書き込まなければならず、AVR328pのメモリがぎりぎりで動作が不安定なまま書き込みをしました。 もっとうまくコードが書ける方法があるはず。 さらに、基板や6p電池が大きいため水鉄砲の中に入らず、無理やり押し込んで配線が飛び出たり汚くなってます。プリント基板化等すれば、より小型にできたと思います。←当時はそんな技術力ない。++