基于Mega128编码器控制步进电机的平衡系统

发布者:cocolang最新更新时间:2015-07-23 来源: 基于Mega128编码器控制步进电机的平衡系统关键字:Mega128  编码器  步进电机  平衡系统 手机看文章 扫描二维码
随时随地手机看文章
    提起编码器,可能大家并不陌生,因为这东西真的很常用,现在的主流编码器一般精度都是比较高的,基本上都是基于光栅的。毕竟用硬件用电刷做到512精度以上是很困难的,而且成本也是很高的,这里我就不多说什么了。
    编码器一般共有三个主通道,每个主通道有分为两个分支;一个VCC,一个GND,一条屏蔽线。前两个通道一般是比较精确的脉冲信号,且之间有四分之一左右的相位差用来判断正反转的,第三通道基本上是旋转一周才会有一个脉冲信号的那种。

 
    提到步进电机,就一定要有一个合适的电机驱动,个人是比较喜欢用L298n这款芯片的,因为它价格低,操作比较简单。
 
    对于这个系统,我是用128的外部中断的下降沿触发方式来捕捉编码器的脉冲的,硬件连接方面电机驱动和主控芯片一定要注意地线的连接。
 
    下面是程序的完整代码下载地址: http://www.51hei.com/f/bmma.rar         

 
这里是delay.h
====================================================================
//根据CPU时钟频率选择
#ifndef F_CPU
//#define F_CPU 7372800
//#define F_CPU 8000000
//#define F_CPU 11059200
//#define F_CPU 12000000
#define F_CPU 16000000
#endif



//------------------------------------------------------------------------------
//1、2、3、5和10us的精确延时,用于需要精确时间的场合,比如DS18B20
//------------------------------------------------------------------------------
#if   F_CPU == 7372800
#define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP()
#define DELAY_2US DELAY_1US;DELAY_1US
#define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US
#define DELAY_5US DELAY_2US;DELAY_3US
#define DELAY_10US DELAY_5US;DELAY_5US

#elif F_CPU == 8000000
#define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP()
#define DELAY_2US DELAY_1US;DELAY_1US
#define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US
#define DELAY_5US DELAY_2US;DELAY_3US
#define DELAY_10US DELAY_5US;DELAY_5US

#elif F_CPU == 11059200
#define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP()
#define DELAY_2US DELAY_1US;DELAY_1US
#define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US
#define DELAY_5US DELAY_2US;DELAY_3US
#define DELAY_10US DELAY_5US;DELAY_5US

#elif F_CPU == 12000000
#define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP()
#define DELAY_2US DELAY_1US;DELAY_1US
#define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US
#define DELAY_5US DELAY_2US;DELAY_3US
#define DELAY_10US DELAY_5US;DELAY_5US

#elif F_CPU == 16000000
#define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP()
#define DELAY_2US DELAY_1US;DELAY_1US
#define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US
#define DELAY_5US DELAY_2US;DELAY_3US
#define DELAY_10US DELAY_5US;DELAY_5US
#endif


//------------------------------------------------------------------------------
//函数声明
//------------------------------------------------------------------------------

void delay_nus(unsigned int);//<10us时误差较大,用于无须精确延时的场合

void delay_nms(unsigned int);


#endif//__DELAY_H


====================================================================
 这里是delay.c
====================================================================
//|文件名称|delay.c
//|--------|--------------------------------------------------------------------
//|描    述|延时文件
//|--------|--------------------------------------------------------------------
//|说    明|delay_us(unsigned int time)用于不需精确定时的场合,<10us时误差较大
//|        |若要精确定时用delay.h里的宏
//|--------|--------------------------------------------------------------------
//|调用文件|delay.h
//|--------|--------------------------------------------------------------------
//|作    者|
//|--------|--------------------------------------------------------------------
//|版    本|
//|--------|--------------------------------------------------------------------
//|时    间|
//|--------|--------------------------------------------------------------------
//|E-mail  |
//|--------|--------------------------------------------------------------------
//|开发环境|ICCAVR6.31
//==============================================================================

