banner
阿珏酱

阿珏酱

いつもとは逆の電車に乗り、見たこともない風景を見に行く
twitter
github
facebook
bilibili
zhihu
steam_profiles
youtube

ESP8266-NodeMCU開発ボードを使用して、私のQQアバターを表示します。

ええ、約束通り自分で 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 チップを中心にした開発ボードです。以下の図を参照してください。
img
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

自分のプラットフォームに適したドライバインストーラをダウンロードしてください。
自分のシリアルポートチップのモデルがドライバのサポート範囲内にあるかどうかを確認する必要があります。

自分の開発ボードに必要なドライバを確認する方法#

  1. 直接見る。下の図の縦長の黒い長方形が USB - シリアルチップです。上にチップのモデル名が書かれています。
    img
  2. 購入した業者に尋ねる。

ディスプレイのハンダ付け#

間違ってハンダ付けしないでください。そうしないとチップが壊れてしまいます。
OLED 接続:

  • GND - GND
  • VCC - VCC
  • SCL - GPIO5(D1)
  • SDA - GPIO4(D2)

ロウ付け中
img

以下はハンダ付けが完了したものです。接続に注意してください。必ずしもこの順序である必要はなく、名前を確認する必要があります。
img

Arduino IDE のインストール#

  1. Arduino IDE をダウンロード
    https://www.arduino.cc/en/software

  2. インストール
    インストールを教える必要がありますか?

  3. 設定
    ツール - ボード - ボードマネージャをクリックし、設定にボードのアドレスを記入します:http://arduino.esp8266.com/stable/package_esp8266com_index.json
    その後、自動的に対応するライブラリファイルがダウンロードされます。その間、ネットワークの科学性を保証する必要があります。

  4. ボードを選択
    NodeMCU1.0(ESP-12EModule)

  5. ポートを選択
    コンピュータのデバイスマネージャで開発ボードの COM ポートを見つけます。

Arduino コード#

時々、私は長々と話すよりも直接コードを見せた方が良いと思います。あなたも私が無駄話をするのではなく、直接コードを見たいと思っているに違いありません。
私はできるだけコードにコメントを付けました(Arduino コードを書く際は C/C++ 言語の規範に従ってください)。

以下の例では、WiFi 接続には <WiFiManager.h> ライブラリを使用し、初回接続時にはスマートフォンを使って ESP8266 が発信する WiFi に接続して設定を行う必要があります。画面に表示するには < U8g2lib.h > ライブラリを使用し、中国語を直接表示できます。

  1. これは 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();
}

img
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();
  }
}

img

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。