使用ESP-IDF开发方式控制RGB LED灯,并将其封装为更加简单的ESP-IDF组件方便调用。

1、准备工作

1.1、硬件模块
  • ESP32-WROVER-E
  • LED
1.2、软件
  • VSCode ESP开发插件
  • ESP-IDF SDK
1.3、连线

RGB LED的三个控制引脚分别连接ESP32开发板的12、14、27号引脚,简图如下: image-20210924210727316

2、代码

2.1、目标

实现一个自定义组件:rgbLEDC,该组件功能包括LED引脚配置(可以通过menuconfig配置)、基本开关控制、颜色调节、呼吸灯效果。

2.2、具体步骤

(1)新建项目rgbLEDAPP; (2)在项目文件夹下新建component文件夹,执行命令 ESP-IDF -> 创建新的ESP-IDF组件: image-20210925122033363 在出现的输入框中填写组件名称:rgbLEDC,完成添加; (3)在rgbLEDC组件文件夹下新建Kconfig文件,用于menuconfig配置,内容如下:

  • Kconfig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
menu "rgbled components config"
config LED_RED_PIN
int "config LED RED pin"
range 0 34
default 27

config LED_GREEN_PIN
int "config LED GREEN pin"
range 0 34
default 14

config LED_BLUE_PIN
int "config LED BLUE pin"
range 0 34
default 12
endmenu

(4)在新建 component.mk文件,内容如下:

1
COMPONNET_ADD_INCLUDEDIRS := include

该选项指定组件头文件路径; (5)编写组件代码

  • 头文件 rgbledc.h
1
2
3
4
5
6
7
8
9
10
11
#pragma once

#include "driver/ledc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

void rgbLED_init();
void rgbLED_on(uint8_t r, uint8_t g, uint8_t b);
void rgbLED_off();
void rgbLED_fade(uint8_t r, uint8_t g, uint8_t b, bool up, int time);

  • 源码 rgbledc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <stdio.h>

#include "rgbledc.h"
#include "sdkconfig.h"

#define LED_RED_CH LEDC_CHANNEL_0
#define LED_GREEN_CH LEDC_CHANNEL_1
#define LED_BLUE_CH LEDC_CHANNEL_2

#define LED_RED_PIN CONFIG_LED_RED_PIN
#define LED_GREEN_PIN CONFIG_LED_GREEN_PIN
#define LED_BLUE_PIN CONFIG_LED_BLUE_PIN

void rgbLED_init()
{
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.timer_num = LEDC_TIMER_0,
.duty_resolution = LEDC_TIMER_13_BIT,
.freq_hz = 5000,
.clk_cfg = LEDC_AUTO_CLK
};

ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

ledc_channel_config_t ledc_red_chan = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LED_RED_CH,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = LED_RED_PIN,
.duty = 0,
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_red_chan));

ledc_channel_config_t ledc_green_chan = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LED_GREEN_CH,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = LED_GREEN_PIN,
.duty = 0,
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_green_chan));

ledc_channel_config_t ledc_blue_chan = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = LED_BLUE_CH,
.timer_sel = LEDC_TIMER_0,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = LED_BLUE_PIN,
.duty = 0,
.hpoint = 0
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_blue_chan));

ledc_fade_func_install(0);
}

void rgbLED_on(uint8_t r, uint8_t g, uint8_t b)
{
uint32_t r_duty = r << 5;
uint32_t g_duty = g << 5;
uint32_t b_duty = b << 5;

ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE,LED_RED_CH,r_duty,0);
ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE,LED_GREEN_CH,g_duty,0);
ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE,LED_BLUE_CH,b_duty,0);
}

void rgbLED_off()
{
ledc_stop(LEDC_LOW_SPEED_MODE,LED_RED_CH,0);
ledc_stop(LEDC_LOW_SPEED_MODE,LED_GREEN_CH,0);
ledc_stop(LEDC_LOW_SPEED_MODE,LED_BLUE_CH,0);
}

void rgbLED_fade(uint8_t r, uint8_t g, uint8_t b, bool up, int time)
{
uint32_t red_duty = r << 5;
uint32_t green_duty = g << 5;
uint32_t blue_duty = b << 5;

if(!up){
//init state:max
ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE,LED_RED_CH,red_duty,0);
ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE,LED_GREEN_CH,green_duty,0);
ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE,LED_BLUE_CH,blue_duty,0);

red_duty = 0;
green_duty = 0;
blue_duty = 0;
}else{
//init state :min
ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE,LED_RED_CH,0,0);
ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE,LED_GREEN_CH,0,0);
ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE,LED_BLUE_CH,0,0);
}

printf("dudy:%d %d %d\r\n", red_duty,green_duty,blue_duty);

ledc_set_fade_time_and_start(LEDC_LOW_SPEED_MODE,LED_RED_CH,red_duty,time,LEDC_FADE_WAIT_DONE);
ledc_set_fade_time_and_start(LEDC_LOW_SPEED_MODE,LED_GREEN_CH,green_duty,time,LEDC_FADE_WAIT_DONE);
ledc_set_fade_time_and_start(LEDC_LOW_SPEED_MODE,LED_BLUE_CH,blue_duty,time,LEDC_FADE_WAIT_DONE);
}

(6)编写主程序代码,这里就直接使用上面编写好的组件编写主程序,实现如下功能来测试组件API:

  • 红灯闪烁三次;
  • 绿色呼吸灯;
  • 黄色显示三个级别亮度:最亮、一半亮度、最弱亮度;
  • 代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "rgbledc.h"

void app_main(void)
{

rgbLED_init();

while(1){

//blink red
for(int i=0; i<3; i++){
rgbLED_on(255,0,0);
vTaskDelay(400/portTICK_PERIOD_MS);
rgbLED_off();
vTaskDelay(400/portTICK_PERIOD_MS);
}

//green led fade up then down
rgbLED_fade(0,255,0,true,4000);
rgbLED_fade(0,255,0,false,4000);

//yellow color
rgbLED_on(255,255,0);
vTaskDelay(2000/portTICK_PERIOD_MS);

rgbLED_on(100,100,0);
vTaskDelay(2000/portTICK_PERIOD_MS);

rgbLED_on(10,10,0);
vTaskDelay(2000/portTICK_PERIOD_MS);

//off
rgbLED_off();
vTaskDelay(1000/portTICK_PERIOD_MS);

}
}

3、测试

3.1、配置引脚

输入命令进行配置:

1
idf.py menuconfig

image-20210925125734265

3.2、编译和烧录

将硬件连接好,并在VSCode中,使用命令:

1
idf.py build flash -p COM6

进行编译并通过串口COM6烧写。

3.3、查看效果

可以看到LED按照预期的效果显示。

  • 视频教程: