按下物理开关时,舵机旋转160度,延迟几秒后喇叭发出声音。
通过AP网络连接后,通过网页的开门1/2/3按钮控制舵机旋转,延迟几秒后喇叭发出声音。
附上接线图:
全部代码:
#include <Servo.h>
#include <Arduino.h>
#include "ESP8266WiFi.h"
#include "ESP8266WebServer.h"
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>
Servo myservo;
SoftwareSerial mySerial(D0, D1); // RX, TX。与mp3有关
ESP8266WebServer server(80);
const int switchPin1 = D8; // 定义外置开关的一个引脚
bool switchState = false; // 用于存储开关状态
void handleRoot() {
String html = "<!DOCTYPE html>\n"
"<html lang=\"en\">\n"
"<head>\n"
"<meta charset=\"UTF-8\">\n"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
"<style>\n"
"body, html {\n"
" height: 100%;\n"
" margin: 0;\n"
" display: flex;\n"
" justify-content: center;\n"
" align-items: center;\n"
" font-family: Arial, sans-serif;\n"
" box-sizing: border-box;\n"
"}\n"
"\n"
".button-container {\n"
" display: flex;\n"
" flex-direction: column;\n"
" align-items: center;\n"
" width: 100%;\n"
" padding: 10px;\n"
" text-align: center;\n"
"}\n"
"\n"
".button {\n"
" width: calc(100% - 40px);\n" /* 减去左右padding的宽度,保持按钮内部内容居中 */
" padding: 15px 20px;\n"
" font-size: 16px;\n"
" font-weight: bold;\n"
" text-align: center;\n"
" text-decoration: none;\n"
" color: #fff;\n"
" background-color: #007BFF;\n"
" border: none;\n"
" border-radius: 5px;\n"
" cursor: pointer;\n"
" margin: 10px 0;\n"
" box-sizing: border-box;\n"
" transition: background-color 0.3s ease;\n"
"}\n"
"\n"
"@media (min-width: 600px) {\n" /* 当屏幕宽度大于或等于600px时 */
" .button {\n"
" font-size: 18px;\n" /* 增大字体 */
" padding: 20px 30px;\n" /* 增大内边距 */
" }\n"
"}\n"
"\n"
".button:hover {\n"
" background-color: #0056b3;\n"
"}\n"
"\n"
".button:active {\n"
" background-color: #004085;\n"
"}\n"
"</style>\n"
"</head>\n"
"<body>\n"
"<div class=\"button-container\">\n"
"<h2>WIFI控制开关</h2>\n"
"<a href=\"/on\" class=\"button\">开门1</a>\n"
"<a href=\"/off\" class=\"button\">开门2</a>\n"
"<a href=\"/fw\" class=\"button\">开门3</a>\n"
"<a href=\"/xh\" class=\"button\">测试舵机</a>\n"
"</div>\n"
"</body>\n"
"</html>\n";
server.send(200, "text/html", html);
}
void handleOn() {
myservo.write(135); // 旋转到135度
delay(1000);
myservo.write(0);
delay(2000);
mp3_play(2); //播放第0002
server.sendHeader("Location", "/");
server.send(303);
}
void handleOff() {
myservo.write(160); // 旋转到160度
delay(1000);
myservo.write(0);
delay(2000);
mp3_play(2); //播放第0002
server.sendHeader("Location", "/");
server.send(303);
}
void handleFw() {
myservo.write(180); // 旋转到180度
delay(1000);
myservo.write(0);
mp3_set_volume(15);//mp3声音
mp3_play(1); //播放第0001
server.sendHeader("Location", "/");
server.send(303);
}
void handleXh() {
myservo.write(0); // 旋转到0度
delay(2000);
myservo.write(90);// 旋转到90度
delay(2000);
myservo.write(180);// 旋转到180度
delay(2000);
myservo.write(0);// 旋转到0度
server.sendHeader("Location", "/");
server.send(303);
}
void setup() {
Serial.begin(115200); //设置舵机波特率
mySerial.begin(9600); //设置MP3波特率
myservo.attach(D5,500,2500);//定义舵机引脚和频率
mp3_set_serial(mySerial);//这是MP3模块
mp3_set_volume(30);//初始化声音为30
myservo.write(0); // 初始化舵机-舵机初始位置
WiFi.mode(WIFI_AP); //设置WiFi模式为AP
WiFi.softAP("WIFI_AP", "12345678"); //设置名称,密码
server.begin(); //开启服务
//设置网页的跳转四个按钮
server.on("/", handleRoot);
server.on("/on", handleOn);
server.on("/off", handleOff);
server.on("/fw", handleFw);
server.on("/xh", handleXh);
pinMode(switchPin1, INPUT_PULLUP); // 设置开关引脚为上拉输入模式
}
void loop() {
server.handleClient();
// 读取开关状态
bool currentState = digitalRead(switchPin1) == LOW; // 假设按下开关时引脚电平为LOW
// 如果开关状态发生变化
if (currentState != switchState) {
switchState = currentState;
// 根据开关状态控制舵机旋转
if (switchState) {
myservo.write(160); // 例如,按下开关时舵机旋转到160度
} else {
myservo.write(0); // 例如,松开开关时舵机旋转到0度
delay(2500);
mp3_play(1); //播放第0001
}
// 打印调试信息
Serial.println(switchState ? "Switch ON" : "Switch OFF");
// 延时一段时间,避免过于频繁的读取开关状态
delay(1500);
}
}