搭建一个关灯神器

自从租房之后，生活环境发生了很大的变化。其实大部分的变化我尚且还算满意，但每当晚上躺在床上玩手机的时候，当困意袭来时，心里总是非常郁闷：我在这边，灯的开关在床的那边。没办法，只得再度下床关灯，再摸黑爬上床 —— 此时睡意早已消失（大哭

于是，我想到了关灯神器 —— 远程操控开关关灯。

方案设计

因为只是想做一个解放双手的小玩具，自然没有打算做的非常复杂。鉴于家里的开关设计（如下图），只需要一个可以通电左右摇摆的舵机即可，给予一定的电信号，就物理控制开关上下拨动

方案很简单，只需要一块单片机和一个舵机就可以，考虑到拨动开关所需的强度，如果开关很硬可以考虑提供额外的电源供电来保持舵机输出功率。好在家里的开关还算听话（勉强刚刚好，鬼知道我调整了多少次角度和高度），这次就不额外添加配件了。

参考 B 站的诸多 "关灯神器"视频, 这里单片机选用了 esp8266，类似下图

舵机则是使用了sg90：

总成本不到 20 元...

(Ps: 网上淘宝现成的开关神器换个马甲，多装个模块就能卖百来块... 可见其中的利润空间，咱们理工男可不能被这种骗了钱去～)

剩下就是控制方案

常见的必然是手机 app 控制，这里必须借助第三方提供，自己写 app 也不是不可以，主要是不想徒增学习成本（说白了还是懒😂），连接方法有蓝牙、WiFi，这里可以看自己的开发板需求。

具体实现

既然搞定了方案，接下来进行实践环节！

硬件实现

硬件方面很简单，注意看卖家给的引脚图不要插错即可。

注意观察，如果发现线序不对，可能需要自己拆下舵机的线材固定器更改线序。运气很好，我买的不需要，就直接插上连 PC 就行了

软件实现

这里需要用到软件和安装包如下

8266 开发板的配置包

开发板开发软件

blink 电灯科技第三方应用的适配库文件

COM 串口驱动

安装 arduino

首先安装 arduino，直接无脑 next 即可

安装完成后打开 arduino，界面如图：

导入 ESP8266 配置包

首先打开 Arduino IDE 菜单 > 文件 > 首选项，在 附加开发板管理器网址 输入框中，填入以下网址：https://www.arduino.cn/package_esp8266com_index.json

然后点击文件夹中的配置包：

导入配置。

安装三方库文件

添加库中添加blinker-library-0.3.80210803.zip

配置开发板

接下来新建文件 -> 保存一下 -> 如下图配置开发板信息

如果没有8266开发选项，如下图，搜索8266，安装上图对应module

接下来就是编写代码，这边已经提供好了一个模板

Copy
#define BLINKER_WIFI
#define BLINKER_MIOT_LIGHT

#include <Blinker.h>
#include <Servo.h>

Servo myservo;//定义舵机

char auth[] = "xxxxxxxx"; //点灯Key
char ssid[] = "SELF-WIFI"; //wifi名称
char pswd[] = "password"; //wifi密码

// 新建组件对象，注意这里的名称要和电灯科技app里保持一致
BlinkerButton Button1("test");

int counter = 0;

//注意如果接入小爱同学，其监听的就是这个电源事件
void miotPowerState(const String & state)//电源类操作
{
BLINKER_LOG("need set power state: ", state);

if (state == BLINKER_CMD_ON) {

myservo.write(150);//收到“on”的指令后舵机旋转150度
BlinkerMIOT.powerState("on");
BlinkerMIOT.print();//反馈状态
delay(1000);//延时1秒
myservo.write(90);//舵机归零，回到垂直状态

}
else if (state == BLINKER_CMD_OFF) {

myservo.write(30); //舵机偏转30°
BlinkerMIOT.powerState("off");
BlinkerMIOT.print();
delay(1000);
myservo.write(90);

}
}

