使用AVR单片机驱动舵机

发布者:花海鱼最新更新时间:2020-01-03 来源: eefocus关键字:AVR单片机  驱动舵机  控制信号 手机看文章 扫描二维码
随时随地手机看文章

1.舵机驱动的基本原理

  (可以参考http://blog.sina.com.cn/s/blog_8240cbef01018hu1.html)

  "控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压。它内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。最后,电压差的正负输出到电机驱动芯片决定电机的正反转。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动。"

简单的来讲,就是输出一个周期为20Ms,不同的占空比对应舵机转过不同的角度。

难点主要在于

  • 舵机控制信号需要保持,这样就比用脉冲控制步进电机要复杂一些。

  • 你需要保持多路PWM,并且要随时调节占空比来获得要求的角度

2.实现思路

网上有用工作在相频修正PWM模式下的T1来产生信号,这样虽然十分精确,然而并不太好实现多路控制.(至少我是没想出来,如果有高手知道怎么做,还望多多指教)

我决定采用以下方法:

  • 将 20ms 等分成240份,这样一份是20000/240 us //分成240份的原因是这样可以算出整数值得TCNT1

  • 将T1配置为溢出中断模式,每20000/240 us溢出一次

  • 中断服务程序更新TCNT1的值,维护一组变量,产生信号。

这样做的优点是方便了多路控制。虽然我只控制了四路舵机,稍加修改就可以控制更多..

然而中断服务程序中维护变量时,产生的微小误差会累加,这样不可避免的会产生较大误差。直接采用计算值肯定不行,最后需要修正。

3.代码

代码还是相当的不成熟...愿各位高手多多指教.

通过传入一个指针给Servo_AngelPWM实现四个舵机的角度控制


#include

#include

#ifndef SERVO_CONTROL_H

#define SERVO_CONTROL_H

#define Servo1  PB7

#define Servo1_1 PORTB|=_BV(Servo1)

#define Servo1_0 PORTB&=~_BV(Servo1)

#define Servo2  PB6

#define Servo2_1 PORTB|=_BV(Servo2)

#define Servo2_0 PORTB&=~_BV(Servo2)

#define Servo3  PB5

#define Servo3_1 PORTB|=_BV(Servo2)

#define Servo3_0 PORTB&=~_BV(Servo2)

#define Servo4  PB4

#define Servo4_1 PORTB|=_BV(Servo2)

#define Servo4_0 PORTB&=~_BV(Servo2)

#define to_us(x) (((x/180.0)*2.0+0.5)*1000)

uint32_t Servo_Flag[4];

uint32_t Servo_Cflag=0;

void Servo_AngelPWM(char *angel)

{

    for(int i=0;i<4;i++)

        Servo_Flag[i]=to_us(angel[i])*3/250;

    TIMSK|=_BV(TOIE1);//开启TC1中断 

}

ISR(TIMER1_OVF_vect)

{

    TIMSK&=~_BV(TOIE1);//关闭TC1中断               //1

    TCNT1=64525;//65535-(1000+10)这个10加的有讲究 //3

    Servo_Cflag++;                                  //4

    if(Servo_Cflag>=239)                          //5

    {

        Servo1_1;

        Servo2_1;

        Servo3_1;

        Servo4_1;

        Servo_Cflag=0;

    }

    else if(Servo_Flag[0]==Servo_Cflag)Servo1_0;  //6

    else if(Servo_Flag[1]==Servo_Cflag)Servo2_0;  //7

    else if(Servo_Flag[2]==Servo_Cflag)Servo3_0;  //8

    else if(Servo_Flag[3]==Servo_Cflag)Servo4_0;  //9

    TIMSK|=_BV(TOIE1);//开启TC1中断                //10

}

#endif


4.后记

给TCNT1赋计算值,也就是65535-1000=64525时,产生的信号大约是47HZ。如我所料,准确性比较差。


然后尝试根据分析语句来修正TCNT1的初值,可以从我的注释看出...修正完后大约是48hz,还是不太准。


最后直接上示波器微调了...当TCNT1为64569(修正值34)时,如上图,产生了比较准确的驱动信号(45度和90度)。


(所以说学会汇编还是很重要的...有时间一定要研究研究)

关键字:AVR单片机  驱动舵机  控制信号 引用地址:使用AVR单片机驱动舵机

上一篇:AVR 嵌入式单片机芯片的中断系统介绍
下一篇:[AVR]使用Gcc编译时各种数据的长度

小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved