[AVR]使用AVR单片机驱动舵机
最近参加了三系举办的小车比赛(好像叫什么"驭远杯")。领导要求我驱动3-4个舵机。研究了几日,总算折腾出一个方案..、
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 <util/delay.h> #include <stdint.h> #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中断 //1TCNT1=64525;//65535-(1000+10)这个10加的有讲究 //3Servo_Cflag++; //4if(Servo_Cflag>=239) //5 {Servo1_1;Servo2_1;Servo3_1;Servo4_1;Servo_Cflag=0;}else if(Servo_Flag[0]==Servo_Cflag)Servo1_0; //6else if(Servo_Flag[1]==Servo_Cflag)Servo2_0; //7else if(Servo_Flag[2]==Servo_Cflag)Servo3_0; //8else if(Servo_Flag[3]==Servo_Cflag)Servo4_0; //9TIMSK|=_BV(TOIE1);//开启TC1中断 //10 } #endif
4.后记
给TCNT1赋计算值,也就是65535-1000=64525时,产生的信号大约是47HZ。如我所料,准确性比较差。
然后尝试根据分析语句来修正TCNT1的初值,可以从我的注释看出...修正完后大约是48hz,还是不太准。
最后直接上示波器微调了...当TCNT1为64569(修正值34)时,如上图,产生了比较准确的驱动信号(45度和90度)。
(所以说学会汇编还是很重要的...有时间一定要研究研究)
转载于:https://www.cnblogs.com/cn-lhc/p/5997855.html
[AVR]使用AVR单片机驱动舵机相关推荐
- 单片机输出脉冲的C语言简易程序,AVR单片机驱动二相步进电机(单极驱动)简易程序,带串口控制...
AVR单片机驱动二相步进电机(单极驱动)简易程序,带串口控制. 编译器为ICC6.31A; #include"iom16v.h" #include"macros.h&qu ...
- Micropython教程之TPYBoard开发板驱动舵机教程(萝卜学科编程教育)
2019独角兽企业重金招聘Python工程师标准>>> 大家应该都看到过机器人的手臂啊腿脚啊什么的一抽一抽的在动弹吧...是不是和机械舞一样的有节奏,现在很多机器人模型里面的动力器件 ...
- STM32CuBeMX驱动舵机
舵机 舵机(Servo),由直流电机.减速齿轮组.传感器和控制电路组成的一套自动控制系统.其控制方式为PWM控制,通过调节控制信号的占空比来实现舵机转动指定角度. 舵机控制 驱动舵机的PWM信号周期需 ...
- 基于51单片机密码锁-舵机开锁-CXM
这个项目的起因还是因为每次进出寝室十分的麻烦才有了这个项目 所以我和我的铁子就决定搞个密码锁 我负责软件我的铁子负责硬件 目录 原理图 主要功能函数讲解 硬件 先简单介绍一下整个架构 原理图 主要功能 ...
- 单片机驱动DM9000网卡芯片(详细调试过程)【下】
http://hi.baidu.com/mcu8031/blog/item/c95903138671c625dc540171.html 单片机驱动DM9000网卡芯片(详细调试过程)[下] 4.验证初 ...
- 单片机led闪烁代码_单片机驱动LED发光二极管的电路以及编程
一.单片机驱动单个发光二极管 1.电路 代码: 1.点亮单个LED二极管 #include<reg51.h> sbit LED1=P1^0:void main(void){LED1=1:w ...
- Linux驱动(3)--单片机驱动与Linux驱动的区别
单片机驱动与Linux驱动的区别 1. MCU与MPU的区别 2. 单片机驱动与Linux驱动的区别 1. MCU与MPU的区别 首先我们先聊一下MCU与MPU之间的区别然后在去关心两者的驱动的不同. ...
- 控制led闪烁次数_单片机驱动LED灯的进阶之路
对于大多数单片机的学习者或者是从事单片机行业的工程师来说,单片机驱动LED闪烁起来的时候,基本都是我们入坑的开始,同时当时的那种兴奋与喜悦都是难以忘怀的,从LED灯亮起,到闪烁,再到各种流水灯,能开心 ...
- K_A08_004 基于 STM32等单片机驱动MX1919模块按键控制直流电机正反转加减速启停
目录 一.资源说明 二.基本参数 1.参数 2.引脚说明 三.驱动说明 1.MX1919模块驱动时序 2.对应程序: 3.PWM信号 四.部分代码说明 接线说明 1.STC89C52RC+MX1919 ...
最新文章
- 二分 + 模拟 - Carries
- 如何使用jQuery检查单选按钮?
- 后门构建工具Backdoor Factory
- javax.validation.ParameterNameProvider
- ndr4108贴片晶振是多少频率_关于山羊挺身你知道多少?这些干货速来了解一下...
- Codeforces Round #371 (Div. 2) C. Sonya and Queries —— 二进制压缩
- AtCoder Regular Contest 088
- pmp全真模拟题100道(含答案)
- 海康威视摄像头web端播放
- 以DMA方式开启DAC输出正弦波
- linux oel7没有网络,sudo su命令不在OEL 7中工作(sudo su command not working in OEL 7)
- QQ截图时窗口自动识别的原理
- canvas绘制飞线效果
- java 7新特性-TWR(Try-with-resources)
- catchlog是什么软件_如何处理异常? catch Exception OR catch Throwable
- python中data是什么意思_C++中cv::Mat中的data属性对应在python中是什么
- 中国煤矿机械行业市场动态调研及未来发展方向分析报告2022-2028年
- Tableau Prep经验总结
- vue中使用quill富文本编辑器
- 计算机与科学技术暑期社会实践,2018年暑期社会实践活动|计算机科学技术学院、软件学院...