ESP8266-ESP-01S
前言
最近闲来无事便想做点类似智能家居控制的事情,经过一番了解之后发现利用ESP8266模块处理是一个热门方案,因为本人对于这方面是小白一个,经过一周多的摸索,终于基本上达到了自己的预期,其间也发现这中间对新手还是有很多巨坑的,所以就在这里做一篇相对完整展示的文章,顺带也强迫自己复盘输出,强化下知识。
一、预期功能
因为是小白,发现网上资料又很多也杂,所以基本看了一遍Arduino基础后决定采用需求导向模式实现,思路如下:朴素的功能需求→细化拆分为关键功能模块→每个功能模块的解决方案(其实就类似盖房子啦)
二、功能逐步实现
1. 端口控制实现
任何利用MCU的控制最终都要落地到利用端口实现,因为已经有Relay控制板,所以这个端口要根据板子的设定来确定:
第1种和第3种就不讲了,讲下第二种,因为Relay板子比较简单,所以直接翻开身子一眼就看穿了,(*^\▽^*) →GPIO0:
#define Y 0 //定义输出端口GPIO0
void setup()
{
Serial.begin(115200);
// 初始化有ESP-01S板子内置的LED及输出端口Y的IO
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, 1);
pinMode(Y, OUTPUT);
digitalWrite(Y, 1);
}
void loop()
{
digitalWrite(LED_BUILTIN, 0);
digitalWrite(Y,0);
delay(1000);
digitalWrite(LED_BUILTIN, 1);
digitalWrite(Y,1);
delay(1000);
}
2. WiFi联网
这里搜了下资料发现常用的基本有5种联网方式,下面也做了一个简单的总结:
不过由于方式太多,篇幅有限,这里就只演示主流的微信配网的方式,其它的可自行另外搜索专题资料:
#include <ESP8266WiFi.h> //WIFI库,配网必需
/* 微信智能配网 */
void smartConfig()
{
WiFi.mode(WIFI_STA);//设置STA模式
Serial.println("\r\nWait for Smartconfig...");//打印log信息
WiFi.beginSmartConfig();//开始SmartConfig,等待手机端发出用户名和密码
while(1)
{
Serial.println(".");
//指示灯闪烁,提示需要配网
digitalWrite(LED_BUILTIN,HIGH);
delay(1000);
digitalWrite(LED_BUILTIN,LOW);
delay(1000);
if(WiFi.smartConfigDone())//配网成功,接收到SSID和密码
{
Serial.println("SmartConfig Success");
Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
WiFi.setAutoConnect(true); // 设置自动连接,这个语句是最重要的语句。
//指示灯快速闪烁5次,提示联网成功
for (int i = 0; i < 5; i++)
{
digitalWrite(LED_BUILTIN,LOW);
delay(400);
digitalWrite(LED_BUILTIN,HIGH);
}
break;
}
delay(1000); // 这个地方一定要加延时,否则极易崩溃重启
}
}
void setup()
{
//网络连接
if (!autoConfig())
{
Serial.println("Start module");
smartConfig();
}
WiFi.begin(WiFi.SSID().c_str(),WiFi.psk().c_str());
}
代码写完之后只需要关注微信公众号“安信可科技”进行如下操作即可:
输入密码即可
3. 天猫精灵接入(小爱、小度同理)
这里就是用点灯科技的语音接入代码直接套用就好了,不懂的就看官网吧:点灯科技-天猫精灵接入
#define BLINKER_PRINT Serial
#define BLINKER_WIFI
#define BLINKER_ALIGENIE_OUTLET
#include <Blinker.h>
char auth[] = "设备秘钥";
char ssid[] = "WiFi SSID";
char pswd[] = "WiFi PSWD";
bool oState = false;
void aligeniePowerState(const String & state)
{
BLINKER_LOG("need set power state: ", state);
if (state == BLINKER_CMD_ON) {
digitalWrite(LED_BUILTIN, HIGH);
BlinkerAliGenie.powerState("on");
BlinkerAliGenie.print();
oState = true;
}
else if (state == BLINKER_CMD_OFF) {
digitalWrite(LED_BUILTIN, LOW);
BlinkerAliGenie.powerState("off");
BlinkerAliGenie.print();
oState = false;
}
}
void aligenieQuery(int32_t queryCode) //天猫精灵语音命令反馈
{
BLINKER_LOG("AliGenie Query codes: ", queryCode);
switch (queryCode)
{
case BLINKER_CMD_QUERY_ALL_NUMBER :
BLINKER_LOG("AliGenie Query All");
BlinkerAliGenie.powerState(oState ? "on" : "off");
BlinkerAliGenie.print(); //将以上属性发送给天猫精灵
break;
case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
BLINKER_LOG("AliGenie Query Power State");
BlinkerAliGenie.powerState(oState ? "on" : "off");
BlinkerAliGenie.print();
break;
default :
BlinkerAliGenie.powerState(oState ? "on" : "off");
BlinkerAliGenie.print();
break;
}
}
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
Blinker.vibrate();
uint32_t BlinkerTime = millis();
Blinker.print(BlinkerTime);
Blinker.print("millis", BlinkerTime);
}
void setup()
{
Serial.begin(115200);
#if defined(BLINKER_PRINT)
BLINKER_DEBUG.stream(BLINKER_PRINT);
#endif
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Blinker.begin(auth, ssid, pswd);
Blinker.attachData(dataRead);
BlinkerAliGenie.attachPowerState(aligeniePowerState);
BlinkerAliGenie.attachQuery(aligenieQuery);
}
void loop()
{
Blinker.run();
}
4. APP界面控件编辑
同样的点灯科技代码套入,只需要注意一点就是界面编辑时控件名称要和代码中的一致:
// 新建组件对象
BlinkerButton Button1("btn-on");
// 按下按键即会执行该函数
void button1_callback(const String & state) //点灯app内控制按键触发
{
BLINKER_LOG("get button state:", state);
if(state == "on")
{
Button1.print("on");
Button1.color("#00A90C");
Button1.text("已打开");
// Button1.icon("icon_1");
digitalWrite(LED_BUILTIN, 0);
digitalWrite(X,0);
delay(20); //回调函数中不能用delay,应为blinker.delay
oState = true; //开关状态保存,主要用于同步给天猫精灵
Blinker.vibrate();
}
else if(state == "off")
{
Button1.print("off");
Button1.color("#808080");
Button1.text("已关闭");
// Button1.icon("icon_2");
digitalWrite(LED_BUILTIN, 1);
digitalWrite(X,1);
delay(20); //回调函数中不能用delay,应为blinker.delay
oState = false; //开关状态保存,主要用于接入天猫精灵
Blinker.vibrate();
}
}
// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
counter++;
Number1.print(counter);
Blinker.vibrate();
uint32_t BlinkerTime = millis();
Blinker.print(BlinkerTime);
Blinker.print("millis", BlinkerTime);
}
界面如下(显示文本“连接中”可是有秒用的,自己体会吧*^▽^*):
三、防坑提示
1.管脚编号、管脚名称、GPIO编号及开发板编码关系
记得一点就是用程序里凡是要用到引脚的位置都用IO编号对应的数字或者主板编号的字符串就好了,例如:使用GPIO0时,可用如下代码初始化,
pinMode(0, OUTPUT) <==>pinMode(‘D3’, OUTPUT);
下表为他们的对应关系:
2.:微信配网条件
①代码里的秘钥一定是正确的;
②你的手机一定是连接着你想要模块儿连接的WiFi;
③手机和模块都在WiFi范围内;
3.:点灯科技APP使用
①获取秘钥时一定使用《阿里云》,不要使用点灯科技的云,否则不支持天猫精灵;
②利用天猫精灵中添加设备→搜索“点灯科技”→绑定账号→设备同步功能接入天猫精灵
4.:别忘了添加库
代码实现离不开的库:binker、DHT、ESP8266
四、完整代码及功能演示
1.完整代码
#define BLINKER_PRINT Serial
#define BLINKER_WIFI
#define BLINKER_ALIGENIE_OUTLET
#include <Blinker.h>
#include <ESP8266WiFi.h> //WIFI库,配网必需
#include <DHT.h>
#define DHTPIN 2 //定义单总线协议传输的数据引脚
#define Y 0 //定义输出端口GPIO0
#define DHTTYPE DHT11 // DHT 11温湿度计
char auth[] = "*********"; //这里填入你在点灯里面获取的秘钥
// 新建组件对象,要和APP组件中的“数据键名”一致
BlinkerButton Button1("btn-on");
BlinkerNumber Number1("num-abc");
int counter = 0;
bool oState = false;
//读取DHTXX传感器相关定义和变量
BlinkerNumber HUMI("humi"); //定义湿度数据键名
BlinkerNumber TEMP("temp"); //定义湿度数据键名
int count = 0; //时间计数
bool WIFI_Status = true; //WIFI状态标志位
//配置网络
bool autoConfig()
{
WiFi.begin();
for (int i = 0; i < 20; i++)
{
int wstatus = WiFi.status();
if (wstatus == WL_CONNECTED)
{
Serial.println("AutoConfig Success");
Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
WiFi.printDiag(Serial);
return true;
break;
}
else
{
Serial.print("AutoConfig Waiting......");
Serial.println(wstatus);
delay(1000);
}
//指示灯快速闪烁,提示尝试连接网络
digitalWrite(LED_BUILTIN,HIGH);
delay(200);
digitalWrite(LED_BUILTIN,LOW);
delay(200);
digitalWrite(LED_BUILTIN,HIGH);
delay(200);
}
Serial.println("AutoConfig Faild!" );
return false;
//WiFi.printDiag(Serial);
}
/* 微信智能配网 */
void smartConfig()
{
WiFi.mode(WIFI_STA);//设置STA模式
Serial.println("\r\nWait for Smartconfig...");//打印log信息
WiFi.beginSmartConfig();//开始SmartConfig,等待手机端发出用户名和密码
while(1)
{
Serial.println(".");
//指示灯闪烁,提示需要配网
digitalWrite(LED_BUILTIN,HIGH);
delay(1000);
digitalWrite(LED_BUILTIN,LOW);
delay(1000);
if(WiFi.smartConfigDone())//配网成功,接收到SSID和密码
{
Serial.println("SmartConfig Success");
Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
WiFi.setAutoConnect(true); // 设置自动连接,这个语句是最重要的语句。
//指示灯快速闪烁5次,提示联网成功
for (int i = 0; i < 5; i++)
{
digitalWrite(LED_BUILTIN,LOW);
delay(400);
digitalWrite(LED_BUILTIN,HIGH);
}
break;
}
delay(1000); // 这个地方一定要加延时,否则极易崩溃重启
}
}
// 按下按键即会执行该函数
void button1_callback(const String & state) //点灯app内控制按键触发
{
BLINKER_LOG("get button state:", state);
if(state == "on")
{
Button1.print("on");
Button1.color("#808080");
Button1.text("已关闭");
// Button1.icon("icon_1");
digitalWrite(LED_BUILTIN, 0);
digitalWrite(Y,0);
delay(20); //回调函数中不能用delay,应为blinker.delay
oState = true; //开关状态保存,主要用于同步给天猫精灵
Blinker.vibrate();
}
else if(state == "off")
{
Button1.print("off");
Button1.color("#00A90C");
Button1.text("已打开");
// Button1.icon("icon_2");
digitalWrite(LED_BUILTIN, 1);
digitalWrite(Y,1);
delay(20); //回调函数中不能用delay,应为blinker.delay
oState = false; //开关状态保存,主要用于接入天猫精灵
Blinker.vibrate();
}
}
//温湿度获取
DHT dht(DHTPIN, DHTTYPE); //生成DHT对象,参数是引脚和DHT的类型
int humi_read = 0, temp_read = 0; //定义整型全局变量 储存传感器读取的温湿度数据
// 心跳包函数
void heartbeat()
{
//将设备端采集的温湿度数据,通过心跳包同步数据的方式,显示到APP上
HUMI.print(humi_read); //给blinkerapp回传湿度数据
TEMP.print(temp_read); //给blinkerapp回传温度数据
}
void dataStorage()
{
Blinker.dataStorage("temp", temp_read);
Blinker.dataStorage("humi", humi_read);
}
void aligeniePowerState(const String & state)
{
BLINKER_LOG("need set power state: ", state);
if (state == BLINKER_CMD_ON)
{
digitalWrite(LED_BUILTIN, 0);
digitalWrite(Y, 0);
BlinkerAliGenie.powerState("on");
BlinkerAliGenie.print();
oState = true;
}
else if (state == BLINKER_CMD_OFF) {
digitalWrite(LED_BUILTIN, 1);
digitalWrite(Y, 1);
BlinkerAliGenie.powerState("off");
BlinkerAliGenie.print();
oState = false;
}
}
void aligenieQuery(int32_t queryCode) //天猫精灵语音命令反馈
{
BLINKER_LOG("AliGenie Query codes: ", queryCode);
switch (queryCode)
{
case BLINKER_CMD_QUERY_ALL_NUMBER :
BLINKER_LOG("AliGenie Query All");
BlinkerAliGenie.powerState(oState ? "on" : "off");
BlinkerAliGenie.temp(temp_read);
BlinkerAliGenie.humi(humi_read);
BlinkerAliGenie.print();
break;
case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
BLINKER_LOG("AliGenie Query Power State");
BlinkerAliGenie.powerState(oState ? "on" : "off");
BlinkerAliGenie.print();
break;
case BLINKER_CMD_QUERY_TEMP_NUMBER:
BLINKER_LOG("AliGenie Query Temperature");
BlinkerAliGenie.temp(temp_read);
BlinkerAliGenie.print(); //将以上属性发送给天猫精灵,使得可以接收到温湿度的数据
break;
case BLINKER_CMD_QUERY_HUMI_NUMBER:
BLINKER_LOG("AliGenie Query Temperature");
BlinkerAliGenie.humi(humi_read);
BlinkerAliGenie.print(); //将以上属性发送给天猫精灵,使得可以接收到温湿度的数据
break;
default :
BlinkerAliGenie.powerState(oState ? "on" : "off");
BlinkerAliGenie.print();
BlinkerAliGenie.temp(20);
BlinkerAliGenie.humi(20);
break;
}
}
// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
counter++;
Number1.print(counter);
Blinker.vibrate();
uint32_t BlinkerTime = millis();
Blinker.print(BlinkerTime);
Blinker.print("millis", BlinkerTime);
}
void setup()
{
Serial.begin(115200);
#if defined(BLINKER_PRINT)
BLINKER_DEBUG.stream(BLINKER_PRINT);
#endif
// 初始化有LED及输出端口Y的IO
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, 1);
pinMode(Y, OUTPUT);
digitalWrite(Y, 1);
//网络连接
if (!autoConfig())
{
Serial.println("Start module");
smartConfig();
}
// 初始化blinker
Blinker.begin(auth,WiFi.SSID().c_str(),WiFi.psk().c_str()); //根据配网得到的WIFI信息和设备秘钥,连接到Blinker云
Blinker.attachHeartbeat(heartbeat);//将传感器获取的数据传给blinker app上
dht.begin();//初始化DHT传感器
Blinker.attachData(dataRead);
//在回调函数中反馈该控制状态
BlinkerAliGenie.attachPowerState(aligeniePowerState);
BlinkerAliGenie.attachQuery(aligenieQuery); //每次呼出天猫精灵,就会调用aligenieQuery()函数
Button1.attach(button1_callback);
}
void loop()
{
Blinker.run();
int h = dht.readHumidity(); //读取DHT11传感器的湿度 并赋值给h
int t = dht.readTemperature(); //读取DHT11传感器的温度 并赋值给t
if (isnan(h) || isnan(t)) //判断是否成功读取到温湿度数据
{
BLINKER_LOG("Failed to read from DHT sensor!");//读取温湿度失败!
}
else
{
//打印
BLINKER_LOG("Humidity: : ", h, " %");
BLINKER_LOG("Temperature: ", t, " °C");
humi_read = h;//将读取到的湿度赋值给全局变量humi_read
temp_read = t;//将读取到的温度赋值给全局变量temp_read
}
Blinker.delay(1000);
}
欢迎有问题的小伙伴私信哦!!!
2.功能演示
B站:
15块钱实现智能家居语音控制(白送完整代码)