eucaly が 2024年01月23日15時48分41秒 に編集
初版
タイトルの変更
Arduinoでリモコン送受信(irremote 3系 汎用版)
タグの変更
Arduino
リモコン
赤外線リモコン
JSON
WiFi
メイン画像の変更
記事種類の変更
製作品
Lチカの変更
ライセンスの変更
(MIT) The MIT License
本文の変更
お久しぶりです、ゆうかりです。 さて今回は。 「お気軽にArduinoでリモコン送受信しようとしたら色々ハマったので、最新ライブラリで汎用性ある制御をどうにかしたのでその記録」って感じ。 モノとしてのゴールは、「受信したリモコンコードをWebサーバへ送信、送信したいリモコンコードをWebサーバから受信」て感じです。 # いままでとこれから Arduinoには、「irremote」というライブラリがあり、お気軽に赤外線リモコンの送受信が実装出来ます。 https://github.com/Arduino-IRremote/Arduino-IRremote ま、適当に実装して使っていたのですが。 新たにリモコン送受信モジュール作ってコンパイルしてみたら。 おや、、、ライブラリの様子が、、、。 ![キャプションを入力できます](https://camo.elchika.com/20591e820f6e5f3deb02488f17a8c866dfd030a3/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38666637633237372d646465642d343333632d393736342d6162303436346433326631302f38663363313932342d383063332d343639622d393163662d386664323363613639396162/) というわけで、irremote v4やv3系に対応した、赤外線リモコン送受信を組んでいきたいなと思ってみたり。 # ハードウェアの準備 みんな大好き秋月電子でサクっと揃えました。 ![キャプションを入力できます](https://camo.elchika.com/b4d338d9524ce34ee65cf3dafa708340595fdec5/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38666637633237372d646465642d343333632d393736342d6162303436346433326631302f35336332333565642d663433372d346337332d623362622d663365306265666636613661/) LEDはそれなりに数をつけ、更に電流を多めに流すために、CPU直結とせず、FET(とトランジスタ)でバッファしました。 各LEDには50mA流れます。 また、結構激しく電流流れるので、CPU基板上のLDOで作られる3.3Vではなく、USB直結の5V系からLEDの電源を取っています。 LEDを並列駆動するときは、なるべく個別に電流制限抵抗を置くのがいいッスよ、LED自体を並列にしてしまうと、個体差から電流配分の偏りが出やすいので!。 なんでわざわざFETとTRでバッファしてるのか、ですが、まあ、「適当にFETでスイッチ組んだら、論理反転してしまった」が正解です。 で、実装。 ![キャプションを入力できます](https://camo.elchika.com/27bdd25310f7c83d8e1429db4b5b366a98bb8195/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38666637633237372d646465642d343333632d393736342d6162303436346433326631302f64643838323836382d326665642d343436312d623061622d393361663063376535323531/) 秋月C基板に納まります。 *写真の基板は、I2Cレベルシフタとか余計なもんが少し実装されとります # プログラムのやりざま まず、赤外線リモコンのコード入出力は、irremote的にいくつかあるのですが。 今回は、 ・リモコンの「ボタン」が識別できるもの ・リモコンの「コードそのもののダンプ的な」もの をハンドリングすることにしました。 Arduinoソース上では、「ボタン識別」が「rawdata」、「コードそのもののダンプ」が「rawcodedata」です。 ボタン識別は、16進数の数バイトなデータ。 そのままでは送信コードとして使えませんが、値に揺れが無いので、if文でそのままハンドリングできます。 コードそのもののダンプは波形的な送信タイミングが記載されており、送信コードとして使用できますが、値が揺れるのでハンドリングは厳しいかと。 赤外線リモコンコードは、各社プロトコルで実装されており、例えば「機器」+「個別ボタン」みたいに分類できるのですが、まあ今回はそこまで必要じゃないっぽいので、使わない方向で。 *というかパナソニックのシーリングライト制御しようと思ったのですけれども、こいつはirremoteに実装されているプロトコルに合致せず、うまくハンドリングできなかったりするのです。 CPUはESP32Cを使用、Wifiがついているので、Arduino的には「リモコン送受信端末」として実装し、リモコンコードの解釈、発行は、連携するWebサーバ側でやる感じで。 リモコン受信 → WebサーバーにGETで情報送信→JSONでリモコンコード受信→リモコンコード発光 みたいな。 # Arduino側ソース こんな感じになりました。 ```c:irdemo.ino #define IR_SEND_PIN 4 #define RAW_BUFFER_LENGTH 750 #include <IRremote.h> #include <HTTPClient.h> #include <WiFi.h> #include <ArduinoJson.h> int receiverPin = 3; int senderPin = 4; int i = 0; int j = 0; int k = 0; uint8_t rawCode[RAW_BUFFER_LENGTH]; uint8_t rawCodeLength; String rawdata(RAW_BUFFER_LENGTH); String rawcodedata(RAW_BUFFER_LENGTH); void setup() { Serial.begin(9600); WiFi.mode(WIFI_STA); delay(500); WiFi.begin("WIFINAME", "WIFIPASSWORD"); IrReceiver.begin(receiverPin, true); IrSender.begin(); } void loop() { rawdata = ""; rawcodedata = ""; if (IrReceiver.decode()) { char str[8]; rawdata = String(IrReceiver.decodedIRData.decodedRawData,HEX); IrReceiver.compensateAndStoreIRResultInArray(rawCode); rawcodedata = ""; j = IrReceiver.decodedIRData.rawDataPtr->rawlen - 1; for (i=0;i<j;i++) { sprintf(str, "%02X", rawCode[i]); rawcodedata.concat(str); } IrReceiver.resume(); Serial.println(rawdata); Serial.println(rawcodedata); } WiFiClient client; HTTPClient http; String httpbody; String path = "type=living"; path += "&data=" + rawdata; path += "&code=" + rawcodedata; String uri = "http://192.168.1.1/cgi/irdemo?" + path; if (!http.begin(client, uri)) { } int httpCode = http.GET(); if (httpCode > 0) { if (httpCode == HTTP_CODE_OK) { httpbody = http.getString(); } } else if (httpCode <= 0) { httpbody = ""; } http.end(); StaticJsonDocument<5120> jsondoc; DeserializationError jsonerror = deserializeJson(jsondoc, httpbody); if (!jsonerror) { for (k=0;k<16;k++) { String kstr = String(k); if (jsondoc[kstr].isNull()) { break; } String irrawdata = jsondoc[kstr]; int codeLength = irrawdata.length(); codeLength /= 2; for (i=0;i<codeLength;i++) { byte subfrom = i * 2; byte subto = subfrom + 2; String ptemp = irrawdata.substring(subfrom, subto); byte ptemp2; char ptemp3[8]; ptemp.toCharArray(ptemp3, 4); sscanf(ptemp3, "%x", &rawCode[i]); } IrSender.sendRaw(rawCode, codeLength, 38); delay(100); } } } ``` # Webサーバ側ソース python 3.11.6で動作してます。 /tmp/irdata.txt に、受信したリモコン情報を吐き出します。 特定のリモコンコードを受信すると、送信したいリモコンコードをjsonにセットして返します。 *サンプルコードでは、「ソニーのネットワークオーディオ用リモコンの特定ボタン」と、 「パナソニックのシーリングライトの制御」の組み合わせになっています。 pythonのCGIモジュールは廃止されるらしいので、CGIモジュールは使ってません、ほんとは使いたいのに・・・。 ```python:irdemo #!/usr/bin/python import urllib.parse import os import sys import json if not os.environ['REQUEST_METHOD'] == 'GET': print('Content-type: text/html\n\nerror') sys.exit() urldict = urllib.parse.parse_qs(os.environ['QUERY_STRING']) if not 'type' in urldict or not 'data' in urldict or not 'code' in urldict: print('Content-type: text/html\n\nerror') sys.exit() formtype = urldict['type'][0] formdata = urldict['data'][0] formcode = urldict['code'][0] if len(formcode) > 10: f = open('/tmp/irdata.txt','a') f.write (formtype + '\t' + formdata + '\t' + formcode + '\n') f.close() irsendcodes = {} if formtype == 'living' and formdata == '64d60': irsendcodes['0'] = '4722090809080A19091A09080A19090909080909091909090909081A0908091A0909091909080A08091A090809090908090809090908091A091A0908091A0909080909190A08091A090809080A190909090809' irsendcodes['1'] = '462209090908091A091A0908091A090809090908091A090809080A19090909190A08091A09080908091A0909090809080909091A09190909091A0908091A090809090809081B090809080909081B0908090809' irsendcodes['2'] = '462209090908091A091A0908091A090809090908091A090809080A19090909190A08091A09080908091A0909090809080909091A09190909091A0908091A090809090809081B090809080909081B0908090809' irsendcodes['3'] = '462209090908091A091A0908091A090809090908091A090809080A19090909190A08091A09080908091A0909090809080909091A09190909091A0908091A090809090809081B090809080909081B0908090809' irsendcodes['4'] = '462209090908091A091A0908091A090809090908091A090809080A19090909190A08091A09080908091A0909090809080909091A09190909091A0908091A090809090809081B090809080909081B0908090809' irsendcodes['5'] = '462209090908091A091A0908091A090809090908091A090809080A19090909190A08091A09080908091A0909090809080909091A09190909091A0908091A090809090809081B090809080909081B0908090809' irsendcodes['6'] = '462209090908091A091A0908091A090809090908091A090809080A19090909190A08091A09080908091A0909090809080909091A09190909091A0908091A090809090809081B090809080909081B0908090809' irsendcodes['7'] = '462209090908091A091A0908091A090809090908091A090809080A19090909190A08091A09080908091A0909090809080909091A09190909091A0908091A090809090809081B090809080909081B0908090809' responseBody = json.dumps(irsendcodes) print('Content-type: application/json\n\n') print(responseBody) ``` # ま、いろいろ遊べるかと 以上習作でした。 そんな難しいことしてないので、応用が利くかと思います。 M5Stackとか、「赤外線LEDが載ってる」Arduino対応モジュールもありますし。 適当なホームオートメーションも組めますし。 赤外線リモコンって、ステキよねっ!。