【ESP32 IDF】pwm脉宽调制技术

文章目录

  • 前言
  • 一、PWM脉宽调制技术介绍
  • 二、pwm的使用
    • 2.1 LEDC定时器结构体
      • 结构体介绍
      • 配置定时器
    • 2.2 配置LEDC通道
      • 结构体介绍
      • 初始化pwm
    • 2.3 设置占空比
      • 设置占空比
      • 更新占空比
  • 三、示例代码
  • 总结


前言

PWM(Pulse Width Modulation,脉宽调制)是一种常用的调节模拟信号的技术,也在嵌入式系统中扮演着重要的角色。ESP32是一款强大的微控制器,具备多个硬件模块支持PWM功能。本文将介绍ESP32 IDF中的PWM脉宽调制技术,包括其原理、应用场景和使用方法。


一、PWM脉宽调制技术介绍

当我们想要控制设备的亮度或速度时,PWM脉宽调制技术就派上用场了。它的原理非常简单,就好像我们在灯泡上使用开关一样。开关可以打开或关闭灯泡,但无法改变亮度。但是,如果我们快速地开关灯泡,让它在打开和关闭之间不断变化,我们就能够通过控制开关的开启时间比例来改变亮度。

PWM脉宽调制的原理就是通过调整脉冲信号的宽度来控制设备的平均电平。脉冲信号是一种快速的开关信号,它会以固定的周期重复。脉冲的宽度(也称为占空比)决定了信号在一个周期内的开启时间比例。通过改变占空比,我们可以调整设备的亮度或速度。

在这里插入图片描述
例如,考虑一个LED灯。当脉冲信号处于高电平状态时,LED灯会亮起;当脉冲信号处于低电平状态时,LED灯会熄灭。如果我们增加脉冲信号处于高电平状态的时间,即增加占空比,LED灯就会更亮。反之,如果减少脉冲信号处于高电平状态的时间,即减小占空比,LED灯就会变暗。
在这里插入图片描述

通过快速调整脉冲信号的宽度,PWM技术可以精确控制设备的亮度或速度,无论是LED灯、电机还是其他设备。这种技术在嵌入式系统和物联网应用中非常常见,因为它简单而高效,能够满足各种控制需求。

大家可以看下面这篇文章来学习如何理解和计算pwm的占空比:【单片机概念基础】迟迟搞不懂预分频系数、PWM占空比等等概念和计算怎么办?
其中pwm的频率就是pwm的周期

二、pwm的使用

2.1 LEDC定时器结构体

结构体介绍

如果你想使用pwm,需要先初始化一个定时器用于输出ledc_timer_config_t,他的定义如下:

typedef struct {
    ledc_mode_t speed_mode;                /*!< LEDC speed speed_mode, high-speed mode or low-speed mode */
    union {
        ledc_timer_bit_t duty_resolution;  /*!< LEDC channel duty resolution */
        ledc_timer_bit_t bit_num __attribute__((deprecated)); /*!< Deprecated in ESP-IDF 3.0. This is an alias to 'duty_resolution' for backward compatibility with ESP-IDF 2.1 */
    };
    ledc_timer_t  timer_num;               /*!< The timer source of channel (0 - 3) */
    uint32_t freq_hz;                      /*!< LEDC timer frequency (Hz) */
    ledc_clk_cfg_t clk_cfg;                /*!< Configure LEDC source clock.
                                                For low speed channels and high speed channels, you can specify the source clock using LEDC_USE_REF_TICK, LEDC_USE_APB_CLK or LEDC_AUTO_CLK.
                                                For low speed channels, you can also specify the source clock using LEDC_USE_RTC8M_CLK, in this case, all low speed channel's source clock must be RTC8M_CLK*/
} ledc_timer_config_t;

speed_mode: LEDC的速度模式,可以是高速模式或低速模式。
他的取值如下:

typedef enum {
#if SOC_LEDC_SUPPORT_HS_MODE
    LEDC_HIGH_SPEED_MODE = 0, /*!< LEDC high speed speed_mode */
#endif
    LEDC_LOW_SPEED_MODE,      /*!< LEDC low speed speed_mode */
    LEDC_SPEED_MODE_MAX,      /*!< LEDC speed limit */
} ledc_mode_t;

