天天看点

第十章 ESP32开发指南---PWM全彩LED灯显示

  • 关注嘉友创科技公众号
    第十章 ESP32开发指南---PWM全彩LED灯显示
  • 源码地址:​​https://github.com/HX-IoT/ESP32-Developer-Guide​​
  • ESP32开发指南QQ群:824870185,内有pdf版,排版整洁。

学习目的及目标

学习LED灯电路及硬件原理

学习ESP32 的PWM(ledc)功能的配置

掌握PWM(ledc)控制全彩LED灯渐变程序

全彩 LED 灯简介

全彩 LED 灯,实质上是一种把红、绿、蓝单色发光体集成到小面积区域中的 LED 灯,控制时对这三种颜色的灯管输出不同的光照强度,即可混合得到不同的颜色,其混色原理与光的三原色混合原理一致。

例如,若红绿蓝灯都能控制输出光照强度为[0:255]种等级,那么该灯可混合得到使用RGB888表示的所有颜色(包括以 RGB三个灯管都全灭所表示的纯黑色)。

全彩 LED 灯控制原理

本教程配套开发板中的 RGB灯就是一种全彩 LED 灯,前面介绍 LED 基本控制原理的时候,只能控制 RGB三色灯的亮灭,即 RGB每盏灯有[0:1]两种等级,因此只能组合出 8种颜色。

要使用ESP32控制 LED灯输出多种亮度等级,可以通过控制输出脉冲的占空比来实现。就是我们今天要学习的PWM功能,在ESP32中就是ledc功能。

第十章 ESP32开发指南---PWM全彩LED灯显示

上图列出了周期相同而占空比分别为 100%、80%、50和 20%的脉冲波形,假如利用这样的脉冲控制 LED 灯,即可控制 LED 灯亮灭时间长度的比例。若提高脉冲的频率,LED 灯将会高频率进行开关切换,由于视觉暂留效应,人眼看不到 LED 灯的开关导致的闪烁现象,而是感觉到使用不同占空比的脉冲控制 LED 灯时的亮度差别。即单个控制周期内,LED 灯亮的平均时间越长,亮度就越高,反之越暗。

把脉冲信号占空比分成 256 个等级,即可用于控制 LED 灯输出 256种亮度,使用三种这样的信号控制 RGB灯即可得到 256*256*256种颜色混合的效果。而要控制占空比,直接使用 ESP32的LEDC功能即可。

硬件设计及原理

同LED章原理图。

本实验板连接了一个 RGB彩灯,RGB彩灯实际上由三盏分别为红色、绿色、蓝色的 LED 灯组成,通过控制 RGB颜色强度的组合,可以混合出各种色彩。

LED标号 LED颜色 接至ESP32的引脚
LP2A 红色 IO2
LP2B 绿色 IO18
LP2C 蓝色 IO19

若您使用的实验板 LED 灯的连接方式或引脚不一样,只需根据我们的工程修改引脚即可,程序的控制原理相同。

软件设计

代码逻辑

第十章 ESP32开发指南---PWM全彩LED灯显示

ESP32的PWM(ledc)接口介绍

LEDC配置函数:ledc_channel_config();

函数原型

esp_err_t ledc_channel_config

(

const ledc_channel_config_t* ledc_conf

)

函数功能 LEDC配置函数
参数

[in] ledc_conf:ledc配置结构体ledc_channel_config_t

typedef struct {

int gpio_num;//IO编号

ledc_mode_t speed_mode;//速度

ledc_channel_t channel;//通道

ledc_intr_type_t intr_type;//中断使能

ledc_timer_t timer_sel; //定时器通道

uint32_t duty; //占空比

} ledc_channel_config_t;

返回值

ESP_OK:成功

ESP_ERR_INVALID_ARG : 参数错误

LEDC渐变安装函数:ledc_fade_func_install();

esp_err_t ledc_fade_func_install

int intr_alloc_flags

LEDC渐变安装使能函数
[in] intr_alloc_flags:分配中断标记

LEDC渐变函数:ledc_set_fade_with_time();

esp_err_t ledc_set_fade_with_time

ledc_mode_t speed_mode,

ledc_channel_t channel,

uint32_t target_duty,

int max_fade_time_ms

LEDC渐变函数

[in] speed_mode:速度

[in] channel:通道

[in] target_duty:目标占空比

[in] max_fade_time_ms:到达目标占空比需要的时间

ESP_ERR_INVALID_STATE:LEDC渐变未安装

ESP_FAIL:LEDC渐变安装失败

LEDC渐变开始函数:ledc_fade_start();

esp_err_t ledc_fade_start

ledc_fade_mode_t wait_done

