一个基于ATMEGA128的直流电机抱死程序

发布者:Alisallll最新更新时间:2016-12-30 来源: eefocus关键字:ATMEGA128  直流电机  抱死程序 手机看文章 扫描二维码
随时随地手机看文章

    先说一下我的硬件情况:一块ATMEGA128实验板;一个带编码器的80:1的变速电机,编码器的输出端连接到单片机的PD4和PD5引脚;一块电机驱动电路,该电路的输入为:24v电源、两路pwm信号输入,输出即为电机的正负极,要用该电路来驱动电机,则必须让两路pwm输入信号的一路占空比为0,另一路不为0,相当于让电机的一极接地,另一极接pwm,通过控制两路pwm的占空比来控制电机的转速和转动方向。pwm信号的输入端连接到单片机的PD6和PD7引脚。

    下面是我的程序的设计思路: 这个程序用了两个定时器:timer0和timer1。

    timer0用来产生pwm。timer0产生pwm信号是这样实现的:程序中有一个timer0的溢出事件计数器,和两个保存两路pwm信号占空比的变量,当timer0溢出事件计数器计数超过100时,如果某个pwm信号占空比不为0,则把相应pwm引脚置高电平,同时清零此计数器,当此计数器等于某个占空比时,则把相应引脚置低电平,从而实现timer0溢出事件计数器从0计数到100时输出一个周期的pwm信号。通过调节timer0的溢出频率,即可调节pwm信号输出的频率。 

     timer1用来对编码器的输出进行计数,同时调整pwm的占空比,实现对电机的控制。对编码器的输出计数是利用了timer1的输入捕捉功能,由于电机可以正转,也可以反转,导致编码器的CHA和CHB的输出也不同,所以可以在程序中可以判断电机是正转还是反转,再对编码器的输出脉冲进行计数,当电机正转的时候计数增加,电机反转的时候计数减少,所以编码器的计数值是有正负的。从而可以知道什么时候该通过调整pwm来控制电机。

    下面是我的调试过程,也算是一点经验吧:以开始的思路是只要编码器的计数值不为0,我就要让电机反方向转动,以保持电机抱死,发送给电机的pwm是固定的数值,但是这样反而是抱不死,它在前后地抖动,而且pwm的占空比越大,电机抖动得越厉害,这样显然不行;后来想了一个办法,就是如果编码器的计数值在一定的范围内,我就不用让电机反方向转动。因为这个电机是变速电机,如果电机里面只转动一点点,在外面看来就相当于不动,这样的话就给电机预留了一部分转动的空间,用来消除抖动,就是说在这个空间内是不发送pwm给电机的,或者说电机两极的pwm占空比都为0。这样一来,当pwm占空比比较低时,是可以消除抖动,但是力气不大,就是说还是可以用钳子拧得动,调了很久都无法在抖动和电机力气之间取得平衡。后来又想了一个办法,在这个基础上再改进,因为之前的pwm占空比都是不变的,所以很难达到令人满意的效果,现在的方法是,根据电机被拧动的角度,或者说编码器的计数值大小来调整pwm的占空比,编码器的计数值偏离0越多(正或负得越大),pwm的占空比就越大,电机的力气也就越大,从而不会出现电机一旦被拧动就马上以最大速度转回去的情况,抖动也就消除了,而且电机力气很大。


编译环境是AVR Studio 5.0,下面是程序代码:
 
 
 
#include
#include
 
 
int forward = 0, reverse = 0;//存储电机正转和反转pwm占空比的变量
int timer0_count = 0;//timer0溢出事件计数器
int capt_count = 0;//输入捕捉事件计数器
 
 
void port_init(void)
{
PORTA = 0x00;
DDRA  = 0x00;
PORTB = 0x00;
DDRB  = 0x00;
PORTC = 0x00; //m103 output only
DDRC  = 0x00;
PORTD = 0x00;
DDRD  = 0xC0;
PORTE = 0x00;
DDRE  = 0x00;
PORTF = 0x00;
DDRF  = 0x00;
PORTG = 0x00;
DDRG  = 0x00;
}
 
 
void timer0_init(void)
{
TCCR0 |= 5;//256分频,普通模式
TIMSK |= 0x01;//timer0溢出中断
TCNT0 = 0xFE;//TCNT0赋初值
}
 
 
void timer1_init(void)
{
TCCR1B = 0x00;//停止
TCCR1A = 0x00;//普通模式
TCCR1C = 0x00;
TCNT1 = 0;//计数初值
TCCR1B = 0xC4;//启动定时器,256分频,使能输入捕捉噪声抑制器,输入捕捉触发沿选择:上升沿
TIMSK = 0x24;//输入捕捉中断使能,T/C1溢出中断使能
}
 