duty_resolution: LEDC通道的占空比分辨率,用于设置PWM信号的精度。
PWM(脉冲宽度调制)信号的精度指的是在一个周期内对信号的分辨率或精确度。它表示了PWM信号在每个周期内可以表示多少个离散的取值。
信号精度的作用在于确定PWM信号在不同占空比下的分辨能力和精确度。一个具有较高精度的PWM信号可以提供更细粒度的控制,使得在不同占空比下可以实现更精确的电平控制。
以下是PWM信号精度的几个作用:
控制精度:信号精度越高,可以实现更精确的控制。例如,如果有一个8位的PWM信号,它可以提供256个离散的取值,而一个10位的PWM信号可以提供1024个离散的取值。因此,10位的PWM信号具有更高的控制精度。
平滑性:较高的信号精度可以提供更平滑的输出。通过增加PWM信号的精度,可以减小输出之间的步进程度,从而实现更平滑的变化。
输出分辨率:信号精度决定了PWM信号可以表达的不同离散电平的数量。较高的信号精度可以提供更多的输出分辨率,允许更精细的电平调节。
应用范围:一些应用需要较高的PWM信号精度,特别是在需要精确控制电机速度、LED亮度或音频信号等应用中。较高的信号精度可以提供更精确的输出来满足这些应用的要求。
总而言之,PWM信号的精度对于实现精确的电平控制和调节至关重要,它影响着输出的平滑性、控制精度和应用范围。选择合适的信号精度取决于具体应用的需求,以确保PWM信号能够满足所需的控制精度和精确度。

bit_num: 在ESP-IDF 3.0版本中已废弃。这是对’duty_resolution’的别名,为了向后兼容ESP-IDF 2.1而存在。
timer_num: 通道的计时器源,范围是0到3。
freq_hz: LEDC计时器的频率,以赫兹(Hz)为单位。
clk_cfg: 配置LEDC的时钟源。对于低速通道和高速通道,可以使用LEDC_USE_REF_TICKLEDC_USE_APB_CLKLEDC_AUTO_CLK指定时钟源。对于低速通道,还可以使用LEDC_USE_RTC8M_CLK指定时钟源,但此时所有低速通道的时钟源必须是RTC8M_CLK

配置定时器

我们可以使用下面这个函数配置定时器:

esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf)

他的参数只需要使用ledc_timer_config_t的指针而已

2.2 配置LEDC通道

结构体介绍

如果你想使用pwm,你需要使用这个结构体ledc_channel_config_t,他的定义如下:

typedef struct {
    int gpio_num;                   /*!< the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16 */
    ledc_mode_t speed_mode;         /*!< LEDC speed speed_mode, high-speed mode or low-speed mode */
    ledc_channel_t channel;         /*!< LEDC channel (0 - 7) */
    ledc_intr_type_t intr_type;     /*!< configure interrupt, Fade interrupt enable  or Fade interrupt disable */
    ledc_timer_t timer_sel;         /*!< Select the timer source of channel (0 - 3) */
    uint32_t duty;                  /*!< LEDC channel duty, the range of duty setting is [0, (2**duty_resolution)] */
    int hpoint;                     /*!< LEDC channel hpoint value, the max value is 0xfffff */
} ledc_channel_config_t;

gpio_num: LEDC输出所连接的GPIO引脚号。例如,如果要使用GPIO16,则gpio_num = 16。
speed_mode: LEDC速度模式,可以是高速模式(LEDC_HIGH_SPEED_MODE)或低速模式(LEDC_LOW_SPEED_MODE)。
channel: LEDC通道号,范围为0到7,共8个通道可以用于LED控制。
他的定义如下:

typedef enum {
    LEDC_CHANNEL_0 = 0, /*!< LEDC channel 0 */
    LEDC_CHANNEL_1,     /*!< LEDC channel 1 */
    LEDC_CHANNEL_2,     /*!< LEDC channel 2 */
    LEDC_CHANNEL_3,     /*!< LEDC channel 3 */
    LEDC_CHANNEL_4,     /*!< LEDC channel 4 */
    LEDC_CHANNEL_5,     /*!< LEDC channel 5 */
#if SOC_LEDC_CHANNEL_NUM > 6
    LEDC_CHANNEL_6,     /*!< LEDC channel 6 */
    LEDC_CHANNEL_7,     /*!< LEDC channel 7 */
#endif
    LEDC_CHANNEL_MAX,
} ledc_channel_t;

intr_type: 中断类型配置,用于设置是否启用FADE中断。可以选择启用渐变中断(LEDC_INTR_FADE_EN)或禁用中断(LEDC_INTR_FADE_DIS)。
timer_sel: 选择通道的计时器源,范围为0到3,共有4个计时器可供选择。计时器用于确定PWM信号的频率。他需要和我们的ledc_timer_config_ttimer_num一致
duty: LEDC通道的占空比值,取值范围为0到(2^duty_resolution - 1)。占空比值表示了PWM信号在一个周期内处于高电平的时间比例,用于控制LED亮度或电机转速等。
hpoint: LEDC通道的高电平时间偏移值,最大值为0xfffff。此值用于设置PWM信号的高电平起始时间,通常用于同步多个LED或控制器。

初始化pwm

我们可以使用下面这个函数来初始化pwm结构体:

esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf)

参数仅仅是pwm的结构体的指针

2.3 设置占空比

设置占空比

我们可以使用下面这个函数设置占空比:

esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty);

参数一和二上面已经介绍过了,这个函数要和上面的设置的一致,参数3为占空比,要注意他的分辨率是多少,进而来设置他的值,比如10分辨率就是0~1024

更新占空比

我们可以使用下面这个函数来更新占空比:

esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel);

参数一和二上面已经介绍过了,这个函数要和上面的设置的一致

三、示例代码

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"

#define LEDC_HS_TIMER          LEDC_TIMER_0
#define LEDC_HS_MODE           LEDC_HIGH_SPEED_MODE
#define LEDC_HS_CH0_GPIO       (16)
#define LEDC_HS_CH0_CHANNEL    LEDC_CHANNEL_0
#define LEDC_TEST_DUTY         (4000)
#define LEDC_TEST_FADE_TIME    (3000)

void pwm_example()
{
    ledc_timer_config_t ledc_timer = {
        .duty_resolution = LEDC_TIMER_13_BIT, // 13-bit duty resolution
        .freq_hz = 5000,                      // PWM frequency
        .speed_mode = LEDC_HS_MODE,            // High-speed mode
        .timer_num = LEDC_HS_TIMER             // Timer index
    };
    
    // Set up PWM timer with the configuration
    ledc_timer_config(&ledc_timer);

    ledc_channel_config_t ledc_channel = {
        .gpio_num = LEDC_HS_CH0_GPIO,
        .speed_mode = LEDC_HS_MODE,
        .channel = LEDC_HS_CH0_CHANNEL,
        .intr_type = LEDC_INTR_DISABLE,
        .timer_sel = LEDC_HS_TIMER,
        .duty = 0,
        .hpoint = 0
    };

    // Set up PWM channel with the configuration
    ledc_channel_config(&ledc_channel);

    // Start PWM
    ledc_fade_func_install(ESP_INTR_FLAG_LEVEL1);

    while (1) {
        ledc_set_duty(ledc_channel.speed_mode, ledc_channel.channel, LEDC_TEST_DUTY);
        ledc_update_duty(ledc_channel.speed_mode, ledc_channel.channel);

        vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS);

        ledc_set_duty(ledc_channel.speed_mode, ledc_channel.channel, 0);
        ledc_update_duty(ledc_channel.speed_mode, ledc_channel.channel);

        vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS);
    }
}

