slide1 n.
Download
Skip this Video
Download Presentation
实验三:直流电机的驱动 与编码器脉冲的采集

Loading in 2 Seconds...

play fullscreen
1 / 59

实验三:直流电机的驱动 与编码器脉冲的采集 - PowerPoint PPT Presentation


  • 103 Views
  • Uploaded on

实验三:直流电机的驱动 与编码器脉冲的采集. 内容概要. 学习 1 种 ATmega64 资源 —— 定时、计数器 3 演示 2 个实验: ( 1 )直流电机的驱动、调速 ( 2 )上述实验的软件仿真 自行做 3 个实验: ( 1 )直流电机的驱动 ( 2 )直流电机的 PWM 调速 ( 3 )光电编码器脉冲信号的读取. 控制什么?. 控制什么?. 用到哪些单片机资源?. 单片机模块 —— 电机控制. 通信模块 —— 和 PC 通信. 电机 驱动 模块 —— 驾驭电机. 电源模块 —— 提供动力.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about '实验三:直流电机的驱动 与编码器脉冲的采集' - niesha


Download Now An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1

实验三:直流电机的驱动 与编码器脉冲的采集

slide2
内容概要
  • 学习1种ATmega64资源 ——定时、计数器3
  • 演示2个实验:
  • (1)直流电机的驱动、调速
  • (2)上述实验的软件仿真
  • 自行做3个实验:
  • (1)直流电机的驱动
  • (2)直流电机的PWM调速
  • (3)光电编码器脉冲信号的读取
slide5
用到哪些单片机资源?

单片机模块——

电机控制

通信模块——和PC通信

电机

驱动

模块——驾驭电机

电源模块——提供动力

输入输出模块——按键控制和状态指示

slide6
让直流电机动起来!
  • M+和M-分别接电源和地,电机就可以转动
  • 交换M+和M-,电机就反向转动
slide9
自己动手之一——驱动直流电机
  • 指令的输入:通过按键
  • 按钮Stop、F.W.、B.W.作为控制按钮
  • Stop(PC3,可触发外部中断INT5):启动、停止
  • F.W.、B.W.( PC0、PC1,可触发外部中断4):正、反转
slide10
调试灯
  • 调试用LED灯,可表示正、反转状态,运行状态等,也可以自定义。
slide11
电机控制I/O
  • PB4、PB5与L298的输入引脚相连
  • 注意:小心滑块撞到支架!
slide12
操作说明
  • 进行电机实验前,确保各接口连接好后,再打开电源。
  • 在使用电机模块时,先打开电源开关,再打开L298使能开关;关闭时,先关闭L298使能开关,再关闭电源开关。

电源开关

L298使能开关

slide14
标志位的设定
  • #define RUN 1
  • #define STOP 0
  • #define FORWARD 0
  • #define BACKWARD 1
  • unsigned char DC_State = STOP; // 电机状态,STOP或RUN
  • unsigned char dir_flag = FORWARD; // 方向标志,FORWARD或BACKWARD
slide15
宏定义
  • #define isButtonFWDown() ((PINC&0B00000001)==0)
  • #define isButtonBWDown() ((PINC&0B00000010)==0)
  • #define isButtonZERODown() ((PINC&0B00000100)==0)
  • #define isButtonSTOPDown() ((PINC&0B00001000)==0)
  • #define LedFWOn() (PORTA &= 0B11111110)
  • #define LedBWOn() (PORTA &= 0B11111101)
  • #define LedZeroOn() (PORTA &= 0B11111011)
  • #define LedRunOn() (PORTA &= 0B11110111)
  • #define LedFWOff() (PORTA |= 0B00000001)
  • #define LedBWOff() (PORTA |= 0B00000010)
  • #define LedZeroOff() (PORTA |= 0B00000100)
  • #define LedRunOff() (PORTA |= 0B00001000)
slide16
自定义函数
  • void DC_Forward()
  • {
  • PORTB |= 0B00010000;
  • PORTB &= 0B11011111;
  • }
  • void DC_Backward()
  • {
  • PORTB |= 0B00100000;
  • PORTB &= 0B11101111;
  • }
  • void DC_Stop()
  • {
  • PORTB &= 0B11001111;
  • }
  • 使用宏定义与自定义函数,可以提高程序的可读性与可维护性。
  • 而宏定义与自定义函数相比,程序的执行效率更高。
slide17
外部中断4的处理程序举例
  • #pragma interrupt_handler int4_isr:6
  • void int4_isr()
  • {
  • //external interupt on INT4
  • delay_ms(50); // 软件防抖
  • if ( DC_State == RUN ) {
  • if ( isButtonFWDown() )
  • {
  • dir_flag = FORWARD;
  • LedFWOn();
  • LedBWOff();
  • }
  • else if ( isButtonBWDown() )
  • {
  • dir_flag = BACKWARD;
  • LedBWOn();
  • LedFWOff();
  • }
  • }
  • }
slide18
外部中断5的处理程序举例
  • #pragma interrupt_handler int5_isr:7
  • void int5_isr()
  • {
  • //external interupt on INT5
  • delay_ms(50);
  • if ( isButtonSTOPDown() ) {
  • if ( DC_State == RUN )
  • {
  • DC_State = STOP;
  • LedRunOff();
  • DC_Stop();
  • }
  • else if ( DC_State == STOP )
  • {
  • DC_State = RUN;
  • LedRunOn();
  • }
  • }
  • else if ( isButtonZERODown() )
  • {
  • }
  • }
slide19
主函数
  • while(1)
  • {
  • if (DC_State == RUN )
  • {
  • if ( dir_flag == FORWARD )
  • DC_Forward();
  • else if ( dir_flag == BACKWARD )
  • DC_Backward();
  • }
  • }
slide20
如何改变电机的转速?
  • 对L298的控制有单极性、双极性2种方式。
  • 单极性工作方式指的是在一个PWM周期内电机的电枢只承受单极性的电压;
  • 双极性工作方式是指在一个PWM周期内电机电枢两端的电压呈正负交替变化。
slide21

PWM波

H

M+

L

转动时间

停止时间

电机正转

电机调速(单极性)
  • 以电机正转为例,在M+端产生PWM波,M-接低电平。则M+为高电平时,电机正转;为低电平时,电机停转。
  • 改变PWM波的占空比即可改变电机的转速,占空比越大,电机转速越快。
  • 脉冲宽度(简称脉宽),就是高电平的时间。

PWM(Pulse Width Modulation):脉冲宽度调制

pwm t c1
如何产生PWM波?(T/C1)
  • 16位的T/C 可以实现精确的程序定时(事件管理)、波形产生和信号测量。其主要功能如下:
  • 用作定时器:可以用作频率发生器等;
  • 用作计数器:可用来对外部引脚的脉冲信号进行计数;
  • 输入捕获功能:可用来测定外部信号的脉宽;
  • 输出比较匹配功能:可用来产生脉宽调制信号(PWM波)。
slide23
相关引脚
  • T1(PD6)
  • OC1A(PB5)
  • OC1B(PB6)
  • OC1C(PB7)
  • ICP1(PD4)
slide26

M+

转动时间

停止时间

电机正转

电机调速(单极性,快速PWM模式)

TOP

OCR1A

TCNT1

溢出时置位,并进行

电机转向控制

BOTTOM

TOP(ICR1)

OCR1A

比较匹配时清零

slide27
软件设计
  • PWM波形产生方法:

我们采用大致20KHz以上的PWM波进行电机的调速,采用Timer1的模式14,快速PWM模式,分频为1。使能overflow interrupt 和compare A interrupt中断,选择OC1A output mode为disconnected普通模式,在匹配中断中清零PB4、PB5,溢出中断中根据方向标志置位PB4或PB5。

这样就用单极性方式产生了方向可变的PWM波形。

slide28
快速PWM模式
  • TOP:用来定义通过波形发生器产生的波形的周期(频率)。我们要求在20kHz,采用快速PWM模式(模式14),TOP值由ICR1寄存器给定。
  • OCR1A:输出比较寄存器,记录输出比较的脉冲数,即调节占空比。这样,如果可以随时改变OCR1A的值,就可以产生可调占空比的PWM波。在模式14中,OCR1A的更新在TCNT1达到TOP时刻。
slide29
输出比较中断

OCR1A

=?

TCNT1←TCNT1+1

比较匹配的标志位

OCF1A置位

(TIFR)

产生PWM

波形可从引脚

OC1A输出

总开关I打开?

(SREG)

分开关OCIE1A

打开?(TIMSK)

输出比较

中断服务

清空

OCF1A

slide30
输出比较单元
  • 双缓冲输出比较寄存器OCR1A一直与TCNT1 的值做比较。
  • 波形发生器用比较结果产生PWM或在输出比较引脚OC1A输出可变频率的信号。
  • 比较匹配结果还可置位比较匹配标志OCF1A,用来产生输出比较中断请求。
