ESP-01とArduinoの使い方:ATコマンド、書き込み、リレー
ESP-01(ESP8266)をArduinoにつなぐ方法を解説します。8本のピン、3.3 Vの電源、ATコマンドでのWi-Fi接続、GPIO0をGNDにつないで行う書き込み、ESP-01Sリレーモジュール、よくあるエラーまでまとめました。
ESP-01は、ESP8266というWi-Fiチップを載せた、とても小さく(24.8 × 14.3 mm)安価なモジュールです。ESP-01をArduinoにつなぐと、UnoやNanoのように無線機能のないボードに、数本の配線だけでWi-Fiを追加できます。モジュールには出荷時からATコマンドのファームウェアが入っています。Arduinoがシリアルで「AT+CWJAP」のような短いテキストのコマンドを送ると、ESP-01がネットワークに接続し、データを送受信します。Arduinoをまったく使わずに、ESP-01を単独のマイコンとしてプログラムすることもできます。中のプロセッサはUnoよりはるかに高速です。
このガイドでは、ESP-01の8本のピン、強力な3.3 V電源が必ず必要な理由、Arduino UnoでのATコマンドの使い方、スマホからLEDを点灯するWebページの作り方、USB-TTL変換モジュールでモジュールに直接書き込む方法(GPIO0をGNDにつなぐ方法)、ESP-01Sリレーモジュールでの電球の制御、Raspberry Pi Picoでの使い方をステップごとに学びます。最後に、よくあるエラーの解決方法と、NodeMCUやESP32のほうがよい選択になるのはどんなときかを紹介します。

