【ESP32 IDF PWM驱动SG90】

IDF乐鑫驱动 SG90

PWM

在这里插入图片描述
在这里插入图片描述

LEDC

LED 控制器 (LEDC) 主要用于控制 LED,也可产生 PWM 信号用于其他设备的控制。该控制器有 8 路通道,可以产生独立的波形,驱动 RGB LED 等设备。

LEDC 通道共有两组,分别为 8 路高速通道和 8 路低速通道。高速通道模式在硬件中实现,可以自动且无干扰地改变 PWM 占空比。低速通道模式下,PWM 占空比需要由软件中的驱动器改变。每组通道都可以使用不同的时钟源。

LED PWM 控制器可在无需 CPU 干预的情况下自动改变占空比,实现亮度和颜色渐变。

设置 LEDC 通道在 高速模式或低速模式 下运行,需要进行如下配置:

  • 定时器配置 指定 PWM 信号的频率和占空比分辨率。

  • 通道配置 绑定定时器和输出 PWM 信号的 GPIO。

  • 改变 PWM 信号 输出 PWM 信号来驱动 LED。可通过软件控制或使用硬件渐变功能来改变 LED 的亮度。

在这里插入图片描述
要设置定时器,可调用函数 ledc_timer_config(),并将包括如下配置参数的数据结构 ledc_timer_config_t 传递给该函数:

  • 速度模式 ledc_mode_t

  • 定时器索引 ledc_timer_t

  • PWM 信号频率(Hz)

  • PWM 占空比分辨率

  • 时钟源 ledc_clk_cfg_t

频率和占空比分辨率相互关联。PWM 频率越高,占空比分辨率越低,反之亦然。如果 API 不是用来改变 LED 亮度,而是用于其它目的,这种相互关系可能会很重要。更多信息详见 频率和占空比分辨率支持范围 一节。

时钟源同样可以限制 PWM 频率。选择的时钟源频率越高,可以配置的 PWM 频率上限就越高。
在这里插入图片描述
如果不知道用什么时钟源,可以选择:LEDC_AUTO_CLK 自动选择时钟源

LEDC 驱动提供了一个辅助函数 ledc_find_suitable_duty_resolution()。传入时钟源频率及期望的 PWM 信号频率,这个函数可以直接找到最大可配的占空比分辨率值。

当一个定时器不再被任何通道所需要时,可以通过调用相同的函数 ledc_timer_config() 来重置这个定时器。此时,函数入参的配置结构体需要指定:

  • ledc_timer_config_t::speed_mode 重置定时器的所属速度模式 (ledc_mode_t)

  • ledc_timer_config_t::timer_num 重置定时器的索引 (ledc_timer_t)

  • ledc_timer_config_t::deconfigure 将指定定时器重置必须配置此项为 true

在这里插入图片描述
在这里插入图片描述

代码驱动Sg90

main.c

/*
 * @Author: i want to 舞动乾坤
 * @Date: 2024-07-23 18:30:30
 * @LastEditors:  i want to 舞动乾坤
 * @LastEditTime: 2024-07-23 18:50:35
 * @FilePath: \pwm_sg90\main\main.c
 * @Description: 
 * 
 * Copyright (c) 2024 by ${i want to 舞动乾坤}, All Rights Reserved. 
 */
#include <stdio.h>
#include "sg90.h"
#include "freeRtos/FreeRTOS.h"

#include "freertos/task.h"
void app_main(void)
{
    sg90_init();
    sg90_SetAngle(0);//归0
    vTaskDelay(1000/portTICK_PERIOD_MS);

    sg90_SetAngle(60);//旋转60度
    vTaskDelay(1000/portTICK_PERIOD_MS);
    sg90_SetAngle(0);//旋转到0
    vTaskDelay(1000/portTICK_PERIOD_MS);
    sg90_SetAngle(180);//旋转到180度
    while (1)
    {
        /* code */

        
    }

}


sg90.c

/*
 * @Author: i want to 舞动乾坤
 * @Date: 2024-07-23 18:30:26
 * @LastEditors: i want to 舞动乾坤
 * @LastEditTime: 2024-07-23 18:53:13
 * @FilePath: \pwm_sg90\main\sg90.c
 * @Description: sg90舵机驱动代码
 * 
 * Copyright (c) 2024 by i want to 舞动乾坤, All Rights Reserved. 
 */