void app_main()
{
    // Initialize the PWM
    ledc_init();

    // Create a task to run the PWM example
    xTaskCreate(pwm_example, "pwm_example", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
}

在这里插入图片描述


总结

本文介绍了ESP32 IDF中的PWM脉宽调制技术。通过利用ESP32的硬件模块支持,我们可以轻松实现高精度的PWM信号生成。PWM技术在许多应用中都有广泛的应用,例如LED亮度控制、电机速度调节等。ESP32 IDF提供了简单且灵活的API,方便开发者配置和控制PWM信号的频率、占空比等参数。通过合理的配置和使用,可以实现精确的信号调节,满足各种应用需求。

在实际应用中,根据具体需求选择合适的PWM引脚和参数配置,可以实现精确的信号控制和实时响应。同时,需要注意PWM信号的频率和占空比的设置,以满足具体应用的要求,并避免信号抖动和资源占用等问题。

通过掌握ESP32 IDF中的PWM脉宽调制技术,开发者可以灵活运用PWM功能,实现各种应用场景。ESP32强大的性能和丰富的功能使其成为嵌入式开发的理想选择。

希望本文对读者对ESP32 IDF中的PWM脉宽调制技术有初步了解,并能在实际开发中灵活运用。通过深入学习和实践,您可以进一步探索PWM技术的更多应用和优化方法。

如有任何疑问或进一步探讨,欢迎留言交流。谢谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/477126.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于yolov5的单目测距实现与总结+相机模型+标定

写这篇文章的目的是为了总结我之前看的标定&#xff0c;相机模型以及单目测距的内容&#xff0c;如果有错误&#xff0c;还请不吝赐教。 参考链接&#xff1a; 相机模型、相机标定及基于yolov5的单目测距实现 深度学习目标检测目标追踪单目测距 单目测距代码部署&#xff08;目…

Linux的基本使用

1.Linux的背景 1.1什么Linux Linux是⼀个操作系统.和Windows是"并列"的关系. 1.2Linux系统的优势 1. 开源(意味着免费,便宜) 2. 稳定(Linux可以运⾏很多年,都不会发⽣重⼤问题) 3. 安全(Linux只有管理员或者特定⽤⼾才能访问Linux内核) 4. ⾃由(不会被强加商业产品和…

点对点协议PPP(数据链路层)

目录 一、点对点协议PPP的特点 二、PPP协议的基本要求 三、PPP协议应满足的需求 四、PPP协议的组成 五、PPP同步传输和异步传输 六、PPP同步传输和异步传输 七、可靠传输问题 八、PPP协议的工作状态&#xff08;同步&#xff09; 九、小结 一、点对点协议PPP的特点 •…

Github 2024-03-21 Go开源项目日报 Top10

根据Github Trendings的统计,今日(2024-03-21统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目10HTML项目1Milvus: 云原生向量数据库与嵌入式相似性搜索 创建周期:1620 天开发语言:Go协议类型:Apache License 2.0Star数量:25568 …

2024.4.11-12中国汽车网络安全及数据安全合规峰

本次安策将在2024年4月11日-12日谈思AutoSec 8周年年会暨中国汽车网络安全及数据安全合规峰会现场展示相关产品&#xff0c;展位号A8&#xff0c;欢迎莅临参观交流。本次会议安策将带给大家汽车行业数据安全合规的最新应用案例。 汽车行业的数字化革命 为推动这场革命&#xff…

Redis进阶(持久化、复制、集群、多线程、缓存)

Redis进阶 1.Redis持久化1.1 什么是Redis持久化&#xff1f;为什么需要持久化&#xff1f;1.2 Redis持久化方式——RDB(Redis DataBase)1.2.1 什么是RDB&#xff1f;1.2.2 备份文件位置1.2.3 触发RDB的方式1.2.3.1 自动触发1.2.3.2 手动触发1.2.3.3 其他触发方式 1.2.4 RDB优缺…

DataEase大屏iframe嵌入自建网站(React)

1、修改dataease 所在的服务器nginx配置 server {listen 80;server_name dataease.ibaiqiu.cn;return 307 https://$host$request_uri; } server {listen 443 ssl;server_name dataease.ibaiqiu.cn;client_max_body_size 30M;ssl_certificate /usr/local/nginx/co…

旅游小程序开发的费用及功能

随着科技的发展和智能手机的普及&#xff0c;越来越多的行业开始利用小程序来进行线上服务。旅游业作为一个重要的服务业&#xff0c;也纷纷推出了自己的旅游小程序&#xff0c;以方便游客在线预订、查询景点信息等。那么&#xff0c;旅游小程序开发的费用是多少&#xff1f;功…

Linux系统编程(笔记)

1、认识计算机系统&#xff08;上&#xff09; 1.1、计算机系统由软硬件构成 1.2、总线 1.3、I/O设备 1.4、内存 1.5、处理器 1.6、计算机硬件组成 2、认识计算机系统&#xff08;下&#xff09; 2.1、什么是操作系统 2.2、Linux内核模块 2.3、操作系统管理硬件&#xff08;职…

OpenLayers基础教程——使用WebGL加载海量数据(1)

1、前言 最近遇到一个问题&#xff1a;如何在OpenLayers中高效加载海量的场强点&#xff1f;由于项目中的一些要求&#xff0c;不能使用聚合的方法加载。一番搜索之后发现&#xff1a;OpenLayers中有一个WebGLPoints类&#xff0c;使用该类可以轻松应对几十万的数据量&#xf…

鸿蒙一次开发,多端部署(三)应用UX设计原则

设计原则 当为多种不同的设备开发应用时&#xff0c;有如下设计原则&#xff1a; 差异性 充分了解所要支持的设备&#xff0c;包括屏幕尺寸、交互方式、使用场景、用户人群等&#xff0c;对设备的特性进行针对性的设计。 一致性 除了要考虑每个设备的特性外&#xff0c;还…

【CSS】flex弹性盒保持均分

通过Flex布局可以将容器均分&#xff0c;给每个小容器设置相同的flex-grow即可。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge">&…

白话讲人工智能、机器学习、深度学习

人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09; 定义&#xff1a; 想象一个聪明的机器人&#xff0c;它能思考、决策和学习&#xff0c;就像电影里的智能角色那样。人工智能就是努力打造这样的智能实体的学科&#xff0c;它试图模仿、扩展乃至超越人…

【精彩回顾】百度智能云千帆产品3月21日发布会

3月21日&#xff0c;AI Cloud Day&#xff1a;百度智能云千帆产品发布会在北京举办。会议聚焦百度智能云千帆大模型平台最新进展&#xff0c;分享思考与实践。百度智能云在发布会期间宣布&#xff1a; >>满足企业“效价比”核心诉求&#xff0c;千帆ModelBuilder大模型服…

Android Studio实现内容丰富的安卓校园助手班级成绩天气管理

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动 1.开发环境 android stuido3.6 jak1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.校园公告 3.课程列表 4.成绩列表&#xff0c;天气列表 5.个人中心…

【JS】JavaScript 中的原型与原型链

JavaScript 中的原型与原型链 原型1 函数中 prototype 指向原型对象2 对象中 __proto__ 指向原型对象3 原型对象中 constructor 指向构造函数4 __proto__ 与 [[Prototype]] 的关系5 所有非空类型数据&#xff0c;都具有原型对象6 new运算符做了哪些事情 原型链1 举个栗子1.1 直…

UI自动测试框架-selenium(1) selenium介绍和选择器

目录 1.selenium是什么 2.定位元素 2.1 css选择器 2.1.1 选择id 2.1.2 class 2.1.3使用标签选择 2.1.4父类选择器 子类选择器 2.2 xpath 1.selenium是什么 selenium是用来做web端自动化测试的框架,它支持各种游览器,各种平台,支持各种语言(如 Python,Java,C#,JS,Ruby..…

elementUI(Vue2)和elementPlus(Vue3)图标icon差异

Vue2用法 <i class"el-icon-edit"></i><el-button type"primary" icon"el-icon-search">搜索</el-button> Vue3用法 <!-- 使用 el-icon 为 SVG 图标提供属性 --> <template><div><el-icon :siz…

神经网络梯度下降优化参数

损失函数 神经网络的最终目的就是最小化损失函数的过程&#xff0c;损失函数越小&#xff0c;证明模型的预测值就越接近真实值。 梯度下降算法 为了最优化损失函数&#xff0c;开发了梯度下降算法&#xff0c;这里的梯度就是高等数学中的梯度。 误差反向传播算法 前向传播…

螺旋卫星通信天线设计与有限元分析matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 卫星搭载用于通讯的螺旋型天线&#xff0c;卫星尺寸&#xff1a; 10cm*10cm*30cm&#xff1b;天线类型&#xff1a;螺旋&#xff1b;天线UHF&#xff08;约1GHz – 3GHz&#…