M5Stack

M5Stack Atomで赤外線リモコンを作る(8)M5Stackに移植

前回の記事M5Stack Atomで赤外線リモコンを作る(7)M5StickCに移植で作成したM5StickC用学習リモコンプログラムをM5Stackに移植してみました。

プログラムの変更

主な変更ポイントは次の通りです。

  • <M5StickC.h>の代わりに<M5Stack.h>をinclude
  • 赤外線LEDのGPIOピン番号を21に変更
  • 赤外線受信センサーのGPIOピン番号を22に変更

変更後のプログラムはこうなりました。

#include <M5Stack.h>

//=== IRremoteESP8266 files
#include <IRrecv.h>
#include <IRremoteESP8266.h>
#include <IRac.h>
#include <IRtext.h>
#include <IRutils.h>

//=== SPIFFS files
#include "FS.h"
#include "SPIFFS.h"

#define IR_LED 21  // IR_LED in M5Stack IR UNIT

// ============ IRremoteESP8266 Tunable Parameters ================
const uint16_t kRecvPin = 22;
const uint32_t kBaudRate = 115200;
const uint16_t kCaptureBufferSize = 1024;
#if DECODE_AC
const uint8_t kTimeout = 50;
#else   // DECODE_AC
const uint8_t kTimeout = 15;
#endif  // DECODE_AC
const uint16_t kMinUnknownSize = 12;
#define LEGACY_TIMING_INFO false

//=== SPIFFS parameters
#define FORMAT_SPIFFS_IF_FAILED true
const char *FILE_NAME = "/irdata";

//== instances for receiving and sending IR messages
IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, true);
decode_results results;  // Somewhere to store the results
IRsend irsend(IR_LED);

//== IR message container
#define BUFFER_SIZE 1024
uint16_t rawData[BUFFER_SIZE]; // IR message container
uint16_t dataLength = 0;       // IR message length

//== variable for remembering mode
bool receiving = false;

void setup() {
  M5.begin(true, true, true); //LCDEnable = true, PowerEnable = true, SerialEnable = true
  Serial.printf("\n\n### IR Remote Controller ###\n");
  Serial.printf("IR Sensor Pin Number =%d \n", kRecvPin);
  irrecv.setUnknownThreshold(kMinUnknownSize);
  irsend.begin();

  Serial.print("Initializeing SPIFFS....");
  showMessage("INITIALIZING");
  SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED); // activate SPIFFS
  Serial.println("Done.");
  readRawDataFromSPIFFS(); // read data if available
  showStatus();
}

void loop() {
  M5.update();
  if (M5.BtnA.wasReleased()) {
    Serial.print("Button wasReleased(): ");
    if (receiving) {
      irrecv.disableIRIn();
      receiving = false;
      deleteRawDataInSPIFFS();
      dataLength = 0;
      showStatus();
    } else if (dataLength > 0) {
      Serial.printf("send rawData[%d]\n", dataLength);
      irsend.sendRaw(rawData, dataLength, 38);
    } else {
      Serial.println("rawData[] is empty. Skip sending");
    }
  } else  if (M5.BtnA.pressedFor(300)) { // 長押しなら赤外線信号を受信モードに遷移し、↓(下矢印)を表示
    irrecv.enableIRIn();
    receiving = true;
    Serial.println("M5.Btn.pressedFor(500): waiting for IR signal");
    showStatus();
    while (! M5.BtnA.wasReleased()) { // ボタンが離されるまで待つ
      delay(50);
      M5.update();
    }
  } else { // 赤外線信号を受信していたら、信号を配列に格納し、○を表示する。
    if (irrecv.decode(&results)) {
      uint16_t *rawData_tmp;
      irrecv.disableIRIn();
      receiving = false;
      if (results.overflow)
        Serial.printf(D_WARN_BUFFERFULL "\n", kCaptureBufferSize);
      rawData_tmp = resultToRawArray(&results);
      dataLength = getCorrectedRawLength(&results);
      Serial.printf("rawData[%d] : ", dataLength);
      for (int i = 0; i < dataLength; i++) {
        rawData[i] = rawData_tmp[i];
        Serial.printf("%d, ", rawData[i]);
      }
      delete[] rawData_tmp;
      Serial.println();
      writeRawDataToSPIFFS();
      showStatus();
    }
  }
}

void readRawDataFromSPIFFS() {
  Serial.printf("reading rawData from SPIFF file: %s \n", FILE_NAME);
  fs::FS fs = SPIFFS;
  File file;

  if (fs.exists(FILE_NAME)) {
    file = fs.open(FILE_NAME);
  } else {
    Serial.printf("file \"%s\" not found in SPIFFS\n", FILE_NAME);
    return;
  }
  int i = 0;
  uint8_t *rawData8 = (uint8_t *)rawData;
  while (file.available()) {
    rawData8[i] = file.read();
    Serial.printf("%d ", rawData8[i]);
    i++;
  }
  Serial.println();
  dataLength = i / 2;
  file.close();

  Serial.printf("dataLength = %d\n", dataLength);
  for (int j = 0; j < dataLength; j++) {
    Serial.printf("%d", rawData[j]);
    Serial.print(" ");
  }
  Serial.println("done");
}

void writeRawDataToSPIFFS() {
  fs::FS fs = SPIFFS;
  Serial.println("writing data to SPIFF");
  File file = fs.open(FILE_NAME, FILE_WRITE);
  file.write((uint8_t *)rawData, dataLength * 2);
  file.close();
  Serial.println("done");
}

void deleteRawDataInSPIFFS() {
  Serial.printf("Deleting rawData in SPIFFS: %s\r\n", FILE_NAME);
  fs::FS fs = SPIFFS;
  if (fs.remove(FILE_NAME)) {
    Serial.println("- file deleted");
  } else {
    Serial.println("- deletion failed");
  }
}

void showStatus() {
  const char *message;
  if (receiving) {
    message = "RECEIVING";
  } else {
    if (dataLength > 0) {
      message = "READY";
    } else {
      message = "NO DATA";
    }
  }
  showMessage(message);
}

void showMessage(const char *message) {
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setRotation(1);
  M5.Lcd.setTextFont(4);
  M5.Lcd.setTextColor(BLUE);
  M5.Lcd.setCursor(27, 0);
  M5.Lcd.print("IR Remote");
  M5.Lcd.setCursor(27, 40);
  M5.Lcd.print(message);
}