このコードには、コンパイルエラーを引き起こす致命的な問題と、コードの可読性やメンテナンス性を損なう問題の2種類があります。

1. 未定義の関数 (コンパイルエラー)

コードは moveForward() や ledOn() といった関数を呼び出していますが、これらの関数がどこにも定義されていません。そのため、このままではコンパイルできません。

モーターの制御やLEDの点灯を行うための具体的な処理を、これらの関数として実装する必要があります。

2. 赤外線コードの扱いの問題 (ロジックと可読性)

コードの冒頭で BTN_UP などの定数を定義していますが、switch 文の中では 0x02 のような直接的な値(マジックナンバー)が使われており、せっかく定義した定数が全く使われていません。

これは、コードを読む人が 0x02 という値が何を意味するのかすぐに理解できないため、非常に読みにくく、間違いの原因にもなります。

IrReceiver.decodedIRData.command が返すのは、赤外線信号のコマンド部分(8ビット)です。したがって、定数をこの8ビットの値で定義し直し、switch 文でその定数名を使うように修正するべきです。

修正・完成版コード

上記の問題点を修正し、不足している関数を実装した完成版のコードを以下に示します。このコードをコピーして使用すれば、意図通りに動作するはずです。

C++

#include <IRremote.hpp>

// ピン定義

const int motor1A = 6;

const int motor1B = 7;

const int motor2A = 4;

const int motor2B = 5;

const int redLED = 10;

const int greenLED = 9;

const int blueLED = 8;

const int irReceiverPin = 2;

// 赤外線コード定義(コマンド部分のみに修正)

#define BTN_1     0x30

#define BTN_2     0x18

#define BTN_3     0x7A

#define BTN_4     0x10

// ... 他のボタンも同様に8ビットのコマンド部分を定義 ...

#define BTN_UP    0x02

#define BTN_DOWN  0x98

#define BTN_RIGHT 0x90

#define BTN_LEFT  0xE0

#define BTN_OK    0xA8 // 元のコードの0xFFA857に対応

void setup() {

  Serial.begin(9600); // デバッグ用にシリアル通信を開始

  IrReceiver.begin(irReceiverPin, ENABLE_LED_FEEDBACK);

  pinMode(motor1A, OUTPUT);

  pinMode(motor1B, OUTPUT);

  pinMode(motor2A, OUTPUT);

  pinMode(motor2B, OUTPUT);

  pinMode(redLED, OUTPUT);

  pinMode(greenLED, OUTPUT);

  pinMode(blueLED, OUTPUT);

}

void loop() {

  if (IrReceiver.decode()) {

    // 受信したコードを16進数でシリアルモニタに表示

    Serial.println(IrReceiver.decodedIRData.command, HEX);

    // 定義した定数名を使って処理を分岐

    handleIR(IrReceiver.decodedIRData.command);

    IrReceiver.resume(); // 次の信号を受信するためにリセット

  }

}

// ========== ここから下に関数を追加 ==========

// モーターを停止する関数

void stopMotors() {

  digitalWrite(motor1A, LOW);

  digitalWrite(motor1B, LOW);

  digitalWrite(motor2A, LOW);

  digitalWrite(motor2B, LOW);

}

// 前進する関数

void moveForward(int duration) {

  digitalWrite(motor1A, HIGH);

  digitalWrite(motor1B, LOW);

  digitalWrite(motor2A, HIGH);

  digitalWrite(motor2B, LOW);

  delay(duration);

  stopMotors();

}

// 後進する関数

void moveBackward(int duration) {

  digitalWrite(motor1A, LOW);

  digitalWrite(motor1B, HIGH);

  digitalWrite(motor2A, LOW);

  digitalWrite(motor2B, HIGH);

  delay(duration);

  stopMotors();

}

// 右に曲がる関数(その場で回転)

void turnRight(int duration) {

  digitalWrite(motor1A, HIGH);

  digitalWrite(motor1B, LOW);

  digitalWrite(motor2A, LOW);

  digitalWrite(motor2B, HIGH);

  delay(duration);

  // stopMotors(); // この後のmoveForwardのために停止しない

}

// 左に曲がる関数(その場で回転)

void turnLeft(int duration) {

  digitalWrite(motor1A, LOW);

  digitalWrite(motor1B, HIGH);

  digitalWrite(motor2A, HIGH);

  digitalWrite(motor2B, LOW);

  delay(duration);

  // stopMotors(); // この後のmoveForwardのために停止しない

}

// LEDを指定時間点灯させる関数

void ledOn(int pin, int duration) {

  digitalWrite(pin, HIGH);

  delay(duration);

  digitalWrite(pin, LOW);

}

// 赤外線信号を処理する関数

void handleIR(unsigned long code) {

  switch (code) {

    case BTN_UP: // 前

      ledOn(blueLED, 1000);

      moveForward(1000);

      break;

    case BTN_DOWN: // 後

      ledOn(greenLED, 1000);

      moveBackward(1000);

      break;

    case BTN_RIGHT: // 右

      ledOn(redLED, 100);

      turnRight(100);

      moveForward(100);

      break;

    case BTN_LEFT: // 左

      ledOn(redLED, 100);

      turnLeft(100);

      moveForward(100);

      break;

    // 数字ボタンの処理

    case BTN_1:

      ledOn(redLED, 1000);

      break;

    case BTN_2:

      ledOn(blueLED, 1000);

      break;

    case BTN_3:

      ledOn(greenLED, 1000);

      break;

    case BTN_4:

      // 2つのLEDを同時に点灯させるには少し工夫が必要

      digitalWrite(redLED, HIGH);

      digitalWrite(blueLED, HIGH);

      delay(1000);

      digitalWrite(redLED, LOW);

      digitalWrite(blueLED, LOW);

      break;

    default: // 定義されていないボタンが押された場合

      stopMotors(); // とりあえず停止

      break;

  }

}