ESP-01とは?どのように動くのか
ESP-01は、Ai-Thinker社がESP8266EXチップを中心に設計した最初の、そして最も小さなモジュールです。ボードには、チップ、26 MHzの水晶振動子、プログラムと設定を保存するフラッシュメモリ、蛇行した形の基板アンテナが載っています。USBポート、レギュレーター、ボタンはありません。そのため、ESP-01はそのままパソコンに挿すことはできず、電源とシリアル接続を自分で用意する必要があります。モジュールの使い方は2通りです。Wi-Fiモデムとして使う方法(ATファームウェアが入っていて、Arduinoがコマンドを送る)と、単独のマイコンとして使う方法(Arduino IDEから自分のプログラムを書き込み、ATファームウェアは消える)です。現在販売されているモジュールの多くは、黒いESP-01S版です。
| 項目 | 値 |
|---|---|
| チップ | ESP8266EX(Tensilica L106、32ビット) |
| クロック周波数 | 80 MHz(160 MHzまで上げられます) |
| フラッシュメモリ | ESP-01:512 KB、ESP-01S:1 MB |
| RAM | データ用RAMは約80 KB。Wi-Fi接続中にプログラムで使えるのは約50 KB |
| Wi-Fi | 802.11 b/g/n、2.4 GHzのみ、基板アンテナ |
| 動作電圧 | 3.0〜3.6 V(推奨3.3 V) |
| 電流 | 接続中の平均70〜80 mA、送信時は約170 mA、瞬間的なピークは300 mA超 |
| ディープスリープ時の電流 | 約20 µA(チップ単体) |
| 使えるGPIO | 4本:GPIO0、GPIO2、GPIO1(TX)、GPIO3(RX) |
| アナログ入力 | なし(ADCピンが外に出ていない) |
| サイズ | 24.8 × 14.3 mm |
| 出荷時のファームウェア | ATコマンドのファームウェア(通常は115200ボー) |
ESP-01とESP-01Sの違い
| 項目 | ESP-01 | ESP-01S |
|---|---|---|
| ボードの色 | たいてい青 | 黒 |
| フラッシュメモリ | 512 KB(後期の黒い版では1 MB) | 1 MB |
| 電源LED | 赤、常に点灯 | なし |
| 青色LED | TX(GPIO1)ラインにつながり、データ送信時に点滅 | GPIO2につながり、ピンがLOWのときに点灯 |
| ピン配置 | 8ピン | 同じ8ピンで完全に互換 |
| 消費電流 | 電源LEDのぶん数mA多い | 少なめで、電池で動かすプロジェクトに向く |
ESP-01のピン配置:8本のピンの役割
ESP-01には2×4に並んだ8本のピンがあり、そのうち入出力として使えるのは4本だけです。ピン名がボードに印刷されていないものもあるので、配線する前に手元のモジュールを販売元のピン配置図と見比べてください。VCCとGNDを逆につなぐと、モジュールは数秒で壊れます。各ピンの役割と、通常動作時の接続は次のとおりです。
| ピン | 役割 | 通常動作時の接続 |
|---|---|---|
| VCC | 3.3 V電源の入力 | 強力な3.3 V電源(300 mA以上) |
| GND | グラウンド | Arduinoと電源で共通のGND |
| TX(GPIO1) | シリアルデータの出力 | ArduinoのRXラインへ |
| RX(GPIO3) | シリアルデータの入力 | ArduinoのTXラインへ(5 Vのボードでは分圧回路を通す) |
| EN(CH_PD) | チップを有効にする | 3.3 Vへ(直接、または10 kΩを通して) |
| RST | LOWでチップを再起動 | 未接続、または10 kΩで3.3 Vにプルアップ |
| GPIO0 | 起動モードを選び、その後は汎用の入出力 | 起動時はHIGH(未接続)、書き込み時はGND |
| GPIO2 | 汎用の入出力(ESP-01Sでは青色LED) | 起動時はHIGHのままにする |
消費電流:Arduinoの3.3 Vピンでは足りない理由
ESP-01が壊れたり、再起動を繰り返したりする問題の多くは電源が原因です。Wi-Fi接続中、モジュールは平均70〜80 mA、送信時には約170 mAの電流を流します。起動時やネットワークへの接続時には、300 mAを超える短いピークも出ます。一方、Arduino Unoの3.3 Vピンの公式な定格はわずか50 mAです。このピンから給電したESP-01は「AT」コマンドには応答することが多いものの、ネットワークに接続しようとした瞬間に電圧が落ちてモジュールがリセットし、ソフトウェアのバグのように見えます。解決策は、5 Vから給電するAMS1117-3.3レギュレーター(1 A)を使い、モジュールのVCCとGNDの間に100〜470 µFの電解コンデンサを入れることです。レギュレーターの仕組みは7805電圧レギュレーターの記事で紹介しています。
| 電源 | 使える? | メモ |
|---|---|---|
| Arduino Unoの3.3 Vピン | 不可 | 公式には50 mA。Wi-Fiへの接続中にモジュールがリセットする |
| USB-TTL変換モジュールの3.3 Vピン | たいてい不可 | チップ内蔵のレギュレーターが出せるのは通常50〜100 mA |
| AMS1117-3.3レギュレーター(5 V入力) | 可 | 最大1 A。出力に10 µF、モジュールのそばに100〜470 µF |
| ESP-01用USBアダプター | 可 | CH340とAMS1117を搭載し、モジュールをそのまま挿せる |
| 単3電池2本(3 V) | ぎりぎり | 電池が減ると電圧が3 Vを下回り、モジュールが不安定になる |
| 1セルのLi-ion電池(3.7〜4.2 V) | 直接は不可 | 3.6 Vの上限を超えるため、低ドロップアウトのレギュレーター(LDO、3.3 V)が必要 |
ESP-01をArduino Unoにつなぐ(ATコマンド用)
Arduino Unoにはハードウェアのシリアルポートが1つ(D0とD1)しかなく、USB接続と共用になっています。そのため、SoftwareSerialライブラリを使ってESP-01をD2とD3につなぐのがいちばん実用的です。Unoに書き込むたびにESP-01を外す必要がなく、シリアルモニタもデバッグ用に自由に使えます。Raspberry Pi Picoはもともと3.3 Vで動くので、分圧回路は必要ありません。
| ESP-01のピン | Arduino Uno | Raspberry Pi Pico | メモ |
|---|---|---|---|
| VCC | AMS1117-3.3の出力 | AMS1117-3.3または3V3(OUT) | Unoの3.3 Vピンでは足りない。Picoの3V3出力の推奨上限は300 mA |
| GND | GND | GND | レギュレーター、ボード、モジュールでGNDを共通にする |
| TX | D2 | GP1(UART0 RX) | 直接つなぐ |
| RX | D3(1 kΩ / 2 kΩの分圧回路を通す) | GP0(UART0 TX) | Picoでは分圧回路は不要 |
| EN(CH_PD) | 3.3 V | 3.3 V | 直接、または10 kΩを通して |
| RST | 未接続 | 未接続 | 必要なら10 kΩで3.3 Vにプルアップ |
| GPIO0 | 未接続 | 未接続 | 通常動作時はGNDにつながない |
| GPIO2 | 未接続 | 未接続 | 起動時はHIGHのままにする |
UnoのD3ピンから出る5 Vの信号を下げるには、D3からESP-01のRXへ1 kΩ、ESP-01のRXからGNDへ2 kΩの抵抗をつなぎます。出力は5 × 2 / (1 + 2) = 3.33 Vです。2 kΩの代わりに2.2 kΩを使うと3.44 Vになり、どちらも安全です。ほかの抵抗値は「分圧回路」ツールで計算できます。逆方向には分圧回路は不要です。ESP-01のTXピンから出る3.3 Vは、UnoがHIGHと判定する3 Vのしきい値を上回っています。シリアル通信の基本はUARTのシリアル通信の記事で詳しく解説しています。
最初のテスト:シリアルモニタからATコマンドを送る
- 下のブリッジ用スケッチをUnoに書き込みます。ほとんどのモジュールはこの速度で出荷されているので、最初はESP_BAUDを115200にしてください(古いモジュールでは9600の場合もあります)。
- シリアルモニタを115200ボーで開き、改行コードをCRおよびLF(Both NL & CR)にします。この設定がないと、モジュールはコマンドの終わりを判断できません。
- ATと入力して送信すると、OKが返ってくるはずです。文字化けする場合は、速度が合っていません。
- SoftwareSerialは115200では安定して読み取れないので、AT+UART_DEF=9600,8,1,0,0でモジュールの速度を9600に恒久的に下げます。返答が文字化けして見えても、コマンドはたいてい届いています。
- スケッチのESP_BAUDを9600に変えてもう一度書き込み、ATコマンドを再度送ります。今度はOKがきれいに表示されるはずです。
- AT+GMRでファームウェアのバージョンを、AT+CWLAPで周囲のWi-Fiネットワークの一覧を確認し、モジュールが正常に動いていることを確かめます。
1#include <SoftwareSerial.h>
2
3SoftwareSerial esp(2, 3); // D2 = RX, D3 = TX (bölücüyle ESP RX'e) / D3 to ESP RX via divider
4
5const long ESP_BAUD = 9600; // ilk denemede 115200 yap / use 115200 on the first try
6
7void setup() {
8 Serial.begin(115200); // Seri Monitör hızı / Serial Monitor speed
9 esp.begin(ESP_BAUD);
10 Serial.println("AT komutu yaz / type an AT command");
11}
12
13void loop() {
14 if (esp.available()) { // ESP-01'den geleni ekrana yaz / ESP-01 -> screen
15 Serial.write(esp.read());
16 }
17 if (Serial.available()) { // klavyeden yazılanı ESP-01'e gönder / keyboard -> ESP-01
18 esp.write(Serial.read());
19 }
20}よく使うESP-01のATコマンド
| コマンド | 働き | 返答の例 |
|---|---|---|
| AT | 接続をテストする | OK |
| AT+RST | モジュールを再起動する | OK ... ready |
| AT+GMR | ファームウェアのバージョンを表示する | AT version:... SDK version:... OK |
| AT+UART_DEF=9600,8,1,0,0 | ボーレートを恒久的に変更する | OK |
| AT+CWMODE=1 | ステーションモード。2 = アクセスポイント、3 = 両方 | OK |
| AT+CWLAP | 周囲のWi-Fiネットワークを一覧表示する | +CWLAP:(3,"AgAdi",-58,...) |
| AT+CWJAP="AgAdi","Sifre123" | Wi-Fiネットワークに接続する(AgAdiはトルコ語で「ネットワーク名」、Sifreは「パスワード」) | WIFI CONNECTED, WIFI GOT IP, OK |
| AT+CIFSR | 取得したIPアドレスを表示する | +CIFSR:STAIP,"192.168.1.45" |
| AT+CIPMUX=1 | 複数接続を有効にする(サーバーには必須) | OK |
| AT+CIPSERVER=1,80 | ポート80でTCPサーバーを起動する | OK |
| AT+CIPSTART=0,"TCP","192.168.1.10",80 | リンク0でサーバーに接続する | 「0,CONNECT」と「OK」 |
| AT+CIPSEND=0,20 | リンク0で20バイトを送信する | > ... SEND OK |
| AT+CIPCLOSE=0 | リンク0を閉じる | 「0,CLOSED」と「OK」 |
Arduino UnoとESP-01でスマホからLEDを操作する
ここからはATコマンドをプログラムにしていきます。下のスケッチはESP-01をネットワークに接続し、ポート80で小さなWebサーバーを立ち上げ、IPアドレスをシリアルモニタに表示します。同じWi-Fiにつないだスマホのブラウザにそのアドレスを入力すると、2つのボタンがあるページが開きます。ボタンでUnoの13番ピンにある内蔵LEDを点灯・消灯できます。LEDの代わりにリレーモジュールをつなげば、同じ方法で電球を操作できます。書き込む前に、前のステップでモジュールの速度を9600にしておいてください。
1#include <SoftwareSerial.h>
2
3SoftwareSerial esp(2, 3); // D2 = RX, D3 = TX (bölücüyle) / D3 via divider
4const int LED_PIN = 13; // Uno'nun dahili LED'i / Uno onboard LED
5
6const char* WIFI_SSID = "AgAdi"; // Wi-Fi adın / your Wi-Fi name
7const char* WIFI_PASS = "Sifre123"; // Wi-Fi şifren / your Wi-Fi password
8
9bool ledOn = false;
10bool pending = false; // cevap bekleyen istek var mı / request waiting for a reply
11int linkId = 0; // ESP-01'in bağlantı numarası (0-4) / connection id (0-4)
12char line[64];
13byte lineLen = 0;
14
15// Beklenen yazıyı süre dolana kadar ara / wait until the expected text arrives or time runs out
16bool waitFor(const char* expect, unsigned long timeout) {
17 unsigned long start = millis();
18 size_t idx = 0;
19 size_t len = strlen(expect);
20 while (millis() - start < timeout) {
21 if (esp.available()) {
22 char c = esp.read();
23 Serial.write(c); // gelen her şeyi göster / echo everything
24 if (c == expect[idx]) {
25 idx++;
26 if (idx == len) return true;
27 } else {
28 idx = (c == expect[0]) ? 1 : 0;
29 }
30 }
31 }
32 return false;
33}
34
35bool sendAT(const char* cmd, const char* expect, unsigned long timeout) {
36 esp.println(cmd); // println sonuna \r\n ekler / println adds \r\n
37 return waitFor(expect, timeout);
38}
39
40void sendPage(int id) {
41 char body[220];
42 snprintf(body, sizeof(body),
43 "<meta name='viewport' content='width=device-width'>"
44 "<h2>LED: %s</h2>"
45 "<a href='/on'><button>AC / ON</button></a> "
46 "<a href='/off'><button>KAPAT / OFF</button></a>",
47 ledOn ? "ACIK / ON" : "KAPALI / OFF");
48 char head[110];
49 snprintf(head, sizeof(head),
50 "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n"
51 "Content-Length: %d\r\nConnection: close\r\n\r\n",
52 (int)strlen(body));
53
54 esp.print("AT+CIPSEND="); // önce kaç bayt gideceğini söyle / announce the length first
55 esp.print(id);
56 esp.print(',');
57 esp.println(strlen(head) + strlen(body));
58 if (waitFor(">", 2000)) { // ">" gelince veriyi yolla / send data after ">"
59 esp.print(head);
60 esp.print(body);
61 waitFor("SEND OK", 5000);
62 }
63 esp.print("AT+CIPCLOSE="); // bağlantıyı kapat / close the connection
64 esp.println(id);
65 waitFor("OK", 2000);
66}
67
68void handleLine() {
69 if (strncmp(line, "+IPD,", 5) == 0) { // yeni istek / new request: +IPD,0,384:GET /on ...
70 linkId = line[5] - '0';
71 if (strstr(line, "GET /on ")) ledOn = true;
72 else if (strstr(line, "GET /off ")) ledOn = false;
73 digitalWrite(LED_PIN, ledOn ? HIGH : LOW);
74 pending = true;
75 } else if (pending && lineLen == 0) { // boş satır = isteğin sonu / empty line = end of request
76 pending = false;
77 sendPage(linkId);
78 }
79}
80
81void setup() {
82 pinMode(LED_PIN, OUTPUT);
83 Serial.begin(115200);
84 esp.begin(9600); // AT+UART_DEF=9600,8,1,0,0 ile ayarlanmış olmalı / set with AT+UART_DEF
85
86 sendAT("AT+RST", "ready", 5000); // temiz başlangıç / clean restart
87 sendAT("AT+CWMODE=1", "OK", 2000); // istemci modu / station mode
88
89 esp.print("AT+CWJAP=\""); // AT+CWJAP="ad","şifre" / AT+CWJAP="ssid","password"
90 esp.print(WIFI_SSID);
91 esp.print("\",\"");
92 esp.print(WIFI_PASS);
93 esp.println("\"");
94 if (!waitFor("OK", 20000)) {
95 Serial.println(F("\nWi-Fi baglanamadi / Wi-Fi failed"));
96 }
97
98 sendAT("AT+CIPMUX=1", "OK", 2000); // sunucu için çoklu bağlantı / multiple connections
99 sendAT("AT+CIPSERVER=1,80", "OK", 2000); // 80 portunda sunucu / server on port 80
100 sendAT("AT+CIFSR", "OK", 2000); // IP adresini yaz / print the IP address
101}
102
103void loop() {
104 while (esp.available()) { // ESP-01'den gelenleri satır satır oku / read line by line
105 char c = esp.read();
106 if (c == '\n') {
107 line[lineLen] = '\0';
108 handleLine();
109 lineLen = 0;
110 } else if (c != '\r' && lineLen < sizeof(line) - 1) {
111 line[lineLen++] = c;
112 }
113 }
114}コードの仕組みは次のとおりです。ブラウザが接続すると、ESP-01はリクエストを+IPD,0,384:GET /on HTTP/1.1という形でArduinoに渡します。ここで0はリンク番号、384は受信したバイト数です。Arduinoはこの行から「GET /on」か「GET /off」を探してLEDを切り替えます。リクエストの終わりを示す空行が届くと、AT+CIPSEND=0,長さで送信するバイト数を知らせ、モジュールが「>」を表示したらページを送り、「SEND OK」の返答のあとにAT+CIPCLOSEでリンクを閉じます。ページはわざと短くしています。Unoの2 KBのRAMでは長いHTMLには足りず、1回のCIPSENDで送れるのは最大2048バイトだからです。もっと複雑なプロジェクトでは、WiFiEspATのようなライブラリを使えば、ATコマンドを自分で管理する手間が省けます。
ESP-01に直接書き込む:GPIO0をGNDにつなぐ方法
ESP-01に入っているESP8266は、32ビット・80 MHzのプロセッサを持ち、Arduino Unoよりずっと高性能です。プロジェクトにリレー、センサー、LEDが1つずつあるだけなら、Arduinoはまったく必要ありません。プログラムをESP-01に直接書き込めばよいのです。ESP8266は起動時にGPIO0、GPIO2、GPIO15のレベルを見て、何をするかを決めます。ESP-01のボードでは、GPIO15はすでにGNDにつながっていて、GPIO2はHIGHのままでなければならないので、起動モードを決めるのはGPIO0だけです。
| GPIO0 | GPIO2 | GPIO15 | 起動モード | 74880ボーで表示される起動メッセージ |
|---|---|---|---|---|
| HIGH(未接続) | HIGH | LOW | 通常動作:フラッシュ内のプログラムが起動 | 「boot mode:(3,x)」(通常起動) |
| LOW(GND) | HIGH | LOW | 書き込み(UARTダウンロード)モード | 「boot mode:(1,x)」と「waiting for host」(ホストを待機中) |
| ESP-01のピン | 接続 | メモ |
|---|---|---|
| VCC | 3.3 Vレギュレーターの出力 | USB-TTL変換モジュールの3.3 Vピンではたいてい足りない |
| GND | USB-TTLのGNDとレギュレーターのGND | すべて共通のグラウンドにする |
| TX | USB-TTLのRXD | クロス接続 |
| RX | USB-TTLのTXD | ジャンパーは3.3 V側にする |
| EN(CH_PD) | 3.3 V | 直接、または10 kΩを通して |
| RST | 未接続(リセットするときだけ一瞬GNDへ) | 必要なら10 kΩで3.3 Vにプルアップ |
| GPIO0 | GND | 書き込み中だけ。終わったら外す |
| GPIO2 | 未接続 | 起動時はHIGHのままにする |
- Arduino IDEで「ファイル」>「基本設定」を開き、「追加のボードマネージャのURL」欄に次のアドレスを追加します:https://arduino.esp8266.com/stable/package_esp8266com_index.json
- ボードマネージャでesp8266を検索し、ESP8266 Communityのパッケージをインストールします。
- 「ツール」>「ボード」からGeneric ESP8266 Moduleを選びます。Flash Sizeは、ESP-01Sなら1MB (FS:64KB OTA:~470KB)、古い青いESP-01なら512KBの選択肢のどれかにします。
- USB-TTL変換モジュールのジャンパーを3.3 Vにし、上の表のとおりにモジュールを配線して、GPIO0はGNDにつないだままにします。
- モジュールの電源をいったん切って入れ直すか、RSTを一瞬GNDに触れさせます。これでモジュールが書き込みモードで起動します。
- 「ツール」>「ポート」でUSB-TTL変換モジュールのポートを選び、スケッチを書き込みます。最初のテストには「ファイル」>「スケッチ例」>「ESP8266」>「Blink」がおすすめです。ESP-01Sでは青色LEDがGPIO2につながっています。
- 「Hard resetting via RTS pin...」(RTSピンでリセット中)と表示されたら、GPIO0をGNDから外してモジュールを再起動します。GPIO0がGNDにつながったままだとプログラムは動かず、モジュールはまた書き込みモードで起動します。
GPIO0とGPIO2でリレーを制御する:ESP-01Sリレーモジュール
ESP-01の汎用ピンはGPIO0とGPIO2ですが、どちらも起動中はHIGHでなければなりません。つまり、これらのピンにつなぐ回路は、ボードの起動中にピンをLOWに引っ張ってはいけません。いちばん安全なのはアクティブLOWの接続です。起動時はピンがHIGHなのでリレーはオフのままで、プログラムがピンをLOWにするとリレーがオンになります。市販のESP-01Sリレーモジュールはまさにこの方式で設計されています。5 Vで動作し、ボード上のレギュレーターがESP-01S用の3.3 Vを作り、GPIO0がトランジスタを介して、接点定格10 A 250 V ACのリレーを駆動します。v4.0以降のボードでは、GPIO0がLOWになるとリレーがオンになります。古いv1.0のボードは、ESP-01Sで動かすのにちょっとした改造が必要な場合があるので、手元のボードのバージョンを確認してください。

