Hey, I’m back as I promised to write the esp8266 development board firmware myself. I made a promise 20 years ago, and today I came back to fulfill my wish ESP8266 serial WiFi module - WiFi killer
Today we also connected the OLED display. The one I bought this time is a 4-pin OLED (128*64), which does not support color display.
NodeMCU Development Board
NodeMCU is an open source IoT hardware development board. Because it supports WIFI function and its usage is very similar to the Arduino development board, it has gained the favor of more and more maker friends from all over the world in recent years. NodeMCU is similar in size to Arduino Nano. It is not developed by the Arduino team, but we can also use the Arduino IDE to develop it.
As the IoT foundation for the Internet of Everything, first of all, the cost of the IoT control board cannot be too high. Expensive IoT control components are not conducive to project cost control and are not conducive to the majority of maker enthusiasts learning and using it. At this point, NodeMCU has an advantage over Raspberry Pi and the Arduino family of IoT platforms.
Attentive friends may have discovered that my development board is now called ESP8266-NodeMCU. However, in other websites or materials, sometimes ESP8266 is used and sometimes NodeMCU is used. So what is the relationship between ESP8266 and NodeMCU?
ESP8266 is a chip (a square thing protected by an iron case), and NodeMCU is a development board with the ESP8266 chip as the core, as shown in the figure below.
It is very difficult to conduct experiments on the ESP8266 chip, because it is difficult for us to connect the pins on the small chip to our computer and then upload the program and other operations. As a result, various development boards around the ESP8266 chip were born. NodeMCU is one of these development boards.
The two rows of pins on the NodeMCU development board are connected to the pins of the ESP8266 chip. With the two rows of pins on the development board, we can easily use DuPont wires to connect the chip pins to the experimental circuit. The NodeMCU development board is also equipped with a USB interface and voltage conversion circuit. These provide us with great convenience. We only need to use a USB data cable to easily power the ESP8266 and upload the program. Of course, the circuit functions on the NodeMCU development board are more than these, so I will not continue to extend them.
Driver installation
Although the driver installation of the development board has been discussed before, it was not detailed enough.
There are many ESP8266 drivers currently on the market, and even the drivers for the same NodeMcu development board may be different. The current mainstream drivers are CH340 and CP210X
To download the driver, please go directly to the official website of the chip manufacturer to download CP210X: https://cn.silabs.com/developers/usb-to-uart-bridge-vcp-drivers CH340C: https://www.wch.cn/downloads/CH341SER_EXE.html
Download the driver installation program suitable for your platform. You need to check whether your serial port chip model is within the support range of the driver.
How to check what drivers your development board requires
- Look directly, the vertical rectangular black bar in the picture below is the USB to serial port chip. The model name of the chip will be written on it

- Ask the merchant you bought from
Welding of display screen
Don’t solder the wrong OLED wiring, otherwise it will burn out the chip:
- GND - GND
- VCC - VCC
- SCL - GPIO5(D1)
- SDA - GPIO4(D2)
Luotie is heating 
The following is the soldered one. Pay attention to the wiring. It is not necessarily in my order. It depends on the name 
Installation of Arduino IDE
-
Download arduino IDE https://www.arduino.cc/en/software
-
Installation. Do you want me to teach you how to install it?
-
Configuration Click Tools-Development Board-Development Board Manager and write the development board address in the settings: http://arduino.esp8266.com/stable/package_esp8266com_index.json Then the corresponding support library file will be automatically downloaded. During this period, the network needs to be scientific.
-
Select the development board NodeMCU1.0(ESP-12EModule)
-
Select the port and find the COM port of your development board in the device manager of your computer.
Arduino code
Sometimes I feel that if I talk a lot, it is better to write the code directly. I think you definitely want to read the code directly instead of listening to me talk a lot of nonsense. I also comment in the code as much as possible (please follow the C/C++ language specification when writing Arduino code)
In the following example, the library is used to connect to WiFi. For the first connection, you need to use your mobile phone to connect to the WiFi sent by ESP8266 and perform network configuration first. The library is used to write to the screen, which supports direct writing of Chinese.
- This is a simple example of connecting to WiFi and displaying pictures on the screen
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiManager.h>
#include <U8g2lib.h>
#define SDA 4 // SDA pin, default gpio4 (D2)
#define SCL 5 // SCL pin, default gpio5(D1)
Adafruit_SSD1306 oled(128, 64, &Wire,-1); //OLED screen instantiation
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); // Select display screen
//Execute only once
void setup() {
u8g2.begin(); // Initialization
u8g2.enableUTF8Print(); // UTF8 allowed
u8g2.setFont(u8g2_font_wqy12_t_gb2312b); //Font size u8g2_font_wqy15_t_gb2312b
//Initialization screen
OLED_Init();
OLED_Showchin(1,13,"Connecting to WiFi....",0);
WiFiManager wifiManager;
wifiManager.autoConnect("ESP8266");
OLED_Showchin(1,27,"WiFi connection successful!",0);
OLED_Showchin(1,41,"Name: " + WiFi.SSID(),0);
OLED_Showchin(1,55,"IP: " + WiFi.localIP().toString(),1);
// Get time
timeClient.begin();
u8g2.setFont(u8g2_font_wqy15_t_gb2312b); //Font size u8g2_font_wqy15_t_gb2312b
OLED_Showchin(1,13,"Ning Xiaojian",0);
OLED_Showchin(1,27,"hhhhhhhhhhhhh",0);
OLED_Showchin(1,55,"Big idiot hahaha",1);
timeClient.update();
OLED_Showchin(1,20,"Current Beijing time: ",0);
OLED_Showchin(1,41,timeClient.getFormattedTime(),1);
delay(1000);
OLED_img();
}
// Repeat the program
void loop() {
//update time
// timeClient.update();
// OLED_Showchin(1,27,"Current Beijing time: ",0);
// OLED_Showchin(1,41,timeClient.getFormattedTime(),0);
}
//Print output to the screen (supports Chinese)
void OLED_Showchin(uint8_t x, uint8_t y, String string, uint8_t boot) {
u8g2.setCursor(x, y); //Set display coordinates
u8g2.print(string); //Specify the string to be printed in the buffer area
u8g2.sendBuffer(); // Send positioning information to the buffer
if(boot == 1){
delay(1000);
u8g2.clearBuffer(); // Clear the cache. In fact, there is clearing in the initialization. It must be added when looping.
}
}
//Screen initialization
void OLED_Init() {
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C); //"SSD1306_SWITCHCAPVCC" indicates that the display is OLED, and "0x3C" is the default communication address of the OLED screen
oled.setTextColor(WHITE);//Turn on pixels to glow
oled.clearDisplay();//Clear the screen
}
//output screen
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t font_size, String string) {
oled.setTextSize(font_size); //Set font size (>=1)
oled.setCursor(x, y); //Set display coordinates
oled.println(string); //Display content
oled.display(); //Turn on display
}
// Painting
void OLED_img() {
//Image data
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();
}