slide31
相关寄存器
  • SREG(状态寄存器)
  • Bit 7 – I: 全局中断使能(总开关)
  • I 置位时使能全局中断。单独的中断使能由其他独立的控制寄存器控制。如果I 清零,则不论单独中断标志置位与否,都不会产生中断。
slide32
相关寄存器
  • TIMSK(定时器中断屏蔽寄存器)(分开关)
  • Bit 5 – TICIE1: T/C1 输入捕捉中断使能
  • Bit 4 – OCIE1A:T/C1 输出比较 A 匹配中断使能
  • Bit 3 – OCIE1B:T/C1 输出比较 B 匹配中断使能
  • Bit 2 – TOIE1:T/C1 溢出中断使能
slide33
相关寄存器
  • TIFR(定时器中断标志寄存器)
  • Bit 5 – ICF1: T/C1 输入捕捉标志
  • Bit 4 – OCF1A: T/C1 输出比较 A 匹配标志

当TCNT1 与OCR1A 匹配成功时,该位被设为"1”。

  • Bit 3 – OCF1B: T/C1 输出比较 B 匹配标志
  • Bit 2 – TOV1: T/C1 溢出标志
slide34
相关寄存器
  • TCCR1A(T/C1控制寄存器A)
  • TCCR1B(T/C1控制寄存器B)
  • TCCR1C(T/C1控制寄存器C)
tccr1c t c1 c
TCCR1C(T/C1控制寄存器C)
  • • Bit 7 – FOCnA: 强制输出比较通道A
  • • Bit 6 – FOCnB: 强制输出比较通道B
  • • Bit 5 – FOCnC: 强制输出比较通道C
slide38
相关寄存器(5个16位)
  • TCNT1(TCNT1H、TCNT1L) (16位的T/C1定时数据寄存器)
  • OCR1A(OCR1AH、OCR1AL) (16位的T/C1双缓冲输出比较寄存器A)
  • OCR1B(OCR1BH、OCR1BL) (16位的T/C1双缓冲输出比较寄存器B)
  • OCR1C(OCR1CH、OCR1CL) (16位的T/C1双缓冲输出比较寄存器C)
  • ICR1(ICR1H、ICR1L)(16位的T/C1输入捕获寄存器)
slide39
自己动手之二——改变电机转速
  • Q:如何改变转速?
  • A:通过串口改变OCR1A的值,从而改变PWM占空比。
  • 通过串口由PC机改变OCR1A的值,从而改变直流电机的转速!
slide40
单极性方式
  • 输入端In1为PWM信号,输入端In2为低电平,电动机正转;输入端In2为PWM信号,输入端In1为低电平,电动机反转。
  • 占空比为0%时制动,为100%时达到最高速;
  • 当EnA为低电平时,驱动桥路上的4个晶体管全部截止,使正在运行的电动机电枢电流反向,电动机自由停止。
  • 但是,控制板的使能端通过按键开关接电源——用急停方式
iccavr t c1
ICCAVR中如何设置T/C1

采用普通方式。

电机采用单极性方式驱动

slide42
定时/计数器1的初始化举例
  • void timer1_init(void)
  • {
  • TCCR1B = 0x00; //stop
  • TCNT1H = 0x00; //setup
  • TCNT1L = 0x00;
  • OCR1AH = 0x02;
  • OCR1AL = 0x27;
  • OCR1BH = 0x02;
  • OCR1BL = 0x27;
  • OCR1CH = 0x02;
  • OCR1CL = 0x27;
  • ICR1H = 0x02; // 20kHz
  • ICR1L = 0x27;
  • TCCR1A = 0x02; // OCR1A未连接,做普通端口操作
  • TCCR1B = 0x19; // start Timer
  • }

( 0227 )H=( 551 )D

slide43
定时/计数器1的比较匹配中断
  • #pragma interrupt_handler timer1_compa_isr:iv_TIM1_COMPA
  • void timer1_compa_isr(void)
  • {
  • //compare occured TCNT1=OCR1A
  • DC_Stop();
  • }
slide44
定时/计数器1的溢出中断处理
  • #pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
  • void timer1_ovf_isr(void)
  • {
  • //TIMER1 has overflowed
  • TCNT1H = 0x00; //reload counter high value
  • TCNT1L = 0x00; //reload counter low value
  • if (DC_State == RUN )
  • {
  • if ( dir_flag == FORWARD )
  • DC_Forward();
  • else if ( dir_flag == BACKWARD )
  • DC_Backward();
  • }
  • else DC_Stop();
  • }
