hiro yamamoto works

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

赤外線リモコンをWi-Fiで中継する(deep-sleepを組み込む)

2024-07-17 15:26:34 | 赤外線リモコン

この投稿は書きかけです。
スケッチは参考程度に見てください。
動作時の電流を測定したので載せておきます。
待機時約84mA 赤外線受信Wi-Fi送信時ピーク約120mA sleep時約0.62mA


ポイント
 赤外リモコン中継送信機の消費電力削減のために、
 ESP32のDeep-sleep Modeを組み込みました。
 XIAO ESP32C3でフィードバックLED点灯を断念し代用LEDをGPIO2に接続
 #define LED_BUILTINでピン指定しても点きません。XIAO ESP32S3ではデフォルトのままでチカチカしてました。

タイトルでは"Wi-Fiで"と表現していますが、正しくは"ESP-NOW"です。
だれでもイメージしやすいように"Wi-Fiで"と表現しています。

SONY製レコーダーのリモコンモード変更設定可能台数不足解決、
同室複数SONY製テレビの赤外線リモコン操作での問題解決に役立ちます。
Tip
SONY新型テレビリモコン(一部機種)は、電源ボタンのみ赤外線で、
以外はbluetooth接続との情報です。
テレビ側設定でbluetoothをOFFで赤外線操作になるが
"googleアシスタント"はbluetooth接続要とのこと。
ちなみにbluetooth接続は、キッチンだと電子レンジの影響が出る可能性があります。


XIAO ESP32C3を使用しました。
Wakeupスイッチ・・・D1(GPIO3)とGND間にプッシュスイッチを接続
状態表示LED・・・D2(GPIO4)と3.3V間に抵抗とLEDを直列接続(抵抗は仮に1K点灯がわかれば良い)
IR_RECEIVE_PIN ・・・D8(GPIO8)
FEEDBACK LED代用・・・D0(GPIO2)をdigitalWrite()で(ESP32C3用)
D0(GPIO2)と3.3V間に抵抗とLEDを直列接続(抵抗は仮に1K点灯がわかれば良い)

ざっくり説明
 IRremote、ESP32 ESPNow、ESP32 DeepSleep各exampleから
 Seeed Studio wiki のXIAO ESP32C3 Getting Started のスケッチから
 必要な部分を使用させていただきました。
DeepSleep組込前スケッチはこちらの記事を見てください
 
 赤外線受信していないときsleep用カウンタを加算、
 赤外線受信し"protocol == SONY"でカウンタクリア
 カウント値が連続100,000,000回(仮)を超えたときに
 "esp_deep_sleep_start()"でsleepする。
 D1(GPIO3)プッシュスイッチでWeakup
 電源表示LED 動作中点滅、sleep中消灯
 ESP32C3でのFEEDBACK LED代用として
 D0(GPIO2)をdigitalWrite()で点消灯している。

参考スケッチ
(XIAO ESP32S3では手直し必要、間違いや抜けがあるかも)

//オリジナル部分を省略して主に追加した部分を記述
#define IR_RECEIVE_PIN 8
#define ledPin 4 //sleep中 点滅LED
uint32_t sleepTime_RepeatCount = 0;
uint32_t detectionCount = 100000000; //delay(1)へ変更に伴う

//ESP-NOW Masterは赤外線リモコンを受信してESP-NOW Slaveへ送る
typedef struct struct_IRSendData {
  char IR_protocol[10];//"SONY"の文字が入れば良い
  uint16_t IR_address;
  uint16_t IR_command;
  uint8_t IR_repeat;
  uint8_t IR_bit;
} struct_IRSendData;
struct_IRSendData IRSendData;
 
uint8_t irSendRepeatCount = 0;
uint32_t LastSendMillis = 0;