/************************************************************************/
/*  timer0溢出中断函数,产生提供给电机的pwm                             */
/************************************************************************/
ISR(TIMER0_OVF_vect)//200kHz
{
TCNT0 = 0xFE;//TCNT0重新赋值
//当timer0_count等于100时,如果正转或反转的占空比不为0,则相应引脚输出高电平
if(++timer0_count >= 100)//对timer0溢出事件计数100次,相当于100分频,最后输出到电机的pwm频率是2kHz
{
timer0_count = 0;
if(forward != 0)//forward, reverse存储电机正转和反转pwm占空比的变量
{PORTD |= (1<<6);}
if(reverse != 0)
{PORTD |=(1<<7);}
}
//当timer0_count等于正转或反转的占空比时,相应引脚输出低电平,实现输出pwm信号
if(timer0_count == forward)
{PORTD &= ~(1 << 6);}
if(timer0_count == reverse)
{PORTD &= ~(1 << 7);}
}
 
/************************************************************************/
/*  timer1输入捕捉中断函数,对编码器输出的上升沿进行计数              */
/************************************************************************/
ISR(TIMER1_CAPT_vect)
{
  if(PIND & (1 << 5))//电机反转
  {capt_count--;}//输入捕捉计数器减1
  else               //电机正转
  {capt_count++;}//输入捕捉计数器加1
}
 
 
/************************************************************************/
/*  timer1溢出中断函数,100Hz,用于调整电机转速和转动的方向,实现电机抱死*/
/************************************************************************/
ISR(TIMER1_OVF_vect)
{
TCNT1 = 64910;                           //重新给TCNT1赋值
static unsigned char motor_state = 0;    //电机的状态,标志电机是正转还是反转,0:正转,1:反转
switch(motor_state)
{
case 0://电机正转时
if(capt_count > 40)              //如果编码器正转计数超过40,则电机需要反转,以保持电机不动
{reverse = capt_count - 40;} //直接把编码器计数值减去40,作为反转的占空比
else if(capt_count < 0)          //如果编码器计数值小于0
{motor_state = 1;}           //进入状态1
else                             //如果编码器计数值在0~40内,为了不发生抖动,不需要反转
{reverse = 0;}               //反转的占空比为0,相当于负极接地
forward = 0;                     //正转的占空比为0,相当于正极接地
break;
 
case 1:
if(capt_count < -40)             //如果编码器反转计数超过40,则电机需要正转,以保持电机不动
{forward = (-capt_count) - 40;}//直接把编码器计数值减去40,作为正转的占空比
else if(capt_count > 0)          //如果编码器计数值大于0
{motor_state = 0;}           //返回状态0
else                             //如果编码器计数值在-40~0内,为了不发生抖动,不需要正转
{forward = 0;}               //正转的占空比为0,相当于正极接地
reverse = 0;                     //反转的占空比为0 ,相当于负极接地
break;
 
default:
break;
}
}
 
 
void Init_Devices(void)
{
cli();//关闭全局中断
port_init();//I/O口初始化
timer1_init();//定时/计数器1初始化
timer0_init();//计时/计数器0初始化
sei();//打开全局中断
}
 
 
int main(void)
{
    Init_Devices();
    while(1)
    {}
 
    return 0;
}
 
 


关键字:ATMEGA128  直流电机  抱死程序 引用地址:一个基于ATMEGA128的直流电机抱死程序

上一篇:atmega8 Flash的使用
下一篇:AVR-atmega16 BOOTLoader 程序

推荐阅读最新更新时间:2024-03-16 15:28

