支持PWM的三色LED灯的软硬件机制和接口介绍

[English]

重要

目前SDK的默认工程的三色灯引脚不支持PWM功能

目前SDK的PWM工程的目前未开放用户使用外部设备修改RGB值,如有开发需求,请联系开发人员!

如需支持PWM,请参考芯片的引脚图,将LED三色灯与PWM1寄存器使用的GPIO引脚相连(例如在7236上,为32,34,36三个引脚)

支持PWM的三色LED灯的硬件配置

我们仍以双灯7236模组为例子,介绍一下硬件配置

本次demo工程中使用BK7236模组如下图所示:

bk7236

bk7236模组

在这个模组中,左侧的LED1与PWM1寄存器控制的GPIO引脚相连,因此,LED1支持PWM功能。

支持PWM的三色LED灯的软件配置

支持PWM的三色LED灯的软件运行逻辑与普通的三色灯逻辑相同,如果您没有阅读三色LED灯的软件设计逻辑,请详见:普通三色LED灯的软硬件机制和接口介绍 下面介绍的是PWM独有的部分,将以上图中的7236模组为基础,对PWM功能进行简单的介绍。

PWM在LED三色灯上的相关介绍

PWM(脉冲宽度调制)是一种常用的模拟信号处理技术,它通过控制脉冲信号的宽度来模拟不同强度的模拟信号。在LED(发光二极管)应用中,PWM主要用于调节LED的亮度。

以下是PWM在LED上的主要用途:

  • 亮度调节 :通过改变PWM的占空比(脉冲高电平的时间与整个周期时间的比例),可以控制LED的亮度。占空比越高,LED的亮度就越高;占空比越低,LED的亮度就越低。

  • 模拟亮度 :虽然LED是数字设备,但通过PWM可以实现类似模拟调节亮度的效果。通过改变PWM的频率和占空比,可以产生不同亮度的连续变化。

  • 消除闪烁 :LED在低亮度时可能会出现闪烁,这会让人感到不适。通过使用适当频率的PWM(通常在几千赫兹以上),可以有效地消除这种闪烁。

  • 色彩控制 :在RGB LED(红色、绿色、蓝色发光二极管)应用中,PWM可以分别控制每个颜色的亮度,从而实现混合色光的调节。

  • 图像显示 :在一些特殊的LED应用中,如LED显示屏,PWM可以用来控制每个像素的亮度,实现动态图像的显示。

总之,PWM在LED中的应用非常广泛,是现代电子设备中调节LED亮度和颜色的一种重要技术。

PWM在bk7236上的相关实现

bk7236上面的PWM相关介绍请参见:

https://docs.bekencorp.com/arminodoc/bk_idk/bk7236/zh_CN/v2.0.1/examples/peripheral/bk_pwm.html?highlight=pwm

对此,我们将使用如下的pwm channel:

颜色引脚

pwm channel

BK_MESH_PWM_RED_PIN

8

BK_MESH_PWM_GREEN_PIN

6

BK_MESH_PWM_BLUE_PIN

10

备注

请根据自己的实际硬件更改!

可以将pwm channel在本工程理解为对应的GPIO引脚,只不过在PWM项目上调用的函数不同而已!

PWM LED实现

demo路径:

components/demos/bk_mesh_led_demo_v2.c

备注

PWM项目与之前的LED项目不适用相同工程,若使用PWM项目,请使用如下编译命令:

make bk7236 -j8 PROJECT=bk_mesh/pwm_led

demo工程上使用的内部API

在demo工程中,使用了一些IDK内部的PWM的API,这些API的介绍如下:

Header File

Functions

bk_err_t bk_pwm_driver_init(void)

Init the PWM driver.

This API init the resoure common to all PWM channels:

  • Init PWM driver control memory

  • Configure PWM common clock to 26M

This API should be called before any other PWM APIs.

返回

  • BK_OK: succeed

  • others: other errors.

bk_err_t bk_pwm_init(pwm_chan_t chan, const pwm_init_config_t *config)