bool ledState = LOW; // sleep中 点滅LED
uint32_t blinkPreviousMillis = 0; // sleep中 点滅LED
const uint16_t blinkInterval = 1000; // sleep中 点滅LED
#include <IRremote.hpp>//"<"と">"は半角に直す
//中略
//以降はsetup()の中
//pinMode(LED_BUILTIN, OUTPUT);//XIAO ESP32S3
  pinMode(ledPin, OUTPUT);//LED スリープ中消灯 動作中点滅する
  pinMode(2, OUTPUT);//GPIO2(D0)//ESP32C3でFEEDBACK LED代用
  digitalWrite(2, HIGH);//ESP32C3でFEEDBACK LED代用起動時点灯するので消しておくため
//LED 3.3V to ANODE ,GPIO2 to CATHODE
/*参考 esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask,
    esp_deepsleep_gpio_wake_up_mode_t mode)*/
//wakeup設定部
  esp_deep_sleep_enable_gpio_wakeup(BIT(D1), ESP_GPIO_WAKEUP_GPIO_LOW);
  //mode -- Select logic function used to determine wakeup condition:
  //ESP_GPIO_WAKEUP_GPIO_LOW: wake up when the gpio turn to low.
  //ESP_GPIO_WAKEUP_GPIO_HIGH: wake up when the gpio turn to high.
  /*ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORSはデフォルト有効
    プルアップ、ダウン抵抗指定不要 外部で行う時は
    ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS オプションを無効にとあったが
    設定方法は見つからんかった*/
//中略
  
  IrReceiver.begin(IR_RECEIVE_PIN)//XIAO ESP32C3の時
  //IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);//XIAO ESP32S3
  
//setup()部分はここまで
loop(){
  digitalWrite(2, HIGH);//XIAO ESP32C3でFEEDBACK LEDの代用
  if (IrReceiver.decode()) { //赤外線
    if (IrReceiver.decodedIRData.protocol == SONY) {
       sleepTime_RepeatCount = 0;
       Serial.println("sleepTime_RepeatCount clear");
    //
   strcpy(IRSendData.IR_protocol, "SONY");
       IRSendData.IR_address = IrReceiver.decodedIRData.address;
       IRSendData.IR_command = IrReceiver.decodedIRData.command;
       IRSendData.IR_repeat = 2;//2で固定
       IRSendData.IR_bit = IrReceiver.decodedIRData.numberOfBits;
       
   //さっき送ったのと今送った時間差300mS以上のときにカウントをリセットする
      uint32_t SendMillis = millis();
      if (SendMillis - LastSendMillis >= 300) { //
        irSendRepeatCount = 0;
      }
      /*Serial.print("irSendRepeatCount = "); Serial.println(irSendRepeatCount);*/
      LastSendMillis = SendMillis;
      //リモコンボタン押し時間が長め(**mS超え)の時 1発目送って少し待って(**mS)2発目送る
      //以降は少ない待ち時間で繰り返し
      if (irSendRepeatCount == 0 || irSendRepeatCount >= 10) {
        sendData();//ESP-NOW
      }
        irSendRepeatCount++;//
    } else if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
      Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
    }
    IrReceiver.resume();
    //
    digitalWrite(2, LOW);//ESP32C3でFEEDBACK LED代用
  } else {
    //
    sleepTime_RepeatCount++;
    //Serial.print("sleepTime_RepeatCount = "); Serial.println(sleepTime_RepeatCount);
    delay(1); //修正して様子みる
    if (sleepTime_RepeatCount >= detectionCount) { //uint32_t detectionCount no-operation-detection count
      
      //Go to sleep now
      Serial.println("Going to sleep now");
      esp_deep_sleep_start();
    } //if (sleepTime_RepeatCount・・・
  } // } else {
  //スリープ中以外にLEDを点滅する
  uint32_t blinkCurrentMillis = millis();
  if (blinkCurrentMillis - blinkPreviousMillis >= blinkInterval) {
    blinkPreviousMillis = blinkCurrentMillis;
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}//loop()


改善点が見つかればつづく