发帖
3 0 0

基于Ai-WB2的HomeAssistant实现RGB彩灯控制功能

云烟
中级会员

6

主题

4

回帖

408

积分

中级会员

积分
408
智能家居 571 3 2026-1-14 17:06:48
[i=s] 本帖最后由 云烟 于 2026-1-14 17:07 编辑 [/i]

基于Ai-WB2的HomeAssistant实现RGB彩灯控制功能

一、准备工作

1.1 硬件清单

硬件名称 数量 备注
Ai-WB2-12F 1 核心控制MCU
typec数据线 1 烧录程序调试

1.2 软件清单

软件/资源 获取地址
HomeAssistant Ai-WB2 智能家居应用仓库 Gitee
HomeAssistant_MQTT-C Gitee

前置要求

  • 熟悉PWM;
  • 对Linux、Git指令有一定的了解;
  • 对回调函数、JSON、MOTT协议有一定了解。

二、克隆完整的HaDevice仓库

  • 建议直接通过 Git 克隆源码仓库,也可点击链接跳转直接下载 ZIP包:
#Gitee
git clone --recursive https://gitee.com/seahi007/HaDevice.git

提示:该仓库包含子模块内容较大,需要耐心等待克隆完成

  • 克隆下来的完整文件如图:

01

三、RGB工程创建与配置

  1. 打开vscode连接WSL,打开刚下载好的仓库,在 HaDevice➡project下找到 USB_Ligth_ctn 文件,将其复制粘贴一份,并更名为 RGB ,删除一些我们不需要的文件,保留以下文件,如图:

01

  1. components文件夹下创建 rgb文件夹,在此文件中创建我们的 rgb.crgb.h驱动文件,并在 bouffalo.mk文件中添加末尾添加 rgb用于编译时连接,如图所示:

01

  1. rgb文件中添加我们的RGB底层驱动代码,代码如下:
  • RGB.h
//RGB.h
#ifndef __RGB_H__
#define __RGB_H__

#include <bl602.h>
#include <bl602_gpio.h>
#include <bl_pwm.h>

//配置PWM参数
BL_Err_Type PWM_Smart_Configure2(PWM_CH_ID_Type ch, uint16_t clkDiv, uint16_t period,uint16_t threshold2);
//初始化PWM
void RGB_init(void);
//设置3个RGB LED
void RGB_set(uint8_t red,uint8_t green,uint8_t blue);
#endif
  • RGB.c
//RGB.c
#include <FreeRTOS.h>
#include <task.h>
#include <blog.h>   
#include <bl602.h>   
#include <bl602_gpio.h> 
#include <bl602_glb.h>  
#include <bl_pwm.h>   
#include "rgb.h"  

/* ------------------------------------------------------------------------- 
 宏定义
------------------------------------------------------------------------- */
/* 根据通道号计算对应寄存器块起始地址
 * BL602 每通道占用 0x20 字节,基地址 + 偏移 + ch*0x20 */
#define PWM_Get_Channel_Reg(ch)  (PWM_BASE + PWM_CHANNEL_OFFSET + (ch) * 0x20)

/* 等待 PWM 停止完成时的超时次数;主频 160 MHz 下约 1 ms */
#define PWM_STOP_TIMEOUT_COUNT   (160 * 1000)

/* ------------------------------------------------------------------------- 
     GPIO 配置表
 *  数组索引 0/1/2 分别对应 R/G/B,顺序与 RGB_set() 保持一致
 *  drive=0   : 驱动能力最低(减小 EMI)
 *  smtCtrl=1 : 使能施密特(抗干扰)
 *  pullType  : 下拉,防止未初始化时 LED 微亮
 *  gpioFun=8 : 功能 8 即为 PWM
 ------------------------------------------------------------------------- */
GLB_GPIO_Cfg_Type cfg[3] = {
    { .drive = 0, .smtCtrl = 1, .gpioMode = GPIO_MODE_OUTPUT,
      .pullType = GPIO_PULL_DOWN, .gpioPin = 14, .gpioFun = 8 }, /* Red   */
    { .drive = 0, .smtCtrl = 1, .gpioMode = GPIO_MODE_OUTPUT,
      .pullType = GPIO_PULL_DOWN, .gpioPin = 17, .gpioFun = 8 }, /* Green */
    { .drive = 0, .smtCtrl = 1, .gpioMode = GPIO_MODE_OUTPUT,
      .pullType = GPIO_PULL_DOWN, .gpioPin = 3,  .gpioFun = 8 }, /* Blue  */
};

