無線を使用できるESP32-WROOMを使います。
Arduino環境で技適付きESP32-WROOM NodeMCUを使って環境の準備、基本的な入出力と通信、無線を使います。
記事の内容と目的
この記事ではESP32-WROOM NODE-MCU ESP-32SをArduino環境で使用するための準備とサンプルスケッチを記載します。
記事の内容は
・主なスペックと基板でできること
・Arduino環境での準備とトラブル
・I/Oとマイコン通信をするためのサンプルスケッチ
・無線を使った通信と、HIDのサンプルスケッチ
Arduino 環境の作成方法はこちら
ESP32-WROOM NODE MCU
NODE MCU ESP-32S
高性能MCUで多くのI/Oピンを使用できる。
WifiとBT(Bluetooth)による無線通信のほか、BTによるHIDデバイスの開発ができる。
アナログ出力(DAC)、静電容量タッチセンサー搭載。
接続 | Micro B |
CPU | ESP32-WROOM-32 Xtensa 32bit LX6 240MHz |
フラッシュMemory | 4MB |
ADC | 16(12bit 0 ~ 4095) |
ADC | 2 |
GPIO | 22(Input/Output) 4(Inputのみ) 6(使用不可) |
PWM | 22 (8bit 0 ~ 255)同時に16本まで使用可能 |
DAC | 2 (8bit 0 ~ 255) 0 ~ 3.3V |
UART | 3 |
I2C | 2 |
SPI | 2 |
ピン配置
![](https://tamanegi-digick.com/wp-content/uploads/2024/05/esp32wm-pin-1024x399.jpg)
外観
![](https://tamanegi-digick.com/wp-content/uploads/2024/06/DEVKIT-top-1024x538.jpg)
![](https://tamanegi-digick.com/wp-content/uploads/2024/06/DEVKIT-back-1024x538.jpg)
400穴ブレッドボードでは、左右1列使用できます。
![](https://tamanegi-digick.com/wp-content/uploads/2024/06/NODEMCUESP32-Breadboard.jpg)
使ってみて
Good
入手性、コスパ、性能面で高いパフォーマンスを発揮します。
安価に無線を使用できる。
多くのモジュールライブラリが対応している。
Bad
GPIO0を使用した書き込みモードを使用しない場合は、書き込みの失敗が多い。
使用できないピン、読み取り専用のピンなどの制約があり、見た目ほどのピンが使用できない。
無線使用時に十分な電力供給がないと起動できない。
技適なし、ニセ技適も多く出回っている。
そのほか
マイコンで手軽に無線を使えることがこの基板の魅力です。
このマイコン以外にも無線を使用できるマイコンが増えてきましたが、ライブラリの設計上特に扱いやすさを感じます。
電波を出すためには技適マークが必要です。
同じESP32-WROOMでも技適マークのついていないものやニセ技適マークも出回っているので、購入前に確認が必要です。
無線以外にもDACのアナログ出力を使えたり、静電容量タッチ入力ができるなど機能は豊富です。
Arduino環境で使用できるマイコン基板では古くなってきましたが、いまだトップクラスの性能です。
準備
ライブラリのインストール
ArduinoIDEでESP32-WROOMを開発するために、ESP32ボードライブラリをインストールします。
この作業を実行するために、あらかじめArduinoIDEがインストールされている必要があります。
ArduinoIDEのインストールとライブラリのインストール方法はこちら。
ボードライブラリ
Arduino IDEのボードマネージャからESP32用のライブラリのインストールとボードの選択をします。
ボードマネージャのURL | https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json |
検索 | ESP |
ボードライブラリ | esp32 by Espressif Systems バージョン x.x.x※ |
選択するボード | esp32 > ESP32 Dev Module |
その他のライブラリ
BLEマウス、BLEキーボードを使用する場合、以下のライブラリを利用しています。
スケッチの書き込み方
スケッチの書き込み方法を4通り紹介します。
方法1:IO0ボタンを押しながら電源を投入し、USBコネクタから書き込む
方法2:GPIO0とGNDをショートさせ、USBコネクタから書き込む
方法3:コンデンサを取り付け、USBコネクタから書き込む
方法4:GPIO0とGNDをショートさせ、USB-UARTを使って書き込む
方法1:IO0ボタンを押しながら電源を投入し、USBコネクタから書き込む
IO0ボタンが実装されているESP32-WROOM基板で使用できます。
ArduinoIDEの書き込みボタンを押して書き込みを開始します。
“Connecting…”メッセージが表示されたらIO0ボタン(画像左側の赤丸)を押し続け、書き込みが始まったらボタンを離します。
“Leaving…”
“Hard resetting via RTS pin…”メッセージが表示されて再起動しない場合はENボタンを押すか、電源の入れなおしをして再起動します。
![](https://tamanegi-digick.com/wp-content/uploads/2024/05/esp32wm-uploading-1024x331.png)
方法2 : GPIO0とGNDをショートさせ、USBコネクタから書き込む
IO0ボタンのない基板からESP32-WROOMを書き込み状態にする方法です。
GPIO0とGNDをショートさせた状態で電源の投入、または赤丸ENボタンを押して再起動します。
ArduinoIDEの書き込みボタンを押して書き込みを開始します。
書き込み後はショートを解除させて再起動します。
![](https://tamanegi-digick.com/wp-content/uploads/2024/05/esp32wm-dlmode.png)
方法3:コンデンサを取り付け、USBコネクタから書き込む
コンデンサを使ってショートさせることで、スケッチの書き込み方法①の作業をしなくても書き込むことができます。
理屈が説明できないので紹介だけになります。
ENとGNDを100uF~300uFのコンデンサでショートさせます。
これでも書き込みに失敗する場合はスケッチの書き込み方法①で行います。
![](https://tamanegi-digick.com/wp-content/uploads/2024/06/NODEMCUESP32-condenser.jpg)
方法4 : コンデンサを取り付け、USBコネクタから書き込む
ESP32-WROOMのUARTから直接書き込みます。
下配線図のように、USB-UART変換アダプタ(FT232RL)を使用して配線します。
ESP32-WROOM基板のUSBコネクタから電源を供給する場合VCCとGNDの配線は不要です。
USB-UART変換アダプタから電源を供給する場合、VCCとGNDを配線します。
方法1または、方法2により書き込み状態で起動します。
ArduinoIDEの書き込みを行うPortは、USB-UART変換アダプタを選択します。
ArduinoIDEの書き込みボタンを押して書き込みを開始します。
![](https://tamanegi-digick.com/wp-content/uploads/2024/05/esp32wm-dl-g0uart.png)
BTペアリング
BT通信をする場合こちらの作業が必要になります。
ノートPC、スマートフォン、タブレットまた、BTレシーバを準備してください。
ペアリングの方法については一般のBT製品と同じですので詳細は省略します。
個々のマニュアルを参照してください。
今回当方の確認方法としてAndroidスマートフォンでのペアリングを掲載します。
1.スケッチを書き込み、マイコンボードを起動させます。
※GPIO0とGNDをショートさせている場合は、ショートを解除してから再起動します。
2.BT設定画面から周囲のBT機器を検索します。
今回のサンプルでは [NODE MCU ESP32]という名前で見つかります。
![](https://tamanegi-digick.com/wp-content/uploads/2024/06/NODEMCUESP32-pairing-1024x500.png)
3.シリアル通信をする場合、シリアル通信用のアプリケーションをインストールします。
参考として当方が利用している「Serial Bluetooth Terminal」を紹介します。
![](https://tamanegi-digick.com/wp-content/uploads/2024/06/NODEMCUESP32-BTserial-1024x488.png)
トラブル
ESP32-WROOMを使って発生したトラブルを記載します。
■起動しない1
電源を入れてもESP32-WROOMが起動しない。
下図は症状を確認するためにUART0(Serial)をモニタした。
起動時のメッセージを繰り返し出力している様子。
![](https://tamanegi-digick.com/wp-content/uploads/2024/05/esp32wm-trouble-uart1-1024x264.png)
この症状が発生した時の原因を列挙します。
・電圧不足
基板への電力供給が少ないときに発生します。
無線使用時に発生しやすく、電源の供給がUSBケーブルの場合供給力の低電源(AC無しのUSBHUBなど)を使うと発生します。
・UART1をデフォルトピンのまま使用する
UART1のデフォルトピンは使用できないピンが設定されていて、ピン変更をしないまま使用すると発生します。
UART1を使用する場合はTX, RXピンを変更して使用します。
変更方法はUART通信に記載します。
基本スケッチ
ボタンLED
説明
ボタンの状態が押下状態(High)ならLEDを点灯、離した状態(Low)ならLEDを消灯させます。
GPIO13は出力設定、GPIO23は入力(PULLDOWN)設定です。
GPIO34~39は回路上でPULLDOWNしないと謎の周期信号が入ってきました。
配線
![](https://tamanegi-digick.com/wp-content/uploads/2024/05/esp32wm-buttonled-wiring.png)
スケッチ
#define LED 13 //LED
#define BUTTON 23 //タクトスイッチ
void setup()
{
pinMode(LED, OUTPUT); //ピン出力設定
pinMode(BUTTON, INPUT_PULLDOWN); //プルダウンで入力
}
void loop()
{
int iStat = digitalRead(BUTTON);
digitalWrite(LED, iStat); //ボタンの状態をLEDに出力
}
結果
ボタンを押下するとLEDが点灯しました。
ボタンを離すとLEDが消灯しました。
DAC、PWM
説明
PWMでのアナログ出力と、DACでのアナログ出力を使ってLEDのゆっくり点灯、ゆっくり消灯をします。
GPIO25はDAC出力、GPIO33はPWM出力します。
LEDの点灯状態の確認と、それぞれの信号をオシロスコープでモニタします。
配線
![](https://tamanegi-digick.com/wp-content/uploads/2024/05/esp32wm-dacpwm-wiring.png)
サンプルスケッチ
#define LED_DAC (25) //DAC出力ピン ESP32-WROOMはGPIO25,26でDAC出力ができる。
#define LED_PWM (33) //PWM出力ピン
void setup()
{
pinMode(LED_DAC, OUTPUT);
pinMode(LED_PWM, OUTPUT);
}
void loop()
{
int i;
//出力諧調 0 - 255
for (i = 0; i < 256; i ++)
{
dacWrite(LED_DAC, i); //DAC出力関数(DACピンでも、analogWriteを使うとPWM制御になります)
analogWrite(LED_PWM, i); //PWM出力関数
delay(5);
}
for (i = 0; i < 256; i ++)
{
dacWrite(LED_DAC, 255 - i); //DAC出力関数
analogWrite(LED_PWM, 255 - i); //PWM出力関数
delay(5);
}
}
結果
黄LEDはDAC制御(LED左側)、青LEDはPWM制御(LED右側)です。
どちらもゆっくりの点灯と消灯ですが、黄LEDは明るさの変化が速く、消灯している時間が長い。
青LEDは明るさの変化が緩やかで、消灯している時間が短い。
オシロスコープで信号を確認します。
黄の線は黄LED(DAC)の信号、青の線は青LED(PWM)の信号です。
どちらも2V/Divで、青は-1Divオフセットしています。(線が重複しないようにずらしている)
黄(DAC)は電圧そのものが変化し、青は0と3.3Vの矩形信号の幅が変化していることがわかります。
黄LEDの消灯時間は電圧不足で発光していない様子がわかります。
UART通信
UARTで使えるピン
ESP32-WROOMではUARTをUART0とUART1の2系統使用できます。
NODE-MCUでは下図のようにデフォルトで使用できるピンはGPIO1, 3のUART0と、GPIO17, 16のUART1で、灰色の塗りつぶし以外は任意のピンに設定できます。
USBシリアルからの入力は GPIO1にTX, GPIO3にRXを設定したUARTと同じ信号の入出力があります。
![](https://tamanegi-digick.com/wp-content/uploads/2024/05/esp32wm-uartpin.png)
UARTを使用するためのオブジェクト名とピン表の関係です。
表記 | オブジェクト名 |
---|---|
UART0 | Serial |
UART1 | Serial1 |
UART2 | Serial2 |
UART1のデフォルトTX, RXピンは使用できないピンに設定されています。
UART1を使用する場合はピン設定を変更する必要があります。
UARTピン設定例
//UART0にGPIO4(TX), GPIO0(RX)を設定し通信を開始します。
Serial.begin(115200, SERIAL_8N1, 0, 4);
//UART1にGPIO2(TX), GPIO15(RX)を設定し通信を開始します。
Serial1.begin(115200,SERIAL_8N1, 15, 2);
//UART2にGPIO8(TX), GPIO5(RX)を設定し通信を開始します。
Serial2.begin(115200,SERIAL_8N1, 5, 8);
サンプル説明
UART0とUART2を使ってパソコンと通信します。
UART0側に入力した文字をUART1側に送信します。
UART2側に入力した文字をUART0側に送信します。
マクロ定義ではUART0(Serialオブジェクト)に使用するピンをTXはGPIO1、RXはGPIO3、UART2(Serial2オブジェクト)に使用するピンをTXはGPIO17、RXはGPIO16を使用します。
配線
![](https://tamanegi-digick.com/wp-content/uploads/2024/05/esp32wm-uart-wiring.jpg)
スケッチ
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 //解像度 128 x 64 で使用します。
#define SCREEN_HEIGHT 64 //SCREEN_HEIGHTは 32 に設定することができます。
#define OLED_RESET -1 //使用しないので -1を設定する。
#define SCREEN_ADDRESS 0x3C //I2Cアドレスは 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//表示制御にはAdafruit製 SSD1306を使用する。
void setup()
{
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
for(;;);
}
display.clearDisplay(); //何か表示されている場合に備えて表示クリア
display.setTextSize(2); //フォントサイズは2(番目に小さい)
display.setTextColor(SSD1306_WHITE); //色指定はできないが必要
display.setCursor(20, 5); //テキストの表示開始位置
display.print(F("TAMANEGI")); //表示文字列
display.setCursor(25, 25);
display.print(F("NODEMCU"));
display.setCursor(25, 45);
display.print(F("ESP-32S"));
display.display(); //バッファ転送(表示)
}
void loop()
{
}
結果
Teratermを2つ起動します。
UART0はCOM8、UART2はCOM10で認識されました。
COM8側から”uart0″と入力すると、COM10側に”uart0″と表示されました。
COM10側から”UART2″と入力すると、COM8側に”UART2″と表示されました。
COMの認識される番号は環境により変わるので、Deviceマネージャなどで確認します。
![](https://tamanegi-digick.com/wp-content/uploads/2024/05/esp32wm-uart-result.jpg)
I2C
I2Cで使えるピン
ESP32-WROOMではI2Cをの2系統使用できます。
NODE-MCUのI2CはデフォルトでGPIO21にSDA, GPIO22にSCLが設定されています。
使用するピンはスケッチで任意のピンに変更できます。
(使用できないピンを除きます。)
UARTを使用するためのオブジェクト名とピン表の関係です。
表記 | オブジェクト名 |
---|---|
I2C | Wire |
I2C1 | Wire1 |
I2Cピン設定例
//I2CにGPIO0(SDA), GPIO4(SCL)を設定し通信を開始します。
Wire.begin(0, 4);
//I2C1にGPIO15(SDA), GPIO2(SCL)を設定し通信を開始します。
Wire1.begin(15, 2);
サンプルの説明
I2Cを使ってSSD1306(OLED 0.96inch)モニタのサンプルを動作させます。
そのほか描画サンプルは
Adafruitサンプルスケッチを参考にしてください。
ファイル(F) > スケッチ例 > Adafruit SSD1306 > ssd1306_128x64_i2c
配線
![](https://tamanegi-digick.com/wp-content/uploads/2024/03/esp32wm-ssd1306-wiring.png)
スケッチ
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 //解像度 128 x 64 で使用します。
#define SCREEN_HEIGHT 64 //SCREEN_HEIGHTは 32 に設定することができます。
#define OLED_RESET -1 //使用しないので -1を設定する。
#define SCREEN_ADDRESS 0x3C //I2Cアドレスは 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//表示制御にはAdafruit製 SSD1306を使用する。
void setup()
{
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
for(;;);
}
display.clearDisplay(); //何か表示されている場合に備えて表示クリア
display.setTextSize(2); //フォントサイズは2(番目に小さい)
display.setTextColor(SSD1306_WHITE); //色指定はできないが必要
display.setCursor(20, 5); //テキストの表示開始位置
display.print(F("TAMANEGI")); //表示文字列
display.setCursor(25, 25);
display.print(F("NODEMCU"));
display.setCursor(25, 45);
display.print(F("ESP-32S"));
display.display(); //バッファ転送(表示)
}
void loop()
{
}
結果
SSD1306に表示ができました。
![](https://tamanegi-digick.com/wp-content/uploads/2024/05/NODEMCUESP32S-I2C-SSD1306.jpg)
SPI(ST7735)
サンプルの説明
SPIを使ってST7735(LCD 1.8inch)モニタのサンプルを動作させます。
そのほか描画サンプルは
Adafruitサンプルスケッチを参考にしてください。
ファイル(F) > スケッチ例 > Adafruit ST7735 and ST7789 Library > graphicstest
NODEMCU ESP-32SではVSPIとHSPIの2系統が使用できます。
どちらのピンア配置もサンプルに掲載されているので用途に応じてコメントを解除してください。
下記サンプルではVSPIで動作します。
配線
VSPIを使用する場合の配線
![](https://tamanegi-digick.com/wp-content/uploads/2024/06/esp32wm-VSPI-ST7735-wiring.png)
HSPIを使用する場合の配線
![](https://tamanegi-digick.com/wp-content/uploads/2024/06/esp32wm-HSPI-ST7735-wiring-1.png)
スケッチ
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
//HSPIを使用する場合、この#defineをコメントアウトする。
#define SPI_VSPI
//ピン番号設定
//VSPIを使用する場合
#ifdef SPI_VSPI
#define TFT_CS 5 // CS
#define TFT_RST 27 // Reset
#define TFT_DC 26 // DC
#define TFT_MOSI 23 // MOSI
#define TFT_SCK 18 // Clock
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
#else
//HSPIを使用する場合
#define TFT_CS 15 // CS
#define TFT_RST 27 // Reset
#define TFT_DC 26 // DC
#define TFT_MOSI 13 // MOSI
#define TFT_SCK 14 // Clock
SPIClass hspi(HSPI);
Adafruit_ST7735 tft = Adafruit_ST7735(&hspi, TFT_CS, TFT_DC, TFT_RST);
#endif
//S/W SPIはこちら。遅いが任意のピンを使用できる。
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCK, TFT_RST);
void setup(void)
{
tft.initR(INITR_BLACKTAB); //Init ST7735S初期化
tft.fillScreen(ST77XX_BLACK); //背景の塗りつぶし
//テキスト表示
tft.setRotation(3); //画面回転
tft.setTextSize(3); //サイズ
tft.setCursor(0, 20); //カーソル位置
tft.setTextColor(ST77XX_RED); //赤
tft.printf("TAMANEGI\n");
tft.setTextColor(ST77XX_GREEN); //緑
tft.printf("TAMANEGI\n");
tft.setTextColor(ST77XX_BLUE); //青
tft.printf("TAMANEGI\n");
tft.setTextColor(ST77XX_YELLOW); //黄
tft.printf("TAMANEGI\n");
}
void loop()
{
}
結果
ST7735のサンプルスケッチが動作しました。
![](https://tamanegi-digick.com/wp-content/uploads/2024/06/esp32wm-SPI-ST7735.jpg)
特別な機能スケッチ
BLE-HID(マウス)
スケッチの説明
BLEマウスとしての動作をします。
マウスカーソルを時計回りに矩形の動作をします。
※このスケッチを書いたESPを起動するたびにマウスカーソルがコントロールされてしまいます。
作業に困る場合は、GPIO0とGNDをショートさせた状態で書き込み起動し、空のスケッチを書き込んでください。
サンプルスケッチ
#include <BleMouse.h>
#define WAIT 10 //カーソルの動作周期(ms)
BleMouse bleMouse; //BLEでマウス動作させるオブジェクト
void setup()
{
bleMouse.begin();
}
void loop()
{
int i = 0;
if(bleMouse.isConnected() == true)
{
for (i = 0; i < 200; i ++) //右へ200カウント
{
bleMouse.move(1, 0, 0);
delay(WAIT);
}
for (i = 0; i < 200; i ++) //下へ200カウント
{
bleMouse.move(0, 1, 0);
delay(WAIT);
}
for (i = 0; i < 200; i ++) //左へ200カウント
{
bleMouse.move(-1, 0, 0);
delay(WAIT);
}
for (i = 0; i < 200; i ++) //上へ200カウント
{
bleMouse.move(0, -1, 0);
delay(WAIT);
}
}
}
結果
マウスカーソルが移動しています。
スマホにBLEマウスをペアリングさせると撮影ができなくなるのでパソコンの画面をスマホで撮影しています。
ジョイスティックを使った入力装置を作ったり、プログラムのGUI動作確認の自動ロボットテストに利用できそうです。
BT(MACアドレスの読み取り)
スケッチの説明
BT機器には固有のMACアドレスが割り当てられています。
MACアドレスは通信相手のBT機器を特定するために使用されます。
本スケッチでは、自分のMACアドレスを読み出します。
サンプルスケッチ
void setup()
{
Serial.begin(115200); //シリアル出力用
uint8_t MACAddress[6]; //MACアドレス保存バッファ
esp_read_mac(MACAddress, ESP_MAC_BT); //MACアドレス読み取り
Serial.printf("MAC Address = %02X:%02X:%02X:%02X:%02X:%02X\n"
, MACAddress[0], MACAddress[1], MACAddress[2], MACAddress[3], MACAddress[4], MACAddress[5]);
}
void loop()
{
}
結果
MACアドレスの読み取りができました。
別のサンプルでは、この読み出したMACアドレスを使ってESP32同士のBT通信を行います。
![](https://tamanegi-digick.com/wp-content/uploads/2024/06/esp32wm-MAC.png)
BT(Serial受信)
スケッチの説明
スマートフォンからBTシリアル通信を行います。
データを受け取ったら、シリアルコンソールへ表示します。
サンプルスケッチ
#include "BluetoothSerial.h"
BluetoothSerial SerialBT; //BLEオブジェクト
void setup()
{
Serial.begin(115200); //コンソール出力用
SerialBT.begin("NODE MCU ESP32"); //NODE MCU ESP32 という名前でBLE通信開始
//スマートフォンなどでBLE機器の検索をすると、この名前が表示される
}
void loop()
{
char BTReceive = 0;
if (SerialBT.available() != 0) //受信があるかを確認
{
BTReceive = SerialBT.read(); //BTから読み取る
Serial.print(BTReceive); //読み取ったデータをコンソール表示
}
}
結果
スマートフォンからBT接続を行いました。
一例として掲載します。
スマートフォンからの送信文字[tamanegi]は、Teraterm上で受信できたことが確認できました。
![](https://tamanegi-digick.com/wp-content/uploads/2024/06/NODEMCUESP32-btserialresult.png)
コメント