本文将介绍如何制作一款基于esp32,并经由wifi网络实现的门铃。
项目起因
今年新家装修的时候,我忽略了门铃的问题。原来门边上设置有一个门铃按钮,但由于原来预留的线都被混凝土掩盖了,没办法找到电缆头在哪里。于是纠结怎么安装一款门铃。到网上一搜,目前有wifi门铃的解决方案,可以把电铃放在不同的房间,但价格相当昂贵,而且还需要220v的电源供电。于是我选择用无线门铃来解决,但结果证明无线门铃的运行并不是非常可靠,而且我不怎么喜欢基于电池的解决方案。于是,开始萌生了采用微控制器来解决这个问题,使旧门铃能复活过来。
工作原理
项目的思路是这样的:设置两片单片机,分别置于室内和室外,当第一个单片机检测到按钮上的按钮动作时,通过wifi网络向第二个单片机发送请求。第二个单片机连接到喇叭,当它收到发送的请求时便播放预设的铃声。项目中我使用了集成wifi的espressif esp32开发板。为了让项目更简单,我还添加了一个便宜的mp3播放器模块。
原件清单
两块 espressif esp32开发板 ;
dfplayer mp3模块和 sd卡;
4欧姆 3w的喇叭;
2个1k的电阻;
两个3.3v led指示灯;
按钮开关;
面包板。
电路组装
这一部分比较简单,没什么值得注意的。基本上就是把所有的元件放在一起。最后,我把led灯忘在扬声器那一侧了。(不过,最后代码中对其进行了处理。)
基于esp32制作门铃之发送侧
门铃的外壳是采用3d打印机打印的,分为两部分,室外部分和室内部分。附件是电路连接图和外壳的3d打印stl文件,需要可下载:
基于esp32制作门铃之发送侧实物
基于esp32制作门铃之接收侧
基于esp32制作门铃之接收侧实物
代码
虽然发射端硬件上仅仅是稍微闪烁一下led,功能比较单一,但接收单元提供了更多的功能,它可以启动一个小型web服务器,为发射端提供界面,也可以通过浏览器直接使用它。它还允许设置扬声器音量。
esp32门铃的设置界面
发送端代码
/*
* sources:
* https://www.arduino.cc/en/tutorial/button
* https://techtutorialsx.com/2017/05/19/esp32-http-get-requests/
*/
#include
#include
const char* ssid = wifi ssid;
const char* password = wifi password;
const char* bellurl = http://192.168.1.149/bell/on;
const int buttonpin = 21; // the number of the pushbutton pin
const int ledpin = 23; // the number of the led pin
int buttonstate = 0;
void setup() {
serial.begin(115200);
btstop(); // turn off bluetooth
pinmode(ledpin, output);
pinmode(buttonpin, input);
connectwifi();
}
void loop() {
if ((wifi.status() == wl_connected)) {
buttonstate = digitalread(buttonpin);
delay(100);
if (buttonstate == high) {
digitalwrite(ledpin, high);
httpclient http;
http.begin(bellurl);
serial.print(get );
serial.println(bellurl);
int httpcode = http.get();
if (httpcode > 0) {
//string payload = http.getstring();
serial.println(httpcode);
//serial.println(payload);
}
else {
serial.println(error on http request);
}
http.end();
delay(200);
}
else {
digitalwrite(ledpin, low);
}
}
else {
serial.println(wifi not connected!);
digitalwrite(ledpin, high);
delay(200);
digitalwrite(ledpin, low);
delay(50);
digitalwrite(ledpin, high);
delay(200);
digitalwrite(ledpin, low);
connectwifi();
}
}
void connectwifi() {
boolean ledstatus = false;
serial.print(connecting to );
serial.println(ssid);
wifi.begin(ssid, password);
while (wifi.status() != wl_connected) {
delay(500);
serial.print(.);
ledstatus = !ledstatus;
digitalwrite(ledpin, ledstatus);
}
serial.println(wifi connected.);
serial.println(ip address: );
serial.println(wifi.localip());
}
接收端代码
/*
sources:
https://www.dfrobot.com/wiki/index.php/dfplayer_mini_sku:dfr0299
https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/esp32_dfplayer_full/esp32_dfplayer_full.ino
https://github.com/pcbreflux/espressif/blob/master/esp32/arduino/sketchbook/esp32_dfplayer_full/setup.png
esp32 web server – arduino ide
*/
#include
#include dfrobotdfplayermini.h
#include
hardwareserial hwserial(1);
dfrobotdfplayermini dfplayer;
int volume = 5;
const char* ssid = wifi ssid;
const char* password = wifi password;
wifiserver server(80); // set web server port number to 80
string header;
string ledstate = ;
const int ledpin = 26;
unsigned long timestamp = 0;
void setup()
{
btstop(); // turn off bluetooth
hwserial.begin(9600, serial_8n1, 18, 19); // speed, type, tx, rx
serial.begin(115200);
// wifi & led ==================================================================
pinmode(ledpin, output);
digitalwrite(ledpin, low);
// connect to wi-fi network with ssid and password
serial.print(connecting to );
serial.println(ssid);
wifi.begin(ssid, password);
while (wifi.status() != wl_connected) {
delay(500);
serial.print(.);
}
// print local ip address and start web server
serial.println();
serial.println(wifi connected.);
serial.println(ip address: );
serial.println(wifi.localip());
server.begin();
delay(500);
dfplayer.begin(hwserial); //use softwareserial to communicate with mp3
dfplayer.settimeout(500); //set serial communication time out 500ms
dfplayer.volume(volume); //set volume value (0~30).
dfplayer.eq(dfplayer_eq_normal);
dfplayer.outputdevice(dfplayer_device_sd);
ledstate = on;
digitalwrite(ledpin, high);
timestamp = millis();
dfplayer.play(1); //play the first mp3
}
void loop() {
wificlient client = server.available(); // listen for incoming clients
if (ledstate == on && (millis() - timestamp) > 2000) {
ledstate = off;
digitalwrite(ledpin, low);
}
if (client) {
string currentline = ; // make a string to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client http request, so send a response:
if (currentline.length() == 0) {
// http headers always start with a response code (e.g. http/1.1 200 ok)
// and a content-type so the client knows what's coming, then a blank line:
client.println(http/1.1 200 ok);
client.println(content-type:text/html);
client.println(connection: close);
client.println();
// turns the gpios on and off
if (header.indexof(get /bell/on) >= 0) {
ledstate = on;
digitalwrite(ledpin, high);
timestamp = millis();
dfplayer.play(1); //play the first mp3
}
else if (header.indexof(get /volume/) >= 0) { // yes, i know this is not restful
string str1 = header;
str1 = str1.substring(header.indexof(get /volume/) + 12);
volume = str1.substring(0, str1.indexof( )).toint();
if (volume 30) {
volume = 30;
}
dfplayer.volume(volume);
serial.print(volume set to );
serial.println(volume);
}
// display the html web page
client.println(
);
client.println(
);
client.println(
);
client.println( html { font-family: sans-serif; display: inline-block; margin: 0px auto; text-align: center; });
client.println(.button { background-color: #4caf50; border: none; color: white; padding: 16px 40px; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;});
client.println(.button2 { background-color: #4caf50; border: none; color: white; padding: 4px 10px; text-decoration: none; margin: 1px; cursor: pointer;} );
client.println(
lewe türklingel
);
client.println(
volume: − + string(volume) + +
);
client.println(
klingeln
);
client.println(
dfplayer status: + printdetail(dfplayer.readtype(), dfplayer.read()) +
);
client.println(
led - state + ledstate +
);
client.println();
// the http response ends with another blank line
client.println();
// break out of the while loop
break;
} else { // if you got a newline, then clear currentline
currentline = ;
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentline += c; // add it to the end of the currentline
}
}
}
// clear the header variable
header = ;
// close the connection
client.stop();
serial.println(client disconnected.);
serial.println();
}
}
string printdetail(uint8_t type, int value){
switch (type) {
case timeout:
return time out!;
break;
case wrongstack:
return stack wrong!;
break;
case dfplayercardinserted:
return card inserted!;
break;
case dfplayercardremoved:
return card removed!;
break;
case dfplayercardonline:
return card online!;
break;
case dfplayerplayfinished:
return play finished!;
break;
case dfplayererror:
switch (value) {
case busy:
return error: card not found;
break;
case sleeping:
return error: sleeping;
break;
case serialwrongstack:
return error: get wrong stack;
break;
case checksumnotmatch:
return error: check sum not match;
break;
case fileindexout:
return error: file index out of bound;
break;
case filemismatch:
return error: cannot find file;
break;
case advertise:
return error: in advertise;
break;
default:
break;
}
break;
default:
break;
}
}
理想、小鹏业绩超预期,造车新势力盘初大涨
Windows 7最新安装方法大全
模拟电子技术难点:三极管的电流分配及放大原理
激光二极管的工作原理解析
采用插即用UPnP扩展实现播放器的设计
基于ESP32和DFPlayer实现WiFi门铃的制作
基于多功能杆的智慧农田农业监测应用
超六类网线价格存在差异的原因
什么是位式控制?
隆达电子第一季营收创下近10年来单季新低 推估或续亏
什么是“HD Ready”标准
苹果建议开发者将原版Mac软件转化为新的通用二进制代码
传感器助力工业互联网转型升级
“无人超市”如何运作 又是否安全
新能源汽车需求压迫下 锂电池材料如何破冰突围
仅需一个主题!就能让小米MIX2拥有“iPhone X”的既视感!
人工智能的恶意用途:预测、预防和缓解,你知道吗?
VR头显为什么要配置透镜
2023年存储芯片市场下滑将比去年减少17%
Stripe改进引擎,已实现对全球卡网络的支持