ESP32-DevKitC-32Dボードの基本的な使い方 ~Arduino IDE編~

ESP32-DevKitC-32DはESP-WROOM-32Dを搭載したボードです。

USB接続するだけで使え手軽にESP32の世界を楽しめます。ESP-WROOM-32Dには1つのモジュール内にWi-FiとBluetooth LEの通信機能が含まれています。マイコンとしても優秀ですが、通信機能を有しているという点が大きな特徴です。

開発環境は大きく2つあります。1つはArduino IDEを使う方法。もう1つはESP-IDFという専用の開発環境を使用する方法です。本ページではまずこれら2つの方法でLEDを点滅させるところから初めてみます。

●注意!!●

これまでにPCにボードを接続したが「ボードが認識しない」というお問い合わせが何件がありましたが、「USBケーブルを交換したら問題なく認識し動作した」ということがほとんどでした。

USBケーブルは必ず品質のよいもの、または動作することが分かっているものをご使用ください。またコネクタはしっかりと挿してください。

とても初歩的なことですが意外にも、USBケーブルの品質やコネクタの差し込み方が悪かったことが原因のトラブルが発生しています。製品をパソコンと接続して仮想COMポートが作られないとすぐに「不良かな?」と疑ってしまいがちですが、今一度基本的な部分、初歩的なところでトラブルを起こしてないかご確認を重ねてお願いいたします。

■Arduino IDEを使う方法 ~IDEの準備~

  1. Arduino IDEを起動します。
    インストールしていない方は公式サイトのこちらからインストールします。
  2. “ファイル”→”環境設定”を開きます。
  3. 追加のボードマネージャのURL”の部分に次のURLをコピーして貼り付けます。
    https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  4. OKボタンを押します。
  5. “ツール”→”ボード”をクリックし更に右側に表示される”ボードマネージャ”をクリックします。
  6. 先ほどURLを環境設定の部分で指定しているので一覧に”esp32 by Espressif Systems”というボードが表示されますのでこれを選択します。バージョンは2.0.3を選択してください。
    インストール後、下図のように正しく2.0.3がインストールされているか確認してください。
  7. “インストール”ボタンを押します。
    これでボードに必要なファイルが自動的にダウンロードされてインストールされます。
  8. インストールが完了すると”ツール”→”ボード”の一覧に”ESP32 Dev Module”という名前が表示されますのでこれを選択します。
  9. 続いて、ESP32-DevKitC-32DとArduino IDEが通信する手段を選択します。
    ESP32-DevKitC-32Dはパソコンと接続すると仮想COMポートが作られます。
    仮想COMポートはSilicon Labs社のCP210xデバイスを使っています。

    デバイスドライバー(仮想COMポートドライバー)は自動的にインストールされる場合がほとんどですが、安定した最新版を下記のサイトからダウンロードしてインストールしておくほうがよいでしょう。
    https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers※”DOWNLOADS”タブに移動して”CP210x Universal Windows Driver”をクリックしてダウンロードしてください。zipファイルを展開すると”CP210xVCPInstaller_x??.exe” があります。??はWindowsのビット数です。64ビット版の場合にはx64を、32ビット版の場合にはx86を実行してください。

    ESP32-DevKitC-32Dをパソコンと接続したらWindowsのデバイスマネージャーの”ポート(COMとLPT)”のツリーから、”Silicon Labs CP210x USB to UART Bridge(COMx)”を探してCOMポート番号を調べます。

     

    パソコンに正しく認識されない場合には、ケーブルを疑ってください。ケーブルが悪くて認識しなかった例が報告されています。

    少なくとも次のことは必ずお試しください。

    ・別のケーブルを使ってみる

    ・別のUSBポートに挿入してみる

    ・USBハブを介している場合にはPCのポートに直接接続する

    ・別のパソコンがあれば別のパソコンで試してみる・・・

     

    ▲UARTのFIFOブッファ設定をお願いします▲

    ドライバーのデフォルト設定ではUSB-UART仮想COMポートのFIFOバッファを使用する設定になっています。これが有効の場合DTR/RTSピン制御のタイミングにずれが生じ自動書き込みができない場合があると報告がありました。(過去1件)

    次の方法でUARTのFIFOバッファを使用しない設定にして頂けますようお願い致します。

    1. Windowsのデバイスマネージャーの”ポート(COMとLPT)”のツリー表示させる。
    2. ツリーから”Silicon Labs CP210x USB to UART Bridge(COMx)”を見つけて右クリックし「プロバティ」を選択。
    3. 「ポートの設定」タブに移動して「詳細設定」をクリックする。
    4. 「FIFOバッファーを使用する」のチェックを外す。

    以上設定は必須ではありませんが過去にこれが原因で自動書き込みができないかったという報告が1件あったため念のため設定されることをおすすめ致します。

  10. “ツール”→”シリアルポート”をクリックして手順9で確認したESP32-DevKitC-32Dのポート番号を選択します。
    そのほかの設定項目が次のようになっていることを確認してください。