1#include <ESP8266WiFi.h>
2#include <ESP8266WebServer.h>
3#include <ESP8266mDNS.h>
4
5const char* ssid = "AgAdi"; // Wi-Fi adın / your Wi-Fi name
6const char* password = "Sifre123"; // Wi-Fi şifren / your Wi-Fi password
7
8const int RELAY_PIN = 0; // ESP-01S röle kartında GPIO0 / GPIO0 on the ESP-01S relay board
9const int RELAY_ON = LOW; // çoğu kartta LOW = çeker; tersse değiştir / LOW = on, swap if yours is inverted
10const int RELAY_OFF = HIGH;
11
12ESP8266WebServer server(80);
13bool relayOn = false;
14
15void sendPage() {
16 String html = F("<!DOCTYPE html><html><head><meta charset='utf-8'>"
17 "<meta name='viewport' content='width=device-width,initial-scale=1'>"
18 "<title>ESP-01</title></head>"
19 "<body style='font-family:sans-serif;text-align:center'>"
20 "<h1>ESP-01 Röle / Relay</h1><p><b>");
21 html += relayOn ? "AÇIK / ON" : "KAPALI / OFF";
22 html += F("</b></p><p><a href='/on'><button>AÇ / ON</button></a> "
23 "<a href='/off'><button>KAPAT / OFF</button></a></p></body></html>");
24 server.send(200, "text/html", html);
25}
26
27void setRelay(bool on) {
28 relayOn = on;
29 digitalWrite(RELAY_PIN, on ? RELAY_ON : RELAY_OFF);
30 server.sendHeader("Location", "/"); // ana sayfaya dön / back to the main page
31 server.send(303, "text/plain", "");
32}
33
34void setup() {
35 digitalWrite(RELAY_PIN, RELAY_OFF); // önce kapalı seviye / off level first
36 pinMode(RELAY_PIN, OUTPUT);
37 Serial.begin(115200);
38
39 WiFi.mode(WIFI_STA);
40 WiFi.begin(ssid, password);
41 while (WiFi.status() != WL_CONNECTED) {
42 delay(500);
43 Serial.print('.');
44 }
45 Serial.println();
46 Serial.println(WiFi.localIP()); // bu adresi tarayıcıda aç / open this address in a browser
47 MDNS.begin("esp01"); // ya da http://esp01.local / or http://esp01.local
48
49 server.on("/", sendPage);
50 server.on("/on", []() { setRelay(true); });
51 server.on("/off", []() { setRelay(false); });
52 server.begin();
53}
54
55void loop() {
56 server.handleClient();
57 MDNS.update();
58}上の方法でスケッチをESP-01Sに書き込んだら、モジュールをリレーボードに挿し、ボードに5 Vを給電します。IPアドレスは、USB-TTL変換モジュールをつないだ状態でシリアルモニタで確認するか、ルーターの接続機器一覧で探してください。ボタンなどの入力を追加したい場合、いちばん適しているのはGPIO3(RX)です。起動時のレベルが関係しないからです。その場合はSerial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY)で、シリアルポートを送信専用で開きます。なお、mDNSに対応したパソコンからはhttp://esp01.localでも開けます。
Raspberry Pi PicoでESP-01を使う(MicroPython)
Wi-FiのないRaspberry Pi Picoにも、ESP-01で無線機能を追加できます。Picoは3.3 Vで動くので分圧回路は不要で、ESP-01のRXをGP0(UART0 TX)に、TXをGP1(UART0 RX)につなぎます。PicoのハードウェアのUARTは115200ボーも問題なく読めるので、モジュールの速度を変える必要もありません。Unoのセクションですでに9600に下げた場合は、コードのbaudrateも9600にしてください。下のMicroPythonのコードをThonnyで実行すると、モジュールがネットワークに接続し、IPアドレスを表示して、30秒ごとに周囲のネットワークを一覧表示します。Pico Wを持っているなら、内蔵のWi-Fiを使うほうが簡単です。Pico WのWi-FiとWebサーバーの記事を参照してください。
1from machine import UART, Pin
2import time
3
4# GP0 (TX) -> ESP-01 RX, GP1 (RX) <- ESP-01 TX
5uart = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
6
7def at(cmd, timeout=2000):
8 uart.write(cmd + "\r\n") # her komut \r\n ile biter / every command ends with \r\n
9 start = time.ticks_ms()
10 resp = b""
11 while time.ticks_diff(time.ticks_ms(), start) < timeout:
12 if uart.any():
13 resp += uart.read()
14 if b"OK" in resp or b"ERROR" in resp or b"FAIL" in resp:
15 break
16 print(cmd, "->", resp) # cevabı göster / show the reply
17 return resp
18
19at("ATE0") # komut yankısını kapat / turn off echo
20at("AT") # OK gelmeli / should answer OK
21at("AT+CWMODE=1") # istemci modu / station mode
22at('AT+CWJAP="AgAdi","Sifre123"', 20000) # Wi-Fi'ye bağlan / join Wi-Fi
23at("AT+CIFSR") # IP adresini sor / ask for the IP
24
25while True:
26 at("AT+CWLAP", 10000) # çevredeki ağları tara / scan nearby networks
27 time.sleep(30)ESP-01、NodeMCU、ESP32のどれを選ぶ?
| 項目 | ESP-01 | NodeMCU(ESP8266) | ESP32 DevKit |
|---|---|---|---|
| チップ | ESP8266 | ESP8266 | ESP32(デュアルコア) |
| 使えるGPIO | 4本(うち2本はTX/RX) | 約11本 | 約25本 |
| アナログ入力 | なし | 1本(A0) | 18チャンネル、12ビット |
| USBでの書き込み | 不可。USB-TTL変換モジュールが必要 | 可 | 可 |
| 電源 | 3.3 Vのみ | USBの5 VまたはVIN | USBの5 VまたはVIN |
| Bluetooth | 非対応 | 非対応 | 対応(ClassicとBLE) |
| サイズ | 24.8 × 14.3 mm | ブレッドボードに挿せるボード | ブレッドボードに挿せるボード |
| 向いている用途 | ArduinoへのWi-Fi追加、リレーやセンサー1つだけ | Wi-Fiの入門、センサー数個 | ピンを多く使うプロジェクトやBluetoothを使うプロジェクト |
ESP-01の最大の長所は、小ささと価格です。既存のArduinoプロジェクトにWi-Fiを追加したり、リレーやセンサー1つを無線化したりするのに最適です。ただしUSBがないので、書き込みのたびに配線をつなぎ替え、レギュレーターを用意し、GPIO0をGNDにつなぐのは手間がかかります。アナログ入力はなく、GPIO16も外に出ていないので、チップのピンに細い線をはんだ付けしない限り、ディープスリープからのタイマーでの復帰は使えません。電池で動かすプロジェクトを計画しているなら、平均電流を電池寿命計算ツールに入力すると、何日持つかがわかります。まだ学習中の場合や、3本より多くのピンが必要な場合は、NodeMCU ESP8266なら同じチップをUSBとレギュレーター付きで使えます。Bluetooth、もっと多くのピン、高い処理能力が必要ならESP32が適しています。ボードの比較はArduinoとESP32の違いは?で紹介しています。
ESP-01で作るプロジェクトのアイデア
- Wi-Fiスマートプラグ:ESP-01Sリレーモジュールと上のスケッチで、スマホから電球を点灯・消灯します。タイマーを追加すれば、夕方に自動で点灯させることもできます。
- ワイヤレス温度センサー:DS18B20センサーをGPIO2につなぎます。データ線の4.7 kΩのプルアップ抵抗が、起動時に必要なHIGHレベルも作ってくれます。
- 温湿度モニター:DHT11の測定値を、スマホで開くWebページに表示します。
- 動きの通知:PIRセンサーをGPIO3につなぎ、動きを検知したらTelegramでメッセージを送ります。方法はESP32のTelegramボットの記事とほぼ同じです。
- ArduinoのプロジェクトにWi-Fiを:Unoで作った気象ステーションの測定値を、ATコマンドでパソコンのプログラムやサーバーに送ります。
- ガレージのドアのリモコン:リレーの接点をドア開閉装置のボタンと並列につなぎ、スマホからドアを開けます。
よくある間違いと解決方法
| 症状 | 考えられる原因 | 解決方法 |
|---|---|---|
| エラー:「Failed to connect to ESP8266: Timed out waiting for packet header」(接続できず、パケットヘッダー待ちでタイムアウト) | モジュールが書き込みモードになっていない、またはTXとRXが逆 | GPIO0をGNDにつないでモジュールの電源を入れ直し、TXをRXDに、RXをTXDにつなぐ |
| シリアルモニタが文字化けする | ボーレートが合っていない。起動メッセージは74880ボー | 115200と9600を試す。起動メッセージを見るには74880を選ぶ |
| ATにまったく返答がない | 改行コードの設定違い、TXとRXが逆、またはENが未接続 | 「CRおよびLF」(Both NL & CR)を選び、線をクロスにして、ENを3.3 Vにつなぐ |
| モジュールがリセットを繰り返す、Wi-Fiへの接続中に切れる | 電流不足 | 別のAMS1117-3.3と100〜470 µFのコンデンサを使い、配線を短くする |
| 「busy p...」という返答 | 前のコマンドが終わる前に次のコマンドを送った | コマンドごとにOKかERRORの返答を待つ |
| 「+CWJAP:3」と「FAIL」 | ネットワークが見つからない(5 GHzのネットワーク、または名前の間違い) | 2.4 GHzのネットワークを使い、大文字と小文字に注意する |
| モジュールがとても熱くなり、LEDが点灯しない | VCCに5 Vをかけた、またはVCCとGNDを逆につないだ | すぐに電源を切る。モジュールはおそらく壊れている |
| リレーをつなぐとモジュールが起動しない | GPIO0やGPIO2につないだ回路が、起動時にピンをLOWに引っ張っている | アクティブLOWの接続にするか、入力をGPIO3に移す |
| 5 Vのリレーモジュールがオフにならない | 3.3 VのHIGHでは、5 Vモジュールのフォトカプラが完全にオフにならない | 3.3 V対応のリレーモジュールか、トランジスタを使った駆動回路を使う |
| Arduino IDEで書き込んだあと、ATコマンドが使えなくなった | 書き込んだプログラムでATファームウェアが上書きされた | esptoolやFlash Download Toolで、EspressifのATファームウェアを書き込み直す |
ESP-01は小さいながらも、IPアドレス、TCP接続、Webサーバー、シリアル通信といったWi-Fiの基本をひととおり学べる優れたモジュールです。うまく動かないときは、まず電源を、次にTX-RXの配線とGPIO0のレベルを確認してください。問題の大半はこの3点にあります。BlueGraysアプリには、Wi-Fi接続、Webサーバー、mDNS、無線アップデート(OTA)、リレーを使ったスマート照明などのプロジェクトが、ステップごとの回路図とコード付きでそろっています。
よくある質問
ESP-01は5Vで動きますか?
いいえ。ESP-01の動作電圧は3.0〜3.6 Vで、VCCピンに5 Vをつなぐとモジュールが恒久的に壊れることがあります。Arduinoの5 Vから給電したい場合は、間にAMS1117-3.3などのレギュレーターを入れ、UnoのTXラインから出る5 Vの信号も分圧回路で3.3 Vに下げてください。
ESP-01にArduinoの3.3Vピンから給電できますか?
おすすめしません。Unoの3.3 Vピンの公式な定格は50 mAですが、ESP-01は送信時に170 mA、短いピークでは300 mA以上を流します。ATコマンドに応答しても、ネットワークへの接続中にリセットしてしまいます。300〜500 mA以上を供給できる別の3.3 Vレギュレーターを使ってください。
ESP-01がATコマンドに応答しないのはなぜですか?
よくある原因は、ボーレートの間違い、シリアルモニタの改行コードが「CRおよびLF」(Both NL & CR)になっていない、TXとRXがクロスになっていない、EN(CH_PD)ピンが3.3 Vにつながっていない、のいずれかです。以前にArduino IDEからモジュールにプログラムを書き込んだ場合は、ATファームウェアが消えているので、もう一度書き込む必要があります。
Arduinoのコードを書き込むとESP-01のATファームウェアは消えますか?
はい。Arduino IDEから書き込んだプログラムは、ATファームウェアの代わりにフラッシュに書き込まれ、モジュールはATコマンドを理解しなくなります。ATモードに戻すには、EspressifのESP8266用ATファームウェアを、esptoolかFlash Download Toolを使って、モジュールのフラッシュサイズに合ったアドレスに書き込みます。
ESP-01とESP-01Sの違いは何ですか?
チップとピン配置は同じです。ESP-01Sはたいてい黒で、フラッシュは1 MB、電源LEDはなく、青色LEDはGPIO2につながっています。古い青いESP-01は、フラッシュが512 KBで、常に点灯する赤い電源LEDと、TXラインにつながった青色LEDがあります。
ESP-01のデフォルトのボーレートは?
最新のATファームウェアが入ったモジュールの多くは115200ボーで出荷されています。古いものでは9600や57600の場合もあります。ただし、起動時に最初に表示されるメッセージは74880ボーです。Arduino UnoでSoftwareSerialを使う場合は、AT+UART_DEF=9600,8,1,0,0で速度を9600に恒久的に下げると、通信が安定します。
この記事を読んだ後に作れるプロジェクト
全プロジェクトを見る
ESP32 Wi-Fi STA接続(LCDディスプレイ付き)
このプロジェクトでは、ESP32をステーション(STA)モードで家庭のWi-Fiネットワークに接続し、安全で障害に強い接続を実現します。SSIDとパスワードを別のsecrets.hファイルに保存してGitへの流出を防ぎ、自動再接続の仕組みを実装します。RSSIによる信号強度とIPアドレスはI2C LCDディスプレイに表示します。内蔵LEDは状態表示に使います。実運用を想定した接続管理の仕組みです。

