ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

释放双眼,带上耳机,听听看~!

了解如何在两个ESP8266 NodeMCU 板之间建立 Wi-Fi 通信 (HTTP) 以交换数据,而无需连接到互联网(不需要路由器)。

您将ESP8266设置为接入点(服务器),将另一个ESP8266设置为工作站(客户端)。然后,服务器和客户端将通过HTTP请求交换数据(传感器读数)。我们将使用 Arduino IDE 对 ESP8266 板进行编程。

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

在此示例中,我们将 BME280 传感器读数从一块板发送到另一块板。接收器将在 OLED 显示屏上显示读数。

如果您有 ESP32 开发板,本网站也有esp32客户端与服务端直接通信的教程。

 项目概况

为了更好地理解一切是如何工作的,请查看下图。

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)
  • ESP8266服务器创建自己的无线网络(ESP8266软接入点)。因此,其他 Wi-Fi 设备可以连接到该网络(SSID:ESP8266-Access-Point,密码:123456789)。
  • ESP8266客户端设置为工作站。因此,它可以连接到ESP8266服务器无线网络。
  • 客户端可以向服务器发出 HTTP GET 请求,以请求传感器数据或任何其他信息。它只需要使用服务器的 IP 地址在某个路由上发出请求:/temperature、/humidity 或 /pressure。
  • 服务器侦听传入的请求,并发送带有读数的适当响应。
  • 客户端接收读数并将其显示在OLED显示屏上。

例如,ESP8266 客户端通过在服务器 IP 地址上发出请求,后跟 /temperature、/humidity 和 /pressure (HTTP GET) 向服务器请求温度、湿度和压力。

ESP8266服务器正在侦听这些路由,当发出请求时,它会通过 HTTP 响应发送相应的传感器读数。

 所需零件

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

在本教程中,需要以下部分:

  • 2 个ESP8266开发板 
  •  BME280 传感器
  • I2C SSD1306 OLED显示屏
  •  连接线
  •  面包板

 安装库

在本教程中,您需要安装以下库:

异步 Web 服务器库

我们将使用以下库来处理 HTTP 请求:

这些库无法通过库管理器进行安装。因此,您需要解压缩库并将它们移动到 Arduino IDE 安装库文件夹。

或者,您可以转到 Sketch > Include Library > Add .ZIP library…,然后选择您刚刚下载的库。

 BME280 库

可以通过Arduino库管理器安装以下库。转到“程序”>“包含库”>“管理库”,然后搜索库名称。

I2C SSD1306 OLED 库

要与OLED显示器连接,您需要以下库。这些可以通过Arduino库管理器进行安装。转到“程序”>“包含库”>“管理库”,然后搜索库名称。

您可能还喜欢: 带ESP8266 SSD1306 OLED显示屏完整指南

#1 ESP8266服务器(接入点)

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

ESP8266服务器是一个接入点 (AP),用于侦听 /temperature、/humidity 和 /pressure URL 上的请求。当它收到这些 URL 上的请求时,它会发送最新的 BME280 传感器读数。

对于测试,我们使用的是 BME280 传感器,但您可以通过修改几行代码(例如:DHT11/DHT22 或 DS18B20)来使用任何其他传感器。

 原理图

将ESP8266连接到 BME280 传感器,如下图所示。

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)
 BME280型 ESP8266
 VIN/VCC封装 3.3V
GND GND
SCL  通用IO 5 (D1)
SDA  通用IO 4 (D2)

#1 ESP8266服务器的Arduino程序

将以下代码上传到您的开发板。

