标题:
单片机+DRV8833直流电机驱动程序,霍尔传感器精确测速
[打印本页]
作者:
D_omino
时间:
2017-11-28 23:55
标题:
单片机+DRV8833直流电机驱动程序,霍尔传感器精确测速
直流电机驱动程序,采用DRV8833驱动,并用霍尔传感器测量转速,测量精确
0.png
(8.92 KB, 下载次数: 125)
下载附件
2017-11-29 03:48 上传
所有资料51hei提供下载:
直流电机驱动程序,采用DRV8833驱动,并用霍尔传感器测量转速,测量精确.zip
(655.84 KB, 下载次数: 163)
2017-11-28 23:54 上传
点击文件名下载附件
下载积分: 黑币 -5
msp430单片机源程序如下:
/*
* DC_Motor.c
*
* Created on: 8-31
* Author: zdl
*/
#include "global.h"
//---------------------相关宏定义-------------------------
#define ENCODE_NUM 4 //测速码盘齿轮数目
#define MAX_SPEED 340 //最大转速(r/s)
#define P_Coefficient 11 //PID反馈中的比例系数
#define I_Coefficient 2 //PID反馈中的微分系数
#define D_Coefficient 1 //PID反馈中的积分系数
//---------------------相关变量定义-----------------------
static uint16_t ui16Speed_Preset = 0; //预设速度
static uint16_t ui16Speed_True = 0; //实测速度,单位XX转/分
uint16_t ui16Speed_Measure = 0; //实测速度,单位XX转/分
static uint16_t ui16Speed_Pecent = 0; //速度百分比,用于更新速度曲线
uint16_t ui16TA0_Overflow_Cnt = 0; //定时器溢出计数
uint16_t ui16TA1_Overflow_Cnt = 0; //定时器溢出计数
static uint8_t ui8FirstFlag = 1; //PID算法中微分项需要判断首次上电
//---------------------局部函数声明---------------------
static void Speed_Disp();
static uint16_t PID_PWM(int16_t i16Error);
static void Get_Fre();
void DC_Motor_Graph()
{
//-----Draw Title-----
GrClearDisplay(&g_sContext);
GrTaskRectDraw();
//-----绘制转速单位-----
GrStringDrawCentered(&g_sContext, "(r/s)", AUTO_STRING_LENGTH, 52, 20, OPAQUE_TEXT);
//-----绘制波形坐标轴-----
GrAxisDraw();
GrFlush(&g_sContext);
}
void DC_Motor_Begin()
{
//--------GPIO Init--------
P2DIR &= ~BIT7; //-----测速中断IO初始化-----
P2IES |= BIT7;
P2IE |= BIT7;
P1DIR |= BIT3 +BIT4; //-----配置P1.3和P1.4电机PWM控制IO参数-----
P1OUT |= BIT3;
P1SEL |= BIT4;
//-----TA1 ContinuousMode Init-----
TIMER_A_configureContinuousMode(__MSP430_BASEADDRESS_T1A3__,//选择TA1定时器
TIMER_A_CLOCKSOURCE_SMCLK,
TIMER_A_CLOCKSOURCE_DIVIDER_1,
TIMER_A_TAIE_INTERRUPT_ENABLE,
TIMER_A_DO_CLEAR);
TA1CTL = TASSEL_2 + MC_2 + TACLR + TAIE; //启动测速
//-----TA0.3 PWM Init------
TIMER_A_generatePWM( __MSP430_BASEADDRESS_T0A5__,//选择TA0定时器
TIMER_A_CLOCKSOURCE_SMCLK,
TIMER_A_CLOCKSOURCE_DIVIDER_1,
SYSMCLK/10000-1, //PWM 10K
TIMER_A_CAPTURECOMPARE_REGISTER_3,
TIMER_A_OUTPUTMODE_SET_RESET ,
SYSMCLK/10000-1
);
//-----首次PID算法置标志位-----
ui8FirstFlag = 1; //PID算法中用于判断第一次的标志位
}
void DC_Motor_Main()
{
Draw_Histogram(0); //更新柱状图
Get_Fre();
Speed_Disp(); //更新预设与实测速度值
Draw_Waveform(&ui16Speed_Pecent,1); //更新速度曲线
GrFlush(&g_sContext); //刷新屏幕
LPM3; //执行函数由WDT定时唤醒
}
void DC_Motor_Quit()
{
//-----GPIO Quit-----
P2DIR |= BIT7;
P2IE &= ~BIT7;
P1SEL &= ~BIT4;
P1OUT &= ~(BIT3+BIT4);
ui8FirstFlag=1;
//-----TA0 Quit-----
TIMER_A_disableInterrupt(__MSP430_BASEADDRESS_T0A5__);
//-----TA1 Quit-----
TIMER_A_disableInterrupt(__MSP430_BASEADDRESS_T1A3__);
}
//-------------速度显示-------------
static void Speed_Disp()
{
//-----更新变量值-----
ui16Speed_Preset=MAX_SPEED*ui8Wheel_Pecent/100;
ui16Speed_Pecent=ui16Speed_True*100/MAX_SPEED;
//-----刷新显示-----
GrStringDrawCentered(&g_sContext, " ",
AUTO_STRING_LENGTH,20,20, OPAQUE_TEXT); //清除前一次显示
GrStringNumberCentered(&g_sContext,
ui16Speed_True,0,20,20);
GrStringDrawCentered(&g_sContext, " ",
AUTO_STRING_LENGTH,113,20, OPAQUE_TEXT); //清除前一次显示
GrStringNumberCentered(&g_sContext,
ui16Speed_Preset,0,113,20);
ui16Speed_True=0;
ui16Speed_Preset=0;
}
//----PID算法,计算出PWM占空比,8192等同100%占空比------
static uint16_t PID_PWM(int16_t i16Error)
{
static int16_t i16Error_Prev = 0;
static int16_t i16Integral = 0;
int16_t i16P_Component ,i16I_Component ,i16D_Component ;
int16_t i16Result;
if(ui8FirstFlag) //首次上电缺乏前次误差,补上。
{
ui8FirstFlag = 0;
i16Error_Prev = i16Error;
i16Integral=0;
}
i16P_Component = P_Coefficient*i16Error;
i16I_Component = I_Coefficient*i16Integral;
i16D_Component = D_Coefficient*(i16Error-i16Error_Prev);
//-----误差积分-----
i16Integral += i16Error;
i16Result = i16P_Component + i16I_Component + i16D_Component;
//-----输出限幅----
if(i16Result > 8192)
i16Result = 8192;
if(i16Result < 0)
i16Result = 0;
return(i16Result);
}
/********************************************************
*
* 以下函数需要放置在中断服务子函数中调用
*
********************************************************/
//-----WDT中断定时更新占空比-----
void Change_PWM_Duty()
{
int16_t i16Error = ui16Speed_Preset - ui16Speed_True;
uint32_t ui16PWM_Duty = PID_PWM(i16Error);
TA0CCR3 = (uint16_t)((ui16PWM_Duty)*TA0CCR0/8192); //改变PWM占空比
}
//-----测量实际转速,此函数在P2中断中被调用-----
static uint16_t ui16PreTemp=0;
void Measure_Freq()
{
uint32_t Speed_Sum;
uint16_t ui16Temp;
ui16Temp=TA1R;
Speed_Sum = (uint32_t)ui16Temp + (uint32_t)65536*ui16TA1_Overflow_Cnt-ui16PreTemp;//测速前的值减去测速后的计数值,那么就是在一段时间内计数的次数
ui16PreTemp = ui16Temp;
ui16TA1_Overflow_Cnt = 0;
ui16Speed_Measure = (uint16_t)( SYSMCLK / Speed_Sum); //计算频率 , 开孔圆盘上有许多小孔,开孔圆盘旋转一周,光敏元件输出的电脉冲个数等于圆盘的开孔数,因此,可通过测量光敏元件输出的脉冲频率
}
//获取测量的速度,应该是获取转速
static void Get_Fre()
{
ui16Speed_True = ui16Speed_Measure/ENCODE_NUM; //返回实测转速值,除以齿轮数目
}
复制代码
作者:
popo321
时间:
2020-3-26 13:45
谢谢分享!
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1