/* =========================================================================
  本地函数
========================================================================= */

/**
 * @brief  自定义 PWM 配置函数(基于官方 PWM_Smart_Configure 修改)
 * @note   与官方版本差异:
 *         1) 时钟源固定为 BUS Clock(PLL 输出),而非外部 32 k/40 M 晶振;
 *         2) 占空比只使用 threshold2(THRE2),THRE1 固定写 0;
 *         3) 输出极性为正相(PWM_POL_NORMAL),优雅停模式。
 *
 * @param  ch        : PWM 通道号(0~5)
 * @param  clkDiv    : 时钟分频,实际 PWM 频率 = BUS_CLK / (clkDiv+1) / (period+1)
 * @param  period    : PWM 周期(计数器最大值),推荐 255 方便 8 bit 占空比
 * @param  threshold2: 高电平结束点(占空比 = (threshold2+1) / (period+1) )
 * @return           : SUCCESS 或 TIMEOUT(停止等待超时)
 */
BL_Err_Type PWM_Smart_Configure2(PWM_CH_ID_Type ch,
                                 uint16_t clkDiv,
                                 uint16_t period,
                                 uint16_t threshold2)
{
    uint32_t tmpVal;
    uint32_t timeoutCnt = PWM_STOP_TIMEOUT_COUNT;

    /* 1. 拿到通道寄存器基地址 */
    uint32_t PWMx = PWM_Get_Channel_Reg(ch);

    /* 2. 如果当前时钟源不是 BUS Clock,则先切换 */
    tmpVal = BL_RD_REG(PWMx, PWM_CONFIG);
    if (BL_GET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL) != PWM_CLK_BCLK) {
        /* 2.1 置位 STOP_EN,请求停止 */
        BL_WR_REG(PWMx, PWM_CONFIG, BL_SET_REG_BIT(tmpVal, PWM_STOP_EN));

        /* 2.2 等待硬件完成停止(STS_TOP 置位) */
        while (!BL_IS_REG_BIT_SET(BL_RD_REG(PWMx, PWM_CONFIG), PWM_STS_TOP)) {
            if (--timeoutCnt == 0) {
                return TIMEOUT;          /* 超时退出,防止死等 */
            }
        }

        /* 2.3 切换时钟源为 BUS Clock */
        tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL, PWM_CLK_BCLK);
    }

    /* 3. 配置输出极性与停止模式 */
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_OUT_INV,   PWM_POL_NORMAL);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_STOP_MODE, PWM_STOP_GRACEFUL);
    BL_WR_REG(PWMx, PWM_CONFIG, tmpVal);

    /* 4. 写分频、周期、占空比 */
    BL_WR_REG(PWMx, PWM_CLKDIV, clkDiv);   /* 分频 */
    BL_WR_REG(PWMx, PWM_PERIOD, period);   /* 周期 */
    BL_WR_REG(PWMx, PWM_THRE1,  0);        /* 通道 1 比较点(未用)*/
    BL_WR_REG(PWMx, PWM_THRE2,  threshold2); /* 通道 2 比较点(决定占空比)*/

    return SUCCESS;
}

/* =========================================================================
  用户 API
 ========================================================================= */

/**
 * @brief  初始化 RGB 三路 GPIO 与 PWM 通道
 * @note   1. 只初始化 GPIO,不立即开灯;
 *         2. 先禁用 PWM 通道,防止旧配置产生毛刺。
 */
void RGB_init(void)
{
    for (int i = 0; i < 3; i++) {
        /* 初始化 GPIO 复用、上下拉、驱动能力 */
        GLB_GPIO_Init(cfg + i);

        /* 计算对应 PWM 通道号(硬件允许 0~5)*/
        PWM_CH_ID_Type ch = cfg[i].gpioPin % PWM_CH_MAX;

        /* 关闭该通道,确保输出低电平 */
        PWM_Channel_Disable(ch);
    }
}
/**
 * @brief  同时设置 R/G/B 三路占空比
 * @param  red   : 0~255
 * @param  green : 0~255
 * @param  blue  : 0~255
 * @note   固定使用 PWM 通道 2/3/4,与 cfg[] 数组顺序无关;
 *         频率 = 1 MHz / 256 ≈ 3.9 kHz,肉眼无频闪。
 */
