本作品通过arduino和涂鸦联网模组配合,实现了将灯带接入智能家居
在涂鸦开发面板采购
可以用其它arduino型号代替,不过需要修改一下pcb,同时串口可能不够用
淘宝搜索ws2812b即可
自己设计制作,在GitHub开源
本项目已经开源在GitHub,链接已编辑在B站视频简介处
本项目已经开源了PCB设计文件,可直接使用。
涂鸦的模组使用十分方便。只需接通电源,使用串口操作即可。
涂鸦的模块可使用两种模式配网,分别是MCU处理和模块自行处理。此处为了减轻Arduino程序开发工作量,选择了模块自行处理。
选择模块自行处理时需要注意在模块上连接一个LED和一个按键。按键拉低5秒以上可恢复出厂设置并重新配网,因此硬件需要设计上拉电阻。
模块除了一组串口用于操作,还预留了一个串口输出内部日志。该引脚可以不接,但本项目将其连接到了Arduino的一个串口,Arduino随后会将日志转发给上位机。
WS2812B灯带每颗灯珠满载功率0.2W,设计时还需要额外考虑线宽满足电流要求。
本项目使用Arduino MEGA 2560。开源的设计可直接插在Arduino MEGA 2560上。
涂鸦官方提供了用于Arduino的库文件。但该库开发还不够完整,为了实现需要的功能,需要做一些修改。
修改过的库已经开源
该文件是官方提供的配置文件。配置使用宏定义的方式进行。需要配置的选项需要都在这里进行。
在这里,我们做以下修改:
/* Distribution mode selection, only three choices, Anti-touch mode is recommende */
#define CONFIG_MODE CONFIG_MODE_DEFAULT //Default working mode
//#define CONFIG_MODE CONFIG_MODE_LOWPOWER //Safe mode (low power working mode)
//#define CONFIG_MODE CONFIG_MODE_SPECIAL // Anti-touch mode (special working mode)
#define WIFI_CONTROL_SELF_MODE //配置为模块自处理
#define WF_STATE_KEY 11//设置LED指示灯引脚
#define WF_RESERT_KEY 2//设置配网按键引脚
该文件是库函数主要部分源代码。因库函数未开发完全,直接设置为模块自处理会导致报错,因此需要做一些修改
unsigned char TuyaWifi::mcu_get_wifi_work_state(void)
{
#ifndef WIFI_CONTROL_SELF_MODE
return wifi_work_state;
#else
return WIFI_SATE_UNKNOW;
#endif
}
void TuyaWifi::mcu_reset_wifi(void)
{
#ifndef WIFI_CONTROL_SELF_MODE
reset_wifi_flag = RESET_WIFI_ERROR;
tuya_uart.wifi_uart_write_frame(WIFI_RESET_CMD, MCU_TX_VER, 0);
#endif
}
程序已经开源
程序代码如下:
#include <FastLED.h>
#include <TuyaWifi.h>
//hardware define
#define OUT_PIN 34
#define LED_NUMS 50
#define MIC_PIN A10
//dpid define
#define DPID_SWITCH 20
#define DPID_MODE 21
#define DPID_LIGHT 22
#define DPID_COLOR 24
//serial define
#define TUYA_SERIAL Serial1
#define LOG_SERIAL Serial2
//datapoint value define
#define STATE_ON 0x01
#define STATE_OFF 0x00
#define MODE_WHITE 0x00
#define MODE_COLOUR 0x01
#define MODE_MIC 0x02
unsigned char pid[] = {"g2kypenftkitli6z"};
unsigned char mcu_ver[] = {"1.0.0"};
unsigned int led_light = 8;
#define COLOR_NUMS 7
CRGB colors[] = {
CRGB::Red,
CRGB::Orange,
CRGB::Yellow,
CRGB::Green,
CRGB::LightGreen,
CRGB::Blue,
CRGB::Purple
};
//dp define
unsigned char dp_array[][2] =
{
{DPID_SWITCH, DP_TYPE_BOOL},
{DPID_MODE, DP_TYPE_ENUM},
{DPID_LIGHT, DP_TYPE_VALUE},
{DPID_COLOR, DP_TYPE_STRING},
};
TuyaWifi my_device(&TUYA_SERIAL);
CRGB leds[LED_NUMS];
unsigned char state = STATE_OFF;
unsigned char mode = MODE_WHITE;
unsigned char led_state = LOW;
unsigned long last_time = 0;
unsigned char led_color = 0;
void setLED(CRGB data) {
for(int i = 0; i < LED_NUMS; i++){
leds[i] = data;
}
}
void setup() {
Serial.begin(115200);
TUYA_SERIAL.begin(115200);
LOG_SERIAL.begin(115200);
my_device.init(pid, mcu_ver);
my_device.set_dp_cmd_total(dp_array, sizeof(dp_array) / 2);
my_device.dp_process_func_register(dp_process);
my_device.dp_update_all_func_register(dp_update_all);
FastLED.addLeds<WS2812, OUT_PIN, GRB>(leds, LED_NUMS);
FastLED.setBrightness(led_light);
last_time = millis();
unsigned char value[1] = {STATE_ON};
dp_process(DPID_SWITCH, value, 1);
}
void loop() {
my_device.uart_service();
while(LOG_SERIAL.available()){
Serial.write(LOG_SERIAL.read());
}
if(state){
switch(mode){
case MODE_COLOUR:
if(millis() - last_time > 50){
last_time = millis();
for(int i = LED_NUMS - 1; i > 0; i--){
leds[i] = leds[i - 1];
}
leds[0] = colors[led_color];
led_color = (led_color + 1) % COLOR_NUMS;
FastLED.show();
}
break;
case MODE_MIC:
unsigned int lightNum = (exp(analogRead(MIC_PIN) / 675.84) - 1) * 1.5 * LED_NUMS / 1.7;
for(int i = 0; i < lightNum && i < LED_NUMS; i++){
leds[i] = CRGB(min(255 * i / (0.8 * LED_NUMS), 255), max(255 * (1 - i / (0.8 * LED_NUMS)), 0), 0);
}
for(int i = lightNum; i < LED_NUMS; i++){
leds[i] = CRGB(0, 0, 0);
}
FastLED.show();
break;
}
}
}
/**
* @description: DP download callback function.
* @param {unsigned char} dpid
* @param {const unsigned char} value
* @param {unsigned short} length
* @return {unsigned char}
*/
unsigned char dp_process(unsigned char dpid,const unsigned char value[], unsigned short length) {
switch(dpid){
case DPID_SWITCH:
state = value[0];
my_device.mcu_dp_update(DPID_SWITCH, state, 1);
if(state == STATE_OFF){
setLED(CRGB(0, 0, 0));
FastLED.show();
}
else{
if(mode == MODE_WHITE){
setLED(CRGB(255, 255, 255));
FastLED.show();
}
}
break;
case DPID_MODE:
mode = value[0];
my_device.mcu_dp_update(DPID_MODE, mode, 1);
if(state){
if(mode == MODE_WHITE){
setLED(CRGB(255, 255, 255));
FastLED.show();
}
}
break;
case DPID_LIGHT:
led_light = value[3];
my_device.mcu_dp_update(DPID_LIGHT, led_light, 4);
FastLED.setBrightness(led_light);
FastLED.show();
break;
}
}
/**
* @description: Upload all DP status of the current device.
* @param {*}
* @return {*}
*/
void dp_update_all(void) {
my_device.mcu_dp_update(DPID_SWITCH, state, 1);
my_device.mcu_dp_update(DPID_MODE, mode, 1);
my_device.mcu_dp_update(DPID_LIGHT, led_light, 4);
}
涂鸦的模块功能强大,使用方便。只要是能想到的,都可以很方便地实现。本项目看起来实现了很强大的功能,但其实只完成了硬件实际操作灯带的逻辑。真正的物联网部分完全交由涂鸦模块完成,极大地提升了开发效率。