ESP32非同期Webサーバー(LCDにIPアドレスを表示)
このプロジェクトでは、ESP32を同じWi-Fiネットワーク上のスマートフォンやパソコンから操作できる非同期Webサーバーにします。ESPAsyncWebServerライブラリを使うと、従来のWebServer.hのように1つのリクエストで処理がブロックされず、複数のリクエストを同時に処理できます。ブラウザーでESP32のIPアドレスを開き、ON/OFFボタン(/onと/offのルート)を押すと、GPIO 5に接続したLEDを点灯・消灯できます。

ESP32 mDNS:bluegrays-esp.localでデバイスにアクセス(LCD付き)
このプロジェクトでは、ESP32にmDNS(Multicast DNS)サービスを追加し、IPアドレスの代わりにbluegrays-esp.localのような覚えやすいホスト名でアクセスできるようにします。DHCPで割り当てられるIPアドレスが変わっても、同じ名前でデバイスにアクセスできます。小さなWebサーバーも動かし、ブラウザーでhttp://bluegrays-esp.local/を開いてLEDを操作します。I2C LCDディスプレイにはホスト名、IPアドレス、LEDの状態をトルコ語と英語で表示します。iOS、macOS、LinuxはmDNSに標準対応しています。

ESP32 OTA更新:無線でファームウェアを書き込み(LCD付き)
このプロジェクトでは、USBケーブルを使わず、Wi-Fi経由でESP32に新しいファームウェアを書き込む方法を学びます。ArduinoOTAライブラリを使うと、ESP32がネットワーク上で検出され、Arduino IDEの「ネットワークポート」タブにbluegrays-otaとして自動表示されます。初回はUSBで書き込み、その後の更新はすべて無線で行えます。設置済みのデバイスにとって非常に重要な機能です。I2C LCDディスプレイには、Wi-Fiの状態、IPアドレス、ホスト名、OTA書き込みの進捗率、エラーメッセージをトルコ語と英語で表示します。