Init the PWM channel.

This API init the PWM channel:

  • Power up the PWM channel

  • Configure the PWM channel clock to 26M

  • Map the PWM channel to dedicated GPIO port

  • Set the period and duty cycle.

For duty/cycle relationship, refer to bk_pwm_set_period_duty()

返回

  • BK_OK: succeed

  • BK_ERR_PWM_NOT_INIT: PWM driver not init

  • BK_ERR_NULL_PARAM: config is NULL

  • BK_ERR_PWM_CHAN_ID: invalid PWM channel

  • BK_ERR_PWM_PERIOD_DUTY: PWM duty/period relationship is invalid

  • others: other errors.

bk_err_t bk_pwm_start(pwm_chan_t chan)

Stop a PWM channel.

This API init the resoure common to all PWM channels:

  • Init PWM driver control memory

  • Configure PWM common clock to 26M

返回

  • BK_OK: succeed

  • others: other errors.

bk_err_t bk_pwm_stop(pwm_chan_t chan)

Stop a PWM channel.

This API init the resoure common to all PWM channels:

  • Init PWM driver control memory

  • Configure PWM common clock to 26M

返回

  • BK_OK: succeed

  • others: other errors.

bk_err_t bk_pwm_set_period_duty(pwm_chan_t chan, pwm_period_duty_config_t *config)

Configure the PWM period and duty cycle.

This API is used to configure the period and duty time. The unit is cycle of PWM channel clock, since the PWM channel clock is default to 26M, the unit is 1/26M (1/26 000 000) seconds.

The beken chip supports up to 3 duties, the exact duty numbers depends on the target type.

EXample1 - the simplest case::

Clock cycle = 1/26M
Initial signal is High
duty_cycle = D1 = 3
duty2_cycle = 0
duty3_cycle = 0
period_cycle = 3 + 2 = 5

                  |<-C->|
                   __    __    __    __    __    __    __    __    __    __    __    __
Clock Signal:   __|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__
                  __________________             _________________             ___________
PWM Signal:    __|                  |___________|                 |___________|

Duty1:           |<------- D1 ----->|

Period:          |<---------- Period1 --------->|<------ Period2 ------------>|

Example2 - 3 duty with initial signal high::

Clock cycle = 1/26M
Duty_cycle = D1 = 1
Duty2_cycle = D2 = 2
Duty3_cycle = D3 = 3
period_cycle = D1 + D2 + D3 = 6

                  |<-C->|
                   __    __    __    __    __    __    __    __    __    __    __    __    __
Clock Signal:   __|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|
                  ______             _________________ _____             _________________
PWM Signal:    __|      |___________|                 |     |___________|                 |__

Duty1:           |<-D1->|<----D2--->|<------D3------->|

Period:          |<--------------- Period1 ---------->|<------------ Period2 ------------>|

Example3 - 3 duty with initial signal low::

Clock cycle = 1/26M
Duty_cycle = D1 = 1
Duty2_cycle = D2 = 2
Duty3_cycle = D3 = 3
period_cycle = D1 + D2 + D3 = 6

                  |<-C->|
                   __    __    __    __    __    __    __    __    __    __    __    __    __
Clock Signal:   __|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|
                __       ___________                         ___________
PWM Signal:       |_____|           |_________________|_____|           |_________________|__

Duty1:           |<-D1->|<----D2--->|<------D3------->|

Period:          |<--------------- Period1 ---------->|<------------ Period2 -------------|

Example4 - 3 duty with initial signal low and period > (D1 + D2 + D3)::

Clock cycle = 1/26M
Duty_cycle = D1 = 1
Duty2_cycle = D2 = 2
Duty3_cycle = D3 = 3
period_cycle = D1 + D2 + D3 + 1 = 7

                  |<-C->|
                   __    __    __    __    __    __    __    __    __    __    __    __    __
Clock Signal:   __|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|  |__|
                __       ___________                   _____       ___________
PWM Signal:       |_____|           |_________________|     |_____|           |______________