// 按下按键即会执行该函数
void button1_callback(const String & state)
{
BLINKER_LOG("get button state: ", state);
if (state=="on")
{
myservo.write(170);//收到“on”的指令后舵机旋转150
delay(1000);//延时
myservo.write(90);//舵机归零垂直

} else if(state=="press"||state=="tap")
{
myservo.write(10);//长按开关按键后舵机旋转10
delay(1000);//延时
myservo.write(90);//舵机归零垂直(90度)
}

}

// 如果未绑定的组件被触发，则会执行其中内容
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
counter++;

}

void setup()
{
// 初始化串口
Serial.begin(115200);
BLINKER_DEBUG.stream(Serial);
// 初始化舵机
myservo.attach(2);//舵机的IO口，nodemcu的D4口
myservo.write(90);//上电时舵机归零垂直
BlinkerMIOT.attachPowerState(miotPowerState);

// 初始化blinker
Blinker.begin(auth, ssid, pswd);
Blinker.attachData(dataRead);

Button1.attach(button1_callback);
}

void loop() {
BLINKER_LOG("Blinked running...");
Blinker.run();
}

接下来，只需要点击左上角编译通过就完成了。

如果编译没有问题，接下来就需要将程序上传到开发板上。首先注意下图端口，经过之前安装 com 端口驱动，理论上这边端口可以正常显示

如果不能，查看设备管理器看是否端口正常显示。

安装 APP

还记得代码里的key吗？接下来就是下载电灯科技 APP 并申请key

一般应用市场都有，如果没有的话可以去官网下.

注册设备

下载并注册点灯科技账号之后，在右上角加号 -> 独立设备 -> 网络接入

一般推荐阿里云 接入，但是我目前的版本只能接入点灯科技服务，实测无论是控制还是接入小爱同学都没有影响，这里就看大家选择。

完成设备注册后如上图所示，这时你会获取一个key，填入代码中即可。

开发界面

这里大家就可以按照代码中发信指引自己制作开关界面。我这边在网上找到一份简单的界面配置文件

Copy
{¨config¨{¨headerColor¨¨transparent¨¨headerStyle¨¨dark¨¨background¨{¨img¨¨assets/img/headerbg.jpg¨¨isFull¨«}}¨dashboard¨|{¨type¨¨btn¨¨ico¨¨fad fa-lightbulb-on¨¨mode¨Ê¨t0¨¨开灯¨¨t1¨¨文本2¨¨bg¨Ì¨cols¨Í¨rows¨Í¨key¨¨test¨´x´Ë´y´Ì¨speech¨|÷¨cus¨¨on¨¨lstyle¨Ë¨clr¨¨#076EEF¨}{ßAßBßC¨fad fa-lightbulb¨ßEÉßF¨关灯¨ßHßIßJÌßKÍßLÍßMßN´x´Ë´y´ÑßO|÷ßRËßSßT}{ßA¨deb¨ßEÉßJÉßKÑßLÌßM¨debug¨´x´É´y´¤D}÷¨actions¨|¦¨cmd¨¦¨switch¨‡¨text¨‡ßQ¨打开?name¨¨off¨¨关闭?name¨—÷¨triggers¨|{¨source¨ßa¨source_zh¨¨开关状态¨¨state¨|ßQßd÷¨state_zh¨|¨打开¨¨关闭¨÷}÷}

将这份文件导入到配置信息即可。（上面的乱码是真的（汗））

导入后配置如下：

接下来就可以自己操控查看配置情况了。

接入小爱同学

接入小爱同学其实很简单，就看第三方服务方提不提供支持

米家 -> 接入其他设备 -> 点灯科技 -> 同步配置即可

设备安装

这一步在实际操作中反倒是最难的，因为每个人情况不同，按钮的强度也不一样，我一开始还是非常担心舵机的功率可能不足以拨动开关的。实际上确实在尝试了很多角度之后总是无法成功实现。

曾经尝试过给舵机扇叶进行延长增大接触面积，但是这些方案最终没有一个很好的实现。最后我尝试回归起点，通过垫高舵机，使得扇叶和开关产生一定的间隔，这样在扇叶旋转的时候，会有一个惯性辅助用力。接着使用纸板和 502 将舵机固定，并用透明胶在外层进行二次辅助固定，最终总算实现了开关的正常拨动（虽然有的时候还是不太灵敏）

最终实现图如下：

效果

这里给出一个链接