写在前面

本着认真分享,让其他和我一样有需要的朋友轻松上手,能有参考意义,所以可能较啰嗦。

特别提示:家用电器220V高压危险,请自行判断,无把握请勿操作!本文只做经验分享,请自行评估风险,若有意外与本文无关。

所需硬件配件

  • 乐鑫 ESP32 *1
  • 5V 4 控继电器 *1
  • 可拔插 220V 连接线1平方 *n
  • 220V 转 5V 电源 *1(给继电器供电(ESP32只能输出3.3V,且电源更有保障不占用插座))

物联网DIY

环境安装

1.Ardunio IDE 点此下载中国大陆安装方法
2.Ardunio ESP32 Blinke支持库点此下载

Windows:将下载好的blinker库解压到 我的电脑>文档>Arduino>libraries 文件夹中
Mac OS:将下载好的blinker库解压到 文稿>Arduino>libraries 文件夹中

3.Ardunio安装ESP32开发板。选择ESP32 Dev Module。重要!!
ESP32开发板安装方法:在Ardunio IDE——文件——首选项——附加开发板管理网址中加入 https://dl.espressif.com/dl/package_esp32_index.json

接着Ardunio IDE——工具——开发板——开发板管理器,搜索 ESP32 安装即可。

【案例一】
前些天脸上冒痘,去医院拿了点药,吃完皮肤更干了。冬天房间一干,更是起皮,贼不爽。于是乎,翻出了不知道啥时候公司节日礼品——超声波加湿器。但是,每天手动开关就很烦,希望和温湿度计联动自动开关。于是就研究了下点灯接入小爱。

以下地址查看完整代码:

1
https://github.com/kuole-o/IoT_xiaoai_blinker/blob/main/xiaoai_on_off/xiaoai_on_off.ino

加湿器是“微动开关”,(微动开关:按一次on,再按一次off那种)我的加湿器更扯,开始工作后,再按一次电源似乎是无响应,也就是按两次才能off。在qq群一位老哥指导下,实现了相关效果。后来直接换了加湿器,因此这部分代码实现且测试过,但硬件没搞。

以下地址查看完整代码:

1
https://github.com/kuole-o/IoT_xiaoai_blinker/blob/main/xiaoai_MicroSwitch_1on_2off/xiaoai_MicroSwitch_1on_2off.ino

【案例二】
后来发现加湿器效果弱,只能从 35%湿度提升到42%左右,17平的卧室。。于是,干脆下单了米家纯净式加湿器。效果果然上来了 不加电,纯蒸发都能保持 55%~60%湿度。

于是乎,又把ESP32改成控制取暖器,夏天控制电风扇。因为想着兼容性强,后面随时控制其他家电,而且继电器还剩一个没用,就按2400w电路设计(导致线材有些粗,1平方的)。下面开干。

  • 首先是控制部分,ESP32控制程序。担心大篇幅代码影响阅读体验,所以完整代码在文末,想现在就看的,用下面链接。
    1
    https://github.com/kuole-o/IoT_xiaoai_blinker/blob/main/xiaoai_4_no_off_BlinkerButton5/xiaoai_4_no_off_BlinkerButton5.ino

物联网DIY

Ardunio控制器连接

  1. ESP32控制引脚13/12/27/25分别链接到继电器1/2/3/4的IN1、IN2、IN3、IN4。ESP32通过microUSB从220V电源上取电。(这里使用了一个220v转5v的电源适配器,不是直接连接到220v电路……)
  2. 继电器输入供电,DC+——电源V+ DC- ——电源V-
  3. 继电器输出:NO常开口分别接拔插式插头——公头。公共端COM一样链接。注意:最好根据线材颜色链接同端口,以免后面错乱。

物联网DIY
物联网DIY
物联网DIY

强电部分电路连接

在不连接负载情况下,对控制板、继电器做控制调试。验证无误后,开始下文的硬件链接。

拆开取暖器,一根3芯控制低温、高温的线,链接到调温旋钮上。此处调节到低温旋钮,用万用表测通断,分辨低温、高温的接头。用电烙铁焊接。

物联网DIY

一根2芯线,控制摇头旋钮的闭合;一根2芯线从取暖器电源线上取电,转给220V降压电源。此处注意连接在“防侧翻保险”后。

物联网DIY
物联网DIY
物联网DIY

最终效果演示

至此,硬件电路链接完成。实测效果如下:

1
我在 Github 上的该仓库:https://github.com/kuole-o/IoT_xiaoai_blinker

完整源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
#define BLINKER_WIFI
#define BLINKER_MIOT_MULTI_OUTLET //设置为小爱多个插座的模式

#include <Blinker.h>

char i;
char auth[] = "******"; //点灯 App 里申请的设备 key
char ssid[] = "******"; //连接的 WiFi 名称
char pswd[] = "******"; //连接的 WiFi 密码

bool oState[5] = { false };

// 新建组件对象,要和APP组件’数据键名’一致
BlinkerButton Button1("btn_a");
BlinkerButton Button2("btn_b");
BlinkerButton Button3("btn_c");
BlinkerButton Button4("btn_d");
BlinkerButton Button5("btn_all");

// 按下Blinker APP按键1即会执行该函数
void button1_callback(const String & state)
{
BLINKER_LOG("get button state: ", state);
digitalWrite(13, !digitalRead(13));
if (state == "on") {
digitalWrite(13, LOW);
Button1.print("on");
Button1.text("摇头:开");
}
else if (state == "off") {
digitalWrite(13, HIGH);
Button1.print("off");
Button1.text("摇头:关");
}
}