これで最初の設定は完了です。

 

 

■Arduino IDEを使う方法 ~プログラムを書いてみる~

 

それではプログラムを早速書いてみましょう。最も簡単なLED点滅プログラムを書いてみます。200ミリ秒間隔で指定したピンをHigh-Lowさせるだけのプログラムです。

今回はピンとして32ピンを指定しました。適宜変更してスケッチを書いてみてください。

※但し35,34は入力専用なので使えません。

では早速コンパイルをしてみましょう。ツールバー画面左上にある「レ」のボタン(検証ボタン)を押します。

ファイルを保存していない場合にはファイル保存のダイアログが表示されますので適当なディレクトリに保存してください。

コンパイルは少し時間がかかります。プログラムに誤りがなければ「コンパイルが完了しました」と表示され、その下のアウトプットウインドウに使用されたフラッシュの容量等が表示されます。

コンパイルが正常完了したことを確認して次に進みます。

 

■ハードウエアの準備

 

ESP32-WROOM-32DはGPIOがHレベルの時3.3Vです。

今回はピンの状態が視認しやすいようにLEDを取り付けます。上記例では32ピンにLEDを接続します。LEDはピンには直結できません。必ず抵抗器を通して接続します。下図は接続例です。ブレットボードなどに装着するとより簡単に配線ができます。

抵抗器は150Ω~470Ω程度の間で選択します。順方向電圧が1.8V、順方向電流が8mA程度のLEDだとすると200Ω程度の抵抗器が必要になります。

LEDは足の長い方がアノード(A)、足の短い方がカソード(K)です。通常はA側をGPIO側にK側をGNDと接続します。該当ピンがHレベルになると電流が流れてLEDが点灯します。

 

■Arduino IDEを使う方法 ~プログラムを書き込む~

ではボードに書き込んでみましょう。

ツールバー2番目の右向き「→」マークのボタンを押してみてください。

 

書き込みが始まります。IDEウインドウ下にオレンジ色の文字で進捗状況が表示されます。書き込みが完了すると「ボードへの書き込みが完了しました」と表示されます。

32ピンと接続したLEDが点滅していることを確認してください。

点滅する周期を変更したりしてプログラムを変えてみてお試しください。

 

書き込み時にエラーが表示されて失敗する場合には?書き込みの仕組みを考察する

書き込み実行時に「A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header」という表示が出て、書き込みに失敗する場合が数件報告されています。(トータル3件ですが)

ESP32はリセット時から復帰する時GPIO0の状態を判定してプログラムの書き込みモードに入るかどうかを判定しています。GPIO0は内部でプルアップされておりこれをLowにした状態でリセットを解除(EN→High)にすることでプログラムの書き込みモードになります。このENとGPIO0の時間差が重要です。リセット解除の後、にある時間が経過(~数十ミリ秒)した後、GPIO0の状態を読んでGPIO0がLowならば書き込みモードに入るという仕組みです。

このENピン(Resetピン)とBOOTピン(GPIO0)の論理操作をUSB経由で自動的に行うためにUARTのDTR/RTSピンを利用します。ここで重要なのはフロー制御時にはRTS=1の時はDTR=1になっていることです。この仕組みを利用することでフロー制御利用時に意図せずリセットされることがないようにします。この仕組みを利用しトランジスターで次のような論理を作ります。

