本系列历史文章目录:
本期给大家带来的是掌控板 Siri 语音识别的第 2 篇:如何通过 Siri 语音识别获取传感器数据。
掌控板 Siri 语音识别的第 1 篇跳转:Siri 语音识别控制 LED 灯
国际惯例,先来看一下演示效果吧。点击下方链接跳转 B 站观看演示视频:
https://www.bilibili.com/video/av98141978/
在上一篇中,我向大家详细展示了如何利用 Siri 控制掌控板和 LED 灯,这一篇是上一篇的进阶,我将继续教大家如何用 Siri 去读取各种传感器的数据。
没看过上一篇的朋友,建议先去看一下第 1 篇的内容。
跳转链接:掌控板 Siri 语音识别的第 1 篇:LED 灯控制
这次主控板选择的仍然是掌控板,当然正如我前面篇章所说的,你也可以选择其他 ESP32 或者 ESP8266 系列开发板,实现的方法和效果是类似的。读取的传感器数据包括掌控板自带的声音传感器、光线传感器、以及外接的 DHT11 温湿度传感器,学习了本篇章之后,希望你可以学会修改相应代码,换成其他传感器。
在这个项目中,我们同样将掌控板 ESP32 设置为一个 Web 服务器,当用户在网页上访问这个服务器的域名地址(或 IP 地址)的时候,就会跳转到如下界面。最终实现的效果是,不仅可以用 Siri 语音识别去获取传感器数据,也可以直接在网页端查看传感器数据。
我们可以通过点击 LED 的切换开关来控制掌控板上的 RGB LED 的亮灭,也可以访问这个切换开关的对应域名地址,来控制 LED 灯的亮灭。
针对传感器,我们可以直接在网页上一次性读取所有传感器的数据,也可以单独访问每个传感器对应的域名地址来读取相应的数据。这样就完成了基本的通过 Web 页面控制掌控板以及读取数据的功能。
在这基础之后,我们可以通过设置一些语音助手,比如 Siri、天猫语音精灵等,通过语音命令访问对应的域名地址,从而实现语音识别开关灯、读取传感器数据的功能。
本项目中,我们需要外接一个 DHT11 温湿度传感器,通过扩展板将它接在掌控板 P0 引脚,如下图所示。声音数据和光线数据,直接通过掌控板账面自带的两个传感器读取即可。
这个项目需要用到 4 个 Arduino 库:除了上一篇章用到的 Adafruit_NeoPixel、ESPAsyncWebServer、AsyncTCP 之外,我们还加入了 DHT 函数库,它的功能主要是读取 DHT11 温湿度传感器的数值。。
Arduino 库安装的教程不是本篇的重点,这里不再赘述,只给出 4 个库的网址,大家可以自行百度查找 Arduino 怎么安装库。
这一篇章的代码是在上一篇章的基础之上进行修改的,所以基础部分不再赘述,只讲解不同与添加部分。
在程序的开头,我们首先引入了需要用到的库函数:
#include "WiFi.h"
#include "ESPAsyncWebServer.h"
#include "Adafruit_NeoPixel.h"
#include "Adafruit_Sensor.h"
#include "DHT.h"
然后设置网络的账号和密码:
const char *ssid = "wifi_name";
const char *password = "wifi_password";
接着定义一些传感器与执行器引脚,并对他们进行一些初始化设置:
#define SOUNDPIN 36 // P10
#define LIGHTPIN 39 // P4
#define LEDPIN 17 // P7
#define DHTPIN 33 // P0
接着定义了 DHT 对象、NeoPixel 对象(RGB LED 灯)和 WebServer 对象:
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
Adafruit_NeoPixel pixels(3, LEDPIN, NEO_GRB + NEO_KHZ800);
AsyncWebServer server(80);
然后是掌控板 Web 服务器的界面设计,界面设计使用的是 HTML 语言,这里先放一个最基础的界面设计。HTML 相关的代码存储在 index_html 变量中。
const char index_html[] PROGMEM = R"rawliteral(
// HTML code here
)rawliteral";
基础的 HTML 页面设计代码如下:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
html {
font-family: "Microsoft Yahei";
text-align: center;
}
style>
head>
<body>
<h2>掌控板家庭数据中心h2>
<a href="/led=on">Light Ona>
<p>p>
<a href="/led=off">Light Offa>
<p>
<span>声音:span>
<span>%SOUND%span>
p>
<p>
<span>光线:span>
<span>%LIGHT%span>
p>
<p>
<span>温度:span>
<span>%TEMPERATURE%span>
<span>℃span>
p>
<p>
<span>湿度:span>
<span>%HUMIDITY%span>
<span>%span>
p>
body>
html>
这段代码在网页中显示的效果如下。我们可以看到很多数据是在两个百分号(%)之间的,比如 %SOUND%,这个是占位符,我们在程序中读取相应传感器的数据之后,就可以自动替换了,程序中会有专门的函数程序去进行替换,这部分下面会讲。
首先是读取 DHT11 温湿度传感器的函数,这部分比较简单,直接参考 DHT 函数库例程就好:
String readDHTTemperature() {
float temperature = dht.readTemperature();
if (isnan(temperature)) {
Serial.println("Failed to read from DHT sensor!");
return "--";
}
else {
Serial.println(temperature);
return String(temperature);
}
}
String readDHTHumidity() {
float humidity = dht.readHumidity();
if (isnan(humidity)) {
Serial.println("Failed to read from DHT sensor!");
return "--";
}
else {
Serial.println(humidity);
return String(humidity);
}
}
然后是 processor() 函数,这个函数的功能主要就是将网页部分的所有占位符替换为相应的传感器数值。它可以根据占位符的名称,返回对应的数据。
// Replaces placeholder with sensor values
String processor(const String& var) {
if (var == "SOUND") {
return String(analogRead(SOUNDPIN));
}
if (var == "LIGHT") {
return String(analogRead(LIGHTPIN));
}
if (var == "TEMPERATURE") {
return readDHTTemperature();
}
if (var == "HUMIDITY") {
return readDHTHumidity();
}
return String();
}
在初始化函数 setup() 中,我们首先对串口、RGB 灯和 DHT11 传感器进行了初始化:
Serial.begin(9600);
pixels.begin();
dht.begin();
然后将掌控板连接到网络,并把 IP 地址在串口中打印出来:
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println("WiFi connected");
// Print ESP32 Local IP Address and Some Tips
Serial.print("Open your brower, and visit: http://");
Serial.println(WiFi.localIP());
Serial.println();
最后就是最重要的 Web 服务器设置。关于 Web 服务器设置的详细教程,可以查看官网:https://github.com/me-no-dev/ESPAsyncWebServer
这里只放出本文需要的代码。当访问根目录“/”时,会显示所有的数据以及相关的控制按钮。这里显示数据调用的就是上面讲到的 processor 函数。
// Root / Webpage
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send_P(200, "text/html", index_html, processor);
});
当访问“/led=on”路径时,设置 LED 灯为亮;当访问“/led=off”路径时,设置 LED 灯为灭。
// Webpage to turn on light
server.on("/led=on", HTTP_GET, [](AsyncWebServerRequest *request) {
pixels.setPixelColor(0, 0xFF0000);
pixels.setPixelColor(1, 0xFF0000);
pixels.setPixelColor(2, 0xFF0000);
pixels.show();
Serial.println("LED is on");
request->send_P(200, "text/plain", "led on");
});
// Webpage to turn off light
server.on("/led=off", HTTP_GET, [](AsyncWebServerRequest *request) {
pixels.setPixelColor(0, 0x000000);
pixels.setPixelColor(1, 0x000000);
pixels.setPixelColor(2, 0x000000);
pixels.show();
pixels.clear();
Serial.println("LED is off");
request->send_P(200, "text/plain", "led off");
});
然后当访问每个传感器相应路径时,比如"/temperature"、"/humidity"、"/sound"、"/light"这些路径,程序会调用相应的函数读取传感器数据,通过串口将数据打印出来,然后将它们转化成文本 String 类型,并显示在网页上:
// Webpage to get the temperature value
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request) {
Serial.print("Temperature: ");
Serial.println(readDHTTemperature());
request->send_P(200, "text/plain", readDHTTemperature().c_str());
});
// Webpage to get the humidity value
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request) {
Serial.print("Humidity: ");
Serial.println(readDHTHumidity());
request->send_P(200, "text/plain", readDHTHumidity().c_str());
});
// Webpage to get the sound value
server.on("/sound", HTTP_GET, [](AsyncWebServerRequest *request) {
Serial.print("Sound: ");
Serial.println(analogRead(SOUNDPIN));
request->send_P(200, "text/plain", String(analogRead(SOUNDPIN)).c_str());
});
// Webpage to get the light value
server.on("/light", HTTP_GET, [](AsyncWebServerRequest *request) {
Serial.print("Light: ");
Serial.println(analogRead(LIGHTPIN));
request->send_P(200, "text/plain", String(analogRead(LIGHTPIN)).c_str());
});
在 setup() 函数的最后,运行 Web 服务器:
server.begin();
至此,整个程序就编写完成了,在 loop() 函数中,不需要做任何事,当然你也可以运行其他你想要的代码。
在 Arduino 中选择掌控板或者 ESP32 相关的芯片,然后将程序上传,打开串口监视器,我们可以看到串口监视器中提示我们访问相应的网址。(如果没看到相应信息,可以按一下掌控板后面的 RST 按键,重启程序)
打开电脑浏览器或者手机浏览器,访问相应的 IP 地址,这里是:192.168.10.202,我们可以看到网页上显示了相应的信息。
尝试访问对应的地址,当访问 192.168.10.202/led=on 时,浏览器和串口监视器中,都输出了相应的提示信息,同时我们也可以看到掌控板上的 RGB 灯也亮了起来。当访问 192.168.10.202/led=off 时,浏览器和串口监视器中,也都输出了相应的提示信息,同时掌控板上的 RGB 灯也熄灭了。
当访问 192.168.10.202/sound 以及其他传感器对应的网址是,浏览器和串口监视器中,也都输出了相应的提示信息,如下图所示。
这部分不是本文的重点,也不会影响最终语音控制的效果,所以如果您对网页设计不感兴趣,也可以略过,直接跳转到下一节。
在上文中,我们已经基本完成了通过网页来控制 LED 灯、以及读取传感器数据的相关功能,但是这个网页毕竟还是太简陋了。所以我们对网页稍微进行一些优化。
具体 HTML 优化代码请下载附件,这部分参考了国外大神的网站:https://randomnerdtutorials.com/
上述代码最终形成的效果如下。
接下来就是语音识别的设置,原理与上一篇 Siri 教程类似。由于笔者手上没有其他语音助手或者智能音箱类产品,所以这里还是以 Siri 为例。
打开 iOS 系统自带的捷径 App(英文名称 Shortcuts),没有没有的话,也可以去 App Store 免费下载:
快捷指令设置如下图所示。捷径的设置原理很简单,就是访问给定的 URL 地址。
由于 iPhone 中的捷径是支持 Siri 语音识别调用的,所以我们可以直接通过 Siri 来运行这个捷径,从而达到语音识别获取传感器数据的效果。
如果不知道怎么设置快捷指令的话,也可以直接下载笔者的指令。复制下面的链接到 iPhone 浏览器中,就会提示你将这个指令添加到手机中。
https://www.icloud.com/shortcuts/4e20f185da76479a90f0716c9521cc7a
唤醒你的 Siri 看看效果吧。不过这里需要注意的是,你的 iPhone 和掌控板,必须处于同一局域网中。
在本章中,我们学习了:
相比上一篇 Siri 控制 LED 灯的内容,如果不考虑网页设计相关内容的话,其实 Arduino 代码端基本是类似的,希望读者可以学会扩展。
如果本文对你有帮助的话,点个赞支持一下喽。
点击下方链接,查看完整代码下载地址:
https://mp.weixin.qq.com/s/w1-XIcgaddqlcSpnqZPD8A