• 【esp32】 PWM控制LED亮度原理及代码详解


    通俗的解释PWM的原理

    PWM:脉冲宽度调制器

    比如你有5V电源,要控制一台灯的亮度。你可以用传统的方式,串联一个可调电阻,改变电阻,灯的亮度就会改变。

    使用PWM调节的原理:保持一定的电压或者电流不变,改变一定周期内的导通和关断的时间。等效于,保持导通,改变电压或者电流的大小。

    【频率控制灯的闪烁:】

    相当于串联了一个开关,假设在1s时间内,0.5s打开,0.5s关闭,那么灯亮0.5s,熄灭0.5s,人看到就是灯在闪烁。如果把频率调高,1s改为1ms,0.5ms打开,0.5ms关闭,那么看起来灯的闪烁频率就很高。

    【占空比控制灯的亮度:】

    当闪烁频率超过一直的阈值时,人眼就感受不到了。比如,在1ms内,0.9ms是关闭的,0.1ms是打开的,那么灯的亮度就只有原来的十分之一了。即通过改变LED的通电时间长短来调节亮度,通电时间长则亮度高。

    ESP32-ledc源码分析

    参考:ESP32 — LEDC_PWM

    占空比:高电平接通时间与周期的比

    分辨率:就是占空比的最小值

    如代码中设置分辨率为 2**13 次方,则占空比为50%时的数字就是 ,(2**13 - 1)* 50% = 4095

    以esp32为例,设置pwm的相关参数:参考库中的 esp-idf-master\examples\peripherals\ledc\ledc_basic\main
    在这里插入图片描述
    注意:占空比的设置,LEDC_DUTY 和分辨率有关

    设置占空比为50%#define LEDC_DUTY (4095) // Set duty to 50%. ((2 ** 13) - 1) * 50% = 4095

    #define LEDC_TIMER              LEDC_TIMER_0
    #define LEDC_MODE               LEDC_LOW_SPEED_MODE
    #define LEDC_OUTPUT_IO          (5) 					// Define the output GPIO
    #define LEDC_CHANNEL            LEDC_CHANNEL_0
    #define LEDC_DUTY_RES           LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
    #define LEDC_DUTY               (4095) // Set duty to 50%. ((2 ** 13) - 1) * 50% = 4095
    #define LEDC_FREQUENCY          (5000) // Frequency in Hertz. Set frequency at 5 kHz
    
    static void example_ledc_init(void)
    {
        // Prepare and then apply the LEDC PWM timer configuration
        ledc_timer_config_t ledc_timer = {
            .speed_mode       = LEDC_MODE,
            .timer_num        = LEDC_TIMER,
            .duty_resolution  = LEDC_DUTY_RES,
            .freq_hz          = LEDC_FREQUENCY,  // Set output frequency at 5 kHz
            .clk_cfg          = LEDC_AUTO_CLK
        };
        ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
    
        // Prepare and then apply the LEDC PWM channel configuration
        ledc_channel_config_t ledc_channel = {
            .speed_mode     = LEDC_MODE,
            .channel        = LEDC_CHANNEL,
            .timer_sel      = LEDC_TIMER,
            .intr_type      = LEDC_INTR_DISABLE,
            .gpio_num       = LEDC_OUTPUT_IO,
            .duty           = 0, // Set duty to 0%
            .hpoint         = 0
        };
        ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
    }
    
    • 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

    两路LED以不同频的方式闪烁

    拓展:
    两路LED以不同频的方式闪烁;代码中不同的GPIO配置不同的定时器和channel,然后设置不同的频率。

    现象:
    不同频率闪烁


    拓展:可以和按键检测结合起来:
    短按,实现灯开,再短按一次,实现灯关
    长按2s,实现双灯不同频闪烁
    长按4s,实现双灯同频闪烁

    中断:设置上升沿和下降沿触发,按下按键和抬起按键之间,发消息给消息队列。

    中断方式:采用中断的方式, 坏处是必须等按键松开才可以计算按键时间长短,用户体验稍差。 好处是相比定时器的方式,会大大减小CPU的资源。

    定时器扫描:开一个线程或者定时器,不断的扫描GPIO的输入状态, 好处是随时扫描到gpio的状态用户体验好。 坏处是浪费cpu资源。

    若开一个定时器,本代码未实现,参考资料:[【ESP32—GPIO输入,按键的长按和短按】]
    通过添加printf信息打印消息,测试原代码发现,存在时间偏差较大的情况,分析代码发现代码存在以下下问题:
    目的是:当按键按下时,开始记录按下的时刻A,按键松开时,记录松开的时刻B,通过 B-A 计算按下的时间。但是源代码中按下按键时,可能多次重新计算了时刻A的值,造成测试不准的现象。
    在这里插入图片描述

  • 相关阅读:
    Pulsar 社区周报 | No.2024-06-07 | Apache Pulsar 新分支 3.3 版本发布
    3D激光SLAM:ALOAM---后端lasermapping数据处理低延时性保障操作
    Angr-CTF学习笔记14-17
    基于Asp.Net Mvc开发的个人博客系统
    数据分析-numpy2
    Transformer推理性能优化技术很重要的一个就是K V cache,能否通俗分析,可以结合代码?
    【MATLAB】利用字符串模拟运算式
    The Kernel Symbol Table
    【数据结构与算法】之递归算法
    Pytorch LSTM 长短期记忆网络
  • 原文地址:https://blog.csdn.net/qq_39217004/article/details/127735130