分享我的第一个点灯程序——家庭控制中心-Arduino中文社区 - Powered by Discuz! Archiver

吉视传媒 发表于 2022-9-29 18:54

分享我的第一个点灯程序——家庭控制中心

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);
}




吉视传媒 发表于 2022-9-29 19:03

最近还做了一些好玩的,等有时间了,和大家分享一下。

点阵时钟





测试仪表


RF监听设备


weiqinglong51 发表于 2022-9-30 19:02

大佬66666
页: [1]
查看完整版本: 分享我的第一个点灯程序——家庭控制中心