部品 · 読了まで15分

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 ESP8266 Wi-Fiモジュール
ESP-01 Wi-Fiモジュール:ESP8266EXチップ、フラッシュメモリ、基板アンテナ(PCBアンテナ)、2×4に並んだ8本のピンが1枚の小さなボードに載っています。

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-Fi802.11 b/g/n、2.4 GHzのみ、基板アンテナ
動作電圧3.0〜3.6 V(推奨3.3 V)
電流接続中の平均70〜80 mA、送信時は約170 mA、瞬間的なピークは300 mA超
ディープスリープ時の電流約20 µA(チップ単体)
使えるGPIO4本:GPIO0、GPIO2、GPIO1(TX)、GPIO3(RX)
アナログ入力なし(ADCピンが外に出ていない)
サイズ24.8 × 14.3 mm
出荷時のファームウェアATコマンドのファームウェア(通常は115200ボー)

ESP-01とESP-01Sの違い

項目ESP-01ESP-01S
ボードの色たいてい青黒
フラッシュメモリ512 KB(後期の黒い版では1 MB)1 MB
電源LED赤、常に点灯なし
青色LEDTX(GPIO1)ラインにつながり、データ送信時に点滅GPIO2につながり、ピンがLOWのときに点灯
ピン配置8ピン同じ8ピンで完全に互換
消費電流電源LEDのぶん数mA多い少なめで、電池で動かすプロジェクトに向く

ESP-01のピン配置:8本のピンの役割

ESP-01には2×4に並んだ8本のピンがあり、そのうち入出力として使えるのは4本だけです。ピン名がボードに印刷されていないものもあるので、配線する前に手元のモジュールを販売元のピン配置図と見比べてください。VCCとGNDを逆につなぐと、モジュールは数秒で壊れます。各ピンの役割と、通常動作時の接続は次のとおりです。

ピン役割通常動作時の接続
VCC3.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Ωを通して)
RSTLOWでチップを再起動未接続、または10 kΩで3.3 Vにプルアップ
GPIO0起動モードを選び、その後は汎用の入出力起動時はHIGH(未接続)、書き込み時はGND
GPIO2汎用の入出力(ESP-01Sでは青色LED)起動時はHIGHのままにする
ESP-01は3.3 Vだけで動作し、チップの動作電圧の上限は3.6 Vです。VCCピンにArduinoの5 Vをつなぐと、モジュールが恒久的に壊れることがあります。また、Arduino UnoのTXピンは5 Vの信号を出すので、ESP-01のRXピンに直接つながず、分圧回路かレベル変換モジュールを通してください。

消費電流: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 UnoRaspberry Pi Picoメモ
VCCAMS1117-3.3の出力AMS1117-3.3または3V3(OUT)Unoの3.3 Vピンでは足りない。Picoの3V3出力の推奨上限は300 mA
GNDGNDGNDレギュレーター、ボード、モジュールでGNDを共通にする
TXD2GP1(UART0 RX)直接つなぐ
RXD3(1 kΩ / 2 kΩの分圧回路を通す)GP0(UART0 TX)Picoでは分圧回路は不要
EN(CH_PD)3.3 V3.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コマンドを送る

  1. 下のブリッジ用スケッチをUnoに書き込みます。ほとんどのモジュールはこの速度で出荷されているので、最初はESP_BAUDを115200にしてください(古いモジュールでは9600の場合もあります)。
  2. シリアルモニタを115200ボーで開き、改行コードをCRおよびLF(Both NL & CR)にします。この設定がないと、モジュールはコマンドの終わりを判断できません。
  3. ATと入力して送信すると、OKが返ってくるはずです。文字化けする場合は、速度が合っていません。
  4. SoftwareSerialは115200では安定して読み取れないので、AT+UART_DEF=9600,8,1,0,0でモジュールの速度を9600に恒久的に下げます。返答が文字化けして見えても、コマンドはたいてい届いています。
  5. スケッチのESP_BAUDを9600に変えてもう一度書き込み、ATコマンドを再度送ります。今度はOKがきれいに表示されるはずです。
  6. AT+GMRでファームウェアのバージョンを、AT+CWLAPで周囲のWi-Fiネットワークの一覧を確認し、モジュールが正常に動いていることを確かめます。