DTR RTS -> EN GPIO0
1 1 1 1
0 0 1 1
1 0 0 1
0 1 1 0

Arduino IDEはプログラムの書き込み実行時にDTRピンとRTSピンを時間差で1/0と制御することで手動でBOOTボタンを押したのと同じようにH/Lが動作するわけです。ほとんどは問題なく動作します。

しかし問題が生じる場合、すなわち自動的に書き込みが実行されずArduino IDEがリトライを繰り返す場合にはこの制御のタイミングがうまくいっていないことが原因です。USB経由の場合UARTの制御線の制御が高速にできないという問題があります。単なるピンのH/Lの遷移だけですがUSB-UART変換ICを介してDTR/RTSを制御すると時間がかかりタイミングがうまくとれないケースがあるようです。DTS=0, RTS=0の時間はEN=1, GPIO0=1となりうまく動作しないことがあるようです。またリセット後ESP32が安定して動作を開始するまで(クロックが安定するまで)~数十ミリ秒程度かかります。このESP32の安定してGPIO0の状態を判定するまでの時間も関係があります。リセット後ESP32が安定して動作するまで時間がかかり、その間にGPIO0がHになってしまった場合などが考えられます。

この問題を解決するためによくENピンとGND間の0.1uF~0.2uF(0.1uF×2個の並列)を取り付けることでENピンの立ち上がり時間を遅らせる方法が紹介されています。

本ボードではほとんどの場合で必要ありませんがどうしても動作しない場合には次の方法をお試しください。

1. UART仮想COMポートのデバイスドライバーにある「FIFOバッファーを使用する」のチェックを外す。
→本ページ上部にピンク色の枠で囲ってある部分に設定方法が記載されています。

2. ENピンとGND間に0.1uF~1uF程度のコンデンサーを追加する

3. ESP32のリセット後の安定動作が遅れていることを考え電源の強化をする。具体的には+5V-GND間に10uF~220uF程度の電解コンデンサーを追加する ※下記に詳述

4. USB-UART変換ICのデバイスドライバーを最新版にする

5. 手動でリセットする

4番の手動リセットの場合には、”BOOT”ボタンを押すことで解決します。書き込み実行する時に転送が開始されたら本体にある”BOOT”ボタンを押し続けます。最後まで押し続けなくても、オレンジ色の進捗状況の表示が出たら離してもOKです。スイッチの押すタイミングがありますので、何回か試行してタイミングをつかんでください。

書き込み実行時に「A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header」と表示されるのは本体の故障ではありません。

 

※電源ラインのノイズはUSBバスパワー給電をしている場合避けられません。USBポートから取り出せる+5Vはとても品質が悪くリプルが重畳している場合がほとんどです。電圧も+5Vぴったりではなく+4.8V程度と低かったり、オシロスコープでよく観察するとリプルが乗っています。こういった品質がよくない電源を使っている関係でESP32の動作に影響がでる可能性があります。リセット後にクロックが安定して、ESP32が動作を開始する時間に品質のよくない電源が影響を与えている可能性があり、それが原因で書き込みモードに移行できないという原因も考えられます。

またWi-Fi接続時にESP32の消費電流が上昇すると、電圧降下が発生して電圧が一時的に下がってWi-Fi接続の安定性に問題が生じる場合があります。その場合、電源ラインに100uF~220uF程度の電解コンデンサーを追加すると電流の増加があっても電圧が低下しないで安定する場合があります。

 

教えて!Goolge先生!!

開発を行ってると様々な問題に直面します。ソフトウエアを作る時やコンパイルした時、書き込みを実行した時、そしてプログラムを動かした時・・・そんな時はぜひGoogleで検索しましょう。

特に「エラーメッセージ」や「エラーコード」が表示される場合にはその内容全文をGoogleで検索してみてください。ESP32シリーズは世界中のユーザーが使用しており、貴方が今経験している問題は”たぶん”過去に多くの先人が経験しているものだと思います。
先人達はブログなどで解決策や原因を記載していることがほとんどです。ほとんどの問題はGoogleで検索すれば解決策が見つかります。
きっと、今貴方が困っていることは過去に誰かが困っていたことだと思われます。そしてそういった情報はほとんどの場合においてGoogleで調べれば関連ページがヒットします。

「おかしい!」「壊れてるんじゃないか!?」「不良品??」そう思う前に検索してみてください。きっと解決策が見つかるはずです。

 

 

■アナログ出力を使ってPWM制御してみる

上の例では32ピンをデジタルピンとして設定としてLEDをON/OFFにしてみました。デジタル設定の場合出力はHighかLowのいずれかです。つまり点灯か消灯です。

しかし、ピンをアナログ出力ピンとして設定するとPWM出力が可能となります。PWMとはPulse Width Modulationの略で日本語ではパルス幅変調といいます。パルス波のデューティー比を変化させる変調方式です。デューティー比とは簡単に言えば、パルス波を出した時の「Highの期間」と「Lowの期間」の割合ことです。例えばHigh期間とLow期間が同じ時間であればデューティー比50%といいます。

 

※出展 https://en.wikipedia.org/

LEDを接続している場合デューティー比を変えると、それはLEDの明るさの変化として現れます。デューティー比が大きい、すなわちHighの期間が長ければLEDは明るく点灯しますし、デューティー比が小さければLEDは暗くなります。

ESP32ではすべてのピンではありませんが多くのピンでアナログ出力ピンとして設定できます。32ピンも設定できますのでここではそれを利用します。なおGPIO32ピンはアナログピン番号は”A4″ですので注意してください。

それではLEDの明るさをソフトに明るして、ソフトに暗くするプログラムを作ってみましょう。

ESP32でPWMを使う場合にはledcWrite()関数を使います。

※Arduinoで使える analogWrite() 関数はESP32では利用できません。

 

ledcSetup(uint8_t chan, double freq, uint8_t bit_num);

chan 利用するチャネル。0~15を指定
freq 基本となるPWMの周波数 ここでは10KHzを指定
bit_num デューティ比を表す分解能のビット数 ここでは8ビットなので256段階

 

brightness変数は明るさを示します。0は消灯です。この値を増減させます。

diff = 1 は変化する率です。1ずつ増減させて0~255の範囲で増減させます。ここの値を大きくするとLEDの明滅の早さが変わります。

ledcWrite(uint8_t chan, uint32_t duty);

chan 利用するチャネル。0~15を指定
duty デューティ比を指定、ここでは8ビットなので指定できる値は0~255

 

5ミリ秒の遅延を入れてwhile文でループすることで明滅を繰り返し実行しています。

変数diffの値を変えて明滅速度が変わることを確認してみてください。

下図はオシロスコープで波形を観察したものです。10KHzの波形のデューティー比が繰り返し変わっていることが確認できます。

 

 

 

 

■ピンの状態を取得してみる

 

ここまでの例ではピンを出力に設定してLEDのON/OFFを試しました。続いてGPIOを入力設定にしてその状態に応じて処理を分岐するプログラムを作ってみましょう。

入力と聞くと「スイッチを付けなくては」と思いますが、幸いなことにこのESP32-DevKitC-32Dには2つのスイッチが付いています。1つはENピンと接続されていてプログラムでは使えませんが”BOOT”と書かれたスイッチはGPIO0と接続されており実験に利用できます。

GPIO0を入力ピンとして使ってみましょう。入力ピンの場合にはスイッチを押していない時にピンの論理状態をHighにするか、Lowにするかをプルアップ又はプルダウンによって決めなければいけません。ESP32では指定したピンを入力ピンに設定するとともにそのピンを内部プルアップする機能があります。これを使えば外部にプルアップ用抵抗器を接続する必要がなく利用できます。但し、プルダウンの設定はできませんのでご注意ください。

次のプログラムはGPIO0のスイッチを押した時にLEDが点灯、離すと消灯するプログラムです。

 

適当にファイル名を付けて保存してコンパイルして書き込んでみてください。

内容はとても簡単です。pinMode()では入力ピンとする時にだけINPUT_PULLUPを引数として指定すると内部プルアップが有効になります。

