eucalyのアイコン画像
eucaly 2024年01月23日作成 (2024年01月23日更新) © MIT
製作品 製作品 Lチカ Lチカ 閲覧数 315
eucaly 2024年01月23日作成 (2024年01月23日更新) © MIT 製作品 製作品 Lチカ Lチカ 閲覧数 315

Arduinoでリモコン送受信(irremote 3系 汎用版)

Arduinoでリモコン送受信(irremote 3系 汎用版)

お久しぶりです、ゆうかりです。

さて今回は。
「お気軽にArduinoでリモコン送受信しようとしたら色々ハマったので、最新ライブラリで汎用性ある制御をどうにかしたのでその記録」って感じ。

モノとしてのゴールは、「受信したリモコンコードをWebサーバへ送信、送信したいリモコンコードをWebサーバから受信」て感じです。

いままでとこれから

Arduinoには、「irremote」というライブラリがあり、お気軽に赤外線リモコンの送受信が実装出来ます。

https://github.com/Arduino-IRremote/Arduino-IRremote

ま、適当に実装して使っていたのですが。
新たにリモコン送受信モジュール作ってコンパイルしてみたら。

おや、、、ライブラリの様子が、、、。

キャプションを入力できます

というわけで、irremote v4やv3系に対応した、赤外線リモコン送受信を組んでいきたいなと思ってみたり。

ハードウェアの準備

回路図は、こんなかんじー。
キャプションを入力できます
みんな大好き秋月電子でサクっと揃えました。

LEDはそれなりに数をつけ、更に電流を多めに流すために、CPU直結とせず、FET(とトランジスタ)でバッファしました。
各LEDには50mA流れます。
また、結構激しく電流流れるので、CPU基板上のLDOで作られる3.3Vではなく、USB直結の5V系からLEDの電源を取っています。
LEDを並列駆動するときは、なるべく個別に電流制限抵抗を置くのがいいッスよ、LED自体を並列にしてしまうと、個体差から電流配分の偏りが出やすいので!。

なんでわざわざFETとTRでバッファしてるのか、ですが、まあ、「適当にFETでスイッチ組んだら、論理反転してしまった」が正解です。

で、実装。
キャプションを入力できます

秋月C基板に納まります。
 *写真の基板は、I2Cレベルシフタとか余計なもんが少し実装されとります

プログラムのやりざま

まず、赤外線リモコンのコード入出力は、irremote的にいくつかあるのですが。
今回は、
・リモコンの「ボタン」が識別できるもの
・リモコンの「コードそのもののダンプ的な」もの
をハンドリングすることにしました。

Arduinoソース上では、「ボタン識別」が「rawdata」、「コードそのもののダンプ」が「rawcodedata」です。
ボタン識別は、16進数の数バイトなデータ。
そのままでは送信コードとして使えませんが、値に揺れが無いので、if文でそのままハンドリングできます。
コードそのもののダンプは波形的な送信タイミングが記載されており、送信コードとして使用できますが、値が揺れるのでハンドリングは厳しいかと。

赤外線リモコンコードは、各社プロトコルで実装されており、例えば「機器」+「個別ボタン」みたいに分類できるのですが、まあ今回はそこまで必要じゃないっぽいので、使わない方向で。
 *というかパナソニックのシーリングライト制御しようと思ったのですけれども、こいつはirremoteに実装されているプロトコルに合致せず、うまくハンドリングできなかったりするのです。

CPUはESP32Cを使用、Wifiがついているので、Arduino的には「リモコン送受信端末」として実装し、リモコンコードの解釈、発行は、連携するWebサーバ側でやる感じで。

リモコン受信 → WebサーバーにGETで情報送信→JSONでリモコンコード受信→リモコンコード発光

みたいな。

Arduino側ソース

こんな感じになりました。

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モジュールは使ってません、ほんとは使いたいのに・・・。

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対応モジュールもありますし。
適当なホームオートメーションも組めますし。

赤外線リモコンって、ステキよねっ!。

eucalyのアイコン画像
いつも、てきとうです
ログインしてコメントを投稿する