// 按下Blinker APP按键2即会执行该函数
void button2_callback(const String & state)
{
BLINKER_LOG("get button state: ", state);
digitalWrite(12, !digitalRead(12));
if (state == "on") {
digitalWrite(12, HIGH);
Button2.print("on");
Button2.text("低温/弱风");
}
else if (state == "off") {
digitalWrite(12, LOW);
Button2.print("off");
Button2.text("低温/弱风");
}
}

// 按下Blinker APP按键3即会执行该函数
void button3_callback(const String & state)
{
BLINKER_LOG("get button state: ", state);
digitalWrite(27, !digitalRead(27));
if (state == "on") {
digitalWrite(27, HIGH);
Button3.print("on");
Button3.text("高温/强风");
}
else if (state == "off") {
digitalWrite(27, LOW);
Button3.print("off");
Button3.text("高温/强风");
}
}

// 按下Blinker APP按键4即会执行该函数
void button4_callback(const String & state)
{
BLINKER_LOG("get button state: ", state);
digitalWrite(25, !digitalRead(25));
if (state == "on") {
digitalWrite(25, HIGH);
Button4.print("on");
Button4.text("未定义:开");
}
else if (state == "off") {
digitalWrite(25, LOW);
Button4.print("off");
Button4.text("未定义:关");
}
}

// 按下Blinker APP按键5即会执行该函数
void button5_callback(const String & state)
{
BLINKER_LOG("get button state: ", state);
digitalWrite(13, !digitalRead(13));
digitalWrite(12, !digitalRead(12));
if (state == "on") {
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
Button1.print("on");
Button2.print("on");
Button1.text("摇头:开");
Button2.text("低温/弱风");
}
else if (state == "off") {
digitalWrite(12, LOW);
digitalWrite(13, LOW);
digitalWrite(27, LOW);
Button1.print("off");
Button2.print("off");
Button3.print("off");
Button1.text("摇头:关");
Button2.text("低温/弱风");
Button3.text("高温/强风");
}
}

// 13-摇头/不摇头;12-低温/弱风;27-高温/强风
void miotPowerState(const String & state, uint8_t num)
{
BLINKER_LOG("need set outlet: ", num, ", power state: ", state);
i = 0; //初始化

if (num == 1) {
i = 13;
}
else if (num == 2) {
i = 12;
}
else if (num == 3) {
i = 27;
}
else if (num == 4) {
i = 25;
}

if (state == BLINKER_CMD_ON) {
switch (i) {
case 12:
digitalWrite(27, LOW);
digitalWrite(i, !digitalRead(27));
BlinkerMIOT.powerState("on", num);
BlinkerMIOT.print();
oState[num] = true;

break;

case 27:
digitalWrite(12, LOW);
digitalWrite(i, !digitalRead(12));
BlinkerMIOT.powerState("on", num);
BlinkerMIOT.print();
oState[num] = true;

break;

default:
digitalWrite(i, HIGH);
BlinkerMIOT.powerState("on", num);
BlinkerMIOT.print();

oState[num] = true;
}

}
else if (state == BLINKER_CMD_OFF) {
switch (i) {
case 12:
digitalWrite(27, LOW);
digitalWrite(i, LOW);
BlinkerMIOT.powerState("off", num);
BlinkerMIOT.print();
oState[num] = false;

break;

case 27:
digitalWrite(12, LOW);
digitalWrite(i, LOW);
BlinkerMIOT.powerState("off", num);
BlinkerMIOT.print();
oState[num] = false;

break;

default:
digitalWrite(i, LOW);
BlinkerMIOT.powerState("off", num);
BlinkerMIOT.print();

oState[num] = false;
}

if (num == 0) {
for (uint8_t o_num = 0; o_num < 5; o_num++) {
oState[o_num] = false;
}
}
}
}

void miotQuery(int32_t queryCode, uint8_t num)
{
BLINKER_LOG("AliGenie Query outlet: ", num, ", codes: ", queryCode);

switch (queryCode)
{
case BLINKER_CMD_QUERY_ALL_NUMBER :
BLINKER_LOG("MIOT Query All");
BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
BlinkerMIOT.print();
break;
case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
BLINKER_LOG("MIOT Query Power State");
BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
BlinkerMIOT.print();
break;
default :
BlinkerMIOT.powerState(oState[num] ? "on" : "off", num);
BlinkerMIOT.print();
break;
}
}

void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);

Blinker.vibrate();

uint32_t BlinkerTime = millis();

Blinker.print("millis", BlinkerTime);
}

void setup()
{
Serial.begin(115200);
BLINKER_DEBUG.stream(Serial);

pinMode(13, OUTPUT);
digitalWrite(13, LOW);
pinMode(12, OUTPUT);
digitalWrite(12, LOW);
pinMode(27, OUTPUT);
digitalWrite(27, LOW);
pinMode(25, OUTPUT);
digitalWrite(25, LOW);

Blinker.begin(auth, ssid, pswd);
Blinker.attachData(dataRead);
Button1.attach(button1_callback);
Button2.attach(button2_callback);
Button3.attach(button3_callback);
Button4.attach(button4_callback);
Button5.attach(button5_callback);

BlinkerMIOT.attachPowerState(miotPowerState);
BlinkerMIOT.attachQuery(miotQuery);

}

void loop()
{
Blinker.run();
}