ESP8266-01とArduino Nanoで作るIoTデバイス:完全ガイド
部品と材料
| 部品 | 数量 | 備考 |
|---|---|---|
| Arduino Nano R3 | 1 | |
| PCBWay カスタムPCB | 1 | オプション |
| Espressif ESP8266 ESP-01 | 1 | |
| 2チャネル リレーモジュール | 1 | |
| LED(汎用) | 2 | |
| ブレッドボード | 1 | |
| ジャンパーワイヤー | 1式 | |
| 抵抗 1kΩ | 2 | |
| 抵抗 2.21kΩ | 1 |
必要な工具と機器
- はんだごて
- 鉛フリーはんだ
- フラックス
使用アプリとオンラインサービス
- Arduino IDE
- Microsoft Visual Studio Code(オプション)
- Autodesk Eagle(オプション、PCB設計用)
プロジェクト概要
はじめに
今回は、インターネットに接続してWi-Fi経由で家電をリモート制御できるデバイスを作ります。Arduinoボード(どのモデルでも可)とESP8266-01 Wi-Fiモジュールを使用します。
スマートホームとは?
Webベースのコントロールパネルから家電を操作できるシステムです。
動作シナリオ

コントロールパネル(Webページ)
HTML、CSS、jQueryでシンプルなWebページを作成し、ユーザーが家電を操作できるようにします。
組み込みハードウェア
Webページから送信された命令をESP8266-01(Webサーバーとして動作)が受信し、Arduinoに伝達。Arduinoは受信データに基づいて照明のON/OFFなどのアクションを実行します。
ESP8266-01の基本
Arduino NanoにはWi-Fi機能がないため、ESP8266-01で補います。ESPファミリーには多くのモデルがありますが、ESP8266-01は以下の理由で選びました:
- メイカーコミュニティで非常に有名で、オンライン情報が豊富
- 価格が安い(約1.5ドル)
- シリアル通信でArduinoと簡単に接続可能
- 内蔵マイクロコントローラーを持ち、単体でもWi-Fiモジュール付きMCUとして動作可能
- GPIOが2本内蔵

ESP8266-01 ピンアウト

| ピン | 機能 |
|---|---|
| VCC | +3.3V電源(5V接続厳禁、破損の原因) |
| GND | グランド |
| CH_PD | チップイネーブル、Highで起動 |
| RST | リセット、Lowでリセット |
| GPIO0, GPIO2 | 汎用入出力 |
| Tx | ArduinoのRxに接続 |
| Rx | ArduinoのTxに接続 |
ESP8266-01の設定
ESP8266-01はシリアル通信でArduinoと通信しますが、Arduinoのハードウェアシリアル(ピン0,1)はデバッグ用シリアルモニタで使用中です。そこでSoftwareSerialライブラリを使い、別のデジタルピン(例:ピン2,3)でソフトウェアシリアルを構築します。
ただし、ESP8266-01の出荷時ボーレートは115,200bpsで、SoftwareSerialではこの速度での通信が不安定です。ATコマンドで9600bpsに変更する必要があります。
通信速度の変更手順
ステップ1:Arduinoに空のスケッチをアップロード

Arduino側で何も実行されていない状態を作ります。
ステップ2:ESP8266-01をArduinoに配線

Arduinoのハードウェアシリアル(ピン0,1)をESP8266-01に直結し、ATコマンドを送信します。
重要なATコマンド

コマンド「4」はファームウェアバージョンによります。AT+CIOBAUD=<baud>が効かない場合はAT+UART_DEF=<baud>,8,1,0,0を試してください。
ステップ3:シリアルモニタで設定
- シリアルモニタを開く
- ボーレートを115,200に設定、「Both NL & CR」を選択
ATを送信し、OKが返ってくるか確認AT+UART_DEF=9600,8,1,0,0(またはAT+CIOBAUD=9600)を送信し、OKを確認- シリアルモニタのボーレートを9600に変更し、再度
ATで動作確認
ステップ4:Wi-Fiネットワークへ接続
AT+CWJAP="SSID","PASSWORD"で接続。成功時はWIFI CONNECTED、WIFI GOT IPが返ります。
インターネットの仕組み(基礎知識)
インターネットは地中に埋設されたケーブル(光ファイバー、銅線、または衛星)のネットワークです。このケーブルに直接接続されたコンピューターをサーバー、間接的に接続されたものをクライアントと呼びます。サーバーには固有のIPアドレスがあり、ドメイン名で管理されます。
Webページの構築
HTML(構造)、CSS(スタイル)、JavaScript/jQuery(インタラクション)でコントロールパネルを作成します。
HTML構造
<!DOCTYPE html>
<html>
<head>
<title>Smart Home System</title>
</head>
<body>
<h1> Smart Home Control Panel</h1>
<h4>Sorry But I'm a Meme Addict!</h4>
<img src="dogMeme.jpg" width="400px" height="400px">
<br>
<button id="111" class="button">LAMP ON</button>
<br>
<button id="110" class="button">LAMP OFF</button>
</body>
</html>
CSSスタイリング
<body style="background-color: seagreen; color: seashell; text-align: center;">
<h1> Smart Home Control Panel</h1>
<h4>Sorry But I'm a Meme Addict!</h4>
<img src="dogMeme.jpg" width="400px" height="400px">
<br>
<button style="margin: 10px;" id="111" class="button">LAMP ON</button>
<br>
<button style="margin:10px;" id="110" class="button"> LAMP OFF</button>
</body>
jQueryでWebサーバーへリクエスト送信
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(".button").click(function () {
var p = $(this).attr('id'); // ボタンのid取得
$.get("https://192.168.1.4:80/", { pin: p }); // GETリクエスト送信
// 注意: IPアドレスはご自身のESP8266のIPに変更してください
});
</script>
ボタンIDの設計思想: 111(ピン11をON)、110(ピン11をOFF)のように、上2桁がArduinoピン番号、最後の1桁が状態(1=ON, 0=OFF)を表します。Arduino側でこれを分解してdigitalWrite(pinNumber, pinState)で制御します。
負荷の接続(LEDでテスト)