LEDC渐变开始函数
[in] wait_done:是否等待

更多更详细接口请参考​​官方指南​​。

渐变RGB彩灯源码编写

获取按键状态,等于0表示按键按下,然后死等松手,切换灯状态。

包含头文件、IO宏定义、ledc宏定义

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

#include <stdio.h>

#include "esp_system.h"

#include "esp_spi_flash.h"

#include "esp_wifi.h"

#include "esp_event_loop.h"

#include "esp_log.h"

#include "esp_err.h"

#include "nvs_flash.h"

#include "freertos/FreeRTOS.h"

#include "freertos/task.h"

#include "driver/ledc.h"

#define LED_R_IO 2

#define LED_G_IO 18

#define LED_B_IO 19

#define LEDC_MAX_DUTY                (8191) //2的13次方-1(13位PWM)

#define LEDC_FADE_TIME     (1000) //渐变时间(ms)

RGB灯PWM(ledc)配置,并使能渐变函数

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

/*

* void ledc_init(void):定时器0用在PWM模式,输出3通道的LEDC信号

*/

void ledc_init(void)

{

//定时器配置结构体

ledc_timer_config_t ledc_timer;

//定时器配置->timer0

ledc_timer.duty_resolution = LEDC_TIMER_13_BIT; //PWM分辨率

ledc_timer.freq_hz = 5000;                        //频率

ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;   //速度

ledc_timer.timer_num = LEDC_TIMER_0;            // 选择定时器

ledc_timer_config(&ledc_timer); //设置定时器PWM模式

//PWM通道0配置->IO2->红色灯

g_ledc_ch_R.channel    = LEDC_CHANNEL_0; //PWM通道

g_ledc_ch_R.duty       = 0; //占空比

g_ledc_ch_R.gpio_num   = LED_R_IO; //IO映射

g_ledc_ch_R.speed_mode = LEDC_HIGH_SPEED_MODE; //速度

g_ledc_ch_R.timer_sel  = LEDC_TIMER_0; //选择定时器

ledc_channel_config(&g_ledc_ch_R); //配置PWM

//PWM通道1配置->IO18->绿色灯

g_ledc_ch_G.channel    = LEDC_CHANNEL_1; //PWM通道

g_ledc_ch_G.duty       = 0; //占空比

g_ledc_ch_G.gpio_num   = LED_G_IO; //IO映射

g_ledc_ch_G.speed_mode = LEDC_HIGH_SPEED_MODE; //速度

g_ledc_ch_G.timer_sel  = LEDC_TIMER_0; //选择定时器

ledc_channel_config(&g_ledc_ch_G); //配置PWM

//PWM通道2配置->IO19->蓝色灯

g_ledc_ch_B.channel    = LEDC_CHANNEL_2; //PWM通道

g_ledc_ch_B.duty       = 0; //占空比

g_ledc_ch_B.gpio_num   =LED_B_IO ; //IO映射

g_ledc_ch_B.speed_mode = LEDC_HIGH_SPEED_MODE; //速度

g_ledc_ch_B.timer_sel  = LEDC_TIMER_0; //选择定时器

ledc_channel_config(&g_ledc_ch_B); //配置PWM

//使能ledc渐变功能

ledc_fade_func_install(0);

}

主函数:渐变RGB灯

RGB灯由0%到100%渐变(暗到亮),历时1秒

RGB灯由100%到0%渐变(亮到暗),历时1秒

 * 应用程序的函数入口

void app_main()

{    

ledc_init();//ledc初始化

    while(1)

//ledc 红灯渐变至100%,时间LEDC_FADE_TIME

ledc_set_fade_with_time(g_ledc_ch_R.speed_mode,

                                     g_ledc_ch_R.channel,

         LEDC_MAX_DUTY,

                                     LEDC_FADE_TIME);

//渐变开始

ledc_fade_start(g_ledc_ch_R.speed_mode,

      g_ledc_ch_R.channel,

      LEDC_FADE_NO_WAIT);

//略过

           vTaskDelay(LEDC_FADE_TIME / portTICK_PERIOD_MS);

//ledc 红灯 渐变至0%,时间LEDC_FADE_TIME

                                      g_ledc_ch_R.channel,

          0,

                                      LEDC_FADE_TIME);

硬件连接

开发板默认已经连接好RGB灯,下载程序即可,使用其他开发板需要修改程序或者修改硬件连接皆可。

效果展示

RGB灯由暗到亮,再由亮变暗,如此循环。

PWM(ledc)总结

渐变在指示灯处比较常用。

不用渐变的时候可以使用,设置占空比函数直接怼。

设置占空比ledc_set_duty();