今回はUARTのサンプル select を動かしてみます。
この記事は JTAG でデバッグすることを前提にして書いています。
環境構築については こちら をご覧になってください。
投稿時の開発環境を記しておきます。
PC:
Windows10 OS
開発ボード :
ESP32-DevKitCーVE
(Soc : ESP32-D0WD-V3)
デバッガー(H/W):
FT2232D
デバッガー (S/W) :
Visual Studio Code + PlatformIO + ESP-IDF Framework
概要
ブロック図を載せておきます。

デバッガー FT2232D は USBシリアルポートを2つ持っていて、JTAGデバッッグの他にシリアル通信を行うことができます。
これによりMonitorとは別に、PCとESP32間でUARTを使うことができます。
今回は Tera Term で COM n2 の通信ポートを使って ESP32 とつないで select プログラムを動かしてみます。
PCから送信したものを ESP32で受け取るという簡単なものです。
selectはsocket通信で使われている手段のようですが、UART通信でも扱うことができます。
socketとUARTを併用して扱うことができるようなので、複数の受信を待つ場合に効果を発揮することができます。
お勉強がてら、ここではUARTひとつのselectサンプルを動かしてみます。
プロジェクトをつくる
使っていたプロジェクトを開いていたら、File – Close Folder して閉じておきます。
その後にVSCodeからPlatformIOをOpenします。
以下の内容でプロジェクトを新規に作成します。
Name : ESP32E-UART-select
Board : Espressif ESP32 Dev Module
Framework : Espressif IoT Development Framework
Name : ESP32E の “E” は Framework (Espressif IoT Development Framework)の頭文字を示しています。
(後から見てわかるように、ESP-IDFを使うことを明示しています)

次にplatformio.ini に以下の3行を追加して、 Ctrl + s で保存しておきます。
COM[4]の4の部分はデバイスマネージャーのポート(COMとLPT)で Silicon Labs CP210x から始まるCOMの番号を記述します。
debug_tool = minimodule
upload_port = COM[4]
monitor_speed = 115200
UARTのAPIリファレンスとサンプル
UARTのAPIは こちら を参照してください。
サンプルプログラムは こちら を参考にしました。
PlatformIOで Eresspsif IoT Development Framework を選択したことにより、以下のローカルフォルダからも参照可能なはずです。
C:\Users\xxxxx\.platformio\packages\framework-espidf\examples\peripherals\uart\uart_select
以下にselectで複数の受信を待つサンプルがありますので、こちらもぜひ試してみてください。
UARTとsocketで複数を受信するサンプルです。
C:\Users\xxxxx\.platformio\packages\framework-espidf\examples\system\select
(xxxxxは皆さまのユーザー名)
コーディングする
main.c を以下のようにコーディングしてビルドしておきます。
//以降にコメント文をつけてみました。
UARTのAPIについては こちら をご覧ください。
#include <stdio.h>
#include <sys/fcntl.h>
#include <sys/errno.h>
#include <sys/unistd.h>
#include <sys/select.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_vfs.h"
#include "esp_vfs_dev.h"
#include "driver/uart.h"
#include "soc\uart_reg.h"
static const char* TAG = "uart_select_example";
// (1)select()を使うスレッド
static void uart_select_task(void *arg)
{
// (2)UART設定用の構造体
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_EVEN,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
// (3)ドライバーのインストール
uart_driver_install(UART_NUM_1, 2*1024, 0, 0, NULL, 0); // NUM_1 でテストする
// (4)パラメーターの設定
uart_param_config(UART_NUM_1, &uart_config);
// (5)UART1として使うピンの指定
uart_set_pin(UART_NUM_1, 23, 22, -1, -1); // NUM_1 を FT2232DのUSB-シリアルで使う
while (true) {
// (6)ファイルディスクプリタの宣言
int fd;
// (7)ファイルディスクプリタのオープン
if ((fd = open("/dev/uart/1", O_RDWR)) == -1) { // 今回のテスト用: uart/0 -> uart/1 に変更
ESP_LOGE(TAG, "Cannot open UART");
vTaskDelay(5000 / portTICK_PERIOD_MS);
continue;
}
// (8)UART1を指定してVFSをセットする
esp_vfs_dev_uart_use_driver(1); // UART1を使うので 0->1に変更
while (true) {
// (9)select()の戻り値
int s;
// (10)select()を使うためのFD構造体
fd_set rfds;
// (11)select()に指定するタイムアウト値 (5秒)
struct timeval tv = {
.tv_sec = 10,
.tv_usec = 0,
};
// (12)構造体の初期化
FD_ZERO(&rfds);
// (13)FDの集合に追加
FD_SET(fd, &rfds);
// (14)select()で待機する
s = select(fd + 1, &rfds, NULL, NULL, &tv);
// s < 0 : 異常
// s == 0 : タイムアウト
// else : 受信した場合 等
if (s < 0) {
ESP_LOGE(TAG, "Select failed: errno %d", errno);
break;
} else if (s == 0) {
ESP_LOGI(TAG, "Timeout has been reached and nothing has been received 1");
} else {
// (15)FDの集合に fd が存在するかチェックする
if (FD_ISSET(fd, &rfds)) {
char buf;
if (read(fd, &buf, 1) > 0) {
ESP_LOGI(TAG, "Received: %c", buf); // (16)受信データあり
} else {
ESP_LOGE(TAG, "UART read error");
break;
}
} else {
ESP_LOGE(TAG, "No FD has been set in select()");
break;
}
}
}
// (17)FDを閉じる
close(fd);
}
// (18)タスクを削除(実際には、ここには来ない)
vTaskDelete(NULL);
}
void app_main(void)
{
// (19)スレッドの生成
xTaskCreate(uart_select_task, "uart_select_task", 4*1024, NULL, 5, NULL);
}
ビルドして実行してみる
ビルドエラーがないことを確認したら F5キーを押してデバッグモードに入ります。
タスクバーが青からオレンジ色にかわったら、もう一度F5キーを押してプログラムを動作させます。
Tera Term を起動して(2)に合わせて通信パラメーターを設定します。
Tera Term から文字を送り、(16)のところに来れば成功です。