ESP32シリーズのArduinoでの判定方法

概要

ESP32シリーズが増えましたので、コードからの判別方法を調べてみました。

調査方法

上記を参考にして、空のスケッチをボード変えつつビルドして、全defineを収集してからdiffを取って差分確認しました。

シリーズ判定方法

defineESP32ESP32-S2ESP32-S3ESP32-C3ESP32-H2
CONFIG_IDF_FIRMWARE_CHIP_ID0x00000x00020x00090x0005
CONFIG_IDF_TARGET“esp32”“esp32s2”“esp32s3”“esp32c3”
CONFIG_IDF_TARGET_ARCH_XTENSA111
CONFIG_IDF_TARGET_ARCH_RISCV1
CONFIG_IDF_TARGET_ESP321
CONFIG_IDF_TARGET_ESP32S21
CONFIG_IDF_TARGET_ESP32S31
CONFIG_IDF_TARGET_ESP32C31
CONFIG_IDF_TARGET_ESP32H21

上記が定義されていました。ESP32-H2はまだ正式リリースされていませんでしたが、ソースの中にすでに判定用定義がありました。実際のコードを見てみるとCONFIG_IDF_TARGET_*で判定するのが良さそうでした。

#if CONFIG_IDF_TARGET_ESP32
  // ESP32
#elif CONFIG_IDF_TARGET_ESP32S2
  // ESP32-S2
#elif CONFIG_IDF_TARGET_ESP32S3
  // ESP32-S3
#elif CONFIG_IDF_TARGET_ESP32C3
  // ESP32-C3
#elif CONFIG_IDF_TARGET_ESP32H2
  // ESP32-H2
#else
  // Other
#endif

上記のようなコードになると思います。

#if CONFIG_IDF_TARGET_ESP32
  // ESP32
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
  // ESP32-S2 & S3
#elif CONFIG_IDF_TARGET_ESP32C3
  // ESP32-C3
#elif CONFIG_IDF_TARGET_ESP32H2
  // ESP32-H2
#endif

条件は||で複数を同時に処理することもできます。

コア数

シリーズプロセッサーコア数
ESP32Xtensa® 32-bit LX6Single/Dual
ESP32-S2Xtensa® 32-bit LX7Single
ESP32-S3Xtensa® 32-bit LX7Dual
ESP32-C332-bit RISC-VSingle
ESP32-C232-bit RISC-VSingle
ESP32-C632-bit RISC-VSingle
ESP32-H232-bit RISC-VSingle
ESP32-C532-bit RISC-V

上記がプロセッサーとコア数の一覧です。ESP32だけESP-SOLO-1という、シングルコアがありますがArduinoではサポートされておらず、ほぼ利用されていないのでデュアルコアを使う事が多いと思います。

デュアルコア#define SOC_CPU_CORES_NUM 2
シングルコア#define SOC_CPU_CORES_NUM 1
#define CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE 1
#define CONFIG_FREERTOS_UNICORE 1

SOC_CPU_CORES_NUMで判定するのが無難ですが、シングルコアの場合だけ特殊処理をする場合にはCONFIG_FREERTOS_UNICOREを使うことが多いようです。

#ifdef CONFIG_FREERTOS_UNICORE
// Single
#endif

#ifndef CONFIG_FREERTOS_UNICORE
// Dual
#endif

#if !CONFIG_FREERTOS_UNICORE
// Dual
#endif

#if SOC_CPU_CORES_NUM > 1
// Dual
#else
// Single
#endif

PSRAM

状態define
PSRAM非搭載
PSRAM無効
PSRAM有効#define BOARD_HAS_PSRAM 1
#define CONFIG_SPIRAM 1
#define CONFIG_SPIRAM_SUPPORT CONFIG_ESP32_SPIRAM_SUPPORT

PSRAMは無効化していると、非搭載のボードと同じくなにも宣言されていないようです。

#if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM
    // PSRAM
#endif

3種類ありますが、内部では上記の処理が使われていました。ArduinoだとBOARD_HAS_PSRAMが宣言されていないと、残り2つを消してしまうのですが、CONFIG系はESP-IDF系の設定なのでなるべく大本の設定であるCONFIG_SPIRAMなどを使ったほうがいいと思います。

ボード名

Arduinoではboards.txtにボード定義があり、そこで定義されている名前を取得することができます。

pico32.name=ESP32 PICO-D4
pico32.build.variant=pico32
pico32.build.board=ESP32_PICO

ちょっと特徴的な名前でわかりやすいESP32 PICO-D4で説明したいと思います。上記の設定の場合には以下の定義が使えます。

#define ARDUINO_BOARD "ESP32_PICO"
#define ARDUINO_ESP32_PICO 1
#define ARDUINO_VARIANT "pico32"

pico32.nameの値はArduino IDEの選択肢に現れるだけで内部では利用していません。pico32.build.boardの値がARDUINO_BOARDに定義され、ARDUINO_${pico32.build.board}のような名前でも定義されます。pico32.build.variantはARDUINO_VARIANTで定義されていますね。ログに出力する場合には文字列の方がよいのですが、判定で利用するのはARDUINO_ESP32_PICOの部分となります。

ちょっと数が多いので、上記に最新のboards.txtから一覧を表示するページを作りました。

Board NameUploaddefine
M5Stack_Core_ESP32921600#define ARDUINO_BOARD “M5Stack_Core_ESP32”
#define ARDUINO_M5Stack_Core_ESP32 1
#define ARDUINO_VARIANT “m5stack_core_esp32”
M5STACK_FIRE921600#define ARDUINO_BOARD “M5STACK_FIRE”
#define ARDUINO_M5STACK_FIRE 1
#define ARDUINO_VARIANT “m5stack_fire”
M5Stick_C1500000#define ARDUINO_BOARD “M5Stick_C”
#define ARDUINO_M5Stick_C 1
#define ARDUINO_VARIANT “m5stick_c”
M5Stick_C_PLUS1500000#define ARDUINO_BOARD “M5Stick_C_PLUS”
#define ARDUINO_M5Stick_C_PLUS 1
#define ARDUINO_VARIANT “m5stick_c_plus”
M5Stack_ATOM1500000#define ARDUINO_BOARD “M5Stack_ATOM”
#define ARDUINO_M5Stack_ATOM 1
#define ARDUINO_VARIANT “m5stack_atom”
M5STACK_Core2921600#define ARDUINO_BOARD “M5STACK_Core2”
#define ARDUINO_M5STACK_Core2 1
#define ARDUINO_VARIANT “m5stack_core2”
M5STACK_Tough921600#define ARDUINO_BOARD “M5STACK_Tough”
#define ARDUINO_M5STACK_Tough 1
#define ARDUINO_VARIANT “m5stack_tough”
M5Stack-Timer-CAM1500000#define ARDUINO_BOARD “M5Stack-Timer-CAM”
#define ARDUINO_M5Stack-Timer-CAM 1
#define ARDUINO_VARIANT “m5stack_timer_cam”
M5Stack-Unit-CAM1500000#define ARDUINO_BOARD “M5Stack-Unit-CAM”
#define ARDUINO_M5Stack-Unit-CAM 1
#define ARDUINO_VARIANT “m5stack_unit_cam”
M5Stack-PoE-CAM1500000#define ARDUINO_BOARD “M5Stack-PoE-CAM”
#define ARDUINO_M5Stack-PoE-CAM 1
#define ARDUINO_VARIANT “m5stack_poe_cam”
M5Stack_Paper921600#define ARDUINO_BOARD “M5Stack_Paper”
#define ARDUINO_M5Stack_Paper 1
#define ARDUINO_VARIANT “m5stack_paper”
M5Stack_CoreInk921600#define ARDUINO_BOARD “M5Stack_CoreInk”
#define ARDUINO_M5Stack_CoreInk 1
#define ARDUINO_VARIANT “m5stack_coreink”
STAMP_PICO1500000#define ARDUINO_BOARD “STAMP_PICO”
#define ARDUINO_STAMP_PICO 1
#define ARDUINO_VARIANT “m5stack_stamp_pico”
STAMP_C3921600#define ARDUINO_BOARD “STAMP_C3”
#define ARDUINO_STAMP_C3 1
#define ARDUINO_VARIANT “m5stack_stamp_c3”

上記はM5Stackの定義となります。こちらはZIPファイルでしか配布していないので、boards.txtだけ取り出すのが難しいので自動化していません。

#ifdef ARDUINO_M5Stack_Core_ESP32
// M5Stack BASIC
#elif ARDUINO_M5STACK_FIRE
// M5Stack Fire
#else
// Other
#endif

などと判定を行います。

#include <M5Unified.h>

void setup() {
  auto cfg = M5.config();
  M5.begin(cfg);

  String name;
  switch (M5.getBoard())
  {
#if defined (CONFIG_IDF_TARGET_ESP32C3)
    case m5::board_t::board_M5StampC3:
      name = "StampC3";
      break;
    case m5::board_t::board_M5StampC3U:
      name = "StampC3U";
      break;
#else
    case m5::board_t::board_M5Stack:
      name = "Stack";
      break;
    case m5::board_t::board_M5StackCore2:
      name = "StackCore2";
      break;
    case m5::board_t::board_M5StickC:
      name = "StickC";
      break;
    case m5::board_t::board_M5StickCPlus:
      name = "StickCPlus";
      break;
    case m5::board_t::board_M5StackCoreInk:
      name = "CoreInk";
      break;
    case m5::board_t::board_M5Paper:
      name = "Paper";
      break;
    case m5::board_t::board_M5Tough:
      name = "Tough";
      break;
    case m5::board_t::board_M5Station:
      name = "Station";
      break;
    case m5::board_t::board_M5Atom:
      name = "ATOM";
      break;
    case m5::board_t::board_M5AtomPsram:
      name = "ATOM PSRAM";
      break;
    case m5::board_t::board_M5AtomU:
      name = "ATOM U";
      break;
    case m5::board_t::board_M5TimerCam:
      name = "TimerCamera";
      break;
    case m5::board_t::board_M5StampPico:
      name = "StampPico";
      break;
#endif
    default:
      name = "Who am I ?";
      break;
  }
}

void loop() {
}

ただし、M5Unifiedライブラリを使っているのであればボード定義ではなく、実際の端末からボード特定をすることができますので、こちらの機能を利用したほうがよいと思います。

上記のスケッチ例が参考になります。

まとめ

都度調べてしまうので、定期的に更新するページとして残しておきたいと思います。

コメント