如何使用继电器实现直流电机的正反转?
一、继电器内部原理 继电器内部由线圈和触点两部分组成。 线圈断电时,公共与常闭触点连通(Normal Close);线圈通电时,公共与常开触点连通(Normal Open)。 二、两只继电器组成的正反转电路 两只继电器组成的正反转电路 三、用继电器实现直流电机正反转的方法 当直流电机两端加正向电压时电机正转,反之则反转。在工业应用中,供电电源一般是12V、24V或48V等。 当两组线圈都断电时,公共触点与常闭触点连通,电路断开,电机停止转动。 当第一组线圈通电、第二组线圈断电时,第一组继电器公共触点与常开触点连通,第二组继电器常闭触点与公共触点连接。 此时电流回路为:电源VCC从第一组继电器常开触点流经公共触点到电机A端,
[嵌入式]
如何使用继电器实现<font color='red'>直流电机</font>的正反转?
基于AVR单片机的新型自动准同期装置的设计
自动准同期装置在电力系统并网中有着十分重要的作用。本文采用ATMEGA128单片机为处理器,开发一种主要用于机组同期操作的自动准同期装置,该装置能自动检测系统侧和对象侧的压差、频差和相差,进行同期操作。如果采用一个同期点配备一个装置的方式,则能大大提高整个系统的同期可靠性。 1 系统的总体设计和硬件框图 作为准同期装置,首先必须要准确地测量系统侧和待并侧的同期参数。也就是精确测量两侧的电压、频率,以及相位差。在这个基础上,装置要进行准确的同期动作以及和上位机的通信。因此,系统的硬件设计和软件流程围绕这三个方面展开。为了减少干扰和便于操作,硬件分为CPU板、信号板和显示按键板。下面的硬件框图清楚地表示了三者之间的连接关系
[单片机]
atmega128 bootloader程序在IAR-AVR下 linker文件的配置及原因
第一步:atmega128的片内flash分区描述 在atmega128 datasheet的275页中有分区描述 对应的在284页中,有具体的应用区与boot区的大小设置 注意:Byte address = word address * 2 这里的BOOT区首地址,$F000 = 0x1E000 根据手册中的描述,我们使用JTAG MKII 烧写器通过软件 Avr Studio 4,配置熔丝位 BOOTSZ为00 注意:这里面的4096 words = 8K bytes 第二步:说明一下linker(.xcl)文件的作用 好了,怎么让我们的程序烧写到flash中是在指定的0x1E000处呢?这就需要在
[单片机]
<font color='red'>atmega128</font> bootloader<font color='red'>程序</font>在IAR-AVR下 linker文件的配置及原因
基于Atmega128嵌入式控制器的设计
  采用Atmega128单片机设计的嵌入式控制器,模拟量输入通道用Atmega128片内A/D转换器,输出用AD421 D/A转换器,数字量I/O通道配置高速先耦器件.用lccavr编译器修改OSTaskStklnit()函数及其相关文件,定义数据类型等以实现MicroC/OS-Ⅱ的移植. 1 引言   嵌入式控制器是机电设备实现自动化的核心部件。故以大型机电设备为控制对象,利用高性能Atmega 128微处理器, 设计了具有现场总线(CANBUS)网络通信和一定通用性的多功能嵌入式智能控制器。 2 硬件设计   系统的硬件结构如图1。   本控制器的核心采用64管脚TQFP封装的Atmega128芯片,具有53
[单片机]
基于<font color='red'>Atmega128</font>嵌入式控制器的设计
PIC16F877单片机在直流电机闭环调速系统中的应用
0引 言        现代工业生产中,电动机是主要的驱动设备,目前在电力拖动系统中已大量采用晶闸管(即可控硅)装置向电动机供电的KZ-D拖动系统,取代了笨重的发电动一电动机的F-D系统,又伴随着微电子技术的不断发展,中小功率直流电机采用单片机控制,调速系统具有频率高,响应快,本文论述了采用PIC16F877单片机作为主控制元件,充分利用了PIC16F877单片机捕捉、比较、模/数转换模块的特点作为触发电路,其优点是:结构简单,能与主电路同步,能平稳移相且有足够的移相范围,控制角可达10000步,能够实现电机的无级平滑控制,脉冲前沿陡且有足够的幅值,脉宽可设定,稳定性与抗干扰性能好等。       1 直流电机调速原理分析   
[工业控制]
AVR(ATMEGA128/16)内部EEPROM读写
下面这程序是128的 /****************************内部EEPROM头文件***************************/ #ifndef __eeprom_H__ #define __eeprom_H__ void EEPROM_write(unsigned int Address, unsigned char Da ta);//写入一个字节 void EEPROM_write_num(unsigned int Address, unsigned char Da ta ,uchar num);//写多个字节 unsigned char EEPROM_read(unsigned int Add
[单片机]
交流电机的优缺点 交流电机功率转速
  交流电机是用于实现机械能和交流电能相互转换的机械。由于交流电力系统的巨大发展,交流电机已成为最常用的电机。交流电机与直流电机相比,由于没有换向器(见直流电机的换向),因此结构简单,制造方便,比较牢固,容易做成高转速、高电压、大电流、大容量的电机。   其主要优点和缺点如下:   优点:   1. 转速范围大:交流电机的转速范围很大,可以从静止到非常高的转速。   2. 高效率:与直流电机相比,交流电机在高负载情况下具有更高的效率。   3. 可靠性高:交流电机的寿命长,维护成本低。   4. 动力强劲:交流电机具有高起动力矩,可用于启动大型负载,如风扇、压缩机等。   缺点:   1. 起动电流大:交流电机起动时需要极
[嵌入式]
基于FPGA的水磁无刷直流电机控制电路
主要介绍基于现场可编程门阵列(Field Programmable Gate Array,FP-GA)及EDA方法学的永磁无刷直流电机控制系统的电子电路设计。FPGA是一种高密度可编程逻辑器件,其逻辑功能的实现是通过把设计生成的数据文件配置进芯片内部的静态配置数据存储器(SRAM)来完成的,具有可重复编程性,可以灵活实现各种逻辑功能。 与ASIC不同的是,PCA本身只是标准的单元阵列,没有一般IC所具有的功能,但用户可以根据需要,通过专门的布局布线工具对其内部进行重新编程,在最短的时间内设计出自己专用的集成电路,从而大大提高了产品的竞争力。由于它以纯硬件的方式进行并行处理,而且不占用CPU资源,所以可以使系统达到很高的性能。这种新
[电源管理]
基于FPGA的水磁无刷<font color='red'>直流电机</font>控制电路
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

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