#include <freeRtos/FreeRTOS.h>
#include <driver/ledc.h>
#include <driver/gpio.h>
#include <freeRtos/task.h>
#define sg90_pin GPIO_NUM_23//信号线的引脚
#define sg90_freq_hz (50)//sg90频率
#define sg90_timer0 LEDC_TIMER_0//定时器0
#define sg90_timer_channel LEDC_CHANNEL_0 //通道0
#define sg90_speedMode LEDC_LOW_SPEED_MODE//低速模式
//为了符合 0.5ms~2.5ms的脉宽  将500~2500 映射到 0度~180度 
#define sg90_min_pulse_width_us 500 //映射到500 的最小脉冲宽度 
#define sg90_max_pulse_width_us 2500//映射到2500的最大脉冲宽度 

/**
 * @description: sg90初始化
 * @param 无
 * @return {*}
 */
void sg90_init()
{
    ledc_timer_config_t ledc_timer_InitStructure=
    {
        .clk_cfg = LEDC_AUTO_CLK,     //自动选择时钟
        .duty_resolution=LEDC_TIMER_13_BIT,//13bit位分辨率
        .freq_hz=sg90_freq_hz,//50hz     T=1/50 =0.02s =20ms 周期
        .speed_mode=sg90_speedMode,//模式位低速模式
        .timer_num=sg90_timer0//使用定时器0
    };
    ledc_timer_config(&ledc_timer_InitStructure);


    ledc_channel_config_t ledc_channel_InitStructure=
    {
        .channel=sg90_timer_channel,//通道0
        .duty=0,//占空比 后面可以再设置 范围:0~ 2^13 -1
        .gpio_num=sg90_pin,
        .hpoint=0,
        .intr_type=LEDC_INTR_DISABLE,//中断使能关闭
        .speed_mode=sg90_speedMode,//低速模式
        .timer_sel=sg90_timer0//定时器 0
    };

    ledc_channel_config(&ledc_channel_InitStructure);
}


/**
 * @description: 设置sg90占空比
 * @param: duty 设置的占空比 范围:0~(2^13) -1
 * @return {*}
 */
void sg90_SetDuty(uint32_t duty)
{
    ledc_set_duty(sg90_speedMode,sg90_timer_channel,duty);
    ledc_update_duty(sg90_speedMode,sg90_timer_channel);
}


/**
 * @description: 设置sg90转动的角度
 * @param: angle 角度 范围:0~180
 * @return {*}
 */
void sg90_SetAngle(float angle)
{
    uint16_t pulse_width_us=0;
    uint32_t duty;
    if(angle>180){angle=180;}
    else if(angle<0){angle=0;}
    //计算过程:0度 对应 500us  180度 对应 2500us  即线性关系 y=kx+b  ,代入 (x=0,y=500)以及(x=180,y=2500)  求解k 和 b ,由传来的参数angle得到最终映射的带宽us数
    pulse_width_us=(sg90_min_pulse_width_us+(sg90_max_pulse_width_us-sg90_min_pulse_width_us)*(angle /180));//将0度和180度映射到 500~2500的脉冲上,返回的结果为高电平持续的时间:单位us
    //占空比= 高电平持续时间 (ps:单位转换为s  1s=10^6us) / 一个周期的时间(1/sg90_freq_hz) (ps单位:秒) 

    //高电平持续时间 =pulse_width_us ,一个周期的时间 (1/sg90_freq_hz)     pulse_width_us*10^-6/(1/sg90_freq_hz) *=pulse_width_us *sg90_freq_hz /10^6(1e6)
   //为什么要乘以 1<<13 -1 即 8192呢,因为13位的分辨率 需要将计算得到的占空比值缩放至 0 到 (1<<13) - 1 的范围内。
    duty=pulse_width_us *sg90_freq_hz *((1<<13)-1)/ 1e6;
    sg90_SetDuty(duty);//设置占空比

}

sg90.h

#ifndef _SG90__H
#define _SG90__H
void sg90_init();
void sg90_SetAngle(float angle);
#endif

目录结构
在这里插入图片描述
完结撒花————————————————————————————

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

i want to舞动乾坤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值