C++ (Arduino IDE)
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」
AT+CWJAPが失敗すると、モジュールは+CWJAP:1(タイムアウト)、+CWJAP:2(パスワードが違う)、+CWJAP:3(ネットワークが見つからない)、+CWJAP:4(接続失敗)のいずれかを表示し、続けてFAILと表示します。ESP8266が認識できるのは2.4 GHzのネットワークだけなので、ネットワークが見つからない場合は、ルーターで2.4 GHz帯が有効になっているか確認してください。コマンドは大文字で入力し、ネットワーク名とパスワードはダブルクォーテーションで囲みます。なお、日本では技適マークのない無線モジュールの使用は電波法で制限されているので、購入時に確認してください。

Arduino UnoとESP-01でスマホからLEDを操作する

ここからはATコマンドをプログラムにしていきます。下のスケッチはESP-01をネットワークに接続し、ポート80で小さなWebサーバーを立ち上げ、IPアドレスをシリアルモニタに表示します。同じWi-Fiにつないだスマホのブラウザにそのアドレスを入力すると、2つのボタンがあるページが開きます。ボタンでUnoの13番ピンにある内蔵LEDを点灯・消灯できます。LEDの代わりにリレーモジュールをつなげば、同じ方法で電球を操作できます。書き込む前に、前のステップでモジュールの速度を9600にしておいてください。

C++ (Arduino IDE)
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だけです。

GPIO0GPIO2GPIO15起動モード74880ボーで表示される起動メッセージ
HIGH(未接続)HIGHLOW通常動作:フラッシュ内のプログラムが起動「boot mode:(3,x)」(通常起動)
LOW(GND)HIGHLOW書き込み(UARTダウンロード)モード「boot mode:(1,x)」と「waiting for host」(ホストを待機中)
ESP-01のピン接続メモ
VCC3.3 Vレギュレーターの出力USB-TTL変換モジュールの3.3 Vピンではたいてい足りない
GNDUSB-TTLのGNDとレギュレーターのGNDすべて共通のグラウンドにする
TXUSB-TTLのRXDクロス接続
RXUSB-TTLのTXDジャンパーは3.3 V側にする
EN(CH_PD)3.3 V直接、または10 kΩを通して
RST未接続(リセットするときだけ一瞬GNDへ)必要なら10 kΩで3.3 Vにプルアップ
GPIO0GND書き込み中だけ。終わったら外す
GPIO2未接続起動時はHIGHのままにする
  1. Arduino IDEで「ファイル」>「基本設定」を開き、「追加のボードマネージャのURL」欄に次のアドレスを追加します:https://arduino.esp8266.com/stable/package_esp8266com_index.json
  2. ボードマネージャでesp8266を検索し、ESP8266 Communityのパッケージをインストールします。
  3. 「ツール」>「ボード」からGeneric ESP8266 Moduleを選びます。Flash Sizeは、ESP-01Sなら1MB (FS:64KB OTA:~470KB)、古い青いESP-01なら512KBの選択肢のどれかにします。
  4. USB-TTL変換モジュールのジャンパーを3.3 Vにし、上の表のとおりにモジュールを配線して、GPIO0はGNDにつないだままにします。
  5. モジュールの電源をいったん切って入れ直すか、RSTを一瞬GNDに触れさせます。これでモジュールが書き込みモードで起動します。
  6. 「ツール」>「ポート」でUSB-TTL変換モジュールのポートを選び、スケッチを書き込みます。最初のテストには「ファイル」>「スケッチ例」>「ESP8266」>「Blink」がおすすめです。ESP-01Sでは青色LEDがGPIO2につながっています。
  7. 「Hard resetting via RTS pin...」(RTSピンでリセット中)と表示されたら、GPIO0をGNDから外してモジュールを再起動します。GPIO0がGNDにつながったままだとプログラムは動かず、モジュールはまた書き込みモードで起動します。
