关于如何用单片机控制多个舵机转速以及来回缓慢转动的...-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 19353|回复: 0

[过期] 关于如何用单片机控制多个舵机转速以及来回缓慢转动的...

[复制链接]
发表于 2013-10-30 22:24 | 显示全部楼层 |阅读模式
本帖最后由 天星1979379768 于 2016-8-20 13:55 编辑

我想用单片机控制多个舵机的转速(不用延时的办法,因为我用同时控制多个舵机的运转,加延时只能控制一个舵机的转速了),同时让舵机来回转动,想法是用IO口输出简单可变PWM脉宽,通过细分PWM脉宽值的方法控制舵机转速(即把一个大的预期角度分成几个小的角度,舵机每转一个小的角度需20ms的时间,5个小的角度就是100ms了),但是遇到个问题:舵机在完成一个预定角度的转动时需要一定的时间,我想要在舵机转完上一个预定的角度后马上改变PWM值让舵机从当前位置转到下一个预期角度,该怎么做?AVR mega32的芯片。下面是想法,延时语句(红色字体部分)是想让舵机转完预期角度,但是舵机在转动过程中有一定的停顿时间(延时的时间是算好的,将预定脉宽值细分成5份,每份执行时间20ms,总共100ms),请问该怎么改?

#include <mega32.h>
#include <delay.h>

#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

#define SERVO PORTA.1        //PWM信号输出端口
#define CENTER 30            //舵机归中数值
uint pwm,cpwm,lpwm;          //预期pwm值,上一个pwm值,当前pwm值
int num=0,sdate=0;           //sdate为脉宽增量值,num用做定时器计数

interrupt [TIM1_OVF] void timer1_ovf_isr(void)//定时器中断溢出函数
{
    TCNT1H=(65536-800)/256;  //定时器1每隔50us溢出一次
    TCNT1L=(65536-800)%256;
    num++;
    sdate=(pwm-lpwm)/5; //得到pwm脉宽微小增量值,将预定pwm脉宽细分,增加转动时间
    if(num<cpwm)
    {
        SERVO=1;             //IO口电平反转,产生舵机控制信号
    }         
    else
    {
        SERVO=0;
    }   
    if(num==400)             //产生周期为20ms舵机控制信号
    {
        num=0;
        if(cpwm!=pwm)
        {
            cpwm=cpwm+sdate; //将当前脉宽值增加微小增量,产生新的PWM脉宽控制信号
        }
    }
}

void main(void)
{
    DDRA=0xff;               //端口初始化
   
    TCCR1B=0x01;             //16MHz时钟频率
    TCNT1H=(65536-800)/256;  //定时器1寄存器初始化
    TCNT1L=(65536-800)%256;  //定时器每隔50us溢出一次
    TIMSK=0x04;

    #asm("sei")              //全局中断使能
   
    cpwm=CENTER;             //当前脉宽值初始化
    lpwm=CENTER;             //上一次脉宽值初始化
    while (1)
    {
        pwm=30;          //第一个预定PWM脉宽值,舵机位置归中
        delay_ms(110);   //等待舵机缓慢转动预定位置
        lpwm=pwm;   //记录上一PWM脉宽值,从而让舵机从当前位置缓慢转到下一个位置
        pwm=40;         //第二个预定PWM脉宽值,舵机从归中位置转到+45度方向
        delay_ms(110);   //等待舵机缓慢转动预定位置
        lpwm=pwm;  //记录上一PWM脉宽值,从而让舵机从当前位置缓慢转到下一个位置
        pwm=50;         //第三个预定PWM脉宽值,舵机从归中位置转到+90度方向
        delay_ms(110);   //等待舵机缓慢转动预定位置
        lpwm=pwm;  //记录上一PWM脉宽值,从而让舵机从当前位置缓慢转到下一个位置
    }
}

下面是我的一个尝试的思路,用标志位,但是还是不起作用

#include <mega32.h>
#include <delay.h>

#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

#define LED PORTA.0
#define SERVO PORTA.1        
//PWM信号输出端口

#define CENTER 30            //舵机归中数值
uchar flag=0;                //舵机执行下一个动作标志位
uint pwm,cpwm,lpwm;          //预期pwm值,上一个pwm值,当前pwm值
int num=0,sdate=0;           
//sdate为脉宽增量值,num用做定时器计数

interrupt [TIM1_OVF] void timer1_ovf_isr(void)//定时器中断溢出函数
{
    TCNT1H=(65536-800)/256;  //定时器1每隔50us溢出一次
    TCNT1L=(65536-800)%256;
    num++;
    sdate=(pwm-lpwm)/5;      //得到pwm脉宽微小增量值,将预定pwm脉宽细分,增加转动时间
    if(num<cpwm)
    {
        SERVO=1;             //IO口电平反转,产生舵机控制信号
    }         
    else
    {
        SERVO=0;
    }   
    if(num==400)             //产生周期为20ms舵机控制信号
    {
        num=0;
        if(cpwm!=pwm)
        {
            cpwm=cpwm+sdate; //将当前脉宽值增加微小增量,产生新的PWM脉宽控制信号
        }
        else
        {
            flag++;  //表明当前角度已经转完,准备转下一个角度
            lpwm=pwm;//记录上一PWM脉宽值,从而让舵机从当前位置缓慢转到下一个位置
            if(flag>=3)
            {
                flag=0;
            }
        }
    }
}

void main(void)
{
    DDRA=0xff;               //端口初始化
   
    TCCR1B=0x01;             //16MHz时钟频率
    TCNT1H=(65536-800)/256;  //定时器1寄存器初始化
    TCNT1L=(65536-800)%256; //定时器每隔50us溢出一次
    TIMSK=0x04;

    cpwm=CENTER;             //当前脉宽值初始化
    lpwm=CENTER;             //上一次脉宽值初始化
    #asm("sei")              
//全局中断使能

    while (1)
    {         
        switch(flag)
        {
            case 0: pwm=50;  //第一个预定PWM脉宽值,舵机位置归中   
                    LED=1;
                    break;
            case 1: LED=0;
                    pwm=30; //第二个预定PWM脉宽值,舵机从归中位置转到+45度                  
                    break;
            case 2:                  
                    pwm=40; //第三个预定PWM脉宽值,舵机从归中位置转到+90度方向
                    break;
            default: break;
        }
    }
}



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-12-4 16:09 , Processed in 0.069360 second(s), 16 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表