Seeed Studio XIAO ESP32-C6をArduinoで動かす

技術開発Arduino,ESP32

概要

Seeed StudioでXIAO RP2040の買い足しをしようとしたところ、XIAO ESP32-C6が思っていたより安かったので買ってみました。
Wi-Fi・Bluetoothが使えて、32bit RISC-V 160MHzのデュアルコアで、価格もRaspberry Pi Pico Wより安いので、使い勝手が良さそうなら今後も仕事で使っていこうかと考えています。

実行環境

MCU: Seeed Studio XIAO ESP32-C6
IDE: Arduino IDE 2.3.5

購入ページ

ピンアサイン

いつものXIAOを踏襲していそうなピンアサインです。

スイッチサイエンス購入ページより引用

ピンの定義

以下はpins_arduino.hの抜粋です。

#define USB_VID          0x2886
#define USB_PID          0x0048
#define USB_MANUFACTURER "Seeed Studio"
#define USB_PRODUCT      "XIAO ESP32-C6"
#define USB_SERIAL       ""

static const uint8_t LED_BUILTIN = 15;
#define BUILTIN_LED LED_BUILTIN  // backward compatibility
#define LED_BUILTIN LED_BUILTIN  // allow testing #ifdef LED_BUILTIN

static const uint8_t TX = 16;
static const uint8_t RX = 17;

static const uint8_t SDA = 22;
static const uint8_t SCL = 23;

static const uint8_t SS = 21;
static const uint8_t MOSI = 18;
static const uint8_t MISO = 20;
static const uint8_t SCK = 19;

static const uint8_t A0 = 0;
static const uint8_t A1 = 1;
static const uint8_t A2 = 2;

static const uint8_t D0 = 0;
static const uint8_t D1 = 1;
static const uint8_t D2 = 2;
static const uint8_t D3 = 21;
static const uint8_t D4 = 22;
static const uint8_t D5 = 23;
static const uint8_t D6 = 16;
static const uint8_t D7 = 17;
static const uint8_t D8 = 19;
static const uint8_t D9 = 20;
static const uint8_t D10 = 18;

static const uint8_t WIFI_ENABLE = 3;
static const uint8_t WIFI_ANT_CONFIG = 14;

Arduino IDEの設定

ボードマネージャにESP32シリーズのURLを追加します。
↓このサイトが説明が丁寧でした。

Lチカ

通常のArduinoと同じコードで動作しました。
アクティブLOWで配線されているので、LOWにすると点灯します。

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
}

GPIO

digitalWrite()の速度を測定しました。リンギングは多分ですが雑に配線して測ったのが原因です。
2回の実行で952nsなので、1回あたりの処理速度は476nsになります。
RP2040が354nsなので若干遅いですね。とはいえArduinoでコーディングする分には十分です。

  digitalWrite(D0, HIGH);
  digitalWrite(D0, LOW);

ADC (アナログ入力)

通常のArduinoと同じ標準関数で実行可能で、A0~A2の3chが使えます。
analogReadResolution()で解像度を変更できますが、デフォルトでハードウェアの最大値の12bitに設定されているので書かなくても動作します。また16bitまで設定できますが出てくるのは計算値なので実質12bitです。

以下、A0の電圧をシリアル通信で出力するコードです。

void setup() {
  Serial.begin(115200);
  pinMode(A0, INPUT);

  // ADCの解像度をビット数で設定(デフォルト:12)
  analogReadResolution(12);
}

void loop() {
  int voltage = analogRead(A0);
  Serial.println(voltage);
  delay(1000);
}

PWM (アナログ出力)

通常のArduinoと同じ標準関数で実行可能で、すべてのピンが対応しています。
またPWM周波数やレンジを設定する関数が追加されているので状況に応じて変更が可能です。

以下、D0からDuty25%・周波数25kHzのPWM信号を出力するコードです。

void setup() {
  pinMode(D0, OUTPUT);             // D0ピンを出力モードに設定
  analogWriteFrequency(D0, 25000); // PWMの周波数を25kHzに設定
  analogWriteResolution(D0, 10);   // PWMの解像度を10ビットに設定
  analogWrite(D0, 256);            // Duty25%のPWM信号を出力
}
void loop() {
  delay(1000);
}

外部割込み

全てのピンで外部割込みが使用可能です。
使用方法も通常のArduinoシリーズと同じです。

以下、D0とGNDが導通したら赤色LEDが点灯するプログラムです。

bool interrupt_flag = false;

// 割り込みハンドラ
void Interrupt() {
  interrupt_flag = true;
}

void setup() {
  pinMode(D0, INPUT_PULLUP);                // ピンD0をプルアップ入力に設定
  pinMode(LED_BUILTIN, OUTPUT);             // 内蔵LEDを出力に設定
  attachInterrupt(D0, Interrupt, FALLING);  // ピンD0に割り込みを設定
}

void loop() {
  if (interrupt_flag) {              // 割り込みが発生した場合
    interrupt_flag = false;          // フラグをリセット
    digitalWrite(LED_BUILTIN, LOW);  // LEDを点灯
    delay(200);
  } else {
    digitalWrite(LED_BUILTIN, HIGH);  // LEDを消灯
  }
}

タイマー割り込み

タイマー割り込みはESP32系のメソッドを使って設定します。
以下、1秒毎に内蔵LEDが点滅するコードです。

hw_timer_t *timer = NULL;
bool timer_flag = false;

// タイマー割り込み処理
void onTimer() {
  timer_flag = true;
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  // タイマー初期化
  timer = timerBegin(1000000);            // タイマーカウントを1MHzに設定(周期:1us)
  timerAttachInterrupt(timer, &onTimer);  // 割り込み処理を指定
  timerAlarm(timer, 1000000, true, 0);    // カウント100万回(1秒)ごとに割り込み処理を実行
}

void loop() {
  // タイマーフラグが立つ度にLEDのON/OFFを切り替え
  if (timer_flag) {
    timer_flag = false;
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  }
}