LEDのアノードをArduinoデジタルピン11、カソードを1kΩ抵抗経由でGNDに接続。
Arduinoスケッチ
#include <SoftwareSerial.h>
SoftwareSerial esp8266(2, 3); // Rx=Pin2, Tx=Pin3
#define serialCommunicationSpeed 9600
#define DEBUG true
int redLED = 12;
int blueLED = 11;
void setup() {
pinMode(redLED, OUTPUT);
pinMode(blueLED, OUTPUT);
digitalWrite(redLED, LOW);
digitalWrite(blueLED, HIGH);
Serial.begin(serialCommunicationSpeed);
esp8266.begin(serialCommunicationSpeed);
InitWifiModule();
digitalWrite(blueLED, LOW);
}
void loop() {
if (esp8266.available()) {
if (esp8266.find("+IPD,")) {
delay(1000);
int connectionId = esp8266.read() - 48;
esp8266.find("pin=");
int pinNumber = (esp8266.read() - 48) * 10;
pinNumber += (esp8266.read() - 48);
int statusLed = (esp8266.read() - 48);
digitalWrite(pinNumber, statusLed);
Serial.println(connectionId);
Serial.print(pinNumber); Serial.print(" "); Serial.println(statusLed);
String closeCommand = "AT+CIPCLOSE=";
closeCommand += connectionId;
closeCommand += "\r\n";
sendData(closeCommand, 1000, DEBUG);
}
}
}
String sendData(String command, const int timeout, boolean debug) {
String response = "";
esp8266.print(command);
long int time = millis();
while ((time + timeout) > millis()) {
while (esp8266.available()) {
char c = esp8266.read();
response += c;
}
}
if (debug) Serial.print(response);
return response;
}
void InitWifiModule() {
sendData("AT+RST\r\n", 2000, DEBUG);
sendData("AT+CWJAP=\"YOUR_SSID\",\"YOUR_PASSWORD\"\r\n", 2000, DEBUG);
delay(3000);
sendData("AT+CWMODE=1\r\n", 1500, DEBUG);
delay(1000);
sendData("AT+CIFSR\r\n", 1500, DEBUG);
delay(1000);
sendData("AT+CIPMUX=1\r\n", 1500, DEBUG);
delay(1000);
sendData("AT+CIPSERVER=1,80\r\n", 1500, DEBUG);
}
注意: コード内のYOUR_SSIDとYOUR_PASSWORDをご自身のWi-Fi情報に書き換えてください。
動作確認
コードをアップロード後、シリアルモニタを開きます。OKが表示されIPアドレスが取得できていれば成功です。Webページを開いて操作を試してください。FAILやERRORが出る場合はSSID/パスワードを見直してください。
高電圧負荷(家電)の制御:リレーの使用

リレーは低電圧信号(5V/0V)で高電圧回路を切り替える機械式スイッチです。エアコンや照明などのAC負荷を制御するには必須です。

2チャネルリレーモジュールのIN1, IN2をArduinoデジタルピン11, 12に接続。負荷側はCOM(コモン)とNO(常時開放)またはNC(常時閉鎖)を使用します。


Webページ拡張(2つの負荷制御)
<button id="111" class="button">Blue LED ON</button>
<button id="110" class="button">Blue LED OFF</button>
<br>
<button id="121" class="button">Red LED ON</button>
<button id="120" class="button">Red LED OFF</button>
IDのルール:121=ピン12 ON、120=ピン12 OFF。
プロフェッショナル化:PCB化
ブレッドボード回路をPCB(プリント基板)化して堅牢性を向上。Autodesk Eagleで設計し、PCBWayで製造可能です。
プロジェクトファイル: PCBWay共有ページ


