お久しぶりです、ゆうかりです。
さて今回は。
「お気軽に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
さんが
2024/01/23
に
編集
をしました。
(メッセージ: 初版)
-
eucaly
さんが
2024/01/23
に
編集
をしました。
ログインしてコメントを投稿する