ESP8266
ESP8266EX
●開発ボード
チップ:ESP8266(
ESP-12F) 32-bit 80/160MHz
Flashメモリ:4MB
WiFi:802.11b/g/n ※技適なし
サイズ:約34.2×25.6mm
重量:約3g
電源:3.3V(最大500mA)または5V
microUSB端子:USB-シリアル変換チップ(CH340)搭載
デジタル入出力ピン:11本。また、D0端子(GPIO16)を除く全ての端子でPWMに対応。入出力は3.3V。
アナログ入力ピン:1本。入力電圧は最大3.2V、AD変換の分解能は10ビットとなる。
UART(UART1はTXのみ)、I2C、SPI

ピン GPIO 機能
TX 1 UART0_TX
RX 3 UART0_RX
D1 5 SCL(I2C)
D2 4 SDA(I2C)
D3 0 FLASH、SPI_CS2、プルアップ
D4 2 オンボードLED、UART1_TXD、プルアップ
D5 14 SCLK(SPI)
D6 12 MISO(SPI)
D7 13 MOSI(SPI)、UART0_CTS
D8 15 SS(SPI)、UART0_RTS、10kプルダウン
D0 16 WAKE ※RSTピンに接続してDeep Sleepをウェイクアップ
A0 A0 アナログ入力(最大3.2V)
回路図
・CPU:ESP8266EX
・電源電圧:3.0~3.6V
・消費電流:平均80mA
・対応WiFiプロトコル:802.11b/g/n(2.4GHz)
・サイズ:18mm×20mm×3mm
・端子ピッチ:1.5mm
・Wi-Fiモード:station/softAP/SoftAP+station
・セキュリティ:WPA/WPA2
・暗号化:WEP/TKIP/AES
・内蔵フラッシュ:2MB
・工事設計認証(技適)番号:206-000519
ESP-WROOM-02 PDFデータシート
・CPU:ESP8266EX
・電源電圧:DC2.7~3.6V
・消費電流:平均80mA
・対応WiFiプロトコル:802.11b/g/n(2.4GHz)
・サイズ:18mm×20mm×3mm
・端子ピッチ:1.5mm
・Wi-Fiモード:station/softAP/SoftAP+station
・セキュリティ:WPA/WPA2
・暗号化:WEP/TKIP/AES
・内蔵フラッシュ:2MB
・工事設計認証(技適)番号:201-171000
ESP-WROOM-02D PDFデータシート
●Arduino IDEでの開発
1.Arduino IDEをインストール
2.Arduino IDE を起動し、ファイルメニューの環境設定を開きます。
設定タブにて、「追加のボードマネージャーのURL」に下記のURLを貼り付けOKボタンを押します。
https://arduino.esp8266.com/stable/package_esp8266com_index.json
3.ツールメニューのボードからボードマネージャを開きます。
一覧が表示されたら「ESP8266」を検索しインストールボタンを押します。
4.インストールが完了したら、再度、ツールメニューから以下の項目を選択します。
ボート:"Generic ESP8266 Module" ※D1 miniの場合は、LOLIN(WEMOS)D1 R2 & miniを選択する。
シリアルポート: ※デバイスマネージャで確認
5.書き込み等の確認は、ファイルメニューのスケッチ例からサンプルを読み込み
コンパイルおよび、書き込みを行う。
●ESP8266チップ情報確認
下記のスケッチを使用してシリアル出力することができます。
#include <ESP8266WiFi.h>
void setup(void) {
delay(1000);
Serial.begin(115200);
Serial.println();
Serial.println("-----ESP-WROOM-02 ( ESP8266 ) Chip Infomation -----");
Serial.println();
Serial.print("Core Version = ");
Serial.println(ESP.getCoreVersion());
Serial.print("CPU Frequency = ");
Serial.print(ESP.getCpuFreqMHz());
Serial.println(" MHz");
Serial.print("ChipID = ");
Serial.println(ESP.getChipId(), HEX); //MACアドレスの下位3バイト
Serial.print("Flash ID = ");
Serial.println(ESP.getFlashChipId(), HEX);
Serial.print("SDK version = ");
Serial.println(ESP.getSdkVersion());
Serial.print("Boot version = ");
Serial.println(ESP.getBootVersion());
Serial.print("Boot Mode = ");
Serial.println(ESP.getBootMode());
Serial.print("Flash Chip IDE Size = ");
Serial.print(ESP.getFlashChipSize()); //Arduino IDE 設定の Flash Size になる
Serial.println(" byte");
Serial.print("Flash Chip Real Size = ");
Serial.print(ESP.getFlashChipRealSize()); //ESP-WROOM-32 内蔵最大 Flash Size になる
Serial.println(" byte");
Serial.print("Flash Frequency = ");
Serial.print(ESP.getFlashChipSpeed());
Serial.println(" Hz");
String mode_str;
switch( ESP.getFlashChipMode() ){
case 0: mode_str = "QIO"; break;
case 1: mode_str = "QOUT"; break;
case 2: mode_str = "DIO"; break;
case 3: mode_str = "DOUT"; break;
case 4: mode_str = "Unknown"; break;
default: break;
}
Serial.println("Flash Chip Mode = " + mode_str);
Serial.print("Free Heap Size = ");
Serial.println(ESP.getFreeHeap());
Serial.print("Free Sketch Size = ");
Serial.println(ESP.getFreeSketchSpace());
Serial.print("Sketch Size = ");
Serial.println(ESP.getSketchSize());
Serial.println();
uint8_t mac0[6];
WiFi.macAddress(mac0);
Serial.printf("WiFi StationAP Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac0[0], mac0[1], mac0[2], mac0[3], mac0[4], mac0[5]);
uint8_t mac1[6];
WiFi.softAPmacAddress(mac1);
Serial.printf("WiFi SoftAP Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac1[0], mac1[1], mac1[2], mac1[3], mac1[4], mac1[5]);
}
void loop() {
}
●UART
UART0とUART1が使用できるが、UART1については送信のみとなる。また、設定できるピン番号が決まっている。
#define SERIAL_MODE SERIAL_FULL //SERIAL_RX_ONLY, SERIAL_TX_ONLY デフォルトはFULL
#define TX_PIN 1 //(TX,RX) 1:(1,3) 2:(2,3) 15:(15,13) デフォルトは1
#define INVERT false //TX、RXピンを入れ替え
#define RX_BUFFER_SIZE 128 //受信バッファサイズ デフォルトは256
void setup() {
Serial.begin(115200, SERIAL_8N1, SERIAL_MODE, TX_PIN, INVERT); //UART0設定
Serial.pins(1, 3); //TX,RXピン指定
Serial.setRxBufferSize(RX_BUFFER_SIZE); // 受信バッファサイズ変更
int buffSize = Serial.getRxBufferSize(); // 受信バッファサイズ取得
Serial1.begin(115200, SERIAL_8N1); //UART1設定 送信のみとなりピン番号もGPIO2固定
delay(3000);
Serial.println();
Serial.print("HelloWorld! RxBufferSize= "); //UART0送信
Serial.println(buffSize);
Serial1.println("Send LogData"); //UART1送信
}
●ソフトウェアSerial
ソフト的にシリアル通信を実装することで上記のハード的なUARTとは別で通信を追加できます。
2ポートまでサポートしていますがその場合、ボーレートは57600bpsまでとなります。
#include <SoftwareSerial.h>
#define SwSeriRxPin 2 //ソフトウェアシリアル RX pin
#define SwSeriTxPin 3 //ソフトウェアシリアル TX pin
#define SwSeriBps 38400 //ソフトウェアシリアル 速度bps
SoftwareSerial SwSerial(SwSeriRxPin, SwSeriTxPin); //RX, TX
void setup() {
Serial.begin(115200);
SwSerial.begin(SwSeriBps, SWSERIAL_8N1); //ソフトウェアシリアルの初期化
}
void loop() {
if(SwSerial.available()) { //受信確認
byte c = SwSerial.read(); //1バイト受信
Serial.write(c);
}
if(Serial.available()) {
byte c = Serial.read();
SwSerial.write(c); //1バイト送信
}
}
//Serialから入力された文字をswSer1とswSer2に送信します。
//ピン14と12、ピン13とピン15を結線してループバックすることでにてSerialにエコーされます。
#include <SoftwareSerial.h>
SoftwareSerial swSer1(14, 12); // pins Rx GPIO14 (D5) and Tx GPIO 12 (D6)
SoftwareSerial swSer2(13, 15);
void setup() {
Serial.begin(115200);
swSer1.begin(57600);
swSer2.begin(57600);
Serial.println("\nESP8266 Software serial test started");
}
void loop() {
while (swSer1.available() > 0) {
Serial.write("1>");
Serial.println((char)swSer1.read());
}
while (Serial.available() > 0) {
char ch = Serial.read();
swSer1.write(ch);
swSer2.write(ch);
}
while (swSer2.available() > 0) {
Serial.write("2>");
Serial.println((char)swSer2.read());
}
}
●I2C
SDA、SCLはすべてのピンで使用可能です。
#include <Wire.h>
void setup(){
Serial.begin(115200);
Wire.begin(); //SDA=2, SCL=14
}
void loop() {
Wire.requestFrom(0x21, 1); //request 1 bytes from Slave ID #21
while (Wire.available()) {
byte b = Wire.read();
Serial.println(b);
}
delay(500);
}
//I2Cスレーブとして使用する場合
#include <Wire.h>
byte b=0;
void requestEvent() {
Wire.write(b++);
}
void setup() {
Serial.begin(115200);
Wire.begin(0x21); //Slave ID #21
Wire.onRequest(requestEvent);
}
void loop() {
}
●SPI
3つのSPIがありそれぞれ、汎用SPI(スレーブ/マスター)、SDIO/SPI(スレーブ)、汎用HSPI(スレーブ/マスター)になります。
・4-Wires
GPIO16 CS(SS) —– CSB
GPIO14 SCLK —– SCK
GPIO13 MOSI(Master Output Slave Input) —– SDI (Slave Data Input)
GPIO12 MISO(Master Input Slave Output) —– SDO (Slave Data Output)
・3-Wire
GPIO14 SCK —– SCK
GPIO13 SD —– SDA
GPIO15 CS —– WS
#include <SPI.h>
void setup() {
Serial.begin(115200);
SPI.begin(); //SPI_SCK, SPI_MISO, SPI_MOSI, SPI_SS
SPI.setFrequency(1000000); //クロック周波数
//SPI.setClockDivider(SPI_CLOCK_DIV2); //SPIクロック分周器を設定 2、4、8、16、32、64、128 通常は使用しない
SPI.setDataMode(SPI_MODE1); //MODEは0から3
SPI.setBitOrder(MSBFIRST); //最上位ビットから送信。LSBFIRST 最下位ビットから
}
void loop() {
uint8_t send = 0x40;
uint8_t recv;
recv = SPI.transfer(send); //1バイト送受信
uint16_t send16 = 0x4041;
uint16_t recv16;
recv16 = SPI.transfer16(send16); //2バイト送受信
uint8_t buf[] = {0x40, 0x41, 0x42, 0x43};
SPI.transfer(buf, sizeof(buf)); //バッファ送受信
//recv = SPI.transfer(0); //受信のみしたい場合でもダミーの送信データを送る
Serial.printf("SPI tx=%d\n", send);
Serial.printf("SPI rx=%d\n", recv);
delay(1000);
}
●WiFi
ESP32とほぼ同等のスケッチで同様の機能が実現できます。
/* WiFi AP+STA
ESP8266をWiFi子機として使用
*/
#include <ESP8266WiFi.h>
#define AP_SSID "aaaa" //親機
#define AP_PW "bbbb"
#define SOFTAP_SSID "cccc" //子機(ESP8266)
#define SOFTAP_PW "dddd"
void setup() {
Serial.begin(115200);
Serial.println("");
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(SOFTAP_SSID, SOFTAP_PW);
WiFi.begin(AP_SSID, AP_PW);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(". ");
}
Serial.println("connected!");
}
void loop() {
// do nothing
}
/* WiFi AP+WebServer
ESP8266でWeb Serverを起動
*/
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#define WIFI_SSID "Your Network's SSID"
#define WIFI_PWD "Password goes here"
ESP8266WebServer server(80);
// HTML
#define HTML_HEADER "<!doctype html>"\
"<html><head><meta charset=\"UTF-8\"/>"\
"<meta name=\"viewport\" content=\"width=device-width\"/>"\
"</head><body>"
#define HTML_FOOTER "</body></html>"
void setup() {
Serial.begin(115200);
WiFi.begin(WIFI_SSID, WIFI_PWD);
// Wait until WiFi is connected
Serial.println("");
while(WiFi.status() != WL_CONNECTED){
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("Connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// Setup WebServer Handlers
server.on("/", [](){
String html = HTML_HEADER "<h1>NodeMCU!</h1>" HTML_FOOTER;
server.send(200, "text/html", html);
});
server.on("/led/on", [](){
String html = HTML_HEADER "<h1>LED ON</h1>" HTML_FOOTER;
server.send(200, "text/html", html);
});
server.on("/led/off", [](){
String html = HTML_HEADER "<h1>LED OFF</h1>" HTML_FOOTER;
server.send(200, "text/html", html);
});
server.begin();
}
void loop() {
server.handleClient();
}
●PWM出力
ハード的には実装されておらずソフト的にハードウェアタイマからの割り込みを使用して実現しています。
スケッチ自体はArduinoと共通です。
#define PWM_PIN 2 //0~16ピンが設定可
#define PWM_FREQ 1000 //frequency(Hz) default:1000
#define PWM_RANGE 1023 //range default:1023
#define DUTY 50 //Duty default:255 ※ただし、255に設定しても90%が最大となる
void setup() {
Serial.begin(115200);
// Initialize PWM
analogWriteFreq(PWM_FREQ);
analogWriteRange(PWM_RANGE);
}
void loop() {
analogWrite(PWM_PIN, DUTY); //PWM出力
delay(1000);
analogWrite(PWM_PIN, 0); //PWM停止
delay(1000);
}
●ADC
アナログ入力は1回路のみになり端子はA0となります。
分解能は10bit、入力電圧範囲は0V〜1.0Vまでです。
アッテネーターがないので、1V以上の電圧を入力する際は外部で抵抗分圧する必要があります。
void setup() {
Serial.begin(115200);
}
void loop() {
int val = analogRead(A0);
Serial.println(val);
delay(500);
}
●赤外線通信 IrDA
IRremoteESP8266ライブラリを使って比較的簡単に使用できます。
//受信
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>
const uint16_t kRecvPin = 12; //受信ピン
const uint16_t kCaptureBufferSize = 1024; //バッファサイズ
const uint8_t kTimeout = 50; //タイムアウト時間
const uint16_t kFrequency = 38000; //赤外線周波数
decode_results results; //結果格納変数
IRrecv irrecv(kRecvPin, kCaptureBufferSize, kTimeout, false); //受信オブジェクト
void setup() {
Serial.begin(115200);
irrecv.enableIRIn(); //受信を開始
}
void loop() {
if (irrecv.decode(&results)) { //データを受け取った場合
Serial.print(resultToHumanReadableBasic(&results)); //結果を人間が読める形にしてシリアルに表示
//下記のように各データを取得する関数もある
decode_type_t protocol = results.decode_type; //赤外線のプロトコルを取得
uint16_t size = results.bits; //データサイズを取得
uint32_t value = results.value;
}
}
//送信
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <IRutils.h>
const uint16_t kIrLed = 17; //赤外線LEDのピンを取得
IRsend irsend(kIrLed); // 送信オブジェクト
bool success = true;
decode_type_t protocol = NEC;
uint16_t size = 32;
const uint32_t value = 0x41B658A7; //部屋の明かりをつけるコード
void setup() {
Serial.begin(115200);
irsend.begin(); // 赤外線LEDの設定
}
void loop() {
success = irsend.send(protocol, value, size); //送信
if (success){
Serial.println("send success");
}
delay(1000);
}
●SPIFFS
ESP8266の内蔵フラッシュメモリを使用してファイルシステムを実現します。
SPIFFSを使うためにはArduino IDEの「ツール」→「Flash Size」でサイズを指定する必要があります。
例えば、Flush Size:"4M(3M SPIFFS)"と指定すると3MのSPIFFSが使えます。
/*
シリアル通信にてコマンドを入力して、ファイルシステムへのアクセスをします。
<コマンドと機能>
●ファイル一覧表示
l<CR>
l:ディレクトリパス<CR>
●ファイルの読み込み、表示
r:ファイルパス<CR>
●ファイルの作成、書き込み ※すでにファイルがあれば追記
w:ファイルパス<CR>
w:ファイルパス,データ<CR>
●ファイル削除
d:ファイルパス<CR>
●フォーマット
f<CR>
※ディレクトリを指定する際は"\"または"/"で区切る。
*/
#include "FS.h"
#define COMMAND_BUF_SIZE 100
char cmd[COMMAND_BUF_SIZE];
int cmdLen = 0;
//ファイル読み込み(ファイル名)
void readFile(char* filePath) {
if (SPIFFS.exists(filePath)) { //ファイル存在確認
File f = SPIFFS.open(filePath, "r"); //ファイルを開く
Serial.print(filePath);
Serial.printf(" (%d byte)\n", f.size());
//file.seek(位置, SeekSet);
while(f.available()){
char b = f.read(); //ファイルから1バイトずつデータを読み取り
Serial.print(b);
}
f.close(); // ファイルを閉じる
} else {
Serial.print("File not found: ");
Serial.println(filePath);
}
}
//ファイル書き込み(コマンド)
void writeFile(char* filePath, char* data) {
if (SPIFFS.exists(filePath)) { //ファイル存在確認
File f = SPIFFS.open(filePath, "a"); //追記
//f.print(c); //キャラクタ書き込み
f.println(data); //キャラクタ書き込み 改行あり
//file.printf("%dms", millis()); //フォーマット指定の書き込み
//f.write(buf, len); //バッファデータ書き込み
//f.write(byte); //1バイト書き込み
f.close(); // ファイルを閉じる
} else {
File f = SPIFFS.open(filePath, "w"); //新規作成
f.println(data); //キャラクタ書き込み 改行あり
f.close(); // ファイルを閉じる
}
Serial.print("Write: ");
Serial.println(filePath);
}
//ファイル削除(ファイル名)
void deleteFile(char* filePath) {
SPIFFS.remove(filePath);
Serial.print("Delete: ");
Serial.println(filePath);
}
//ファイル一覧(ディレクトリ名)
void fileList(char* dirPath) {
Dir d = SPIFFS.openDir(dirPath); //ディレクトリを開く
int cnt = 0;
while (d.next()) {
Serial.print(d.fileName());
File f = d.openFile("r"); //読み取りモードで開く
Serial.printf(" (%d byte)\n", f.size());
cnt++;
}
Serial.printf("%d files\n", cnt);
}
//コマンド処理
void command() {
if(cmdLen == 2) {
switch(cmd[0]) {
case 'l': //ファイル一覧
cmd[0] = 0;
fileList(cmd); //ルートディレクトリ指定
return;
case 'f': //フォーマット
SPIFFS.format(); //フォーマット
Serial.println("Format!");
return;
}
} else if(cmdLen > 3) {
if(cmd[1] == ':' && cmd[cmdLen-1] == 0x0d) {
cmd[cmdLen-1] = 0; //文字列終了
int i = 0;
int dataIndex = cmdLen - 1;
switch(cmd[0]) {
case 'r': //ファイル読み込み
readFile(cmd+2);
return;
case 'w': //ファイル書き込み
//FilePathとdataを分離
do {
if(cmd[i] == ',') {
cmd[i] = 0; //ファイルパス文字列終端
dataIndex = i + 1; //データ開始位置
break;
}
}while(++i < cmdLen);
writeFile(cmd+2, cmd+dataIndex);
return;
case 'd': //ファイル削除
deleteFile(cmd+2);
return;
case 'l': //指定ディレクトリのファイル一覧
fileList(cmd+2);
return;
}
}
}
Serial.println("Command error!");
}
void setup(){
Serial.begin(115200);
if(!SPIFFS.begin()) {
Serial.println("\nSPIFFS initialization failed!");
}
Serial.println("\nStarting SPIFFS TEST.");
}
void loop(){
if(Serial.available()){
cmdLen = 0;
while(Serial.available()) {
uint8_t b = Serial.read();
if(cmdLen < COMMAND_BUF_SIZE) cmd[cmdLen++] = b; //バッファ を超えた分は捨てる
}
command();
}
delay(200);
}
●CPU動作クロック
ESP8266のCPU周波数は標準で80MHzになっていますが、160MHzに変更ができます。ただし、消費電力は増加します。
また、動作中でも80MHz、160MHそれぞれに切り替えができます。
system_update_cpu_freq(160);
●Deep Sleep使用方法
3種類のスリープモードがあり消費電力が最小なのはdeep-sleepモードになる。
WAKEピン(IO16) を RST ピンに繋いでおく必要がある。→ 指定時間経過後にリセットが実行され再起動する。
ただし、直接繋ぐと書き込み動作が不安定になるため、470Ω~1kΩの抵抗かダイオードを接続すると良い。
ダイオードの場合はアノード側をRST、カソード側をGPIO16に接続する。
DeepSleep後もデーターを保持しておきたい場合は、RTCメモリーを使用する。
領域は512バイトあり、電源投入時には不定な値が入っているので注意が必要。
//5分間スリープ μ秒で時間設定
ESP.deepSleep(5 * 60 * 1000 * 1000 , WAKE_RF_DEFAULT);
//RTC書込
ESP.rtcUserMemoryWrite(offset, &data1, sizeof(data1));
//RTC読込
ESP.rtcUserMemoryRead(offset, &data1, sizeof(data1));
//RTCメモリ読み書き
#define DEEP_SLEEP_TIME 10*1000000 //スリープ時間 us
#define RTC_BUFF_SIZE 20 //最大508バイト 最後4バイトはSUM値で使用する
unsigned int rtcDataAddr = 0;
unsigned int rtcData[RTC_BUFF_SIZE/4]; //データ 4バイト単位
void ReadRtcData() {
ESP.rtcUserMemoryRead(rtcDataAddr, rtcData, RTC_BUFF_SIZE); //データ読込
unsigned int sum;
ESP.rtcUserMemoryRead(rtcDataAddr+RTC_BUFF_SIZE, &sum, 4); //SUM読込
if(sum != dataSum()) { //SUM確認
for(int i=0; i < RTC_BUFF_SIZE/4; i++) rtcData[i] = 0; //全データクリア
}
}
void WriteRtcData() {
ESP.rtcUserMemoryWrite(rtcDataAddr, rtcData, RTC_BUFF_SIZE); //データ書込
unsigned int sum = dataSum();
ESP.rtcUserMemoryWrite(rtcDataAddr+RTC_BUFF_SIZE, &sum, 4); //SUM書込
}
unsigned int dataSum() {
unsigned int sum = 0;
for(int i=0; i < RTC_BUFF_SIZE/4; i++) sum += rtcData[i] ^ i; //sum計算
return sum;
}
void setup() {
Serial.begin(115200);
Serial.println("RTC Data:");
ReadRtcData();
}
void loop() {
rtcData[0]++;
for(int i=0; i < RTC_BUFF_SIZE/4; i++) Serial.println(rtcData[i]);
delay(3000);
WriteRtcData();
//deep sleepモード移行()
Serial.printf("deep sleep(wake up in %dus)", DEEP_SLEEP_TIME);
Serial.println();
ESP.deepSleep(DEEP_SLEEP_TIME); //指定時間us後に起動 ※WAKEピンとRSTピンを接続すること
}