Duty1:           |<-D1->|<----D2--->|<------D3------->|

Period:          |<--------------- Period ----------------->|

Attention

1. The period should great or equal to (D1 + D2 + D3)

Attention

2. If the duty Dx is 0, then Dx+1 to D3 should also be 0. If D1 is 0, it indicates the duty ratio is 0% and the signal is always low.

Attention

3. If D1 equals period, it indicates the duty ratio is 100% and the signal is always high.

Attention

4. The signal strengh between two successive duties is opposite, e.g. if signal of D1 is high, then signal of D2 is low.

Attention

5. The initial signal is the signal strengh of D1 if D1 is not 0.

Attention

6. The duty/period configuration is very flexible, different configurations may have same result.

返回

  • BK_OK: succeed

  • BK_ERR_NULL_PARAM: config is NULL

  • BK_ERR_PWM_CHAN_NOT_INIT: PWM channel not init

  • BK_ERR_PWM_CHAN_ID: invalid PWM channel

  • BK_ERR_PWM_PERIOD_DUTY: PWM duty/period relationship is invalid

  • others: other errors.

demo工程上使用的对外API

与普通LED三色灯软件设计相同,PWM工程同样需要注册对外的API,对外API接口如下:

Header File

Functions

int bk_mesh_256led_demo_set_vendor_info(uint8_t *vendor_ptr, uint8_t type, uint8_t layer)

APP set PWM LED Color and blink time.

参数
  • vendor_ptr – vendor_ptr is the pointer formatted by Vendor format,it contains the RGB value and blink time

  • type – type is not use, the parameter is retained to align with the global variable function pointer

  • layer – layer is not use, the parameter is retained to align with the global variable function pointer

返回

  • BK_OK: succeed

  • others: other errors

uint8_t *bk_mesh_256led_demo_get_vendor_info(struct bk_mesh_256_color_light_msg *led_info, uint8_t *len)

APP get PWM LED Color and blink time.

参数
  • led_info – led_info is the pointer of struct bk_mesh_256_color_light_msg,it contains the RGB value and blink time

  • len – len is used for BK MESH NET to used to form a reply frame

返回

  • reply frame head ptr

int bk_mesh_256_led_demo_inform_vendor_info(uint8_t type, uint8_t layer)

SDK set PWM LED Color and blink time through specified events.

参数
  • type – type is the event type

  • layer – layer is the specified layer.diff layer shows diff color and blink time

返回

  • BK_OK: succeed

  • others: other errors

int bk_mesh_pwm_led_init()

pwm led init.

返回

  • BK_OK: succeed

  • others: other errors

备注

这几个函数的具体实现可以由客户自行实现,也可以使用demo中已经写好的函数实现。

这几个函数只是PWM LED内部的具体设置实现,下面我们要做的就是将这些API统一到对应的vendor API上。

与LED三色灯工程一样,所有的vendor信息都存储在 g_vendor_info 这个全局结构体下,而在PWM项目上,我们需要关注的则是 struct bk_mesh_256_color_light_msg led_256_control

结构体struct bk_mesh_256_color_light_msg的定义如下:

Header File

Structures

struct bk_mesh_256_color_light_msg

Public Members

u8 type_msg

SDK event type

u8 layer

SDK layer

u16 time

LED Blink time

u8 bitmap[3]

PWM LED RGB Value

pwm_period_duty_config_t red_config

Red Value for duty and cycle

pwm_period_duty_config_t green_config

Green Value for duty and cycle

pwm_period_duty_config_t blue_config

Blue Value for duty and cycle

每个成员的解释如下:

变量

类型 | 说明

type_msg

u8

上一次配置的消息类型,在inform函数中使用

layer

u8

上一次配置的层级信息,在inform函数中使用

time

u16

上一次配置的闪烁时间

bitmap

u16[3]

上一次配置的RGB值,其中从低到高为R,G,B(中间暂存,不代表最后的配置值)

red_config

pwm_period_duty_config_t

上一次配置的R值,还包括周期数和占空比