void RGB_set(uint8_t red, uint8_t green, uint8_t blue)
{
    /* Green -> 通道 2 */
    PWM_Smart_Configure2(2, 80, 255, green);
    PWM_Channel_Enable(2);

    /* Blue  -> 通道 3 */
    PWM_Smart_Configure2(3, 80, 255, blue);
    PWM_Channel_Enable(3);

    /* Red   -> 通道 4 */
    PWM_Smart_Configure2(4, 80, 255, red);
    PWM_Channel_Enable(4);
}

四、实体参数配置

  1. 开启CONFIG_ENTITY_ENABLE_LIGHT资源,需要通过以下方式开启Bianry sensor资源:
  • 打开 HomeAssistant-ChomeAssistantDevConfig.h
  • 设置 CONFIG_ENTITY_ENABLE_LIGHT1

01

  1. 打开 HomeAssistant/HomeAssistant-C/homeAssistantPort.h 注释掉 #define CONFIG_Ai_M6x 并使用 #define CONFIG_Ai_WB2如图:

01

  1. 创建实体信息,需要把light 的信息填写完整结构体:ha_lh_entity_t,在 homeAssistantdev_ha.c中第37行中添加以下内容:
static ha_lh_entity_t light = {
              .name = "云烟的RGB彩灯",/* 实体显示名称,在HomeAssistant界面中显示 */
              .unique_id = "light_1",/* 实体唯一标识符,用于在MQTT主题中区分设备 */
              /* RGB灯光相关配置 */
              .rgb = {
                .rgb_command_topic = "light_1/rgb/set",/* MQTT命令主题:用于接收来自HomeAssistant的颜色设置命令 */
                .rgb_state_topic = "light_1/rgb/state", /* MQTT状态主题:用于向HomeAssistant发送当前灯光状态 */
                .red = 0,/* RGB颜色初始值:红色分量 (0-255) */
                .green = 0, /* RGB颜色初始值:绿色分量 (0-255) */
                .blue = 0, /* RGB颜色初始值:蓝色分量 (0-255) */
              }
            };
            homeAssistant_device_add_entity(CONFIG_HA_ENTITY_LIGHT, &light);//向HomeAssistant注册灯光实体
            homeAssistant_device_send_entity_state(CONFIG_HA_ENTITY_SWITCH, &sw1, 0);//发送开关实体状态到HomeAssistant,当前为关

01

  1. 配置接受控制指令;Light实体可以接收开关指令,颜色指令、亮度指令等。当设备收到指令后,会触发 HA_EVENT_MQTT_COMMAND_LIGHT_SWITCHHA_EVENT_MQTT_COMMAND_LIGHT_RGB_UPDATE,事件相关描述请参考 HomeAssistant MQTT 控制事件 ,添加以下代码:
/**
* @brief RGB灯光开关事件处理
* 处理来自HomeAssistant的RGB灯光开关命令
* 根据开关状态控制RGB灯的实际亮灭,并处理颜色逻辑
*/
case HA_EVENT_MQTT_COMMAND_LIGHT_SWITCH:
/**
* @brief 记录开关状态变化日志
* 通过HA_LOG_I宏串口输出记录开关状态变化,便于调试和监控
* 使用三元运算符将布尔状态转换为"ON"/"OFF"字符串
*/
HA_LOG_I("<<<<<<<<<< HA_EVENT_MQTT_COMMAND_LIGHT_SWITCH=%s\r\n", 
dev->entity_light->command_light->light_state ? "ON" : "OFF");
/**
* @brief 向HomeAssistant发送状态确认
* 将当前开关状态发送回HomeAssistant,确保状态同步
* CONFIG_HA_ENTITY_LIGHT: 实体类型为灯光
* &light: 指向灯光实体结构体的指针
* dev->entity_light->command_light->light_state: 当前开关状态
*/
homeAssistant_device_send_entity_state(CONFIG_HA_ENTITY_LIGHT, &light,
dev->entity_light->command_light->light_state);  
/**
* @brief 根据开关状态控制RGB灯
* 处理开关状态变化,控制RGB灯的实际亮灭
*/
if (!(dev->entity_light->command_light->light_state)) {
/**
* @brief 关闭状态:熄灭RGB灯
* 当开关状态为关闭时,将所有RGB通道设置为0
* RGB_set(0, 0, 0): 红色=0, 绿色=0, 蓝色=0 (完全熄灭)
*/
RGB_set(0, 0, 0);
} else {
/**
* @brief 开启状态:智能颜色处理
* 当开关状态为开启时,检查当前颜色设置
* 如果所有颜色通道都为0,提供默认亮度
* 否则使用当前设置的颜色值
*/
if (dev->entity_light->command_light->rgb.red == 0 && 
dev->entity_light->command_light->rgb.green == 0 && 
dev->entity_light->command_light->rgb.blue == 0) {
RGB_set(90, 90, 90);
} else {
/**
* @brief 使用当前颜色设置
* 如果已有颜色设置,直接使用当前RGB值
* 保持用户之前设置的颜色偏好
*/
RGB_set(dev->entity_light->command_light->rgb.red,
dev->entity_light->command_light->rgb.green,
dev->entity_light->command_light->rgb.blue);
}
}
break;
/**
* @brief RGB颜色更新事件处理
* 处理来自HomeAssistant的RGB颜色变化命令
* 直接应用新的颜色值到RGB灯
*/
//RGB颜色事件
case HA_EVENT_MQTT_COMMAND_LIGHT_RGB_UPDATE:
/**
* @brief 记录颜色变化日志
* 
* 通过HA_LOG_I宏记录RGB颜色值变化
* 格式:R,G,B 分别显示红、绿、蓝三个通道的数值
* 便于调试和追踪颜色变化历史
*/
HA_LOG_I("<<<<<<<<<< HA_EVENT_MQTT_COMMAND_LIGHT_RGB_UPDATE=%d,%d,%d\r\n",
dev->entity_light->command_light->rgb.red,
dev->entity_light->command_light->rgb.green,
dev->entity_light->command_light->rgb.blue);

