第15回

マイコン向け設計演習

これまでの要素を組み合わせ、マイコン向けのクラス群を組み立てる。

LEDクラス

class LED {
public:
    LED(int pin);

    void on();
    void off();
    void toggle();

private:
    int pin;
    bool state;
};

Motorクラス

class Motor {
public:
    Motor(int pin);

    void setSpeed(int speed);
    void stop();

private:
    int pin;
    int speed;
};

Sensorクラス

class Sensor {
public:
    virtual void update() = 0;
};

IMU

class IMU : public Sensor {
public:
    void update() override;

private:
    float roll;
    float pitch;
    float yaw;
};

FlightMode

enum class FlightMode {
    MANUAL,
    AUTO,
    LANDING
};

組み合わせる

ここまでで、本講座で扱う道具がすべて出そろった。

要素使っている機能学んだ回
LED / Motorクラス・カプセル化・.hpp / .cpp分割第6〜8回
Sensor抽象クラス・純粋仮想関数第12回
IMU継承・override第10〜11回
FlightModeenum classによる状態管理第9回
全体のまとめ役1クラス1責務のクラス設計第14回

動かして確かめる

演習に入る前に、まずこのサンプルを動かして結果を見る。追加の部品は要らない。光るのはボードに載っている内蔵LEDで、それ以外はシリアルモニタの出力で確かめられる。code/examples/15-mcu-design/を開き、pio run -t uploadで書き込んでからpio device monitorで出力を見る(手順と、外付けのLEDなどをつなぐ場合は開発環境にまとめてある)。

code/examples/15-mcu-design/
├── include/
│   ├── Sensor.hpp      抽象クラス(第12回)
│   ├── IMU.hpp         Sensor を継承(第10〜11回)
│   ├── LED.hpp         クラス・カプセル化(第6〜8回)
│   └── FlightMode.hpp  enum class(第9回)
└── src/
    ├── IMU.cpp / LED.cpp
    └── main.cpp
code/examples/15-mcu-design/src/main.cpp(loop())
void loop() {
    // センサは種類を問わずまとめて更新する
    for (int i = 0; i < SENSOR_COUNT; i++) {
        sensors[i]->update();
    }

    // 状態によってふるまいを変える
    switch (mode) {
    case FlightMode::MANUAL:
        led.off();
        break;

    case FlightMode::AUTO:
        led.on();
        break;

    case FlightMode::LANDING:
        led.toggle();
        break;
    }

    // IMUの値はまとめ役(この例では main.cpp)が取り出して使う
    Serial.print(modeName(mode));
    Serial.print("  roll=");
    Serial.println(imu.getRoll());

    advanceMode();
    delay(200);
}
シリアルモニタの出力
mode -> MANUAL
MANUAL  roll=0.50
MANUAL  roll=1.00
      :
MANUAL  roll=5.00
mode -> AUTO
AUTO  roll=5.50
AUTO  roll=6.00
      :
AUTO  roll=10.00
mode -> LANDING
LANDING  roll=10.50

確かめること。

  • 10周ごとにモードが切り替わり、LEDの出方が変わる(消灯 → 点灯 → 点滅)
  • Sensor*の配列、enum class、LEDクラスが1つのプログラムで一緒に動いている
  • main.cppにはまだ「モードごとの判断」が残っている。これをどのクラスに移すべきかを考える
  • このサンプルにはMotorがまだない。足すときにどのファイルを触ることになるかを見積もる

演習:自分のクラス図を書く

  • 上記5つを.hpp / .cppに分割して実装する
  • main.cppが短く保たれているかを確認する
  • 最終課題で作るものを想定し、クラス図を紙に書いてみる

この演習がそのまま最終課題の下書きになる。