使用PWM的正占空比控制舵机转动

1.舵机:常见的角度控制外设,通常在机器人、航模等产品上比较常见,外观如下:

2.驱动原理:通过输出固定周期为20ms的PWM波形驱动舵机,其中正占空比(0.5~2.5ms)决定舵机的转动的角度为-90°到90°

  

3.舵机硬件原理:

   

4.外设接线图

舵机单片机
黑线GND
红线VCC(+5)
黄线PWM输出控制IO

5.参考代码(基于nRF 52840)

#define BSP_PWM_IO 12
static void demo1(void)
{
    NRF_LOG_INFO("Demo 1/ 0.5ms 0du");

    /*
     * This demo uses only one channel, which is reflected on LED 1.
     * The LED blinks three times (200 ms on, 200 ms off), then it stays off
     * for one second.
     * This scheme is performed three times before the peripheral is stopped.
     */

    nrf_drv_pwm_config_t const config0 =
    {
        .output_pins =
        {
            BSP_PWM_IO,                           // channel 0
            NRF_DRV_PWM_PIN_NOT_USED,             // channel 1
            NRF_DRV_PWM_PIN_NOT_USED,             // channel 2
            NRF_DRV_PWM_PIN_NOT_USED,             // channel 3
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
        .base_clock   = NRF_PWM_CLK_250kHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = 5000,
        .load_mode    = NRF_PWM_LOAD_COMMON,
        .step_mode    = NRF_PWM_STEP_AUTO
    };
    APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
    m_used |= USED_PWM(0);

    // This array cannot be allocated on stack (hence "static") and it must
    // be in RAM (hence no "const", though its content is not changed).
    static uint16_t /*const*/ seq_values[] =
    {
        4375
    };

    nrf_pwm_sequence_t const seq =
    {
        .values.p_common = seq_values,
        .length          = NRF_PWM_VALUES_LENGTH(seq_values),
        .repeats         = 0,
        .end_delay       = 0
    };

    (void)nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRF_DRV_PWM_FLAG_LOOP);
}

说明:

设置固定周期为20ms

基础时钟为250KHz,那么基础时钟周期为1s/250*1000 = 1000ms / 250000Hz =0.004ms

.base_clock   = NRF_PWM_CLK_250kHz,

如果需要设置PWM的周期为20ms,那么需要设置 20ms/0.004ms = 5000

.top_value    = 5000,

设置正占空比,由于Nordic默认设置的是负占空比,需要转换(A是设置的正占空比的时间,B是我们需要设置的seq_values的值):

A/20 = (5000-B)/5000

比如需要设置舵机转到90°,对应的正占空比时间为2.5ms,即A = 2.5,那么B应该是4375,即

static uint16_t /*const*/ seq_values[] =
{
   4375
};

 

  • 16
    点赞
  • 103
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的使用AVR单片机控制舵机转动,并使用按键控制PWM占空比的程序示例,使用的是ATmega16单片机和PD5口作为PWM输出口,PB0口作为按键输入口。 ``` #include <avr/io.h> #include <util/delay.h> #define PWM_DDR DDRD #define PWM_PORT PORTD #define PWM_PIN 5 #define KEY_DDR DDRB #define KEY_PORT PORTB #define KEY_PIN PINB #define KEY_BIT 0 void pwm_init(void) { // 配置定时器1为PWM模式,使用非反转模式 TCCR1A |= (1 << COM1A1) | (1 << WGM11) | (1 << WGM10); TCCR1B |= (1 << WGM13) | (1 << WGM12); // 配置定时器1时钟源为系统时钟的1/8 TCCR1B |= (1 << CS11); // 设置PWM输出引脚为输出模式 PWM_DDR |= (1 << PWM_PIN); } void key_init(void) { // 设置按键输入引脚为输入模式,上拉电阻使引脚默认为高电平 KEY_DDR &= ~(1 << KEY_BIT); KEY_PORT |= (1 << KEY_BIT); } int main(void) { uint16_t pwm_duty = 1000; uint16_t pwm_period = 20000; uint8_t key_pressed = 0; pwm_init(); key_init(); while (1) { // 检测按键是否按下,如果按下则调整PWM占空比 if ((KEY_PIN & (1 << KEY_BIT)) == 0) { _delay_ms(10); // 延时去抖 if ((KEY_PIN & (1 << KEY_BIT)) == 0) { key_pressed = 1; pwm_duty += 100; if (pwm_duty > pwm_period) { pwm_duty = 1000; } } } else { key_pressed = 0; } // 设置PWM占空比 OCR1A = pwm_duty; // 等待一段时间,使舵机旋转到目标角度 _delay_ms(50); } } ``` 在这个程序中,我们首先定义了PWM输出口和按键输入口的引脚号,然后在 `pwm_init()` 函数中配置了定时器1为PWM模式,并将PWM输出引脚设置为输出模式。在 `key_init()` 函数中将按键引脚设置为输入模式并上拉电阻。 在 `main()` 函数中,我们通过一个循环来不断检测按键是否按下,并根据按键状态调整PWM占空比。当按键被按下时,我们将PWM占空比加上100,并将其限制在PWM周期内。然后将这个占空比值写入OCR1A寄存器中,即可控制舵机转动角度。 最后,为了让舵机旋转到目标角度,我们在每次设置新的PWM占空比后等待一段时间,这个时间可以根据具体的舵机转速和惯性来调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值