ESP32とNTPでインターネットから正確な時刻を取得
ESP32をWi-Fiに接続し、NTP(Network Time Protocol)サーバーからミリ秒精度の現在時刻を取得します。configTzTime()関数でタイムゾーンを自動適用し、夏時間を採用する国ではPOSIX TZ文字列で夏時間と標準時間の切り替えも自動管理します。時刻はシリアルモニタと、必要に応じて接続するI2C LCDに表示します。configTzTime()がSNTPサービスを開始し、ネットワークにアクセスできる間は定期的に再同期します。

ESP32スマート照明(PIR + LDR + リレー + OLED)
ESP32で廊下やトイレ、食品庫の照明をスマート化します!PIRモーションセンサー、LDR光センサー、リレーモジュールを使い、「暗い場所で動きを検知すると点灯する」定番の仕組みを作ります。周囲が明るければ動きを検知しても点灯しないため、日中の無駄な電力消費を抑えられます。照明は30秒間点灯し、動きが続くとタイマーがリセットされて点灯時間が延びます。SSD1306 OLEDには大きな文字で状態(ON / DAYTIME / WAITING)とカウントダウンを表示します。

ボタンを押すたびに220V電球の点灯・消灯を切り替え
小さなボタンで、家庭の電球を点灯・消灯してみませんか?ボタンを押すとArduinoがリレーを切り替えて電球を点灯させ、もう一度押すと消灯させます。リレーは、ボードの弱い信号で家庭用電源を安全に切り替える仲介役です。220ボルトを扱う際は、必ず大人に手伝ってもらってください。

2台のArduinoで一方向通信
2台のArduinoを1本のワイヤーで通信させます。一方のボタンを押すともう一方のLEDが点灯し、もう一度押すと消灯します。送信側のボードがボタンの押下を短いメッセージで伝え、受信側のボードはそのメッセージを受け取るとLEDの点灯と消灯を切り替えます。機器同士が情報を伝える仕組みを、最もシンプルな形で確かめられます。
ほかの記事
BlueGraysアプリ
この回路をスマホでステップごとに作る
回路図、コード、部品リストを1つの画面で確認できます。Arduino、ESP32、Picoのプロジェクトを200件以上用意しています。

