发帖
6 1 0

【Ai-WB2评测】BLE+PWM控制RGB灯

sujingliang
论坛元老

17

主题

15

回帖

5640

积分

论坛元老

积分
5640
Ai-WB2系列 60 6 前天 20:52
[i=s] 本帖最后由 sujingliang 于 2025-4-1 21:14 编辑 [/i]

一、RGB灯控制APP
找了一个app可以通过BLE控制RGB灯

其BLE控制RGB命令格式如下:

0x4e 0x4f 0x30 0x4 0xc5 0x0 0xff 0xff 0xf1
固定格式 固定格式 固定格式 固定格式 RED GREEN BLUE ALPHA 未知

命令共9个字节
头四字节固定为0x4e 0x4f 0x30 0x4 ,可以用来判断后面是控制RGB的指令
第5个字节为RED
第6个字节为GREEN
第7个字节为BLUE
第8个字节为ALPHA
第9个字节没弄明白是什么,没有使用

二、编写BLE从机程序
以applications/bluetooth/ble_slave为模板。

1、增加PWM控制RGB灯代码
pwmled.h

#ifndef __PWM_LED_H__
#define __PWM_LED_H__
// pwmled.h

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

BL_Err_Type PWM_Smart_Configure2(PWM_CH_ID_Type ch, uint16_t clkDiv, uint16_t period,uint16_t threshold2);
void pwm_led_init(void);
void pwm_led_set(uint8_t red,uint8_t green,uint8_t blue);
void rgb_control(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha);
#endif

BL_Err_Type PWM_Smart_Configure2(PWM_CH_ID_Type ch, uint16_t clkDiv, uint16_t period,uint16_t threshold2);
配置PWM参数

void pwm_led_init(void);
初始化PWM

void pwm_led_set(uint8_t red,uint8_t green,uint8_t blue);
设置3个RGB LED

void rgb_control(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha);
加上alpha控制3个RGB LED

pwmled.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 "pwmled.h"

#define PWM_Get_Channel_Reg(ch)  (PWM_BASE+PWM_CHANNEL_OFFSET+(ch)*0x20)
#define PWM_STOP_TIMEOUT_COUNT          (160*1000)


GLB_GPIO_Cfg_Type cfg[3] = {
    {
        .drive = 0,
        .smtCtrl = 1,
        .gpioMode = GPIO_MODE_OUTPUT,
        .pullType = GPIO_PULL_DOWN,
        .gpioPin = 14,  /// red
        .gpioFun = 8,
    },
    {
        .drive = 0,
        .smtCtrl = 1,
        .gpioMode = GPIO_MODE_OUTPUT,
        .pullType = GPIO_PULL_DOWN,
        .gpioPin = 17,  /// green
        .gpioFun = 8,
    },
    {
        .drive = 0,
        .smtCtrl = 1,
        .gpioMode = GPIO_MODE_OUTPUT,
        .pullType = GPIO_PULL_DOWN,
        .gpioPin = 3,  /// blue
        .gpioFun = 8,
    },
};

/// @brief Copy from PWM_Smart_Configure. Use Bus Clock instead of External Crystal Clock for PWM Timer
/// @param ch PWM Channel
/// @param clkDiv PWM clock divider
/// @param period PWM period
/// @param threshold2
/// @return
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;
    /* Get channel register */
    uint32_t PWMx = PWM_Get_Channel_Reg(ch);

    tmpVal = BL_RD_REG(PWMx, PWM_CONFIG);
    // if(BL_GET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL) != PWM_CLK_XCLK){
    if(BL_GET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL) != PWM_CLK_BCLK){
        BL_WR_REG(PWMx, PWM_CONFIG, BL_SET_REG_BIT(tmpVal, PWM_STOP_EN));
        while(!BL_IS_REG_BIT_SET(BL_RD_REG(PWMx, PWM_CONFIG), PWM_STS_TOP)){
            timeoutCnt--;
            if(timeoutCnt == 0){
                return TIMEOUT;
            }
        }
        // tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL, PWM_CLK_XCLK);
        tmpVal = BL_SET_REG_BITS_VAL(tmpVal, PWM_REG_CLK_SEL, PWM_CLK_BCLK);
    }
    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);

    /* Config pwm division */
    BL_WR_REG(PWMx, PWM_CLKDIV, clkDiv);

    /* Config pwm period and duty */
    BL_WR_REG(PWMx, PWM_PERIOD, period);
    BL_WR_REG(PWMx, PWM_THRE1, 0);
    BL_WR_REG(PWMx, PWM_THRE2, threshold2);

    return SUCCESS;
}