- This is an HTTP request, and then the weather information for the past four days is displayed on the screen.
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiManager.h> //Introduce WiFiManager library
#include <ArduinoJson.h> //Introduce ArduinoJson library
#include <U8g2lib.h> //Introduce U8g2 library
#define SDA 4 // SDA pin, default gpio4 (D2)
#define SCL 5 // SCL pin, default gpio5(D1)
//Select display screen
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /*clock=*/SCL, /*data=*/SDA, /*reset=*/U8X8_PIN_NONE);
// URL to request
const char* url = "http://t.weather.itboy.net/api/weather/city/101230308";
// Wi-Fi automatically connects
void connectToWiFi() {
WiFiManager wifiManager;
wifiManager.autoConnect("ESP8266"); // Automatically connect to a saved Wi-Fi network, or set up an access point with a specified name
if (WiFi.status() == WL_CONNECTED) {
Serial.println("Connected to Wi-Fi");
} else {
Serial.println("Not connected to Wi-Fi");
}
}
//Initiate an HTTP GET request and return a response
String httpRequest(const char* url) {
WiFiClient client;
HTTPClient http;
http.begin(client, url); // Using WiFiClient and URL
int httpCode = http.GET(); // Initiate request
String payload;
if (httpCode > 0) {
Serial.printf("HTTP GET request sent, response code: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK) {
payload = http.getString(); // Get the response content
Serial.println("Response content:");
Serial.println(payload); //Print response content
}
} else {
Serial.printf("HTTP GET request failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end(); // Close the connection
return payload;
}
//Global variables store weather data
StaticJsonDocument<2048> doc;
int dayIndex = 0;
unsigned long previousMillis = 0;
const long interval = 5000; //Switch display every 5 seconds
// Parse JSON and save weather information
bool parseWeather(const String& payload) {
DeserializationError error = deserializeJson(doc, payload); // Deserialize JSON
if (!error) {
Serial.println("JSON parsed successfully!");
return true;
} else {
Serial.print("JSON parsing failed: ");
Serial.println(error.c_str());
return false;
}
}
// Display weather information
void displayWeather(int index) {
if (!doc["data"]["forecast"][index]) return; // Check whether JSON data exists
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(); // Clear the buffer first
// Display date and week in one line
snprintf(buffer, sizeof(buffer), "%s %s", ymd, week);
OLED_Showchin(0, 15, buffer, 2); // Adjust text size to 1
// Display high and low temperatures in one line
snprintf(buffer, sizeof(buffer), "%s %s", high, low);
OLED_Showchin(0, 35, buffer, 2); // Adjust text size to 1
//Display weather type
snprintf(buffer, sizeof(buffer), "%s", type);
OLED_Showchin(0, 55, buffer, 3); // Adjust text size to 1
//Display prompt information
// snprintf(buffer, sizeof(buffer), "%s", notice);
// OLED_Showchin(0, 55, buffer, 1); // Adjust text size to 1
u8g2.sendBuffer(); // Send buffer content to the display
}
//Print output to the screen (supports Chinese and set font size)
void OLED_Showchin(uint8_t x, uint8_t y, const char* string, uint8_t textSize) {
u8g2.setCursor(x, y); //Set display coordinates
switch (textSize) {
case 1:
u8g2.setFont(u8g2_font_wqy12_t_gb2312b); //Set the minimum font
break;
case 2:
u8g2.setFont(u8g2_font_wqy13_t_gb2312b); // Set large font
break;
case 3:
u8g2.setFont(u8g2_font_wqy15_t_gb2312b); //Set the maximum font
break;
}
u8g2.print(string); //Specify the string to be printed in the buffer area
}
void setup() {
Serial.begin(115200);
delay(1000);
u8g2.begin(); // Initialize U8g2
u8g2.enableUTF8Print(); // Allow UTF8
connectToWiFi(); // Connect to Wi-Fi
if (WiFi.status() == WL_CONNECTED) {
String payload = httpRequest(url); // Initiate HTTP request
if (!payload.isEmpty()) {
if (parseWeather(payload)) { // Parse weather data
displayWeather(dayIndex); // Display initial weather data
}
}
} else {
Serial.println("Unable to connect to Wi-Fi");
}
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
dayIndex = (dayIndex + 1) % 4; // Switch to the next day's data
displayWeather(dayIndex); // Display weather information
}
// Check WiFi connection status and reconnect if disconnected
if (WiFi.status() != WL_CONNECTED) {
connectToWiFi();
}
}