#include "delay.h"

#if F_CPU == 7372800
void delay_nus(unsigned int time)
{
  unsigned int i;
  for(i=0;i


/*步进电机旋转一周子函数*/
void one_circle(void)
{
  unsigned int i;
for(i=0;i<3200;i++)
{
EN_1;
delay_us(100);
EN_0;
delay_us(100);
}
}
/*步进电机根据编码器计算的数值旋转任意角度子函数*/
void circle(unsigned int xcircle)
{
  unsigned int i,j;
for(j=0;j
#include
#include

//一些变量的定义
int k=0;
unsigned int x=1,d=0,c=0,cir=0;
unsigned int a,aa,q,angle=0,p=0;
//595(数码管)显示数组
unsigned char led[]=
{
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F, // 9
};
//外部中断0~3向量号码
#pragma interrupt_handler Zhongduan_0:2
#pragma interrupt_handler Zhongduan_1:3
#pragma interrupt_handler Zhongduan_2:4

//端口输入输出初始化
void init_xianshi(void)
{
DDRA=0XFF;
DDRB=0XFF;//595控制口
DDRC=0XFF;//正反转提示LED
PORTC=0XFF;//LED初始化(暗)
}


//595串入一字节并处发送一字节子函数
void send_595(unsigned char dat)
{
   unsigned char i;
   LCK_0;
   SDI_1;
   SCK_0;
   //上面的三条语句为了初始化端口状态
   for(i=0;i<8;i++)
   {
    LCK_0;//时钟线拉低
 
    if(dat&0x80)
        SDI_1;
     else SDI_0;
     dat=dat<<1;
   delay_us(100);  
    LCK_1;          //时钟线拉高将数据读入595的移位寄存器    
    delay_us(100); 
   }
   SCK_1; //发送数据到并行端口
   SCK_0;   
}

void jiaoduzhuanhuan(void)
{
  init_xianshi();
  EIMSK=0X0F;
  EICRA=0XAA; 
 while(1)
  { 
 if(a!=aa) /*如果有角度变化就执行下面的程序*/
 {
angle++;
 
if(!(PING&0X04))
cir++; 
while(cir)
{
if(!k)
  {
   delay_ms(800);
 if(d<=3)
     one_circle();
 d++;
  }
 }  
 
 if(!(PING&0X02))
 {
 while(PING&0X01)
 {
   DIR_0;
  circle(1);
   p++;
   while(p==angle);
 }
  while(PING&0X01);
 if(q=-1)//正转
 DIR_1;
 circle(1);

 if(q==1)  //反转
 DIR_1;
 }
 
  aa=a;
 

  if(!x)
  {
PORTC=0X00;
  }
  }
  /*下面为数码管显示编码器当前计数的数值*/
  PORTA=0X08; 
  send_595(0x00);
  send_595(led[abs(k)%10]);
  PORTA=0X01; 
  send_595(0x00);
  send_595(led[(abs(k)%100)/10]);
  PORTA=0X02; 
  send_595(0x00);
  send_595(led[(abs(k)%1000)/100]);
  PORTA=0X04; 
  send_595(0x00);
  send_595(led[abs(k)/1000]);
SEI(); /*使能中断*/
  } 
}

 void Zhongduan_0(void)
 {
  CLI();
  x=0;
 ////////////////// 
  if(PIND&0X02)
  q=-1;
  if(!(PIND&0X02))
  q=1;
  ////////////////
  k=k+q;
  SEI();
 }

 void Zhongduan_1(void)
 {
 CLI();

 if(PIND&0X01)
 q=1;
 k=k+q;
 if(abs(k)==10000)
 {
   k=0;
 }
 a=k;
 //EIMSK=0X0E;
 SEI();
 }
 void Zhongduan_2(void)
 {
  CLI();
  k=0;
  SEI();
  }
====================================================================
 这里是main.c
====================================================================
#include
#include
#include"delay.h"
#include"caiji.h"
#include"dianji.h"

void init(void)
{
  DDRC=0X03;
PORTC=0X00;
}

void main(void)
{
  init();     //初始化子函数
  jiaoduzhuanhuan(); //主程序的实现
}
====================================================================
关键字:Mega128  编码器  步进电机  平衡系统 引用地址:基于Mega128编码器控制步进电机的平衡系统

上一篇:基于Mega128的DHT11温湿度传感器
下一篇:avr EEPROM 数据丢失问题 原因与解决方案

推荐阅读最新更新时间:2024-03-16 14:26

PLC 控制步进电机分度的设计与实现
1、引言   大型轴承内、外套上的分度、打孔是轴承中的关键工序 ,它的工艺水平和质量的高低直接影响轴承的质量、寿命和制造成本。目前轴承行业大型轴承内、外套的分度方式普遍采用人工分度方式 ,其分度精度低、累积误差大 、工作效率低、工人劳动强度大,对轴承性能的提高造成很大的影响。我们所研制的大型数控分度头,采用 PLC 可编程控制器 ,控制步进电机驱动蜗轮蜗杆对执行工件进行自动分度, 结构简单、制造费用低,较好地解决了生产中的实际问题。 2、总体设计方案   步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件。在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,即给电机加一个脉冲信号,电机
[嵌入式]
基于L297和L298的步进电机驱动器的设计
引言 步进电机广泛应用于对精度要求比较高的运动控制系统中,如机器人、打印机、软盘驱动器、绘图仪、机械阀门控制器等。目前,对步进电机的控制主要有由分散器件组成的环形脉冲分配器、软件环形脉冲分配器、专用集成芯片环形脉冲分配器等。分散器件组成的环形脉冲分配器体积比较大,同时由于分散器件的延时,其可靠性大大降低;软件环形分配器要占用主机的运行时间,降低了速度;专用集成芯片环形脉冲分配器集成度高、可靠性好,但其适应性受到限制,同时开发周期长、需求费用较高。 步进电机控制 步进电机是数字控制电机,它将脉冲信号转变成角位移,即给一个脉冲信号,步进电机就转动一个角度,因此非常适合于单片机控制。步进电机可分为反应式步进电机(VR)、永磁式步
[单片机]
基于L297和L298的<font color='red'>步进电机</font>驱动器的设计
msp432快速入门第十一节之编码器
(一)编码器介绍 首先可以在man手册中查看TAx的功能(function),发现他不支持直连编码器,然后看了下timer32,发现timer32也不支持,不过好消息是发现TAx定时器支持输入捕获,那我们只能使用输入捕获来计算编码器的数值了,如果是步方向编码器可以直接拿来用了,如果是正交编码器需要使用D触发器鉴相,具体电路可以百度搜索,我自己使用的是正交编码器,利用74HC74D双D触发器来鉴相,这样可以直接给两个电机使用了。 (二)移植输入捕获程序 仿照TI的官方例子进行配置输入捕获: (1)配置TAx定时器 /* Timer_A Continuous Mode Configuration Parameter */ co
[单片机]
msp432快速入门第十一节之<font color='red'>编码器</font>
步进电机的速度 - 扭矩曲线
步进电机的速度 - 扭矩曲线 它们是如何创建的以及它们的含义选择步进电机时,您会尝试选择满足您的速度和扭矩要求以及一些安全裕度的电机。但是您如何比较电机供应商之间的电机性能。大多数供应商提供速度 - 扭矩特性曲线,以了解电机的预期性能。步进电机速度 - 扭矩曲线显示步进电机在给定速度下与特定驱动器结合使用时可提供多少扭矩。这意味着,根据不同的电机和驱动器组合,步进电机系统可获得不同的性能。本文将介绍如何生成步进电机的速度 - 扭矩曲线以及在曲线上寻找的重要点是什么。 定义明确的速度 - 扭矩曲线应包括以下信息。 1. 电源输入:这是提供给驱动器的电压。对于直流输入电压驱动器,此相同电压通常直接施加到电机绕组。对于交流输入电压驱
[嵌入式]
<font color='red'>步进电机</font>的速度 - 扭矩曲线
伺服电机与步进电机的区别分析
  随着全数字式交流伺服系统的出现,交流伺服电机也越来越多地应用于数字控制系统中。为了适应数字控制的发展趋势,运动控制系统中大多采用步进电机或全数字式交流伺服电机作为执行电动机。   步进电机作为一种开环控制的系统,和现代数字控制技术有着本质的联系。在目前国内的数字控制系统中,步进电机的应用十分广泛。随着全数字式交流伺服系统的出现,交流伺服电机也越来越多地应用于数字控制系统中。为了适应数字控制的发展趋势,运动控制系统中大多采用步进电机或全数字式交流伺服电机作为执行电动机。虽然两者在控制方式上相似(脉冲串和方向信号),但在使用性能和应用场合上存在着较大的差异。现就二者的使用性能作一比较。      一、控制精度不同      两
[机器人]
两相双极步进电机驱动中电流再生时的电流衰减
两相双极步进电机的驱动:什么是Decay? 在驱动步进电机时,需要进行Decay(电流衰减)控制。 Decay是一种在关断对电机的电源供给时使电流衰减的方法,有Slow Decay(慢速衰减)和Fast Decay(快速衰减)两种基本方法。 以下是上一篇中给出的步进电机驱动波形中的一部分。输出电压OUT是PWM 信号 ,因此输出电流是与PWM信号联动ON/OFF的平均电流。由于驱动的是线圈,所以输出电流的波形是锯齿波,而不是PWM电压输出的方波。下图是输出电流的放大波形。 蓝色波形是Slow Decay时的波形,由于衰减的斜率小,故电流衰减速度慢,PWM关断期间的电流衰减也较慢。因此,在导通时达到设定电流值的时间也缩短
[嵌入式]
两相双极<font color='red'>步进电机</font>驱动中电流再生时的电流衰减
使用L6506 实现步进电机的电流控制
L6506是一款可以检测并监控 步进电机 或其他相类似设备 电流 的线性 集成电路 。可与功率驱动级芯片像L293D、L298N,L6201/02/03配套使用,针对感性负载组成恒流驱动 电路 。 L6506可以针对两相双极或四相单极性电机配置。图1是L6506配套L298N实现的双极性电机驱动电路。图2中的电路实现了一个四相单极性电机驱动电路。在这两个电路中,L6506用于监控每个电机绕组内的电流。其工作原理是通过监测流过检测 电阻 (Rsense)上的 电压 来监测电流,利用脉宽调制控制使电流维持在某个设定的值。芯片内部的 振荡器 负责驱动双路斩波器,引脚1上的阻容网络就是用于设置工作频率,其计算方法如下:   R
[嵌入式]
51单片机控制步进电机硬件连接部分
1、概要: 本案例讲解的内容是51单片机控制步进电机硬件连接部分。后续会分别讲解单片机程序,S曲线加减速方法,上位机等相关内容 2、功能原理图: 2.1、51单片机: ①输出脉冲到TB6600驱动器PUL端口,从而控制步进电机转动 ②控制TB6600驱动器ENA端口,从而控制步进电机使能 ③控制TB6600驱动器DIR端口,从而控制步进电机转动方向 2.2、步进电机: ①提供机械动力 2.3、稳压电源: ①为步进电机提供电源 2.4、TB6600驱动器: ①二相四线步进电机专用驱动器 3、实物图: ** ①** 、51****单片机控制板一个 ** ②** 、二相四线步进电机一个 ** ③** 、稳压电源一个 ** ④** 、
[单片机]
51单片机控制<font color='red'>步进电机</font>硬件连接部分
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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