/**
* @brief 直接应用新的RGB颜色
* 
* 将HomeAssistant发送的RGB值直接应用到RGB灯
* 不检查开关状态,假设灯光已开启
* RGB_set(): 同时设置红、绿、蓝三个通道的PWM占空比
*/
RGB_set(dev->entity_light->command_light->rgb.red,
dev->entity_light->command_light->rgb.green,
dev->entity_light->command_light->rgb.blue);

/**
* @brief 向HomeAssistant确认状态更新
* 将更新后的状态发送回HomeAssistant
* 确保HomeAssistant界面显示的状态与实际灯光状态一致
*/
homeAssistant_device_send_entity_state(CONFIG_HA_ENTITY_LIGHT, &light,
dev->entity_light->command_light->light_state);

01

5.找到 mian添加如下的初始化代码:

// 初始化EasyFlash闪存系统
   // easyflash_init();
 // 初始化RGB 控制
blog_info("[RGB] Initializing RGB LED control...");
RGB_init();
RGB_set(255, 255, 255);
vTaskDelay(pdMS_TO_TICKS(1000));
RGB_set(0, 0, 255);
vTaskDelay(pdMS_TO_TICKS(1000));
RGB_set(0, 255, 0);
vTaskDelay(pdMS_TO_TICKS(1000));
RGB_set(255, 0, 0);
vTaskDelay(pdMS_TO_TICKS(1000));
RGB_set(0, 0, 0);

    // 初始化设备状态管理
   // device_state_init(NULL);
  1. 编译烧录,输入以下指令
//编译
make
//烧录
make flash -j32
//或指定USB口
make flash p=/dev/ttyUSB0 -j32
  • 编译成功:

01

  • 烧录成功:

01

五、配网

01

  1. 重复按复位键5次(每次间隔1S左右)
  2. GPIO4的配置灯闪烁就是配网状态
  3. 打开微信小程序搜索 <安信可IOT>
  4. 进入Blufi配网 界面点击 扫描设备
  5. 找到一个名称:"USB-light-xxxx"的设备
  6. 点击连接之后,输入WiFi名称密码
  7. 点击更多信息,并选择MQTT服务器(只需要配置一次)
  8. 输入 MQTT服务器地址和端口号(只需要配置一次)
  9. 输入完成点击 配置WiFi
  10. 等待GPIO4的配置灯熄灭即可配网成功

六、使用

  1. 打开HomeAssistant 的MQTT 集成,就能看到USB 小夜灯控制器设备。

01

  • 最终呈现效果如下:

01

──── 0人觉得很赞 ────

使用道具 举报

换成灯带就更漂亮了,赞个👍
介绍很详细,回头试试去
2026-1-15 20:12:32
这个好玩😍
您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 30670 个
  • 话题数: 44748 篇