hiro yamamoto works

マイコンハード、ソフトを作ったりしています。
お家や現場のお困りごと解決に!
内容利用は自己責任でお願いします。

赤外線リモコンWi-Fi中継の応用 Webページからテレビを操作(SDメモリ内データで操作できた)

2024-03-13 10:23:04 | 赤外線リモコン

この投稿は書きかけです。
間違いやコードの文字化けがあるかもしれません。

赤外線リモコンWi-Fi中継の送信機応用です。
赤外線リモコン信号が届かない場所にあるテレビを、Webページから操作します。
事前にプログラムした一連の動作を実行させます。

「本当に正しくテレビが操作できるのか?!」
リモコンデータはテレビ側に設置された赤外線送信機の中にあり、
Web経由でスタートスイッチを押しているだけなので、
テレビとの間に遮蔽物がなければ操作できるはずです。

説明を省略している部分がありますので読み直して加筆します。
前の投稿も参考になります。

SimpleWiFiServerのwebページで、LEDを点灯するリンクをクリックすると、
テレビを操作する赤外線リモコン信号が送信されます。

スケッチの概要

IRremote ライブラリのSendRawDemoを改変し、
WiFiManagerAdvanced、SimpleWiFiServerと合体、EEPROMライブラリ追加
(Wi-Fi認証以外のネットワーク設定はEEPROMへ保存)
SimpleWiFiServerのwebページをリモコン用に改変すると良いが、そのままでも操作はできる。
SDライブラリ追加

SDメモリのルートにirremoTV.txtというファイルを置いて、
赤外線リモコンで送信するデータを記述しています。
例です
#参考にsendSony()関数の引数名と型
#sendSony(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t numberOfBits)
#aNumberOfRepeatsは2固定のようなので省略しています
#データー番号,アドレス,コマンド,numberOfBits,インターバル時間(mS)のように並んでいます
C00 1 ,15,12,10000 # 0x1,0x15,2,12,1000 TV Power ON(ON-OFF)
#以降はコメントとして取り扱われます
C01 1,15,12,200 # 0x1,0x15,2,12,200 # 入力切換え
C02 1,65,12,200 # 0x1,0x65,2,12,200 # 決定
#このように記述します


スケッチの追加点を紹介しておきましょうか
(サンプルスケッチを改変しています。ライブラリ開発者に感謝します)
#include "FS.h"
#include "SD.h"
#include "SPI.h"
//中略
uint16_t IRco[20][5];
//中略
  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  readFile(SD, "/irremoTV.txt");//SDのルートにあるirremoTV.txtというファイルを読み込む
//中略
//readFile()関数です。setup(){}の前か後ろ、またはloop()の}以降に置きます。
void readFile(fs::FS &fs, const char * path) {
  Serial.printf("Reading file: %s\n", path);   File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }
 //中略
//読み込んだファイルからリモコン信号のaddress、command等を2次元配列へ入れていく
//aAddressのuint16_t型に合わせて配列を作りaCommand以降のuint8_t型はキャストすればよいか‹
  //関数へ与える引数の型は次の通りです。
  //sendSony(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t numberOfBits)
  //uint16_t IRco[20][5];//[行][列] イメージは横書きフォーマット
  Serial.print("Read from file: ");
  while (file.available()) {
    //Serial.write(file.read());
    String line = file.readStringUntil('\n');//終端文字'\n'が検出されるまで読んで文字列全体をlineへ入れる
    line = line.substring(0, line.indexOf('#'));//インデックス0(行頭)から(#までのインデックス数)の文字列取得
    if (line.substring(0, 3) == "C00") { //開始位置(0)は含むが終了位置(3)は含まれない
      String command0_0 = line.substring(4, 8); //address
      command0_0.trim();//スペース等を除去
      IRco[0][0] = strtol(command0_0.c_str(), NULL, 16);//address uint16_t
      String command0_1 = line.substring(9, 11);//command uint8_t
      IRco[0][1] = strtol(command0_1.c_str(), NULL, 16);//.toInt();
      //repeatは2固定のようなので省略しようと思う
      String command0_2 = line.substring(12, 14);//Bit
      IRco[0][2] = command0_2.toInt();
      String command0_3 = line.substring(15, 20);//interval
      command0_3.trim();//スペース等を除去
      IRco[0][3] = command0_3.toInt();
      //Serial.println(ss); Serial.println(ssid);
    } else if (line.substring(0, 3) == "C01") {
      String command1_0 = line.substring(4, 8); //address
      command1_0.trim();//スペース等を除去
      IRco[1][0] = strtol(command1_0.c_str(), NULL, 16);//address uint16_t
      String command1_1 = line.substring(9, 11);//command uint8_t
      IRco[1][1] = strtol(command1_1.c_str(), NULL, 16);//.toInt();
      //repeatは2固定のようなので省略しようと思う
      String command1_2 = line.substring(12, 14);//Bit
      IRco[1][2] = command1_2.toInt();
      String command1_3 = line.substring(15, 20);//interval
      command1_3.trim();//スペース等を除去
      IRco[1][3] = command1_3.toInt();
    } else if//中略
//同じパターンの繰り返しでやっていますがもっと良い書き方あると思います。
中略
loop()
//SimpleWiFiServerスケッチを改変して使います
        if (currentLine.endsWith("GET /H")) {
//LEDを制御する代わりにIrSender.sendSony()を実行している
          //digitalWrite(5, HIGH); // GET /H turns the LED off
          //関数へ与える引数の型は次の通りです。
          //sendSony(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats,
          // uint8_t numberOfBits)
          /*2次元配列 IRco[0][0]*/
//aNumberOfRepeatsは2固定のようなので直接書いています
         IrSender.sendSony(IRco[0][0], (uint8_t)IRco[0][1] , 2, IRco[0][2]); //POWER ON-OFF
          //IRco[0][3] POWER ONから次の操作を受け付けるまでの待ち時間
          delay(IRco[0][3]);
          IrSender.sendSony(IRco[1][0], (uint8_t)IRco[1][1] , 2, IRco[1][2]);
          delay(IRco[1][3]);
          IrSender.sendSony(IRco[2][0], (uint8_t)IRco[2][1] , 2, IRco[2][2]);
//中略
        }
        if (currentLine.endsWith("GET /L")) {
          //digitalWrite(5, LOW); // GET /L turns the LED on
//LEDを制御する代わりにIrSender.sendSony()を実行している
//割り当てる操作を固定するならば次のように書けば良い
          IrSender.sendSony(0x1, 0x15, 2, 12);//TV Power OFF(ON-OFF)
          //delay(1000);
        }
//後略