/*
  
  更多Arduino/ESP8266/ESP32等教程请访问: https://www.qutaojiao.com
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

// Import required libraries
#include <ESP8266WiFi.h>
#include "ESPAsyncWebServer.h"

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

// Set your access point network credentials
const char* ssid = "ESP8266-Access-Point";
const char* password = "123456789";

/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

String readTemp() {
  return String(bme.readTemperature());
  //return String(1.8 * bme.readTemperature() + 32);
}

String readHumi() {
  return String(bme.readHumidity());
}

String readPres() {
  return String(bme.readPressure() / 100.0F);
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  Serial.println();
  
  // Setting the ESP as an access point
  Serial.print("Setting AP (Access Point)…");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readTemp().c_str());
  });
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readHumi().c_str());
  });
  server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", readPres().c_str());
  });
  
  bool status;

  // default settings
  // (you can also pass in a Wire library object like &Wire2)
  status = bme.begin(0x76);  
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
  
  // Start server
  server.begin();
}
 
void loop(){
  
}

 

代码的工作原理

首先包括必要的库。包括 ESP8266WiFi.h 库和 ESPAsyncWebServer.h 库来处理传入的 HTTP 请求。

#include <ESP8266WiFi.h>
#include "ESPAsyncWebServer.h"

包括以下库以与 BME280 传感器连接。

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

在以下变量中,定义接入点网络凭据:

const char* ssid = "ESP8266-Access-Point";
const char* password = "123456789";

我们将 SSID 设置为 ESP8266-Access-Point,但您可以为其指定任何其他名称。您也可以更改密码。默认情况下,它设置为 123456789。

为名为 bme 的 BME280 传感器创建实例。

Adafruit_BME280 bme;

在端口 80 上创建异步 Web 服务器。

AsyncWebServer server(80);

然后,创建三个函数,将温度、湿度和压力作为 String 变量返回。

String readTemp() {
  return String(bme.readTemperature());
  //return String(1.8 * bme.readTemperature() + 32);
}

String readHumi() {
  return String(bme.readHumidity());
}

String readPres() {
  return String(bme.readPressure() / 100.0F);
}

在 setup() 中,初始化串行监视器以进行演示。

Serial.begin(115200);

使用前面定义的 SSID 名称和密码将您的ESP8266设置为接入点。

WiFi.softAP(ssid, password);

然后,处理ESP8266将侦听传入请求的路由。

例如,当 ESP8266 服务器收到 /temperature URL 上的请求时,它会将 readTemp() 函数返回的温度作为 char 发送(这就是我们使用 c_str() 方法的原因。

server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readTemp().c_str());
});

当 ESP 收到 /humidity 和 /pressure URL 上的请求时,也会发生同样的情况。

server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readHumi().c_str());
});
server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readPres().c_str());
});

以下行初始化 BME280 传感器。

bool status;

// default settings
// (you can also pass in a Wire library object like &Wire2)
status = bme.begin(0x76);
if (!status) {
  Serial.println("Could not find a valid BME280 sensor, check wiring!");
  while (1);
}

最后,启动服务器。

server.begin();

因为这是一个异步 Web 服务器,所以 loop() 中没有任何内容。

void loop(){

}

测试 ESP8266 服务器

将代码上传到您的主板并打开串行监视器。您应该得到如下内容:

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

这意味着接入点已成功设置。

现在,为了确保它正在侦听温度、湿度和压力请求,您需要连接到其网络。

在您的智能手机中,转到 Wi-Fi 设置并连接到 ESP8266-Access-Point。密码已123456789。

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

连接到接入点后,打开浏览器并键入 192.168.4.1/temperature

您应该在浏览器中获取温度值:

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

尝试以下 URL 路径以获取湿度 192.168.4.1/humidity:

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

最后,转到 192.168.4.1/pressure URL:

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

如果您获得有效读数,则意味着一切正常。现在,您需要准备另一块ESP8266板(客户端)来为您提出这些请求,并将它们显示在OLED显示屏上。

#2 ESP8266客户端(站)

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

ESP8266 客户端是连接到 ESP8266 服务器的 Wi-Fi 站。客户端通过对 /temperature、/humidity 和 /pressure URL 路由发出 HTTP GET 请求,从服务器请求温度、湿度和压力。然后,它在OLED显示屏上显示读数。

 原理图

将OLED显示器连接到ESP8266板,如下图所示。

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)
Pin ESP8266
Vin 3.3V
GND GND
SCL  通用IO 5 (D1)
SDA  通用IO 4 (D2)

Arduino Sketch for #2 ESP8266 客户端

将以下代码上传到其他ESP8266(客户端):

 

代码的工作原理

包括用于 Wi-Fi 连接和发出 HTTP 请求的必要库:

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

#include <ESP8266WiFiMulti.h>

您需要创建一个 WiFiMulti 实例。

ESP8266WiFiMulti WiFiMulti;

插入ESP8266服务器网络凭据。如果更改了 ESP8266 服务器中的默认网络凭据,则应在此处更改它们以匹配。

const char* ssid = "ESP8266-Access-Point";
const char* password = "123456789";

然后,保存客户端将发出 HTTP 请求的 URL。ESP8266服务器具有 192.168.4.1 IP 地址,我们将对 /temperature、/humidity 和 /pressure URL 发出请求。

const char* serverNameTemp = "http://192.168.4.1/temperature";
const char* serverNameHumi = "http://192.168.4.1/humidity";
const char* serverNamePres = "http://192.168.4.1/pressure";

包括用于与OLED显示器连接的库:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

设置OLED显示尺寸:

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 64  // OLED display height, in pixels

使用您之前定义的大小和 I2C 通信协议创建显示对象。

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

初始化字符串变量,这些变量将保存服务器检索到的温度、湿度和压力读数。

String temperature;
String humidity;
String pressure;

设置每个请求之间的时间间隔。默认情况下,它设置为 5 秒,但您可以将其更改为任何其他间隔。

const long interval = 5000; 

在 setup() 中,初始化 OLED 显示屏:

// Address 0x3C for 128x64, you might need to change this value (use an I2C scanner)
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
  Serial.println(F("SSD1306 allocation failed"));
  for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.setTextColor(WHITE);

注意:如果您的 OLED 显示器不工作,请使用 I2C 扫描仪程序检查其 I2C 地址并相应地更改代码。

将 ESP8266 客户端连接到 ESP8266 服务器网络。

while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}
Serial.println("");
Serial.println("Connected to WiFi");

In the loop() 是我们发出 HTTP GET 请求的地方。我们创建了一个名为 httpGETRequest() 的函数,该函数接受我们想要发出请求的 URL 路径作为参数,并将响应作为 String 返回。

可以在项目中使用 next 函数来简化代码:

String httpGETRequest(const char* serverName) {
  WiFiClient client;
  HTTPClient http;
    
  // Your IP address with path or Domain name with URL path 
  http.begin(client, serverName);
  
  // Send HTTP POST request
  int httpResponseCode = http.GET();
  
  String payload = "--"; 
  
  if (httpResponseCode>0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  http.end();

  return payload;
}

我们使用该函数从服务器获取温度、湿度和压力读数。

temperature = httpGETRequest(serverNameTemp);
humidity = httpGETRequest(serverNameHumi);
pressure = httpGETRequest(serverNamePres);

在串行监视器中打印这些读数以进行调试。

Serial.println("Temperature: " + temperature + " *C - Humidity: " + humidity + " % - Pressure: " + pressure + " hPa");

然后,在OLED显示屏中显示温度:

display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("T: ");
display.print(temperature);
display.print(" ");
display.setTextSize(1);
display.cp437(true);
display.write(248);
display.setTextSize(2);
display.print("C");

 湿度:

display.setTextSize(2);
display.setCursor(0, 25);
display.print("H: ");
display.print(humidity);
display.print(" %"); 

最后,压力读数:

display.setTextSize(2);
display.setCursor(0, 50);
display.print("P:");
display.print(pressure);
display.setTextSize(1);
display.setCursor(110, 56);
display.print("hPa");

display.display();

我们使用计时器而不是undefined器每 x 秒发出一次请求。这就是为什么我们有 previousMillis、currentMillis 变量并使用 millis() 函数的原因。我们有一篇文章展示了计时器和undefined之间的区别,您可能会觉得有用(或阅读ESP8266计时器)。

将程序上传到 #2 ESP8266(客户端)以测试一切是否正常工作。

测试 ESP8266 客户端

当两块板相当接近并通电时,您会看到 ESP #2 每 5 秒从 ESP #1 接收一次新的温度、湿度和压力读数。

这是您应该在ESP8266客户端串行监视器上看到的内容。

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

传感器读数也显示在OLED中。

ESP8266两块板之间的客户端-服务器 Wi-Fi 通信 (NodeMCU)

就是这样!您的两个ESP8266板正在相互通信。

 总结

在本教程中,我们向您展示了如何使用 HTTP 请求将数据从一个ESP8266板发送到另一个板。如果您需要在两块或更多板之间设置无线通信,并且附近没有路由器,则此项目非常有用。

给TA打赏
共{{data.count}}人
人已打赏
Nodemcu/ESP8266Nodemcu/ESP8266-基础动态

中断和定时器使用 - NodeMCU

2023-12-9 21:10:16

Nodemcu/ESP8266Nodemcu/ESP8266-进阶动态

WebSocket 服务器:控制输出 - ESP8266 NodeMCU

2023-12-9 21:37:07

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索
'); })();