ESP-IDFを使ってみる

Arduino Libraryの利用


Arduino LibraryはC++で書かれています。
ESP-IDFもC++をサポートしていますが、使用する言語仕様がバージョンにより異なります。
- IDF v4.4.x 以下 ― C++11
- IDF v5.0.x ― C++20
- IDF v5.1.x 以上 ― C++23

ESP-IDF コンポーネントの多くは、初期化関数の引数としてConfiguration Structuresを使用します。
C で記述された ESP-IDF の例では、通常、指定された初期化子を使用して、これらの構造を読みやすく保守しやすい方法で指定します。

C 言語と C++ 言語では、指定初期化子に関するルールが異なります。
例えば、C++23 (現在 ESP-IDF のデフォルト) では、順序外指定初期化、ネストされた指定初期化、指定初期化子と通常の初期化子の混在、配列の指定初期化はサポートされていません。
従って、ESP-IDF C のコードを C++ に移植する場合、構造体初期化子に変更が必要になります。

ESP-IDFのWiFi、SPI、I2C、UARTなどのデバイスドライバーは全てコンポーネントとして提供されていて、
C 言語からの呼び出しに対応しています。
これらをC++ 言語から呼び出すことはできません。
具体的にはWiFiドライバーの初期化を行う以下のコードは、ネストされた初期化を使っているので、C++ 言語ではコンパイルすることができません。
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_ESP_WIFI_SSID,
            .password = EXAMPLE_ESP_WIFI_PASS,
            /* Authmode threshold resets to WPA2 as default if password matches WPA2 standards (pasword len => 8).
             * If you want to connect the device to deprecated WEP/WPA networks, Please set the threshold value
             * to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with length and format matching to
             * WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK standards.
             */
            .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD,
            .sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
        },
    };

Arduino環境にはSerial、i2c、SPIなどのオブジェクトがあり、このオブジェクトを使ってデバイスを操作しますが、
ESP-IDFにはこれらのオブジェクトはありません。
Serial、i2c、SPIの読み取り/書き込みはESP-IDFコンポーネントに変更する必要があります。

Arduino環境には多数のライブラリが登録されていますが、Arduino環境はC++を採用しています。
Arduino環境のライブラリをESP-IDFで使う場合、ほとんどの場合、初期化のコードをC言語に書き換える必要が有ります。
例外としてデバイスに依存しない計算ライブラリなどは、C++ 言語のまま利用することができますが、
main.cをmain.cppに変更する必要が有ります。

main.cをmain.cppに変更した場合、main.cに含まれていたWiFiなどのデバイス初期化コードはコンパイルできなくなります。
デバイス初期化コードは新たなC 言語ソースを作成し、これをmain関数から呼び出す必要が有ります。
要するにESP-IDFでC++ を使うのはとっても面倒と言う事です。

Arduino環境のC++ライブラリを、C言語に書き換える手順はざっくり書くと以下の様になります。
・クラスを廃止
・コンストラクタ、デストラクタを関数に変更
・クラス変数をstatic変数に変更
・Serial、i2c、SPIのオブジェクト操作をコンポーネント呼び出しに変更

また、Arduino環境では同じ名前の関数に、異なる引数を定義することができますが、これをすべて違う名前の関数に変更する必要が有ります。
void hoge();

//void hoge(int i);
void hoge1(int i);

//void hoge(char c);
void hoge2(char c);

//void hoge(char *buf);
void hoge3(char *buf);

続く....