ピンの状態はdigitalRead()関数で読み込みます。戻り値はint型変数に代入します。その値をif文で判定します。スイッチを押していない時はプルアップによりGPIO0はHighレベルなのでLEDは消灯に、押した時はLowなのでLEDを点灯させます。

 

 

■WEBサーバー機能でブラウザからLEDを制御をする

 

次に同じ回路でスケッチを変更しWEBサーハー機能を試してみましょう。ESP32はWi-Fi通信機能が付いていますのでそのままWi-Fiに接続できます。またTCP/IPなどネットワーク接続に必要なプロトコルスタックを内蔵しているので簡単にネットワーク通信ができます。

WEBサーバー機能を使うことでブラウザから本機にアクセスしてLEDを消灯させたり点灯させたり、点滅させたり制御ができます。

1からプログラムを書くのはちょっとしんどい・・そんな時はArduino IDEでしスケッチ例がたくさん利用できます。ここではWi-Fiサーバーのスケッチ例を使い、その内容を少し変更させてWEBサーバー機能を試してみましょう。

①Arduino IDEの”ファイル”→”スケッチ例”をクリックします。

②”ESP32 Dev Module用のスケッチ例”という部分があるのでその中にある”WiFi”→”SimpleWebServer”をクリックします。

③WiFiサーバーのサンプルスケッチが読み込まれます。実はほとんどの内容はこれで完成しています。ここでは下記のように少しプログラムを改造してみましょう。

まず下記のSSIDとパスワードを定数に代入する部分にはご自分のWi-Fi環境のSSIDとパスワードをセットしてください。これが間違っているとそもそもWi-Fiに接続できないのですべて失敗してしまいます。
では次のようにスケッチを変更してみましょう。

 

内容としては最初のhtml配列のところで、HTMLデータを代入しています。注意すべき点は行替えのところには”\”(もしくはバックスラッシュ)を入れることです。Arduino IDEのフォント設定が英語フォントの場合には\はバックスラッシュとして表示されます。

また”(ダブルクォーテーション)は、\” として書くことも注意してください。間違えるとブラウザでアクセスした時正しいページが表示されません。特にタグの部分の文字列に注意してください。

この部分以外はほぼそのままですが、LEDが接続されたGPIOのピン番号を32ピンに変更しています。

またデフォルトのスケッチ例だと点灯と消灯しかありませんので、この例では点滅する部分を追加しています。またブラウザで表示した時デフォルトの場合には点灯と消灯のリンク表示ですが、この例ではボタンを表示させて点滅機能を割り当てています。

★LED点灯/消灯/点滅の仕組み★

LED点灯時は http://yourAddress/H

LED消灯時は http://yourAddress/L

LED点滅時は http://yourAddress/?blink

へ飛ぶように作られています。いずれもHTTPのGETメソッドを使っています。一番簡単な方法なのでGETメソッドを使っていますが、改造すればもちろんPOSTメソッドでも作れます。

もう1つポイントとしては、ボタンです。ボタンはtype属性をsubmitとしています。その前にaction属性を使ってボタンが押された時、ページのトップに移動するようにしています。そうしないと、例えば  http://192.168.0.100/H の状態でボタンを押すと http://192.168.0.100/H/?blink となってしまい正しく判定ができなくなってしまうためです。

 


さてここまで書けたらコンパイルして実際のボードを書き込んでみましょう。

ボードに書き込む前にシリアルターミナルを表示させておきます。そうすることでモジュールが正しくWi-Fiに接続できたか、またDHCPで割り当てられたIPアドレスがいくつなのかを知ることができます。

Arduino IDEの”ツール”→”シリアルモニタ”をクリックしてシリアルモニターを表示させておきましょう。

スケッチに間違いがなければコンパイル後、書き込みが実行されます。もしエラーが表示された場合には間違いがないかよく確認してください。

 


プログラムが動作すると動作ログがシリアルモニターに表示されます。

下図のように接続されたSSIDと本機に割り当てらたれIPアドレスが表示されますのでこれを控えておきます。

もし接続できない場合にはSSIDやパスワードが間違っている可能性があります。

では早速このIPアドレスにブラウザから接続してみましょう。ブラウザを起動してアドレス欄にIPアドレスを入力してエンターキーを押します。