書き込みを楽にするなら、CH340とAMS1117を搭載したESP-01用USBアダプターが使えます。モジュールをそのまま挿すだけです。こうしたアダプターの中にはUART/PROGの切り替えスイッチ付きのものがあります。スイッチのないモデルでは、GPIO0とGNDの間にボタンかジャンパーをはんだ付けする必要があります。USB-TTL変換モジュールがない場合は、Arduino UnoのRESETピンをGNDにつなぎ、ボードのUSBチップを橋渡しとして使うこともできます。この場合はTXをTXへ、RXをRXへそのままつなぎ、5 Vの信号はやはり分圧して下げる必要があります。詳しくはUSB-TTL変換モジュールの記事を参照してください。

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で動かすのにちょっとした改造が必要な場合があるので、手元のボードのバージョンを確認してください。

5 Vリレーモジュール
リレーを使うと、小さな制御信号で230 Vの電球を点灯・消灯できます(日本の商用電源は100V(50/60Hz)です)。ESP-01Sリレーボードでは、同じ種類のリレーがESP-01のGPIO0ピンにつながっています。
C++ (Arduino IDE)
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でも開けます。

リレーの接点に商用電源をつなぐ場合は、必ず電源を切った状態で配線し、むき出しの接点を残さず、回路を絶縁されたケースに収めてください。リレーに10 Aと書かれていても、小さなボードの銅箔パターンはその電流に耐えられないことがあります。数百ワットを超える負荷はこのモジュールで駆動しないでください。詳しくはリレーモジュールとは?を参照してください。

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サーバーの記事を参照してください。

MicroPython
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-01NodeMCU(ESP8266)ESP32 DevKit
チップESP8266ESP8266ESP32(デュアルコア)
使えるGPIO4本(うち2本はTX/RX)約11本約25本
アナログ入力なし1本(A0)18チャンネル、12ビット
USBでの書き込み不可。USB-TTL変換モジュールが必要可可
電源3.3 VのみUSBの5 VまたはVINUSBの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ファームウェアを書き込み直す
モジュールが本当に起動しているかを確かめるには、シリアルモニタを74880ボーにしてモジュールをリセットします。boot mode:(3,x)と表示されれば通常モード、boot mode:(1,x)なら書き込みモードで起動しています。何も表示されない場合は、電源、ENの接続、TX-RXの配線のどれかに問題があります。

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ディスプレイ付き)
#127上級

ESP32 Wi-Fi STA接続(LCDディスプレイ付き)

このプロジェクトでは、ESP32をステーション(STA)モードで家庭のWi-Fiネットワークに接続し、安全で障害に強い接続を実現します。SSIDとパスワードを別のsecrets.hファイルに保存してGitへの流出を防ぎ、自動再接続の仕組みを実装します。RSSIによる信号強度とIPアドレスはI2C LCDディスプレイに表示します。内蔵LEDは状態表示に使います。実運用を想定した接続管理の仕組みです。

4.4(21)
34
ESP32非同期Webサーバー(LCDにIPアドレスを表示)
#129上級

ESP32非同期Webサーバー(LCDにIPアドレスを表示)

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

4.8(16)
26
ESP32 mDNS:bluegrays-esp.localでデバイスにアクセス(LCD付き)
#131上級
プレミアム

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に標準対応しています。

4.8(14)
23
ESP32 OTA更新:無線でファームウェアを書き込み(LCD付き)
#132上級
プレミアム

ESP32 OTA更新:無線でファームウェアを書き込み(LCD付き)

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

4.6(14)
22
ESP32とNTPでインターネットから正確な時刻を取得
#128上級
プレミアム

ESP32とNTPでインターネットから正確な時刻を取得

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

4.5(13)
21
ESP32スマート照明(PIR + LDR + リレー + OLED)
#141上級
プレミアム

ESP32スマート照明(PIR + LDR + リレー + OLED)

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

4.3(6)
11
ボタンを押すたびに220V電球の点灯・消灯を切り替え
#20上級
プレミアム

ボタンを押すたびに220V電球の点灯・消灯を切り替え

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

4.5(33)
44
2台のArduinoで一方向通信
#57中級
プレミアム

2台のArduinoで一方向通信

2台のArduinoを1本のワイヤーで通信させます。一方のボタンを押すともう一方のLEDが点灯し、もう一度押すと消灯します。送信側のボードがボタンの押下を短いメッセージで伝え、受信側のボードはそのメッセージを受け取るとLEDの点灯と消灯を切り替えます。機器同士が情報を伝える仕組みを、最もシンプルな形で確かめられます。

4.4(37)
50