分享我的第一个点灯程序——家庭控制中心
2020年,在B站上初识ESP8266,被ESP8266的低门槛、高性价比深深吸引,2020年6月20日,买下我的第一块ESP8266开发板,开始入坑。打小就喜欢鼓捣电子设备,现在的工作也涉猎智能家居相关的产品,所以一直想把自己的家里弄得科技感强一点,于是开始一边学习,一边开始用ESP8266来实现一些智能控制的小功能,由于是我的第一个Arduino程序,所以代码比较乱,各位请见谅,不过,不得不说,Arduino的确很好上手,blinker也帮我解决了手机程序的问题。目前主要实现了如下几项功能:
1、通过红外发射管,可控制客厅的灯光、电视机等家电;
2、通过温湿度传感器,可获取室内的温湿度数据;
3、通过光敏电阻,可获取室内的亮度信息;
4、通过WIFI接入物业的门控、梯控系统,可以解锁楼下单元门、呼叫电梯到指定的楼层;
5、配置了一块0.96吋的OLED小屏幕可显示天气信息;
6、通过点灯科技接入小度音箱,可通过小度音箱控制灯光、家电、单元门、电梯等。
模块让我塞到墙壁盒里了,先看一下手机端的截图和配套的OLED图吧。
#define BLINKER_P RINT Serial
#define BLINKER_WIFI
#define BLINKER_DUEROS_LIGHT
#define BLINKER_WITHOUT_SSL
#include <WiFiUdp.h>
#include <Blinker.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include "DHTesp.h"
#include "OneButton.h"
#include <ESP8266HTTPClient.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
//定义128X64四针OLED模块连接管脚
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0 , /* clock=*/ 5, /* data=*/ 4, /* reset=*/ U8X8_PIN_NONE);
int flag = 0;
boolean _up = false;
int incomingByte =0;//读取串口
//定义GPIO
#define IRPIN 14//红外发射管 GPIO14
#define K1PIN 13 //按键1 GPIO13
#define K2PIN 12 //按键2 GPIO12
#define K3PIN 16 //按键3 GPIO16
#define K4PIN 0//按键4 GPIO0
#define DHTPIN 2 //温湿度传感器 GPIO2
#define DHTTYPE DHT11
OneButton button1(K1PIN, true);
OneButton button2(K2PIN, true);
//OneButton button3(K3PIN, true);
OneButton button4(K4PIN, true);
//定义WIFI密码、设备密码
char auth[] = "***";
char ssid[] = "***";
char pswd[] = "***";
//定义全局变量
int lightbright = 100; //灯光初始亮度
String lightstate = "off"; //灯光初始状态
int count = 0; //循环计数器
float humi_read = 0, temp_read = 0;//温湿度
float bright ; //光敏电阻
//初始化各模块
WiFiUDP udp; //初始化UDP
IRsend irsend(IRPIN); //初始化IR发射管
DHTesp dht; //初始化温湿度传感器
//初始化APP组件
BlinkerButton BtnLightPwr("btn-light-pwr");
BlinkerButton BtnLightMode("btn-light-mode");
BlinkerNumber NumTemp("num-temp");
BlinkerNumber NumHumi("num-humi");
BlinkerNumber NumBright("num-bright");
BlinkerSlider Slider1("ran-bright");
BlinkerButton BtnTvPwr("btn-tv-pwr");
BlinkerButton BtnTvMode("btn-tv-mode");
BlinkerButton BtnTvVolp("btn-tv-volp");
BlinkerButton BtnTvVolm("btn-tv-volm");
BlinkerButton BtnDoor0502("btn-door-0502");
BlinkerButton BtnLift1004("btn-lift-1004");
BlinkerButton BtnDoor0401("btn-door-0401");
BlinkerButton BtnLift0302("btn-lift-0302");
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
Blinker.vibrate();
uint32_t BlinkerTime = millis();
Blinker.print("millis", BlinkerTime);
if (data.length() == 9) {
doorOpen(data);
}
}
//心跳包
void heartbeat()
{
BtnLightPwr.print(lightstate);
Slider1.print(lightbright);
NumTemp.print(temp_read);
NumHumi.print(humi_read);
NumBright.print(bright);
}
//图表数据
void dataStorage()
{
Blinker.dataStorage("temp", temp_read);
Blinker.dataStorage("humi", humi_read);
Blinker.dataStorage("bright", bright);
}
// app 端按下按键即会执行该函数 回调函数
void BtnLightPwr_callback(const String & state) {
BLINKER_LOG("灯光开关按钮被按下: ", state);
if (state == "on") {
irsend.sendNEC(0x1FE7887);
} else if (state == "off") {
irsend.sendNEC(0x1FE48B7);
}
lightstate = state;
BlinkerDuerOS.powerState(lightstate);
BlinkerDuerOS.report();
BtnLightPwr.print(lightstate);
}
void BtnLightMode_callback(const String & state) {
BLINKER_LOG("灯光模式切换按钮被按下");
irsend.sendNEC(0x1FE609F);
lightbright = 100;
}
void BtnTvPwr_callback(const String & state) {
BLINKER_LOG("电视开关按钮被按下");
irsend.sendSony(0xa90, 12);
}
void BtnTvMode_callback(const String & state) {
BLINKER_LOG("电视信源切换按钮被按下");
irsend.sendSony(0xA50, 12);
}
void BtnTvVolp_callback(const String & state) {
BLINKER_LOG("电视音量加按钮被按下");
irsend.sendSony(0x490, 12);
}
void BtnTvVolm_callback(const String & state) {
BLINKER_LOG("电视音量减按钮被按下");
irsend.sendSony(0xc90, 12);
}
void Slider1_callback(int32_t value)
{
BLINKER_LOG("灯光亮度调整为: ", value);
int temp = 0;
temp = value - lightbright;
if ( temp > 0 ) {
for (intcounter = 1; counter <= temp * 0.63; counter++) {
irsend.sendNEC(0x1FEF807);
Blinker.delay(50);
}
if (lightbright > 100) lightbright = 100;
}
else {
for (int counter = 1; counter <= -temp * 0.63; counter++) {
irsend.sendNEC(0x1FE50AF);
Blinker.delay(50);
}
if ( lightbright < 1) lightbright = 1;
}
lightbright = value;
BlinkerDuerOS.brightness(lightbright);
BlinkerDuerOS.report();
}
void BtnDoor0502_callback(const String & state) {
doorOpen("050210990");
Blinker.vibrate();
}
void BtnLift1004_callback(const String & state) {
doorOpen("050210991");
Blinker.vibrate();
}
void BtnDoor0401_callback(const String & state) {
doorOpen("040103020");
Blinker.vibrate();
}
void BtnLift0302_callback(const String & state) {
doorOpen("040103021");
Blinker.vibrate();
}
//小度电源类回调
void duerPowerState(const String & state)
{
BLINKER_LOG("小度设置灯光开关: ", state);
if (state == BLINKER_CMD_ON) {
lightstate = "on";
irsend.sendNEC(0x1FE7887);
}
else if (state == BLINKER_CMD_OFF) {
lightstate = "off";
irsend.sendNEC(0x1FE48B7);
}
BtnLightPwr.print(lightstate);
BlinkerDuerOS.powerState(lightstate);
BlinkerDuerOS.print();
}
//用户自定义亮度控制的回调函数:
void duerBright(const String & duBright)
{
BLINKER_LOG("(不生效)小度设置灯光亮度: ", duBright);
BlinkerDuerOS.brightness(100);
BlinkerDuerOS.print();
if (duBright == "99") {//开门
doorOpen("050210990");
}
else if (duBright == "98") {//叫梯
doorOpen("050210991");
}
}
//用户步长设置亮度的回调函数
void duerRelativeBright(int32_t duBright)
{
BLINKER_LOG("小度调整灯光亮度: ", duBright);
lightbright += duBright;
BlinkerDuerOS.brightness(lightbright);
BlinkerDuerOS.print();
if ( duBright > 0 ) {
for (intcounter = 1; counter <= duBright * 0.63; counter++) {
irsend.sendNEC(0x1FEF807);
Blinker.delay(50);
}
if (lightbright > 100) lightbright = 100;
}
else {
for (int counter = 1; counter <= -duBright * 0.63; counter++) {
irsend.sendNEC(0x1FE50AF);
Blinker.delay(50);
}
if ( lightbright < 1) lightbright = 1;
}
Slider1.print(lightbright);
}
//小度模式的设置接口
void duerMode(const String & mode)
{
BLINKER_LOG("小度设置灯光模式: ", mode);
BlinkerDuerOS.mode(mode);
BlinkerDuerOS.print();
if (mode == "None") {
// 切换冷暖光
irsend.sendNEC(0x1FE609F);
}
else if (mode == "SLEEP" or mode == "NIGHT") {
irsend.sendNEC(0x1FEA05F);
BtnLightPwr.print("on");
lightstate = "on";
}
else if (mode == "ENERGY_SAVING") {
// 辅助灯
irsend.sendNEC(0x1FE48B7);
Blinker.delay(50);
irsend.sendNEC(0x1FE20DF);
BtnLightPwr.print("on");
lightstate = "on";
}
else if (mode == "TV" or mode == "VIDEO") {
// 电视遥控器
}
//wsMode = mode;
}
void click1() {
Serial.println("Button 1 click.");
if (lightstate == "on") {
irsend.sendNEC(0x1FE48B7);
lightstate = "off";
u8g2.setPowerSave(0);
u8g2.setCursor(24, 40);
u8g2.print("关闭客厅灯");
u8g2.sendBuffer();
Blinker.delay(2000);
u8g2.clearBuffer();
u8g2.setPowerSave(1);
} else if (lightstate == "off") {
irsend.sendNEC(0x1FE7887);
lightstate = "on";
u8g2.setPowerSave(0);
u8g2.setCursor(24, 36);
u8g2.print("打开客厅灯");
u8g2.sendBuffer();
Blinker.delay(2000);
u8g2.clearBuffer();
u8g2.setPowerSave(1);
}
BlinkerDuerOS.powerState(lightstate);
BlinkerDuerOS.report();
BtnLightPwr.print(lightstate);
}
void click2() {
Serial.println("Button 2 click.");
time_t run_time = Blinker.runTime();
int run_d = run_time / 86400;
int run_h = (run_time - run_d * 86400) / 3600;
int run_m = (run_time - run_d * 86400 - run_h * 3600) / 60;
int run_s = run_time - run_d * 86400 - run_h * 3600 - run_m * 60;
String run_str = String(run_d) + "-" + String(run_h) + ":" + String(run_m) + ":" + String(run_s);
u8g2.setPowerSave(0);
u8g2.setCursor(0, 15);
u8g2.print("运行时间:" + run_str);
u8g2.setCursor(0, 31);
u8g2.print("室内温度:" + String(temp_read) + " ℃");
u8g2.setCursor(0, 47);
u8g2.print("室内湿度:" + String(humi_read) + " %");
u8g2.setCursor(0, 63);
u8g2.print("室内亮度:" + String(bright));
u8g2.sendBuffer();
Serial.println("显示室内温度");
WiFiClient client;
HTTPClient http;
Serial.print(" begin...\n");
if (http.begin(client, "http://api.help.bj.cn/apis/weather/?id=101060101")) {// HTTP
Serial.print(" GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
Serial.printf(" GET... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http.getString();
Serial.println(payload);
DynamicJsonDocument doc(1000);
DeserializationError error = deserializeJson(doc, payload);
JsonObject obj = doc.as<JsonObject>();
String w_weather = doc["weather"].as<char*>();//晴
String w_temp = doc["temp"].as<char*>(); //10
String w_humidity = doc["humidity"].as<char*>();//24%
String w_wd = doc["wd"].as<char*>(); //西南风
String w_wdforce = doc["wdforce"].as<char*>();//4级
String w_aqi = doc["aqi"].as<char*>(); //156
String w_pm25 = doc["pm25"].as<char*>(); //156
Blinker.delay(6000);
u8g2.clearBuffer();
u8g2.setCursor(0, 15);
u8g2.print("室外天气:" + w_weather);
u8g2.setCursor(0, 31);
u8g2.print("空气质量:" + w_aqi);
u8g2.setCursor(0, 47);
u8g2.print("温度:" + String(w_temp) + "℃ 湿度:" + String(w_humidity));
u8g2.setCursor(0, 63);
u8g2.print("风力:" + w_wd + w_wdforce);
u8g2.sendBuffer();
Serial.println("显示室外天气");
Blinker.delay(6000);
u8g2.clearBuffer();
u8g2.setPowerSave(1);
Serial.println("关闭屏幕");
}
} else {
Serial.printf(" GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
} else {
Serial.printf("[HTTP} Unable to connect\n");
}
}
void click3() {
Serial.println("Button 3 click.");
doorOpen("050210990");
u8g2.setPowerSave(0);
u8g2.setCursor(24, 36);
u8g2.print("打开单元门");
u8g2.sendBuffer();
Blinker.delay(2000);
u8g2.clearBuffer();
u8g2.setPowerSave(1);
}
void click4() {
Serial.println("Button 4 click.");
doorOpen("050210991");
u8g2.setPowerSave(0);
u8g2.setCursor(32, 36);
u8g2.print("呼叫电梯");
u8g2.sendBuffer();
Blinker.delay(2000);
u8g2.clearBuffer();
u8g2.setPowerSave(1);
}
//新方法,发送给进行转发
void doorOpen(const String & doorNum)
{
IPAddress NewWIFIIP(192, 168, 99, 1);
String lift[] = {"0101", "0102", "0103", "0201", "0202", "0401", "0402", "0501", "0502", "0503", "0601", "0602", "0701", "0702", "0801", "0802", "0901", "0902", "1001", "1002", "1101", "1102", "1103", "1201", "1202", "1301", "1302"};
String unitNum = doorNum.substring(0, 4);
int ip = 0;
for (ip = 0; ip <= 24; ip++) {
if (unitNum == lift)break;
}
String ipstr = String(ip+1);
if (ipstr.length() == 1)
{
ipstr = "0" + ipstr;
}
Serial.println(ipstr);
char door ;
strcpy(door, (ipstr + doorNum).c_str());
udp.beginPacket(NewWIFIIP, 20625);
udp.write(door, 11);
udp.endPacket();
}
void setup() {
// 初始化串口,并开启调试信息
Serial.begin(9600);
BLINKER_DEBUG.stream(Serial); //串口打印调试信息
// BLINKER_DEBUG.debugAll();
// 初始化有LED的IO
pinMode(LED_BUILTIN, OUTPUT);//LED_BUILTIN 宏就是开发板指示灯的io口
digitalWrite(LED_BUILTIN, HIGH);
// 初始化blinker
Blinker.begin(auth, ssid, pswd);
//Blinker.begin(auth);
Blinker.attachData(dataRead);
Blinker.attachHeartbeat(heartbeat);
Blinker.attachDataStorage(dataStorage);
BtnLightPwr.attach(BtnLightPwr_callback); //绑定按键执行回调函数
BtnLightMode.attach(BtnLightMode_callback);
BtnTvPwr.attach(BtnTvPwr_callback);
BtnTvMode.attach(BtnTvMode_callback);
BtnTvVolp.attach(BtnTvVolp_callback);
BtnTvVolm.attach(BtnTvVolm_callback);
BtnDoor0502.attach(BtnDoor0502_callback);
BtnLift1004.attach(BtnLift1004_callback);
BtnDoor0401.attach(BtnDoor0401_callback);
BtnLift0302.attach(BtnLift0302_callback);
Slider1.attach(Slider1_callback);
Slider1.print(lightbright);
BlinkerDuerOS.attachPowerState(duerPowerState); //小度语音操作注册函数
BlinkerDuerOS.attachRelativeBrightness(duerRelativeBright);
BlinkerDuerOS.attachBrightness(duerBright);
BlinkerDuerOS.attachMode(duerMode);
//红外模块初始化
irsend.begin();
//温湿度传感器初始化
dht.setup(DHTPIN, DHTesp::DHTTYPE);
button1.attachClick(click1);
button2.attachClick(click2);
//button3.attachClick(click3);
button4.attachClick(click4);
//初始化OLED
u8g2.enableUTF8Print();//必须否则中文不显示。
u8g2.begin();
u8g2.setFont(u8g2_font_wqy14_t_gb2312);
pinMode(K3PIN, INPUT);
//设备启动后需要的一些操作
Blinker.wechat("家庭网关上线", "家庭网关上线", "家庭网关上线"); //发送微信
irsend.sendNEC(0x1FE7887); //关灯
}
void loop() {
Blinker.run();/*每次运行都会将设备收到的数据进行一次解析。
在使用WiFi接入时,该语句也负责保持网络连接*/
if (Serial.available() > 0)
{
incomingByte = Serial.read();
BLINKER_LOG("读到:", incomingByte);
switch (incomingByte) {
case 1:
BLINKER_LOG("开灯");
BtnLightPwr_callback("on");
break;
case 2:
BLINKER_LOG("关灯");
BtnLightPwr_callback("off");
break;
case 3:
BLINKER_LOG("灯光切换模式");
irsend.sendNEC(0x1FE609F);
lightbright = 100;
break;
case 4:
BLINKER_LOG("灯亮一点");
duerRelativeBright(20);
break;
case 5:
BLINKER_LOG("灯暗一点");
duerRelativeBright(-20);
break;
case 6:
BLINKER_LOG("灯睡眠模式");
duerMode("SLEEP");
break;
case 7:
BLINKER_LOG("灯节能模式");
duerMode("ENERGY_SAVING");
break;
case 8:
BLINKER_LOG("灯冷暖光切换");
irsend.sendNEC(0x1FE609F);
break;
case 9:
BLINKER_LOG("打开/关闭电视");
irsend.sendSony(0xa90, 12);
break;
case 10:
BLINKER_LOG("电视信源切换");
irsend.sendSony(0xA50, 12);
break;
case 11:
BLINKER_LOG("电视大点声");
irsend.sendSony(0x490, 12);
break;
case 12:
BLINKER_LOG("电视小点声");
irsend.sendSony(0xc90, 12);
break;
case 13:
BLINKER_LOG("开门");
doorOpen("050210990");
break;
case 14:
BLINKER_LOG("呼叫电梯");
doorOpen("050210991");
break;
case 15:
BLINKER_LOG("激活电梯");
doorOpen("050210992");
break;
default:
Serial.println("default");
}
}
count = count + 1;
button1.tick();
button2.tick();
//button3.tick();
button4.tick();
if (digitalRead(K3PIN) == LOW)
flag = 1;
if ((digitalRead(K3PIN) == HIGH) && (flag == 1))
{
_up = true;flag = 0;
}
if (_up)
{
_up = false;
click3();
}
if (count % 1000 == 0) {
float h = dht.getHumidity();
float t = dht.getTemperature();
if (dht.getStatusString() != "OK")
{
BLINKER_LOG("Failed to read from DHT sensor!");
}
else
{
BLINKER_LOG("湿度:", h, " %");
BLINKER_LOG("温度:", t, " ℃");
humi_read = h;
temp_read = t;
}
bright = analogRead(0);
BLINKER_LOG("亮度:", bright);
}
else if(count > 180000) {
count = 0;
}
Blinker.delay(10);
}
最近还做了一些好玩的,等有时间了,和大家分享一下。
点阵时钟
测试仪表
RF监听设备
大佬66666
页:
[1]