こんばんは。
今回は ESP32 – DevKitC ( ESP-WROOM-32 開発ボード )とフルカラー 有機EL ( OLED ) SSD1331を使って、天気予報をエクセルで自作したフォントを表示させてみました。
電子工作的に文字列を抽出するのが比較的やりやすい Yahoo! Japan RSS サイトから天気予報を取得してみました。
因みに、Yahoo! RSS サイトの利用は個人使用の場合は基本的に無料だそうですが、それ以外の利用は Yahoo! Japan さんにお問い合わせしてくださいね。
ESP8266 の以前の記事や、こちらの記事では、天気予報を取得しても、ディスプレイには日本語テキスト表示しかしていませんでしたが、今回はそれを自作ロゴでフォント化して表示させてみました。
ロゴの方が文字よりも格段に読み取りやすくなりますね。
ところで、最近、Yahoo! Japan RSS サイトは全て SSL 化 ( https )へ移行し始めていて、つい数日前まで天気予報ページだけまだ http ページだったのですが、つい昨日( 2017/5/28 )に確認したら、ここも https ページに移行されていました。
これで、私が取得したいページは全てSSL 化されてしまったので、 Arduino core for the ESP32 のライブラリも、WiFi.h のインクルードでは取得できません。
WiFiClientSecure.h をインクルードしなければなりませんので、スケッチもそれに変更しました。
ただ、Yahoo! RSS の天気予報では降水確率は取得できません。
週間の予報になっているので、更に情報を絞って、今日と明日の天気だけ表示させてシンプル化しました。
これを応用すれば、天気予報でLED の色を変えたり、モーターを回したりすることも将来的には可能です。
ということで、以下解説してみます。
準備するもの
ESP32 – DevKitC ( ESP-WROOM-32 開発ボード )
日本で使える技適を取得した ESP-WROOM-32 を搭載した Wi-Fi & Bluetooth マイコンボードです。
私は秋月電子通商さんで購入しました。
http://akizukidenshi.com/catalog/g/gM-11819/
Amazon.co.jp ではちょっと高いですが、以下の販売店で売っていました。
※2018/01/30時点で、Amazon.co.jp では Espressif system純正の ESP32-DevKitC は販売されていません。秋月電子通商さんか、マルツパーツさんで購入してください。
カラー OLED SSD1331 モジュール
最近このフルカラー 有機EL ( OLED )の記事ばかり書いていますが、フルカラーOLED としては安価なのにとても優れた小型ディスプレイだと思います。
日本の販売店では殆ど売っていないのが寂しいところです。
Amazon.co.jp では以下で売っていますが、中国販売店です。
確実なことが言えなくて申し訳ないのですが、品質や到着時間は全く分かりません。よく吟味して選んでください。
あと、Amazonプライム対応のものもありましたね。
また、Amazon 以外ですが、秋月電子通商さんにもありました。
http://akizukidenshi.com/catalog/g/gM-11560/
Pmod というのは良く分からなく、これは使ったことが無いのですが、同じ SSD1331 で SPI 通信なので使えると思われます。
SparkFun マイクロSDカードスロット・ピッチ変換基板
いつも私が使っているものです。
これには2.54mmピンヘッダは付属しておりませんので、別途ハンダ付けする必要があります。
micro SDHC カード
私が使って動作確認が取れている micro SDHC カードは以下のものです。
ブレッドボード SAD-101 ( サンハヤト )
このブレッドボードは ESP32 – DevKitC を挿し込んでも、片側1列、もう片側2列の空きがある、私のお勧めブレッドボードです。
他のメーカーの場合、ブレッドボードに空きが無いので注意してください。
1/4W 10kΩ程度の固定抵抗 2つ
これは、SPI通信のMOSI ( Master Output Slave Input ) 端子と MISO ( Master Input Slave Output )端子をプルアップするためのものです。
2.54mmピッチ ピンヘッダ
SparkFun micro SD カードスロットにはピンヘッダが付属していないので、ハンダ付けしておいてください。
Microsoft Excel
自作フォントを編集するためのWindows ソフトです。
ジャンパーワイヤー
パソコン、USBケーブル等
Wi-Fi環境
インターネットにつながっている Wi-Fi 環境が必要です。
事前に ESP32 – DevKitC が接続できるようにルーターのセキュリティ等の設定を済ませておいてください。
接続する
以前の記事と同様で、micro SDHC カードスロットは VSPI 接続。
OLED SSD1331 は HSPI 接続です。
MOSI ( Master Output Slave Input )や、MISO ( Master Input Slave Output )には必ずプルアップ抵抗を接続しておいてください。
Arduino core for the ESP32 のインストール
Arduino IDE のバージョン推奨は 1.8.2 以上です。
予めインストールしておいてください。
Arduno core for the ESP32 は、つい最近 Wi-Fi が繋がりにくい不具合がありましたが、今は完全に解消されていますので、最新版をインストールしてください。
インストール方法は以下のページを参照してください。
Arduino core for the ESP32 のインストール方法
ライブラリのインストール
前回の記事で紹介した、Arduino core for the ESP32 用の私の自作 ESP32_SSD1331ライブラリをインストールしてください。
ライブラリの掲載先は GitHub の以下のページにありますので、ZIPファイルをダウンロードしてください。
https://github.com/mgo-tec/ESP32_SSD1331
ZIPファイルのままArduino IDE にインストールする方法は以下のページを参照してください。
GitHubにある ZIP形式ライブラリ のインストール方法 ( Arduino IDE )
フォントファイルのダウンロードおよび作成
フォントファイルは GitHub の以下のページにありますので、ZIPファイルをダウンロードして解凍して使用してください。
https://github.com/mgo-tec/Excel_Make_Font_CSV
font フォルダの中に MyFont.fnt というファイルで、既にバイナリ化したフォントファイルがあります。
今回は自分でフォントを編集することが面倒な人の為に予めバイナリ化しておきました。
自分流にフォントを変更したい場合は、
MyFont_ver2.0.xlsx
というエクセルファイルを下図の赤枠囲いの中を編集してください。
1 を入力すればフォントを変えられます。
(以前の記事と編集方法が変わっています)
ご自分の好きな形に編集してみてください。
赤い文字のフォント番号は連番になっていて、後で紹介する Arduino IDE スケッチで使用します。
その後、下図の様にCSV_fileOUTput というシートを開いて、CSV 形式で保存してください。
以前の記事と異なるのは、16バイト毎に横に表示させたことです。
Stirling などのバイナリエディタの表示形式と揃えるためにこうしました。
その後は、micro SDHC カードにArduino IDE で以下のスケッチでコンパイル書き込みして、バイナリ形式フォントファイルを出力します。
CSV文字出力が横に16文字になったので、スケッチも変更しました。
MyFont_CSV_Binary_Convert_ver2.0.ino
これの詳しい方法は以下のページを参照してください。
方法はちょっと異なりますが、ほぼ同じようなものです。
エクセル で 16 x 16 ドットフォントを自作して、フルカラー 有機EL ( OLED ) 時計を作ってみた
micro SDHC カードにフォントファイルをコピーする
先ほどダウンロードしたフォントファイルを micro SDHC カードに保存します。
micro SDHC カードのルートに font というフォルダを作成して、そこに MyFont.fnt ファイルをコピーしてください。
micro SDHC カードは通常は FAT32 でフォーマットされていますが、そうでない場合は以下のページを参照してフォーマットしておいてください。
micro SD 、micro SDHC カードの初期化(フォーマット)方法
Yahoo! Japan RSS 天気予報ページアドレスを調べる
では、SSL ( https )化された Yahoo! Japan RSS サイトのご自分の地域のアドレスを調べます。
まず、パソコンのブラウザ等で以下のトップページにアクセスしてください。
https://weather.yahoo.co.jp/weather/rss/
ここでご自分の天気を知りたい地方をクリックして、URL覧からアドレスを調べます。
例えば、「東京」ならば、
https://rss-weather.yahoo.co.jp/rss/days/4410.xml
というアドレスになります。
パソコンやスマホのブラウザのURL入力欄にアドレスが表記されています。
これでサーバー等のアドレスが以下のように判明できます。
HOSTサーバー: rss-weather.yahoo.co.jp
ターゲットページ: /rss/days/4410.xml
これを次のスケッチに入力していきます。
Arduino IDE スケッチの入力
では、Arduino IDE を起動して以下のスケッチを入力してみてください。
ブラウザからスケッチをコピーしたら、必ず一旦保存してください。そうしないと正しく表示されませんので要注意!!
【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)
/* * Copyright (c) 2017 Mgo-tec * Released under the MIT license * https://opensource.org/licenses/mit-license.php */ #include <WiFiClientSecure.h> #include <SD.h> #include "ESP32_SSD1331.h" const char* ssid = "xxxx"; //ご自分のルーターのSSIDに書き換えてください const char* password = "xxxx"; //ご自分のルーターのパスワードに書き換えてください const char* MyFont_file = "/font/MyFont.fnt"; //自作フォントファイル名を定義 const uint8_t CS_SD = 5; //SD card CS ( Chip Select ) const uint8_t SCLK_OLED = 14; //SCLK const uint8_t MOSI_OLED = 13; //MOSI (Master Output Slave Input) const uint8_t MISO_OLED = 12; //これは実際は使っていない。MISO (Master Input Slave Output) const uint8_t CS_OLED = 15; const uint8_t DC_OLED = 16; //OLED DC(Data/Command) const uint8_t RST_OLED = 4; //OLED Reset ESP32_SSD1331 ssd1331(SCLK_OLED, MISO_OLED, MOSI_OLED, CS_OLED, DC_OLED, RST_OLED); uint8_t MyFont_buf[34][2][16]; //自作フォントを格納する //-----Yahoo記事取得引数初期化------------------------- uint64_t WebGetTime = 0; bool Web_first_get = true; //**********セットアップ******************** void setup() { Serial.begin(115200); delay(10); Serial.println(); Serial.print(F("Connecting to ")); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.println(F("WiFi connected")); delay(1000); Serial.println(WiFi.localIP()); delay(10); SD.begin(CS_SD, SPI, 24000000, "/sd"); File MyF = SD.open(MyFont_file, FILE_READ); if (!MyF) { Serial.print(MyFont_file); Serial.println(" File not found"); return; }else{ Serial.print(MyFont_file); Serial.println(" File read OK!"); } //自作フォントを一気にグローバル変数(SRAM)に読み込む for(int i=0; i<34; i++){ MyFont_SD_Read(MyF, 2, i, MyFont_buf[i]); } MyF.close(); ssd1331.SSD1331_Init(); //「今日」表示 ssd1331.SSD1331_8x16_Font_DisplayOut(2, 0, 32, 0, 7, 0, MyFont_buf[17]); ssd1331.SSD1331_8x16_Font_DisplayOut(2, 16, 32, 0, 7, 0, MyFont_buf[10]); //「明日」表示 ssd1331.SSD1331_8x16_Font_DisplayOut(2, 0, 48, 7, 1, 0, MyFont_buf[19]); ssd1331.SSD1331_8x16_Font_DisplayOut(2, 16, 48, 7, 1, 0, MyFont_buf[10]); } //**************メインループ******************* void loop() { //300秒(5分)毎に Yahoo!Japan RSS 天気予報取得 if(Web_first_get == true || (millis() - WebGetTime) > 300000UL){ String weather_str; uint8_t from1, from2, to1; String w_str1, dummy1, w_str2; weather_str = Web_Get("rss-weather.yahoo.co.jp", "/rss/days/4410.xml", '>', "</rss", "】 ", " - ", "|"); Serial.println(weather_str); from1 = weather_str.indexOf('|', 0); from2 = weather_str.indexOf('|', 2); to1 = weather_str.indexOf('|', 2); w_str1 = weather_str.substring(from1, to1); dummy1 = weather_str.substring(from2); w_str2 = dummy1.substring(0, dummy1.indexOf('|', 2)); Serial.print("本日 = "); Serial.println(w_str1); Serial.print("明日 = "); Serial.println(w_str2); YahooRSS_Weather_Display(w_str1, 0, 48, 32, MyFont_buf); YahooRSS_Weather_Display(w_str2, 1, 48, 48, MyFont_buf); WebGetTime = millis(); Web_first_get = false; } } //****************** Webページから http GET ****************** String Web_Get(const char* host, String target_ip, char char_tag, String Final_tag, String Begin_tag, String End_tag, String Paragraph) { String ret_str = ""; WiFiClientSecure Sec_client; if (Sec_client.connect(host, 443)) { Serial.print(host); Serial.print(F("-------------")); Serial.println(F("connected")); Serial.println(F("--------------------WEB HTTP GET Request")); String str1 = "GET " + target_ip + " HTTP/1.1\r\n"; str1 += "Host: " + String( host ) + "\r\n"; str1 += "User-Agent: BuildFailureDetectorESP32\r\n"; str1 += "Connection: close\r\n\r\n\0"; //http1.1では、closeを使うと、サーバーの応答後に切断される。最後に空行必要 Sec_client.print( str1 ); Serial.println( str1 ); }else { // if you didn't get a connection to the server: Serial.println(F("connection failed")); } if(Sec_client){ String dummy_str; uint16_t from, to; Serial.println(F("--------------------WEB HTTP Response")); while(Sec_client.connected()){ while (Sec_client.available()) { if(dummy_str.indexOf(Final_tag) == -1){ dummy_str = Sec_client.readStringUntil(char_tag); if(dummy_str.indexOf(Begin_tag) >= 0){ from = dummy_str.indexOf(Begin_tag) + Begin_tag.length(); to = dummy_str.indexOf(End_tag); ret_str += Paragraph; ret_str += dummy_str.substring(from,to); ret_str += " "; } }else{ while(Sec_client.available()){ Sec_client.read(); //サーバーから送られてくるデータを余すことなく受信することが重要 yield(); } delay(10); Sec_client.stop(); Serial.println(F("--------------------Sec_client Stop")); break; } yield(); } yield(); } } ret_str += "\0"; if(Sec_client){ delay(5); Sec_client.stop(); delay(5); Sec_client.flush(); Serial.println(F("--------------------Sec_client Stop")); } return ret_str; } //*********** 天気予報表示 ********************** void YahooRSS_Weather_Display(String str, uint8_t wDay, uint8_t x0, uint8_t y0, uint8_t fntBuf[][2][16]){ uint8_t Sunny_red = 7, Sunny_green = 3, Sunny_blue = 0; //256bit color 晴れ uint8_t Cloudy_red = 3, Cloudy_green = 3, Cloudy_blue = 1; //256bit color 曇り uint8_t Rain_red = 0, Rain_green = 0, Rain_blue = 3; //256bit color 雨、大雨、暴風雨 uint8_t Snow_red = 7, Snow_green = 7, Snow_blue = 3; //256bit color 雪 uint8_t Thunder_red = 7, Thunder_green = 7, Thunder_blue = 0; //256bit color 雷 uint8_t L_red = 7, L_green = 7, L_blue = 3; //256bit color 線 uint8_t red = 7, green = 7, blue = 3; uint8_t fnt_num = 0; //自作フォント番号 bool Single = true; ssd1331.Display_Clear(x0, y0, x0+16*3-1, y0+16-1); if((str.indexOf("時々") >= 0) || (str.indexOf("一時") >= 0)){ Single = false; fnt_num = 27; ssd1331.SSD1331_8x16_Font_DisplayOut(2, x0+16, y0, L_red, L_green, L_blue, fntBuf[fnt_num]); }else if(str.indexOf("後") >= 0){ Single = false; fnt_num = 28; ssd1331.SSD1331_8x16_Font_DisplayOut(2, x0+16, y0, L_red, L_green, L_blue, fntBuf[fnt_num]); }else if(str.indexOf("時々") < 0 && str.indexOf("後") < 0){ Single = true; } if(str.indexOf("晴") == 1){ red = Sunny_red; green = Sunny_green; blue = Sunny_blue; fnt_num = 20; }else if(str.indexOf("曇") == 1){ red = Cloudy_red; green = Cloudy_green; blue = Cloudy_blue; fnt_num = 21; }else if(str.indexOf("雨") == 1){ red = Rain_red; green = Rain_green; blue = Rain_blue; fnt_num = 22; }else if(str.indexOf("雪") == 1){ red = Snow_red; green = Snow_green; blue = Snow_blue; fnt_num = 24; }else if(str.indexOf("雷") == 1){ red = Thunder_red; green = Thunder_green; blue = Thunder_blue; fnt_num = 25; }else if((str.indexOf("暴風雨") == 1) || (str.indexOf("大雨") == 1)){ red = Rain_red; green = Rain_green; blue = Rain_blue; fnt_num = 23; } if(Single == false){ ssd1331.SSD1331_8x16_Font_DisplayOut(2, x0, y0, red, green, blue, fntBuf[fnt_num]); if(str.indexOf("晴") > 1){ red = Sunny_red; green = Sunny_green; blue = Sunny_blue; fnt_num = 20; }else if(str.indexOf("曇") > 1){ red = Cloudy_red; green = Cloudy_green; blue = Cloudy_blue; fnt_num = 21; }else if(str.indexOf("雨") > 1){ red = Rain_red; green = Rain_green; blue = Rain_blue; fnt_num = 22; }else if(str.indexOf("雪") > 1){ red = Snow_red; green = Snow_green; blue = Snow_blue; fnt_num = 24; }else if(str.indexOf("雷") == 1){ red = Thunder_red; green = Thunder_green; blue = Thunder_blue; fnt_num = 25; }else if((str.indexOf("暴風雨") == 1) || (str.indexOf("大雨") == 1)){ red = Rain_red; green = Rain_green; blue = Rain_blue; fnt_num = 23; } ssd1331.SSD1331_8x16_Font_DisplayOut(2, x0+16*2, y0, red, green, blue, fntBuf[fnt_num]); }else{ ssd1331.SSD1331_8x16_Font_DisplayOut(2, x0+16, y0, red, green, blue, fntBuf[fnt_num]); } } //*************SDカード読み込み************** void MyFont_SD_Read(File F, uint8_t ZorH, uint8_t num, uint8_t buf[2][16]){ F.seek(num * (16 * ZorH)); F.read(buf[0], 16); F.read(buf[1], 16); }
【解説】
●6行目:
Yahoo! RSS 天気予報が SSL 化されたことにより、WiFiClientSecure.h をインクルードしなければなりません。これは WiFi.h よりも SRAM を多く消費します。
●8行目:
有機EL ( OLED ) SSD1331 の自作ライブラリのインクルードです。
●10-11行目:
ご自分のルーター環境の SSID やパスワードに書き換えてください。
●13行目:
micro SDHC カードに保存してあるフォントファイルを定義します。
●15-22行目:
ESP32 – DevKitC の GPIO 設定です。
OLED への MISO ( Master Input Slave Output ) は使いません。
●24行目:
自作ライブラリ ESP32_SSD1331 のクラス初期化です。
●26行目:
自作フォントを格納する3次元配列です。
全角は 16×16 ピクセルですが、8×16ピクセルを2つ組み合わせます。
とりあえず 34 文字のフォントを格納します。
●29-30行:
Yahoo! Japan RSS 天気予報を取得するための変数初期化です。
●34-53行:
ルーター(アクセスポイント)と接続します。
これはサンプルスケッチをそのまま利用しています。
●55-71行:
micro SDHC カードからフォントを読み込んで、MyFont_buf へ格納します。
68行では 252行以降の関数を呼んでいます。
●73行:
自作ライブラリ、ESP32_SSD1331 を初期化する関数です。
●76-80行:
「今日」と「明日」という自作フォントを OLED に表示させています。
ESP32_SSD1331 の関数の使い方については以下のページを参照してください。
有機EL ( OLED ) SSD1331 ライブラリを作成しました
●85行:
起動初回と300秒(5分)毎に Yahoo! RSS 天気予報を取得するためのif文です。
●90行:
ここで、SSL化したYahoo! Japan RSS のサイトから各地方の天気予報文字列を取得して、String文字列 weather_str へ格納しています。
ここでは週間予報が取得できます。
ホストサーバーを指定し、天気予報を取得する各地域のターゲットページを指定しています。
HOSTサーバーやターゲットページは先に説明しましたので、ここで入力します。
Web_Get関数は 110-175行にあるので、詳細は後で述べます。
●93-100行:
weather_str 文字列から Ardunio 標準 String クラス関数の substring やindexOf を使って、週間天気予報文字列から「今日」と 「明日」の天気予報をそれぞれ抽出しています。
Ardunio 標準 String クラス関数については以下のページを参照してください。
●102-103行:
177-250行の関数を呼んで、有機EL ( OLED )ディスプレイ SSD1331 に自作フォントを表示させています。
●110-175行:
SSL 化された Yahoo! Japan RSS サイトから文字列を抽出する関数です。
116行目で SSL ポート443 を開いて Yahoo! RSS ホストサーバーにアクセスして、ターゲットページに GETリクエストを送ります。
138-139行のSec_client.connected(); や Sec_client.available(); でサーバーからのレスポンスを待って文字列を取得します。
141-148行で、欲しい文字列を抽出します。
150-157行でサーバーから送られてくる文字列を余すことなく全て受け取ります。
1文字でも受け取り漏らすと、後でエラーの可能性が出てくるので、ここは重要です。
受け取って、サーバーからの有効な文字列が無くなったら切断します。
そして、取得した文字列 ret_str を返します。
●177-250行:
抽出した「今日」と「明日」の天気予報文字列からフォント番号を割り当ててディスプレイに表示させる関数です。
178-183行で天気ロゴフォントの色を256色カラーで指定します。
191-201行では、「時々」や「一時」、「のち」などの文字列を表示させる条件分岐です。
フォント番号は先に述べたエクセルファイルからフォント番号を指定します。
Single がfalse ならばフォントを2つ表示させ、 true ならばフォントを1つ表示させます。
203-221行では天気予報文字列のうち最初に現れる文字からフォント番号を割り当てます。
223-244行では「時々」や「一時」などがあった場合にはフォントを2つ表示させるので、2番目に現れる天気文字を抽出してフォントを割り当てます。
●252-256行:
ここで micro SDHC カードからフォントファイルを読み込み、配列に格納します。
16×16 ピクセルのフォントなので、32バイト読み込みますが、8×16ピクセル毎に配列を分けます。
将来的に半角にも対応するためでもあります。
コンパイル書き込み実行
ブラウザからスケッチをコピーしたら、必ず一旦保存してください。そうしないと正しく表示されませんので要注意!!
では、ご自分のWi-Fiルーターを起動し、インターネットに接続できる状態にしておいて、上記のスケッチをコンパイル書き込み実行してみてください。
そして、間髪入れずにシリアルモニターを115200bps で起動してください。
すると、こんな感じで表示されていればOKです。
※ Arduino IDE 1.8.1 以下では文字化けします。
1.8.2 以降を使用してください。
そして、有機EL ( OLED ) SSD1331 ではこんな感じに表示されればOKです。
写真ではうまく表示されていませんが、実際は色はもっと鮮やかです。
まとめ
どうでしょうか?
うまく表示できたでしょうか?
実はお天気表示としてはロゴフォントがまだ足りないかもしれません。
霧や吹雪などは作っていません。
その場合はご自分でフォントを追加してみてください。
将来的には降水確率まで表示させたいと思っています。
これができれば、ニュース記事電光掲示板とNTP時計と組み合わせると、この小さい画面で社会人に必要な情報が得られるガジェットっぽいものができますね。
実はそういうものが既に私の手元では完成しています。
近々記事にしたいと思っています。
以上、もし何か不具合等ありましたらコメント等でご連絡いただけるとありがたいです。
ではまた・・・。
Amazon.co.jp 当ブログのおすすめ
コメント
mgo-tec 様
電子工作初心者です。こちらのサイト(天気予報を自作フォントで表示してみた)を参考にさせていただいているのですが、ESP32への書き込みがどうしてもうまくいきません。プログラムのコンパイルは成功するのですが、ESP32への書き込みで「A fatal error occurred: Timed out waiting for packet content」というエラーが出てしまいます。古いバージョンのArduino core for the ESP32をいくつか試してみても、何度書き込みをしてみても、ダメで…。
何か対策かあれば教えていただきたいです。
よろしくお願いします。
kirahijiさん
記事をご覧いただき、ありがとうございます。
まず、お聞きしたいのは、デバイスは何を使っていますでしょうか?
M5Stack ですか?
ESP32-DevKitC ですか?
ESPr Developer 32 ですか?
また、以下の記事は参照されましたでしょうか?
ESP32 ( ESP-WROOM-32 , M5Stack )自分的 トラブルシューティング まとめ
ご返信、ありがとうございます。
デバイスはESP32-DevKitCを使っています。
トラブルシューティングのまとめサイトには一通り目を通し、色々試してはみたのですが、なかなかうまくいかず、、、。
kirahijiさん
ESP32-DevKitC は最新のものですか?
最近、秋月電子さんから ESP-WROOM-32D のボードが発売されていて、パーツも一新されています。
http://akizukidenshi.com/catalog/g/gM-13628/
その場合、もしかしたら、USBシリアルのドライバが認識しないかも知れません。
Facebookの ESP8266/ESP32環境向上委員会でそういう情報があったかもしれませんので、見てみて下さい。
また、パソコンが MAC の場合はUSBシリアルドライバのインストールが必要かも知れません。
私はWindowsしか持っていないので、正直分かりませんが・・・。
あと、パソコンに接続する USBケーブルが粗悪だったり、1m以上長かったり、USBハブを使っていたりするとダメです。
良質で太く短いケーブルに替えて、USBハブを使わず、パソコン直に挿してください。
または、Arduino IDE の「ツール」の Upload Speed を下げてみて下さい。
あとは、試しに、リセットボタンとは別の ENボタンを押し続けながらコンパイル書き込みして、終わったらボタンを放してみて下さい。
ENボタンがダメならリセットボタンを押し続けながらコンパイル書き込みしてみて下さい。
以上をそれぞれ試してみて下さい。