欢迎光临
我们一直在努力

速度测量光电编码器设计及验证

文章目录

    • 概要
    • 整体架构流程
    • 技术细节
    • 小结

概要

1.电路功能:使用光电传感器对直流电机转速进行测量,并用数码管显示当前转速。 2.工作原理:利用遮断式红外控制原理对通过的物件计数。红外发光管与光电接收管相对摆放,每当物件通过一次,红外光被遮挡一次,光电接收管的输出电压发生一次变化,这个变化的电压信号通过放大和处理后,形成计数脉冲,送入单片机进行计数,同时利用单片机定时器定时一段时间,即可测出电机的速度。 3.基本要求:使用模块电路,搭建测速系统,满足:A、速度可显示范围 1~9999。B、可设置3档速度模式。 4.扩展要求:使用分立原件(非模块),设计电路基本要求,并且满足:利用PID原理,实现电机速度的稳定闭环控制。

整体架构流程

` 电机转速测量技术在工业自动化、精密制造、航空航天等领域有广泛应用,大部分设备是通过光电码盘或霍尔元件测量电机转速,反馈至伺服驱动器实现闭环控制。 本设计转速信号采集部分选用的是光电码盘和红外光电传感器,其电路可分为前端信号采集、信号处理、显示和电机驱动三个部分。 (一)方案设计框图 在这里插入图片描述

(二)电路工作原理 具体电路图如下图所示,包括电源、单片机、光电信号采集与处理、电机驱动、显示五部分。 在这里插入图片描述

1.电源部分:整个系统采用5V供电,可利用烧录器提供的5V或者可调电源提供的5V信号。 2.光电信号采集与处理:可以采用槽型光电耦合器作为传感器,其输出信号经过LM393比较器进行处理,将信号整形放大输出,当有无物体遮挡,模块输出高低电平,同时有LED同步显示输出。模块输出的计数脉冲信号送入后续电路进行处理。 在这里插入图片描述 在这里插入图片描述

3.显示部分:采用四位共阳数码管,由四个PNP型三极管来驱动,由单片机P0、P3端口控制。 4.电机驱动部分:采用TB6612芯片驱动电机,芯片内部集成双通道H桥电路,可通过端口给定逻辑实现电机正反转、制动等功能,改变输入PMW信号占空比可控制电机转速变化。 在这里插入图片描述

(三)主要元件介绍 1.TB6612 TB6612FNG是一款新型驱动器件,能独立双向控制2个直流电机,它具有很高的集成度,同时能提供足够的输出能力,运行性能和能耗方面也具有优势,因此在集成化、小型化的电机控制系统中,它可以作为理想的电机驱动器件。AINI/AIN2、BIN1/BIN2、PWMA/PWMB为控制信号输人端;A01/A02、B01/B02为2路电机控制输出端;STBY为正常工作/待机状态控制引脚;VM(<10 V)和VCC(2.7~5.5 V)分别为电机驱动电压输入和逻辑电平输入端。具体引脚定义与控制逻辑见下图所示。 在这里插入图片描述 在这里插入图片描述

2.LM393 LM393是一种广泛使用的电压比较器IC,提供8引脚DIP、SO-8和其他封装。LM393包含两个独立的高精度比较器运算放大器,可由单电源或双电源供电。电源电压范围宽,可以用于多种应用。该芯片需要低工作电流,非常适合便携式和电池供电设备,输出驱动逻辑系统可以用在数字电路中。LM393的最大输出电流为20mA,足以驱动晶体管和逻辑系统。

在这里插入图片描述 在这里插入图片描述

技术细节

PCB顶层 PCB顶层 PCB底层 PCB底层

#include <reg52.h>
#include <intrins.h>
#include <stdlib.h>

// =================== 1. ???? ===================
#define MOTOR_DISK_HOLES 36 // ???????36?
#define PID_PERIOD_MS 50 // PID ???? 50ms

// =================== 2. ???? ===================
sbit DIG_1 = P3^4;
sbit DIG_2 = P3^7;
sbit DIG_3 = P3^6;
sbit DIG_4 = P3^5;

// TB6612
sbit PWM_PIN = P2^0;
sbit AIN2 = P2^1;
sbit AIN1 = P2^2;

// ??
sbit KEY_SW1 = P1^0;

// =================== 3. ???? ===================
volatile unsigned int pulse_count = 0;
int real_rpm = 0;
int target_rpm = 0;

// — PID ?? (?? 1000 RPM ??????) —
int Kp = 120; // ?? (1.2) – ?????
int Ki = 45; // ?? (0.45) – ?????????
int Kd = 0; // ??

long err = 0;
long last_err = 0;
long sum_err = 0;

int pwm_duty = 0;
unsigned char pwm_tick = 0;
unsigned int pid_timer = 0;
unsigned char speed_mode = 0;

// ?????
unsigned char code SMG_Code[] = {0x28, 0xEE, 0x32, 0xA2, 0xE4, 0xA1, 0x21, 0xEA, 0x20, 0xA0};
unsigned char Display_Buf[4] = {0x28, 0x28, 0x28, 0x28};

// =================== ???? ===================
void Delay_Short(unsigned int t);
void Display_Scan();
void Set_Display_Num(int num);
void PID_Compute_Fast();
void Motor_Set_Mode(unsigned char mode);

// =================== ??? ===================
void main()
{
AIN1 = 0; AIN2 = 0; PWM_PIN = 0;

// ???0 ???
TMOD &= 0xF0; TMOD |= 0x01;
TH0 = (65536 100) / 256;
TL0 = (65536 100) % 256;
ET0 = 1; TR0 = 1;

// ????0 ???
IT0 = 1; EX0 = 1; EA = 1;

while(1)
{
Display_Scan(); // ??????

if(KEY_SW1 == 0)
{
Delay_Short(200); // ??
if(KEY_SW1 == 0)
{
speed_mode++;
if(speed_mode > 3) speed_mode = 0;

// ????????
Motor_Set_Mode(speed_mode);

while(KEY_SW1 == 0) Display_Scan();
}
}
}
}

// =================== ???? ===================
void Int0_Routine() interrupt 0
{
pulse_count++;
}

void Timer0_Routine() interrupt 1
{
TH0 = (65536 100) / 256;
TL0 = (65536 100) % 256;

// — PWM ?? —
pwm_tick++;
if(pwm_tick >= 100) pwm_tick = 0;

if(target_rpm > 0)
{
if(pwm_tick < pwm_duty) PWM_PIN = 1;
else PWM_PIN = 0;
}
else
{
PWM_PIN = 0;
}

// — PID ?? (50ms) —
pid_timer++;
if(pid_timer >= 500)
{
pid_timer = 0;

// ?? RPM: (?? * 1200) / 36
real_rpm = (int)(((long)pulse_count * 1200) / MOTOR_DISK_HOLES);
pulse_count = 0;

if(target_rpm > 0)
{
PID_Compute_Fast();
AIN1 = 1; AIN2 = 0; // ??
}
else
{
pwm_duty = 0;
sum_err = 0;
AIN1 = 0; AIN2 = 0;
}

Set_Display_Num(real_rpm);
}
}

// =================== ?? PID ?? ===================
void PID_Compute_Fast()
{
long output_val;

// 1. ????
err = (long)target_rpm (long)real_rpm;

// 2. ????
sum_err += err;

// ????
if(sum_err > 4000) sum_err = 4000;
if(sum_err < 4000) sum_err = 4000;

// 3. ?? P + I
output_val = (Kp * err) + (Ki * sum_err);

// 4. ??? (??100)
output_val = output_val / 100;

// 5. ???? (????)
// ???1000?,?????????,?? 25
if(target_rpm > 0)
{
output_val += 25;
}

// 6. ????
if(output_val > 100) output_val = 100;
if(output_val < 0) output_val = 0;

pwm_duty = (int)output_val;
}

// =================== ?????? (????) ===================
void Motor_Set_Mode(unsigned char mode)
{
switch(mode) {
case 0:
target_rpm = 0;
break;
case 1:
target_rpm = 1000; // ???????? 1000
break;
case 2:
target_rpm = 2000; // ???????? 2000
break;
case 3:
target_rpm = 3000; // ???????? 3000
break;
}
// ??:?????????????2000?,????3000??,
// PWM????100%,?????????????????
}

// =================== ????? ===================
void Set_Display_Num(int num)
{
if(num < 0) num = 0;
if(num > 9999) num = 9999;

Display_Buf[0] = SMG_Code[num / 1000];
Display_Buf[1] = SMG_Code[num % 1000 / 100];
Display_Buf[2] = SMG_Code[num % 100 / 10];
Display_Buf[3] = SMG_Code[num % 10];
}

void Display_Scan()
{
P0 = 0xFF; DIG_1 = 0; DIG_2 = 1; DIG_3 = 1; DIG_4 = 1; P0 = Display_Buf[0]; Delay_Short(30);
P0 = 0xFF; DIG_1 = 1; DIG_2 = 0; DIG_3 = 1; DIG_4 = 1; P0 = Display_Buf[1]; Delay_Short(30);
P0 = 0xFF; DIG_1 = 1; DIG_2 = 1; DIG_3 = 0; DIG_4 = 1; P0 = Display_Buf[2]; Delay_Short(30);
P0 = 0xFF; DIG_1 = 1; DIG_2 = 1; DIG_3 = 1; DIG_4 = 0; P0 = Display_Buf[3]; Delay_Short(30);
P0 = 0xFF;
}

void Delay_Short(unsigned int t)
{
while(t);
}

小结

本文设计并实现了一个基于51单片机的直流电机转速测量与控制系统。系统采用遮断式红外光电传感器(槽型光电耦合器)进行转速信号采集,通过LM393比较器对信号进行整形放大,生成计数脉冲送入单片机。单片机(STC89C52)通过定时器中断和外部中断对脉冲进行计数与定时,计算出实时转速,并驱动四位共阳数码管进行显示。电机驱动部分采用TB6612芯片,通过PWM信号控制电机转速。系统实现了三档速度模式(0、1000、2000、3000 RPM)的切换,并引入了简化的PID控制算法,对电机转速进行闭环调节,以提高系统的稳定性和响应速度。整个设计涵盖了从传感器信号采集、处理、显示到电机驱动的完整流程,并提供了详细的电路原理图、PCB布局以及核心单片机代码,是一个完整的嵌入式测控系统实践案例。

赞(0)
未经允许不得转载:171主机测评 » 速度测量光电编码器设计及验证
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址