slide45
通信协议
  • 每帧包含3字节数据:
  • 字节0:0xaa (帧开始标志)
  • 字节1:速度高4位(bit3~bit0)
  • 字节2:速度低8位
  • 速度范围(0x0001~0x0227),参见TIMER1初始化中ICR1取值
slide47
串口通信程序举例
  • unsigned char ReceivedData[3]; // 接收缓存
  • unsigned char receive_flag=0; // 接收完成标志,1表示接收一帧结束
  • #pragma interrupt_handler uart1_rx_isr:iv_USART1_RXC
  • void uart1_rx_isr(void)
  • {
  • static unsigned char rece_num=0;
  • unsigned char data;
  • data=UDR1;
  • if(( 0xAA == data )&&( 0 == rece_num ) || rece_num > 0 )
  • { ReceivedData[ rece_num ] = data;
  • rece_num++; }
  • if ( 3 == rece_num )
  • { rece_num = 0;
  • receive_flag = 1; }
  • }
slide48
主函数中修改脉冲宽度
  • while(1)
  • {
  • if (receive_flag == 1)
  • {
  • OCR1AH = ReceivedData[ 1 ];
  • OCR1AL = ReceivedData[ 2 ];
  • DC_State = RUN;
  • receive_flag = 0;
  • }
  • }
slide51
读取编码器的脉冲
  • 增量式编码器输出的是连续的脉冲信号,通过得到一秒钟内的脉冲个数,利用已知的编码器线数(如我们用的编码器为500线)可得到电机转速,或者直接以每秒的脉冲数作为速度,具体以计算方便为准。
  • 对此有两种较为常见的做法:测频率和测脉宽法。
  • 我们采用测频率法(或测周期法),该方法是设定一个固定的采样时间T,比如1秒,采样一次得到的脉冲个数N,那么速度为
  • V=N/T ( pulse / sec )
slide52
自己动手之三——测得编码器脉冲数
  • 1. 测得直流电机在最大的转速下,20ms内的脉冲数。
  • 2.利用串口调试助手读取该脉冲数,并估算大致范围。
slide53
如何分配单片机资源?
  • T/C0——产生20ms定时
  • T/C1——驱动电机
  • T/C3——采集编码器脉冲 ,上升沿
  • USART1——串口通信
  • Q:20ms内编码器脉冲有多少?
  • A:16位的T/C3。(为什么?)
  • Q:何时采集编码器脉冲?
  • A:20ms计时溢出中断服务中。
slide54
串口协议的修改
  • 采用问答式发送上个20ms内编码器读数,对串口协议做了如下修改:
  • 字节1的第7位为1作为查询编码器读数的命令
  • 增加一个发送标志位:
  • unsigned char txd_flag=0; // 为1表示发送编码器读数
slide55
定时/计数器0中断服务程序
  • #pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
  • void timer0_ovf_isr(void)
  • {
  • unsigned int encoder;
  • TCNT0 = 0x29; //reload counter value
  • encoder = TCNT3;
  • TCNT3 = 0;
  • if (txd_flag==1)
  • {
  • UDR1 = 0XAA;
  • while ( !( UCSR1A & (1<<UDRE1)) );
  • UDR1 = encoder>>8;
  • while ( !( UCSR1A & (1<<UDRE1)) );
  • UDR1 = encoder;
  • while ( !( UCSR1A & (1<<UDRE1)) );
  • txd_flag=0;
  • }
  • }
slide56
接收命令的执行
  • while(1)
  • {
  • if (receive_flag == 1)
  • {
  • if ((ReceivedData[1]&0x80)!=0)
  • {
  • txd_flag=1;
  • ReceivedData[ 1 ]-=0x80;
  • }
  • OCR1AH = ReceivedData[ 1 ];
  • OCR1AL = ReceivedData[ 2 ];
  • DC_State = RUN;
  • receive_flag = 0;
  • }
  • }
slide57
思考几个问题
  • 尝试一下用其他PWM模式驱动电机,比较各种模式的优缺点。
  • 用单极性方式和双极性方式产生PWM波的优缺点各是什么?
  • 为什么选择20ms定时?是否可以选择其他的时间长度?
  • 为什么使用16位的定时/计数器?可以用8位的吗?
slide58
实践大作业二分组报名
  • 121名同学
  • 5套直线运动模块
  • 实验安排:分四次,每次5组,时间1.5小时