green_config

pwm_period_duty_config_t

上一次配置的G值,还包括周期数和占空比

blue_config

pwm_period_duty_config_t

上一次配置的B值,还包括周期数和占空比

对于pwm_period_duty_config_t的解释,请参见如下网址:

此外,为了表征编译的版本支持PWM项目,需要在初始化函数中执行下列操作:

g_vendor_info.vendor_bitmap |= BK_MESH_DEMO_SUPPORT_PWM_LED;

其中, BK_MESH_DEMO_SUPPORT_PWM_LED 占用Bitmap中的BIT2,目前为内部消息机制使用,用户如需在外部APP中设置,请参见TODO 开发者文档!

备注

使用PWM工程需要开启CONFIG_BK_WIFI_MESH_DEMO_PWM_LED,并且需要注意的是,只有LED1支持PWM,而LED2只支持单一颜色的配置。 而在使用双LED的bk7236硬件模组情况下,不需要开启CONFIG_BK_WIFI_MESH_DEMO_LED,这个宏是为了单一LED灯硬件组准备的。

demo工程上使用的对外API的注册

与LED三色灯工程相同,上面提到的PWM LED工程使用到的对外的API也是在vendor统一对外的API中使用, 整体通过以 g_vendor_info.vendor_bitmap 存储的内部bit值和 Vendor API 所携带的外部bit值进行比较而判断执行哪个工程(当然也有对应宏的保护) 下图为PWM工程的Vendor API内部的执行流程图:

Vendor API flow for PWM

Vendor API flow for PWM

备注

set vendor函数目前在SDK内部有支持,但是Beken给出的手机APP侧目前不支持配置,因此默认SDK不支持PWM LED的配置!

如有必要可自行实现APP侧设置或联系开发者!

demo工程上使用的外部消息区域的Vendor字段格式

PWM LED工程使用外部消息区域的Vendor字段格式与三色LED工程相同,只是区别如下:

- PWM LED工程使用bitmap中的BIT2作为标记
  • PWM LED工程使用bitmap2 Content字段

下面介绍一下PWM LED工程相关Vendor字段格式

Bitmap2

  • Bitmap0目前被PWM LED工程所用,用户的外部设备和节点之间通信,如涉及到PWM LED交互,则需要将此bit置1。

    • 当该bit为1时代表本命令支持PWM LED控制

    • 当该bit为0时代表本命令不支持PWM LED控制

备注

本字段在 CONFIG_BK_WIFI_MESH_DEMO_PWM_LED 配置为true的情况下生效!

Bitmap2 Content

备注

本字段在 CONFIG_BK_WIFI_MESH_DEMO_PWM_LED 配置为true的情况下生效!

Bitmap0 Content的结构如下:

vendor_bitmap0

PWM Bitmap2 COntent

下面介绍一下Bitmap2 Content里面各个字段的含义:

  • color bitmap:想要配置或者查询的颜色,在PWM LED工程下,采用RGB各占一个字节的模式,因此长度为3个字节,因此本字段格式如下:

    pwm led_color_bitmap

    pwm color bitmap

  • time:想要配置或者查询的颜色闪烁时间

    该字段配置闪烁时间,单位为毫秒。当此值非0时,默认LED灯闪烁。

内部状态设置机制

下表是目前使用到的内部消息:

枚举

事件说明

NODE_POWER_ON

节点开机

NODE_START_NET

开始组网

NODE_NET_FAIL

组网失败

NODE_NET_LAYER

根据层级配置颜色,SDK默认,颜色见下表

NODE_BREAKDOWN

节点失效

NODE_REVOVER

节点恢复

NODE_LAYER_CHANGE

节点层级更改

NODE_STOP

节点停止

目前SDK默认的层级-颜色对照表:

层级

颜色

1

red

2

green

3

blue

4

yellow

5

magenta

6

cyan

特殊事件颜色:

事件

颜色

NODE_POWER_ON

white

NODE_BREAKDOWN

当前颜色闪烁

NODE_STOP

white