トラブルシューティング
- ESPがWi-Fi接続済みでもボタンが効かない場合:
- Webブラウザからポート80(HTTP)でリクエスト送信しているか確認
- PCとESPが同じアクセスポイントに接続されているか確認
- jQueryコードのIPアドレスが正しいか確認
- 負荷がArduinoピン11, 12に接続されているか確認
- Webページコード修正後は保存し、ブラウザでリロード
まとめ
HTML/CSS/jQueryでWebページ作成、ESP8266-01をWebサーバーとして動作させ、Arduinoで家電を無線制御する一連の流れを学びました。詳細はブログ www.makesomestuff.org をご覧ください。ご質問はコメント欄へどうぞ!
コード一覧
Webページ(HTML + jQuery)
<!DOCTYPE html>
<html>
<head>
<title>Smart Home System</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body style="background-color: seagreen; color: seashell; text-align: center;">
<h1> Smart Home Control Panel</h1>
<h4>Sorry But I'm a Meme Addict!</h4>
<img src="dogMeme.jpg" width="400px" height="400px">
<br>
<button style="margin: 10px;" id="111" class="button">Blue LED ON</button>
<button id="110" class="button">Blue LED OFF</button>
<br>
<button style="margin:10px;" id="121" class="button"> Red LED ON</button>
<button id="120" class="button">Red LED OFF</button>
<script>
$(".button").click(function () {
var p = $(this).attr('id');
$.get("https://192.168.1.4:80/", { pin: p });
});
</script>
</body>
</html>
最終Arduinoコード
#include <SoftwareSerial.h>
SoftwareSerial esp8266(2,3);
#define serialCommunicationSpeed 9600
#define DEBUG true
int redLED =12;
int blueLED =11;
void setup() {
pinMode(redLED,OUTPUT);
pinMode(blueLED,OUTPUT);
digitalWrite(redLED,LOW);
digitalWrite(blueLED,HIGH);
Serial.begin(serialCommunicationSpeed);
esp8266.begin(serialCommunicationSpeed);
InitWifiModule();
digitalWrite(blueLED,LOW);
}
void loop() {
if(esp8266.available()) {
if(esp8266.find("+IPD,")) {
delay(1000);
int connectionId = esp8266.read()-48;
esp8266.find("pin=");
int pinNumber = (esp8266.read()-48)*10;
pinNumber = pinNumber + (esp8266.read()-48);
int statusLed =(esp8266.read()-48);
digitalWrite(pinNumber, statusLed);
Serial.println(connectionId);
Serial.print(pinNumber);
Serial.print(" ");
Serial.println(statusLed);
String closeCommand = "AT+CIPCLOSE=";
closeCommand+=connectionId;
closeCommand+="\r\n";
sendData(closeCommand,1000,DEBUG);
}
}
}
String sendData(String command, const int timeout, boolean debug) {
String response = "";
esp8266.print(command);
long int time = millis();
while( (time+timeout) > millis()) {
while(esp8266.available()) {
char c = esp8266.read();
response+=c;
}
}
if(debug) Serial.print(response);
return response;
}
void InitWifiModule() {
sendData("AT+RST\r\n", 2000, DEBUG);
sendData("AT+CWJAP=\"YOUR_SSID\",\"YOUR_PASSWORD\"\r\n", 2000, DEBUG);
delay(3000);
sendData("AT+CWMODE=1\r\n", 1500, DEBUG);
delay(1500);
sendData("AT+CIFSR\r\n", 1500, DEBUG);
delay(1500);
sendData("AT+CIPMUX=1\r\n", 1500, DEBUG);
delay(1500);
sendData("AT+CIPSERVER=1,80\r\n", 1500, DEBUG);
}
回路図


製造プロセス
- TinyML言語検出器:Edge ImpulseとArduino Nano 33 BLE Senseで「はい」を多言語判別
- Arduino NanoとMPU-6050で作るリアルタイムジャイロスコープゲーム
- Arduinoデジタルダイス: LCD表示の乱数ジェネレーター自作
- Arduinoで超音波レベーション(浮遊)装置を自作:ステップバイステップガイド
- Arduinoとスマホで作るスマート電圧計 – 簡単DIYプロジェクト
- ArduinoとMAX30100で作るリアルタイムIoT心拍数モニター
- ESP8266・Arduino・超音波センサーで作るスマートIoTジャー:リアルタイム中身監視
- Arduino超音波センサーとProcessingで作るリアルタイム距離測定ソナー
- Bolt IoTとArduino UNOでLED輝度をシームレス制御
- Arduino IoT CloudとAlexaでテレビを音声操作:ステップバイステップガイド
- Arduino NanoとRDA5807Mで作るコンパクトFMラジオ