上図のように表示されればOKです。

「ここ」の部分をクリックしてその通りにLEDが点灯したり消灯したりするか確認してください。

続いて「点滅開始」をクリックするとLEDが点滅すること確認してください。なおこのプログラムでは割込を使わずに点滅するサブルーチンをloop関数の中で定期的に呼び出して点滅させています。loop関数内ではWi-Fiの処理も行っておりWi-Fiの処理の方に時間がかかると点滅が止まる場合があります。このプログラムはデモなのでその点はあまり気にしていませんが、より実用的なプログラムを書く場合には割込を使うなど工夫が必要になります。

※割込例はスケッチ例内にある”Ticker”→”Blinker”などが参考になります。

 

 

■スイッチを押すとLINEに通知する

 

もう少し複雑なプログラムにも挑戦してみましょう。

皆様お使いになっていると思うメッセージングサービスのLINEに通知を送る内容です。ESP32-DevKitC-32DのGPIO0のスイッチが押されると、LINEで”スイッチが押されました”と通知されるプログラムを作ってみましょう。

LINEに通知をするにはいくつかの方法があります。今回は “LINE Notify“というサービスを使ってみます。あらかじめ登録しておいたグループに対して通知を送れます。その他にはIFTTTというサービスを使った方法もあります。

まずは”LINE Notify“を友達に追加します。”LINE Notify“のページに飛ぶとトップページにQRコードが表示されますのでスマホのLINEアプリでこのQRコードをスキャンして友達を追加してください。


最初に「アクセストークン」と呼ばれる文字列を取得します。このトークンを使うことでESP32プログラム内からLINEに対して通知が送れるようになります。

  1. LINE Notify“にアクセスしてログインしてください。
  2. 右上のアカウント名のところをクリックするとメニューが表示されますので「マイページ」を選択します。
  3. 「アクセストークンの発行」のところにある「トークンを発行する」ボタンを押します。
  4. トークン名は通知される時に表示されますので、ここでは適当に「ESP32スイッチ」とかにしておきます。
    続いて「通知を受信するトークルームを選択してください」のところではグループを選択しますが、自分だけが受信する場合には「1:1でLINE Notifyから通知を受け取る」にチェックを入れて発行するを押してください。

  5. トークンが発行されます。
    このトークンはとても大切ですので必ず控えておいてください。
    赤文字で表示されたトークンを続いて作るプログラムの中で使用します。

 

では早速プログラムを書いてみましょう。今回はGPIO0を内部プルアップされた入力ピンとして使用し、スイッチが押されると(GP0がLowになると)LINEに通知が飛ぶようにします。

Wi-Fiへの接続部分などは先の例と同じですので解説は省略します。

 

プログラム中の your ssid と your password には実際にご利用のWi-Fi環境のパラメーターを記述してください。

もう一カ所修正する部分は “const char* token = “your LINE Notify token”;“ の部分です。your LINE Notify token の部分には先ほどの手順で発行したLINE Notifyのトークンをそのままコピーしてください。

修正部分は上記の箇所のみです。

今回はシリアルターミナルでログを見たいのでArduino IDEの”ツール”→”シリアルモニタ”を選択してモニターを表示させておいてください。では早速コンパイルして書き込んでみてください。

書き込みが成功するとシリアルモニターにWi-Fiへの接続状況が表示されます。接続が正しく完了すると本機に割り当てられたIPアドレスが表示されます。

続いて本体の”BOOT”ボタン(GPIO0ボタン)を1回押してください。LINE APIのサーバーに接続を試みます。成功すれば下記のようにログに表示されます。

Connecting to LINE API Server..
Connected!

続いて処理が行われます。処理中はLEDが点灯しています。処理が5秒から10秒程度で完了しLINE Notifyに通知が送られてきます。スマホ等で確認してみましょう。

どうでしょうか?正しく通知は送られてきましたか?

この仕組みを使えばいろいろと応用ができそうです。もちろんGPIOを増やして使うこともできますし、変化のあったGPIO毎にメッセージ内容も変えられるのでいろいろと楽しめそうです。