65.9K
CodeProject 正在变化。 阅读更多。
Home

通过浏览器连接 ESP32 板

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2020年6月18日

CPOL

3分钟阅读

viewsIcon

23433

downloadIcon

518

基于板的自动化和环境控制

引言

本文探讨了如何与 Arduino 或 ESP32 等单片机开发板交互,以控制实际过程的功能。

这些设备可以通过多种方式与外部世界交互:通过串口、LCD、蓝牙和 Wi-Fi 等通信协议。

串口需要连接到 PC 或手机的电缆;LCD 是一种输出设备,因此需要一些输入设备;蓝牙和 Wi-Fi 是双向的,并且不需要电缆。

要通过蓝牙访问开发板,我们需要在检查设备上安装一个程序;通过将 Wi-Fi 用作 WEB 服务器,我们可以通过浏览器访问开发板,该浏览器是从开发板下载的 HTML 页面,其中包含 JavaScript 指令,充当控制程序。

在本文中,我展示了一个基于运行在 ESP32 开发板上的 WiFi WEB 服务器的解决方案,该开发板使用 Arduino IDE 1.8.12 开发。 我尝试创建一个并非微不足道的应用程序,以突出连接的显著特征:该应用程序可以显示由三线传感器 DHT22 读取的温度和湿度,并且可以修改内部时钟。

从 WiFi 开始

可以编程 WiFi 在现有的 WiFi 网络中运行,或者像这里所关注的那样,作为接入点运行。 在所有情况下,我们都需要两个库: *WiFi.h* 库用于设置 WiFi 部分,*WebServer.h* 库用于构建网页。

在这里,我简要地讨论了实现服务器所需的指令,互联网上有很多页面非常详细地说明了它们,相反,我将专注于那些允许创建有效应用程序而又不过分关注美学的功能。 无论如何,您可以参考所附的源代码,我希望它是自我解释的。

...
#include <WiFi.h>
#include <WebServer.h>
...
// SSID & Password ******************************************************
const char* ssid = "Sermig_Condor";
const char* password = "";
// IP Address ***********************************************************
IPAddress local_ip(192, 168, 1, 1);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
WebServer server(80);  // Object of WebServer(HTTP port, 80 is default)
...

有趣的部分从 `setup` 函数开始

void setup() {
...
  // Create SoftAP
  WiFi.softAP(ssid, password);
  WiFi.softAPConfig(local_ip, gateway, subnet);
...
  server.on("/", handle_root);
  server.onNotFound([](){server.send(404, "text/plain", "The content was not found.");
  });
  server.begin();
...
}

`WebServer` 模拟了一个事件驱动的应用程序,即 `server.on("/", handle_root)` 将一个函数附加到一个请求,在上面的例子中,获取根页面 `"/"` 的请求将由函数 `handle_root` 满足。 我们可以将函数附加到服务器最终必须提供的每个“页面”,还可以将函数附加到未知的请求:`server.onNotFound([](){server.send(...);});`。

与 WiFi 交互

在循环函数中,有 `listen` 指令和一个延迟,用于模拟开发板的功能,例如,对控件、传感器等的定时循环。

串行通信用于模拟中断来激活 WiFi,它需要不断地监听(注意小的 `delay(10)`)

void loop() {
    while (Serial.available() > 0) {
      char cmd = Serial.read();
      if (cmd == 115) listen = !listen;	// s start/stop listening
      Serial.println(listen?"WEB on":"WEB off");
    }
  if(listen) server.handleClient();
  else delay(1980);
  delay(10);
}
管理请求的函数(在右侧)不是特别有趣。
URL 中存在的参数数量(通过方法 `args()` 获得)区分请求,即,如果数量为 `0`,则发送包含 JavaScript 的根页面(参见下面的 HTML 页面和以更易读形式编写的 JavaScript 代码),否则,它(可能)是一个 Ajax 请求,并通过方法 `arg("c")`,该函数检索并执行所需的命令。
void handle_root() {
  if (server.args() == 0) {    
     server.send(200, "text/html", H+T); // Handle root url (/)
  } else {
    char command = server.arg("c").charAt(0);
    char answer[50];
    switch (command) {
      case 104:        // h set time
        setTime(server.arg("n").toInt());
        sprintf(answer,"%s","New time");
        break;
      case 116:        // t temperature and humidity
        getTemperature();
        strcpy (answer,workBuffer);
        break;
    }
    sprintf(workBuffer, "%s %s", getTime(),answer);
    Serial.println(workBuffer);
    server.send(200, "text/html",workBuffer);
  }
}
<!DOCTYPE html>
<html>
<meta name='viewport' content='width=device-width, initial-scale=1' />
<body>
<h1>Condor Web Server with ESP32 - AP Mode</h1>
<input type=button value='Set time' onClick='ajx("c=h&n="+$("n").value)'/>
<input type=number id=n value='36000'/>
<p><input type=button value='Get temp.' onClick='ajx("c=t")'/>
<pre id='f'></pre>";
</body>
</html>	
<script type='text/javascript'>
$=i=>document.getElementById(i);
ajx=u=>{
	var x = new XMLHttpRequest();
	x.onreadystatechange = () => {
		if (x.readyState == 4) {
		if (x.status == 200) $('f').innerHTML += '\\n'+x.responseText;
		else $('f').innerHTML = 'Err: ' + x.status;
		}
	};
	x.open('GET', '?'+u, true);
	x.send(null)
}
</script>

`meta` 标签告诉浏览器适应客户端大小,因此在手机上,该页面是可以接受的。 该页面包含两个按钮,带有相关的 `onClick` 事件,一个文本输入数字和一个 `pre` 格式化的标签,用于接收答案。

Ajax 函数在接收到数据时,直接将其添加到 `pre` 格式化的标签中。

访问开发板

检查设备必须连接 WiFi 开发板(通过 `网络和互联网` 部分中的 App `设置`),并在浏览器中插入 IP,在此示例中为 `192.168.1.1`;它应该出现一个页面,用户可以在其中请求温度和湿度或设置时钟输入自午夜以来的秒数。

最后的 remarks

我是自动化领域的新手,因此欢迎任何问题、批评或建议。

历史

  • 2020年6月17日:初始版本
© . All rights reserved.