ええ、約束通り自分で ESP8266 の開発ボードのファームウェアを書くと言った私が戻ってきました。
20 年に約束した、今日は戻ってきて願いを果たしました ESP8266 シリアル WiFi モジュール - WiFi キラー
今日は OLED ディスプレイも接続しました。今回購入したのは 4 ピンの OLED(128*64)で、カラー表示には対応していません。
NodeMCU 開発ボード#
NodeMCU はオープンソースの IoT ハードウェア開発ボードで、WIFI 機能をサポートし、Arduino 開発ボードと非常に似た使い方をするため、近年、世界中のクリエイターたちにますます人気を集めています。NodeMCU のサイズは Arduino Nano に似ています。これは Arduino チームが開発したものではありませんが、Arduino IDE を使用して開発することもできます。
あらゆるものがつながる IoT の基盤として、まず IoT 制御ボードのコストは高すぎてはいけません。高価な IoT 制御部品はプロジェクトのコスト管理に不利であり、多くのクリエイター愛好者が学び、使用することにも不利です。この点で、NodeMCU は Raspberry Pi や Arduino ファミリーの IoT プラットフォームよりも優位性があります。
注意深い友人はすでに気づいているかもしれませんが、私の開発ボードは ESP8266-NodeMCU と呼ばれています。しかし、他のウェブサイトや資料では、時々ESP8266 と呼ばれ、時々NodeMCU と呼ばれています。では、ESP8266 と NodeMCU の関係は何でしょうか?
ESP8266 はチップ(鉄のケースに保護された四角いもの)であり、NodeMCU は ESP8266 チップを中心にした開発ボードです。以下の図を参照してください。
ESP8266 チップを実験操作するのは非常に難しいです。なぜなら、小さなチップのピンをコンピュータに接続してプログラムをアップロードするなどの操作を行うのが難しいからです。そこで、ESP8266 チップを中心にしたさまざまな開発ボードが誕生しました。NodeMCU はこれらの開発ボードの一つです。
NodeMCU 開発ボードの 2 列のピンは ESP8266 チップのピンに接続されています。開発ボードの 2 列のピンを使うことで、ジャンパーワイヤーを使ってチップのピンを実験回路に簡単に接続できます。NodeMCU 開発ボードには USB インターフェースと電圧変換回路も搭載されています。これにより、私たちは大きな便利さを得ることができます。USB データケーブル 1 本で ESP8266 に電力を供給し、プログラムをアップロードする操作を簡単に実現できます。もちろん、NodeMCU 開発ボードの回路機能はこれだけではありませんので、これ以上は続けません。
ドライバのインストール#
以前に開発ボードのドライバのインストールについて説明しましたが、詳細ではありませんでした。
現在、市場にはさまざまな ESP8266 ドライバがあり、同じ NodeMcu の開発ボードのドライバも異なる場合があります。現在の主流は CH340 と CP210X のドライバです。
ドライバのダウンロードは、チップの製造元の公式ウェブサイトから直接行ってください。
CP210X:https://cn.silabs.com/developers/usb-to-uart-bridge-vcp-drivers
CH340C:https://www.wch.cn/downloads/CH341SER_EXE.html
自分のプラットフォームに適したドライバインストーラをダウンロードしてください。
自分のシリアルポートチップのモデルがドライバのサポート範囲内にあるかどうかを確認する必要があります。
自分の開発ボードに必要なドライバを確認する方法#
- 直接見る。下の図の縦長の黒い長方形が USB - シリアルチップです。上にチップのモデル名が書かれています。
- 購入した業者に尋ねる。
ディスプレイのハンダ付け#
間違ってハンダ付けしないでください。そうしないとチップが壊れてしまいます。
OLED 接続:
- GND - GND
- VCC - VCC
- SCL - GPIO5(D1)
- SDA - GPIO4(D2)
ロウ付け中
以下はハンダ付けが完了したものです。接続に注意してください。必ずしもこの順序である必要はなく、名前を確認する必要があります。
Arduino IDE のインストール#
-
Arduino IDE をダウンロード
https://www.arduino.cc/en/software -
インストール
インストールを教える必要がありますか? -
設定
ツール - ボード - ボードマネージャをクリックし、設定にボードのアドレスを記入します:http://arduino.esp8266.com/stable/package_esp8266com_index.json
その後、自動的に対応するライブラリファイルがダウンロードされます。その間、ネットワークの科学性を保証する必要があります。 -
ボードを選択
NodeMCU1.0(ESP-12EModule) -
ポートを選択
コンピュータのデバイスマネージャで開発ボードの COM ポートを見つけます。
Arduino コード#
時々、私は長々と話すよりも直接コードを見せた方が良いと思います。あなたも私が無駄話をするのではなく、直接コードを見たいと思っているに違いありません。
私はできるだけコードにコメントを付けました(Arduino コードを書く際は C/C++ 言語の規範に従ってください)。
以下の例では、WiFi 接続には <WiFiManager.h> ライブラリを使用し、初回接続時にはスマートフォンを使って ESP8266 が発信する WiFi に接続して設定を行う必要があります。画面に表示するには < U8g2lib.h > ライブラリを使用し、中国語を直接表示できます。
- これは WiFi に接続し、画面に画像を表示する簡単な例です。
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiManager.h>
#include <U8g2lib.h>
#define SDA 4 // SDAピン、デフォルトgpio4(D2)
#define SCL 5 // SCLピン、デフォルトgpio5(D1)
Adafruit_SSD1306 oled(128, 64, &Wire,-1); //OLEDスクリーンのインスタンス化
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP,"pool.ntp.org", 8*3600, 60000);
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /*clock=*/SCL, /*data=*/SDA, /*reset=*/U8X8_PIN_NONE); // スクリーンを選択
// 1回だけ実行
void setup() {
u8g2.begin(); // 初期化
u8g2.enableUTF8Print(); // UTF8を許可
u8g2.setFont(u8g2_font_wqy12_t_gb2312b); //フォントサイズ u8g2_font_wqy15_t_gb2312b
// スクリーンの初期化
OLED_Init();
OLED_Showchin(1,13,"WiFiに接続中....",0);
WiFiManager wifiManager;
wifiManager.autoConnect("ESP8266");
OLED_Showchin(1,27,"WiFi接続成功!",0);
OLED_Showchin(1,41,"名称: " + WiFi.SSID(),0);
OLED_Showchin(1,55,"IP: " + WiFi.localIP().toString(),1);
// 時間を取得
timeClient.begin();
u8g2.setFont(u8g2_font_wqy15_t_gb2312b); //フォントサイズ u8g2_font_wqy15_t_gb2312b
OLED_Showchin(1,13,"寧小建",0);
OLED_Showchin(1,27,"hhhhhhhhhhhh",0);
OLED_Showchin(1,55,"大バカハハハ",1);
timeClient.update();
OLED_Showchin(1,20,"現在の北京時間: ",0);
OLED_Showchin(1,41,timeClient.getFormattedTime(),1);
delay(1000);
OLED_img();
}
// プログラムを繰り返し実行
void loop() {
// 時間を更新
// timeClient.update();
// OLED_Showchin(1,27,"現在の北京時間: ",0);
// OLED_Showchin(1,41,timeClient.getFormattedTime(),0);
}
// スクリーンに出力(中国語をサポート)
void OLED_Showchin(uint8_t x, uint8_t y, String string, uint8_t boot) {
u8g2.setCursor(x, y); //表示座標を設定
u8g2.print(string); // 指定されたバッファに印刷する文字列
u8g2.sendBuffer(); // 位置情報をバッファに送信
if(boot == 1){
delay(1000);
u8g2.clearBuffer(); // バッファをクリア、実際には初期化時にクリアされるが、ループ時には必ず追加する必要がある
}
}
// スクリーンの初期化
void OLED_Init() {
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C); //"SSD1306_SWITCHCAPVCC"はディスプレイがOLEDであることを示し、"0x3C"はOLEDスクリーンのデフォルト通信アドレス
oled.setTextColor(WHITE);//ピクセルを点灯
oled.clearDisplay();//クリア
}
// スクリーンに出力
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t font_size, String string) {
oled.setTextSize(font_size); //フォントサイズを設定 (>=1)
oled.setCursor(x, y); //表示座標を設定
oled.println(string); //表示内容
oled.display(); //表示を開始
}
// 描画
void OLED_img() {
// 画像データ
const unsigned char gImage_1[518] = { 0X00,0X01,0X40,0X00,0X40,0X00,
0X00,0X40,0X00,0X00,0X00,0X3E,0XF0,0X00,0X00,0X80,0X00,0X00,0X00,0X1F,0XE0,0X00,
0X00,0X00,0X00,0X00,0X00,0X06,0XB0,0X00,0X01,0X00,0X00,0X00,0X00,0X03,0XF8,0X00,
0X00,0X00,0X00,0X00,0X00,0X03,0XFC,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XDC,0X00,
0X04,0X00,0X00,0X00,0X00,0X01,0XC0,0X00,0X0E,0X00,0X00,0X00,0X00,0X00,0X80,0X00,
0X06,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0X00,0X00,0X00,0X10,0X00,0X00,0X00,
0X08,0X00,0X00,0X00,0X0E,0X00,0X00,0X00,0X08,0X00,0X00,0X00,0X8F,0X00,0X00,0X00,
0X00,0X00,0X02,0X02,0X47,0X00,0X00,0X00,0X00,0X00,0X01,0X10,0X63,0X80,0X00,0X00,
0X00,0X00,0X01,0XC9,0X73,0XC0,0X00,0X00,0X00,0X00,0X00,0XE4,0X79,0XE0,0X00,0X00,
0X00,0X02,0X00,0XFA,0XF9,0XE0,0X00,0X00,0X10,0X02,0X00,0X7D,0X8C,0XF0,0X00,0X00,
0X10,0X03,0X01,0X7E,0X90,0XF1,0X80,0X00,0X10,0X01,0X20,0XFD,0X1C,0X7B,0XE0,0X00,
0X00,0X01,0XA0,0X7D,0X03,0X7B,0X20,0X00,0X10,0X01,0XD8,0XFF,0X8B,0X7E,0X30,0X00,
0X00,0X01,0XFC,0X7F,0X83,0XB6,0X10,0X00,0X00,0X00,0XF7,0XFF,0XC7,0XBE,0X10,0X00,
0X00,0X01,0X8F,0XFF,0XE3,0XF6,0X10,0X00,0X01,0X01,0X4F,0XFF,0XFF,0XFF,0X10,0X00,
0X00,0X01,0XCF,0XFF,0XFF,0XDF,0X10,0X00,0X00,0X01,0XC3,0XFF,0XFF,0XDF,0X70,0X00,
0X01,0X03,0XE3,0XFF,0XFF,0XDF,0XE0,0X00,0X04,0X01,0XE7,0XFF,0XFF,0XDF,0XE4,0X00,
0X07,0X00,0XFB,0XFF,0XFF,0XDF,0XC0,0X00,0X07,0X00,0XFB,0XFF,0XFF,0XFE,0X00,0X00,
0X13,0X00,0X7F,0XFF,0XFF,0XFC,0X00,0X00,0X01,0X20,0X3F,0XFF,0XFF,0XFC,0X00,0X00,
0X00,0X00,0X3F,0XFF,0XFF,0XF8,0X00,0X0B,0X00,0X00,0X1F,0XFE,0X0F,0XF8,0X00,0X1F,
0X00,0X00,0X1F,0XF8,0X6F,0XF0,0X00,0XFF,0X00,0X00,0X1F,0XE1,0XFF,0XF0,0X05,0XFF,
0X00,0X00,0X0F,0XF3,0XFF,0XE0,0X03,0XFF,0X00,0X40,0X0F,0XF7,0XFF,0XC0,0X07,0XFF,
0X00,0X00,0X07,0XFF,0XFF,0X80,0X07,0XFF,0X08,0X00,0X07,0XFF,0XFF,0X00,0X0F,0XFF,
0X00,0X00,0X23,0XFF,0XFE,0X00,0X0F,0XFF,0X00,0X08,0X60,0XFF,0XFE,0X00,0X0F,0XFF,
0X00,0X40,0X20,0X3F,0XFE,0X00,0X1F,0XFF,0X00,0X00,0X10,0X0B,0XFF,0X80,0X1F,0XFF,
0X00,0X00,0X40,0X00,0X3F,0X00,0X1F,0XFF,0X00,0X00,0X10,0X00,0X3F,0X00,0X1F,0XFF,
0X20,0X00,0X02,0X00,0X3F,0X00,0X3F,0XFF,0X00,0X00,0X00,0X00,0X7F,0X80,0X3F,0XFF,
0X00,0X00,0X00,0X10,0X7F,0X80,0X7F,0XFF,0X00,0X00,0X00,0X80,0X7F,0X80,0X7F,0XFF,
0X10,0X00,0X00,0X00,0X7F,0X80,0XFF,0XFF,0X30,0X00,0X00,0X00,0X7F,0X80,0XFF,0XFF,
0X10,0X10,0X00,0X00,0X7F,0XC1,0XFF,0XFF,0X00,0X00,0X00,0X00,0X7F,0XF3,0XFF,0XFF,
0X00,0X00,0X01,0X00,0X3F,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X04,0X3F,0XFF,0XFF,0XFF,
0X00,0X00,0X00,0X00,0X3F,0XFF,0XFF,0XFF,0X00,0X00,0X10,0X80,0X1F,0XFF,0XFF,0XFF,
0X01,0X00,0X00,0X05,0X1F,0XFF,0XFF,0XFB,0X00,0X00,0X00,0X00,0X1F,0XF7,0XFF,0XFC,
0X00,0X00,0X00,0X00,0X1F,0XFB,0XFF,0XFF,0X00,0X00,0X40,0X00,0X19,0XFF,0XFF,0XFF,
};
oled.clearDisplay();
oled.drawBitmap(3, 1, gImage_1, 64, 64, WHITE);
oled.display();
}
2. これは HTTP リクエストを発起し、画面に近 4 日間の天気情報を表示するものです。
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiManager.h> // WiFiManagerライブラリをインポート
#include <ArduinoJson.h> // ArduinoJsonライブラリをインポート
#include <U8g2lib.h> // U8g2ライブラリをインポート
#define SDA 4 // SDAピン、デフォルトgpio4(D2)
#define SCL 5 // SCLピン、デフォルトgpio5(D1)
// スクリーンを選択
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /*clock=*/SCL, /*data=*/SDA, /*reset=*/U8X8_PIN_NONE);
// リクエストするURL
const char* url = "http://t.weather.itboy.net/api/weather/city/101230308";
// Wi-Fi自動接続
void connectToWiFi() {
WiFiManager wifiManager;
wifiManager.autoConnect("ESP8266"); // 保存されたWi-Fiネットワークに自動接続、または指定された名前のアクセスポイントを設定
if (WiFi.status() == WL_CONNECTED) {
Serial.println("Wi-Fiに接続されました");
} else {
Serial.println("Wi-Fiに接続されていません");
}
}
// HTTP GETリクエストを発起し、レスポンスを返す
String httpRequest(const char* url) {
WiFiClient client;
HTTPClient http;
http.begin(client, url); // WiFiClientとURLを使用
int httpCode = http.GET(); // リクエストを発起
String payload;
if (httpCode > 0) {
Serial.printf("HTTP GETリクエストが送信されました、レスポンスコード: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK) {
payload = http.getString(); // レスポンス内容を取得
Serial.println("レスポンス内容:");
Serial.println(payload); // レスポンス内容を印刷
}
} else {
Serial.printf("HTTP GETリクエストが失敗しました、エラー: %s\n", http.errorToString(httpCode).c_str());
}
http.end(); // 接続を閉じる
return payload;
}
// 天気データを保存するグローバル変数
StaticJsonDocument<2048> doc;
int dayIndex = 0;
unsigned long previousMillis = 0;
const long interval = 5000; // 5秒ごとに表示を切り替える
// JSONを解析し、天気情報を保存
bool parseWeather(const String& payload) {
DeserializationError error = deserializeJson(doc, payload); // JSONを逆シリアル化
if (!error) {
Serial.println("JSON解析成功!");
return true;
} else {
Serial.print("JSON解析失敗: ");
Serial.println(error.c_str());
return false;
}
}
// 天気情報を表示
void displayWeather(int index) {
if (!doc["data"]["forecast"][index]) return; // JSONデータが存在するか確認
char buffer[128];
const char* high = doc["data"]["forecast"][index]["high"].as<const char*>();
const char* low = doc["data"]["forecast"][index]["low"].as<const char*>();
const char* ymd = doc["data"]["forecast"][index]["ymd"].as<const char*>();
const char* week = doc["data"]["forecast"][index]["week"].as<const char*>();
const char* type = doc["data"]["forecast"][index]["type"].as<const char*>();
const char* notice = doc["data"]["forecast"][index]["notice"].as<const char*>();
u8g2.clearBuffer(); // バッファをクリア
// 日付と曜日を1行に表示
snprintf(buffer, sizeof(buffer), "%s %s", ymd, week);
OLED_Showchin(0, 15, buffer, 2); // テキストサイズを1に調整
// 高温と低温を1行に表示
snprintf(buffer, sizeof(buffer), "%s %s", high, low);
OLED_Showchin(0, 35, buffer, 2); // テキストサイズを1に調整
// 天気の種類を表示
snprintf(buffer, sizeof(buffer), "%s", type);
OLED_Showchin(0, 55, buffer, 3); // テキストサイズを1に調整
// 提示情報を表示
// snprintf(buffer, sizeof(buffer), "%s", notice);
// OLED_Showchin(0, 55, buffer, 1); // テキストサイズを1に調整
u8g2.sendBuffer(); // バッファの内容をディスプレイに送信
}
// スクリーンに出力(中国語とフォントサイズの設定をサポート)
void OLED_Showchin(uint8_t x, uint8_t y, const char* string, uint8_t textSize) {
u8g2.setCursor(x, y); // 表示座標を設定
switch (textSize) {
case 1:
u8g2.setFont(u8g2_font_wqy12_t_gb2312b); // 最小フォントを設定
break;
case 2:
u8g2.setFont(u8g2_font_wqy13_t_gb2312b); // 大フォントを設定
break;
case 3:
u8g2.setFont(u8g2_font_wqy15_t_gb2312b); // 最大フォントを設定
break;
}
u8g2.print(string); // 指定されたバッファに印刷する文字列
}
void setup() {
Serial.begin(115200);
delay(1000);
u8g2.begin(); // U8g2を初期化
u8g2.enableUTF8Print(); // UTF8を許可
connectToWiFi(); // Wi-Fiに接続
if (WiFi.status() == WL_CONNECTED) {
String payload = httpRequest(url); // HTTPリクエストを発起
if (!payload.isEmpty()) {
if (parseWeather(payload)) { // 天気データを解析
displayWeather(dayIndex); // 初期天気データを表示
}
}
} else {
Serial.println("Wi-Fiに接続できません");
}
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
dayIndex = (dayIndex + 1) % 4; // 次の日のデータに切り替え
displayWeather(dayIndex); // 天気情報を表示
}
// WiFi接続状態を確認し、切断されている場合は再接続
if (WiFi.status() != WL_CONNECTED) {
connectToWiFi();
}
}