void pwm_led_init(void)
{
    for (int i = 0; i < 3; i++) {
        GLB_GPIO_Init(cfg + i);

        PWM_CH_ID_Type ch = cfg[i].gpioPin % PWM_CH_MAX;
        PWM_Channel_Disable(ch);
    }
}

void pwm_led_set(uint8_t red,uint8_t green,uint8_t blue)
{
    PWM_Smart_Configure2(2, 80, 255, green);
    PWM_Channel_Enable(2);

    PWM_Smart_Configure2(3, 80, 255, blue);
    PWM_Channel_Enable(3);

    PWM_Smart_Configure2(4, 80, 255, red);
    PWM_Channel_Enable(4);

}

void rgb_control(uint8_t red, uint8_t green, uint8_t blue,  uint8_t alpha)
{
    uint8_t t_red,t_green,t_blue;


    // 应用透明度/亮度
    t_red = red*alpha/255;
    t_green = green*alpha/255;
    t_blue = blue*alpha/255;

    pwm_led_set(t_red,t_green,t_blue);
}

2、ble_interface.c中修改如下

static ssize_t ble_uuid1_write_val(struct bt_conn *conn, const struct bt_gatt_attr *attr,
                                   const void *buf, u16_t len, u16_t offset,
                                   u8_t flags)
{
    uint8_t *recv_buffer;
    recv_buffer = pvPortMalloc(sizeof(uint8_t) * len);
    memcpy(recv_buffer, buf, len);
    printf("recv ble data len: %d\r\n", len);

    if(recv_buffer[0]==0x4e&&recv_buffer[1]==0x4f&&recv_buffer[2]==0x30&&recv_buffer[3]==0x04){
        //pwm_led_set(recv_buffer[4],recv_buffer[5],recv_buffer[6]);
        rgb_control(recv_buffer[4],recv_buffer[5],recv_buffer[6],recv_buffer[7]);
        printf("pwm_led_set\r\n");
    }

    for (size_t i = 0; i < len; i++)
    {
        printf("0x%x ", recv_buffer[i]);
    }
    printf("\r\n");
    vPortFree(recv_buffer);

    return len;
}

其中增加了:

if(recv_buffer[0]==0x4e&&recv_buffer[1]==0x4f&&recv_buffer[2]==0x30&&recv_buffer[3]==0x04){
        //pwm_led_set(recv_buffer[4],recv_buffer[5],recv_buffer[6]);
        rgb_control(recv_buffer[4],recv_buffer[5],recv_buffer[6],recv_buffer[7]);
        printf("pwm_led_set\r\n");
    }

即当UUID1收到写入值后,判断头4个字节是否为0x4e 0x4f 0x30 0x4,
如果是,调用rgb_control控制RGB灯改变颜色。

三、运行
手机上运行该APP

搜索到BLE,并连接

将uuid改为和配置一致

进入界面后,可以操作了。

操作后串口输出:

──── 1人觉得很赞 ────

使用道具 举报

还是蓝牙操控方便,这个APP哪里下载?
棒~
高级
赞~👍
高端起来了
喔,不错,我去复刻试试
您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 28268 个
  • 话题数: 40226 篇