ESP32 (Arduino Core) 2.0系から3.0系への移行

No Image

Arduino Core for ESP32 はもうずいぶん前、1年前くらいに、2.0系から3.0系にバージョンアップされました。
破壊的変更が多く混乱がありましたが、だいぶ慣れてきました。
ただ、公式の説明がよく分からなかったり、移行の仕方が載っているWeb記事が引っかからなかったり大変です。
未だに古い記事などでは2.0系のコード記述で変換もひと手間かかります。
あまりにも解説記事が少ないので、覚え書きとして自分のサイトに載せちゃおうと考えました。

スポンサーリンク


公式は下記のサイトです。
新旧の関数が列挙されているくらいで、具体例がほとんどないんですよね...

特に困るのが、PWM (LEDC) とタイマー割り込みです。
とりあえずはここに絞って解説します。

PWM (LEDC)

主にsetup関数に書くことが多かった、ledcSetupledcAttachPinがなくなってledcAttachにまとまっています。
PWMの出力関数であるledcWriteは同じ関数ですが、引数が変わって第1引数がチャンネルからピンになりました。

2.0系
const int led_pin = 18;   // 出力ピン
const int led_channel = 0;
const int freq = 5000;    // 周波数 5 kHz
const int resolution = 8; // 8bit = 0-255

void setup() {
  // チャンネルに周波数と分解能を設定
  ledcSetup(led_channel, freq, resolution);
  // ピンとチャネルを関連付け
  ledcAttachPin(led_pin, led_channel);
  ledcWrite(led_channel, duty);
}

2.0系ではチャンネルをわざわざ設定しなければならないのが面倒でしたね。

3.0系
const int led_pin = 18;   // 出力ピン
const int freq = 5000;    // 周波数 5 kHz
const int resolution = 8; // 8bit = 0-255

void setup() {
  // ピンと周波数・分解能をまとめて設定(チャネルは自動割り当て)
  ledcAttach(led_pin, freq, resolution);
  ledcWrite(led_pin, duty);
}

3.0系ではチャンネルを気にせず記述できるようになりました。
どうしてもチャンネルが必要な場合は、ledcAttachChannelを使って書きます。

3.0系(チャンネル指定版)
const int led_pin = 18;
const int freq = 5000;
const int resolution = 8;
const int channel = 2; // 明示的にチャネル2を使用

void setup() {
  ledcAttachChannel(led_pin, freq, resolution, channel);
  ledcWrite(led_pin, duty);
}

タイマー割り込み

タイマー割り込みはLチカを例にとって書いてみます。
timerBegintimerAttachInterruptは引数が変わり、timerAlarmWritetimerAlarmEnabletimerAlarmにまとめられています。

2.0系
hw_timer_t *timer = NULL;
volatile bool led_state = false;

void IRAM_ATTR on_timer() {
  led_state = !led_state;
  digitalWrite(LED_BUILTIN, led_state);
}

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

  // タイマー番号0, 分周80, カウントアップ
  // 80MHz / 80 = 1MHz のクロック
  timer = timerBegin(0, 80, true);
  // 割り込みハンドラ登録
  timerAttachInterrupt(timer, &on_timer, true);
  // 1000000カウントでアラーム(=1秒)
  timerAlarmWrite(timer, 1000000, true);
  // アラーム有効化
  timerAlarmEnable(timer);
}

void loop() {
}

スポンサーリンク

2.0系ではタイマーの分周比を書くのが特徴的でしたよね。

3.0系
hw_timer_t *timer = NULL;
volatile bool led_state = false;

void IRAM_ATTR on_timer() {
  led_state = !led_state;
  digitalWrite(LED_BUILTIN, led_state);
}

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

  // 周波数を直接指定(ここでは1MHz = 1µsごとにカウントアップ)
  timer = timerBegin(1000000);
  // 割り込み関数を登録
  timerAttachInterrupt(timer, &on_timer);
  // アラーム設定: 1000000カウントごと(=1秒)、繰り返し
  timerAlarm(timer, 1000000, true, 0);
}

void loop() {
}

ワンショットタイマーの場合は、timerAlarmの第3引数をfalse指定することで実現できます。
例:timerAlarm(timer, 1000000, true, 0);
ちなみに第4引数は無限回の繰り返しであれば 0 で、有限回数であれば数値を書いてあげます。


もう2.0系のプログラムを書くことはないのですが、どうしても以前のプログラムを置き換えるタイミングで考えなければなりません。
その度に毎回悩んでいますし、AIも時々嘘をつきますのでなかなか面倒なんです。
そんなことに頭を使っている人は私以外いないと思いますがね...

ESP32 (Arduino Core) 2.0系から3.0系への移行

スポンサーリンク

Leave a Comment