查看完整视频
小黑屋思过中,禁止观看!
评论并刷新后可见

您需要在视频最下面评论并刷新后,方可查看完整视频

积分观看

您支付积分,方可查看完整视频

{{user.role.value}}
付费视频

您支付费用,方可查看完整视频

¥{{user.role.value}}
专属视频

只允许以下等级用户查看该视频

升级
会员专享

视频选集

两板之间的ESP32客户端-服务器Wi-Fi通信

  • 视频介绍
  • 视频选集
  • 交流讨论
释放双眼,带上耳机,听听看~!

本篇教程将给大家讲解如何在两个ESP32板之间进行HTTP通信,以通过Wi-Fi在不连接互联网(路由器)的情况下交换数据。简而言之,您将学习如何使用HTTP请求将数据从一个板发送到另一个板。ESP32开发板将使用Arduino IDE进行编程。

出于演示目的,我们将BME280传感器的读数从一块板发送到另一块板。接收器将在OLED显示屏上显示读数。

项目概况

一个ESP32板将充当服务器,另一个ESP32板将充当客户端。下图概述了所有工作原理:

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

例如,ESP32客户端通过在服务器IP地址上进行请求,然后再在服务器上请求温度,湿度和压力给服务器/temperature/humidity 和 /pressure, 分别。

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

 

所需材料

  1. 2个ESP32开发板
  2. BME280传感器
  3. I2C SSD1306 OLED显示屏
  4. 面包板*2
  5. 连接线
  6. 安装好esp32环境的Aruino IDE 或者使用在线编译环境:https://notes.qutaojiao.com

 

安装库

对于本教程,您需要安装以下库:

异步Web服务器库

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

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

或者,您可以转到 “草图”  >“ 包含库”  >“ 添加.ZIP库…”, 然后选择刚下载的库。

BME280库

可以通过Arduino Library Manager安装以下库。转到 草图 包括库管理库, 然后搜索库名称。

I2C SSD1306 OLED库

要与OLED显示器连接,您需要以下库。这些可以通过Arduino Library Manager安装。转到草图>包括库>管理库,然后搜索库名称。

#1 ESP32服务器(接入点)

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

出于演示目的,我们使用的是BME280传感器,但是您可以通过修改几行代码来使用任何其他传感器。

原理图,示意图

如下图所示,将ESP32连线至BME280传感器:

BME280 ESP32
VIN / VCC 3.3伏
地线 地线
SCL GPIO 22
SDA GPIO 21

##1 ESP32服务器的Arduino程序

// Import required libraries
#include <WiFi.h>
#include <ESPAsyncWebServer.h>

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

// Set your access point network credentials
const char* ssid = "ESP32-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(){
  
}

 

代码如何工作

首先包括必要的库。包括 WiFi.h  图书馆和 ESPAsyncWebServer.h 库来处理传入的HTTP请求:

#include "WiFi.h"
#include "ESPAsyncWebServer.h"

包括以下库以与BME280传感器接口:

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

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

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

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

名为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名称和密码将ESP32设置为访问连接热点:

WiFi.softAP(ssid, password);

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

例如,当ESP32服务器收到请求时, /temperature URL,它发送由 readTemp()  用作字符(这就是为什么我们使用 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(){

}

测试ESP32服务器

将代码上传到板上,然后打开串行监视器。您应该获得如下信息:

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

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

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

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

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

 

尝试使用此URL路径获取湿度 192.168.4.1/humidity

 

最后,前往 192.168.4.1/pressure 网址:

 

如果获得有效的读数,则表示一切正常。现在,您需要准备另一个ESP32开发板(客户端)来为您提出这些请求,并将其显示在OLED显示屏上。

 

#2 ESP32客户端(Station)

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

原理图,示意图

如下图所示,将ESP32连线至OLED显示器:

有机发光二极管 ESP32
VIN / VCC VIN
GND GND
SCL GPIO 22
SDA GPIO 21

 

#2 ESP32客户端的Arduino程序

#include <WiFi.h>
#include <HTTPClient.h>

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

//Your IP address or domain name with URL path
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";

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

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

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

String temperature;
String humidity;
String pressure;

unsigned long previousMillis = 0;
const long interval = 5000; 

void setup() {
  Serial.begin(115200);
  
  // 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);
  
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) { 
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  unsigned long currentMillis = millis();
  
  if(currentMillis - previousMillis >= interval) {
     // Check WiFi connection status
    if(WiFi.status()== WL_CONNECTED ){ 
      temperature = httpGETRequest(serverNameTemp);
      humidity = httpGETRequest(serverNameHumi);
      pressure = httpGETRequest(serverNamePres);
      Serial.println("Temperature: " + temperature + " *C - Humidity: " + humidity + " % - Pressure: " + pressure + " hPa");
      
      display.clearDisplay();
      
      // display temperature
      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 humidity
      display.setTextSize(2);
      display.setCursor(0, 25);
      display.print("H: ");
      display.print(humidity);
      display.print(" %"); 
      
      // display pressure
      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();
      
      // save the last HTTP GET Request
      previousMillis = currentMillis;
    }
    else {
      Serial.println("WiFi Disconnected");
    }
  }
}

String httpGETRequest(const char* serverName) {
  HTTPClient http;
    
  // Your IP address with path or Domain name with URL path 
  http.begin(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;
}

 

代码如何工作

引入用于Wi-Fi连接和发出HTTP请求所需的库:

#include <WiFi.h>
#include <HTTPClient.h>

插入ESP32服务器网络连接信息。如果您已更改ESP32服务器中的默认网络凭据,则应在此处进行更改以匹配:

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

然后,保存客户端将在其中发出HTTP请求的URL。ESP32服务器具有192.168.4.1 IP地址,我们需要设置/temperature/humidity, 和 /pressure 网址:

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 <SPI.h>
#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

创建一个 display 具有您之前定义的大小并具有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地址,并相应地更改代码。

将ESP32客户端连接到ESP32服务器网络:

WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) { 
  delay(500);
  Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");

在里面 loop() 是我们发出HTTP GET请求的地方。我们创建了一个名为httpGETRequest() 接受我们要发出请求的URL路径作为参数,参数类型为 String:

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

String httpGETRequest(const char* serverName) {
  HTTPClient http;
    
  // Your IP address with path or Domain name with URL path 
  http.begin(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();

我们使用计时器而不是延迟来每x秒发送一个请求。这就是为什么我们有previousMilliscurrentMillis变量,并使用 millis()功能。

将程序上传到ESP32(客户端)以测试一切是否正常。

测试ESP32客户端

将两块板都重启后,您会看到ESP#2每隔5秒从ESP#1接收一次新的温度,湿度和压力读数。

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

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

两个开发板正在互相交换数据:

 

给TA买糖
共{{data.count}}人
人已赞赏
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索