小规模
位置控制 先进的位置控制系统已在工业控制应用中使用了数十年。通常这些系统既复杂又昂贵,而且是必要的。在当今的电子市场中,存在允许非常小且便宜的位置控制系统的选项。现在可以以经济实惠的方式提供小规模的先进控制系统,甚至可以围绕固定的电子硬件定制多种设计。这为增强制造控制创造了许多选择,从而减少了材料损失并节省了时间和金钱。本文描述了一个简单的设计,后来基于该设计创建了一个强大的小型化运动控制系统。 使用Microchip 的
小型化伺服控制器
dsPIC 系列 16 位微控制器允许以非常低的硬件成本开发复杂的控制方案。对于该应用,选择了dsPIC33FJ64MC802-I/MM-ND器件作为合适的控制器。选择该部分的重要原因如下:
64K x 8 闪存,16K x 8 RAM
Microchip 的 MPLAB C 免费评估版
通过 MPLAB ICD3 实现的低成本调试器/编程器
高达 40MIPS 的运行速度
除了这些因素之外,dsPIC33FJ64MC802-I/MM-ND 还具有大量有用的外设,非常适合许多控制应用。这些外设包括定时器、正交编码器硬件、10 位或 12 位模数转换器、UART、SPI、I2C、专为电机控制而设计的 PWM 模块、看门狗定时器、带 PLL 的内部振荡器和许多中断驱动特性。许多外围设备可以映射到各种 IC 焊盘,从而简化印刷电路板的布线。在此伺服设计中,选择了
稳健的飞思卡尔 MC33926PNB-ND来提供微控制器和直流电机之间的接口。然而,几乎任何H 桥 IC可以插入到这个设计中,一旦控制系统完善,就可以轻松调整电机尺寸。选择 MC33926PNB 的原因如下:
简化的设计示例
之前我们讨论了选择用于创建小型伺服系统的主要部件。为了提供更多细节,我们将基于这些部分设计一个闭环比例控制器(见图 1)。使用 dsPIC33 AD 和 PWM 模块,我们可以快速生成 12 位模拟控制和模拟反馈系统。通过使用内部 RC 振荡器和 PLL 以 36.85 MIPS 的速度运行,以及 250 µS 的控制环路,可以节省额外的资金。
dsPIC33 固件还将监控来自 H 桥 IC 的故障和电流反馈。如果存在故障条件,微控制器将尝试在每个控制回路中重置 H 桥。如果电机负载电流超过大约 2 A,dsPIC33 固件将关闭 PWM 信号。
以 20 KHz 运行 dsPIC33 PWM 模块允许 PWM 值介于 0(0% 占空比)和 3685(100% 占空比)之间。这接近 12 位的分辨率,与我们的 12 位模拟测量非常匹配。PWM 信号是通过将误差信号(模拟控制测量 - 模拟反馈测量)乘以比例项常数生成的。选择比例项值是通过反复试验完成的,多种值提供了平滑控制。
PWM 输出 = 比例项 *(模拟控制 - 模拟反馈)
PWM 输出必须限制在不超过 +3685 且不低于 -3685 以使其保持在 PWM 模块的 100% 占空比值的边界内(20 KHz 时) )。这也在固件中处理。
除了 MC33926PNB-ND 内置的保护功能外,如果负载电流超过约 2 A,则负载电流会受到监控以关闭电机。MC33926PNB-ND 提供电机负载电流的 0.24% 的比例反馈电流。一个 270 欧姆的电阻器将反馈电流转换为由 dsPIC33 监控的电压。在 2 A 时,该电压为 1.296 V,或 1608 位(使用 dsPIC33 上的 12 位 AD)(3.3V/4096 = 0.805mV/位)。反馈电流是粗略测量,在 500 mA 以上时精度仅为 ±20%。但是,它对于保护控制系统仍然有用。
图 1:闭环比例控制器示例。
在测试此设计时,我们使用了具有 65.5:1 齿轮比的 Pittman GM9236S025-R1 12 V 减速电机。齿轮比阻止了快速响应,如下面的斜坡波形测试信号(图 3)所示,但在其他方面创建了强大的伺服系统。反馈是通过直接连接到电机轴的电位计传递的。12 V 电机电压由 5 V 线性稳压器(示意图中未显示)降压,进而为板载 3.3 V 线性稳压器供电。
图 2:伺服对正弦控制信号的响应。
图 3:伺服对斜坡控制信号的响应。
物理原型
此设计的原型被放置在一个 24 引脚、600 mil 宽的 DIP 封装中。2 层板的布线包括一个串行通信端口、限位开关输入连接、一个正交编码器端口,以及读取持续时间为 5 µs 至 20 ms 的脉冲的能力。
电路板上还布置了连接,以允许使用各种 Microchip 工具进行调试。该设计是使用 MPLAB ICD3 调试器 / 编程器完成的。
固件
本设计的固件是使用 Microchip 的 C30 C 编译器(版本 3.25)的免费评估版编写的。MPLAB IDE 版本 8.66.00.00 用作开发环境。调试和编程是使用在固件版本 1.26.52 上运行的 MPLAB ICD3 完成的。
此处列出的固件执行具有模拟控制输入和模拟反馈的简单运动控制系统。比例控制以及过温、过流和欠压保护均在固件或硬件中实现。下面提供的固件可用作使用相同硬件的更复杂系统的起点。
事实上,该硬件用于实现完整的 PID 控制算法,具有串行命令接口和多种控制和反馈选项。该设计目前由 Solutions Cubed, LLC 制造,作为 Synaptron 高准控制器。
//------------------------------------------------ ---------
//
//------------------------- ------------------------------
// 应包含以下文件在 MPLAB 项目中:
//
// synaptron_opensource_01.c -- 主源代码文件
// traps.c -- dsPIC33F 陷阱的显式定义
// p33FJ64MC802.h -- dsPIC 的头文件
// p33FJ64MC802.gld -- 链接描述文件文件
//------------------------------------------------ --------------------
// 修订历史
// 1/10/12 -- synaptron_opensource_01.c -- 初始实现
//-------- -------------------------------------------------- ----------
#define FCY 36850000ULL
#include “p33FJ64MC802.h” // 寄存器位定义在这里
/******************** *************************************************
配置位和定义语句
************************************************ ***********************/
/* 振荡器设置 */
_FOSCSEL(FNOSC_FRCPLL & IESO_OFF);
_FOSC(FCKSM_CSDCMD & OSCIOFNC_ON & POSCMD_NONE & IOL1WAY_OFF);
/* 上电复位 */
_FPOR( PWMPIN_ON & HPOL_OFF & LPOL_OFF & ALTI2C_OFF & FPWRT_PWR32)
/* 看门狗定时器 */
_FWDT(FWDTEN_ON & WINDIS_OFF & WDTPRE_PR32 & WDTPOST_PS64);
/* 代码保护 */
_FBS(BWRP_WRPROTECT_OFF);
_FSS(SWRP_WRPROTECT_OFF);
_FGS(GWRP_OFF);
/* 程序/调试 */
_FICD(ICS_PGD1 & JTAGEN_OFF);
/* 应用程序定义语句、变量、常量 */
#define FAULT PORTBbits.RB12
#define ENABLE PORTBbits.RB13
#define PWMSTATE_STOPPED 0x0000
#define PWMSTATE_FORWARD 0x0201
#define PWMSTATE_REVERSE 0x0102
unsigned int AnalogControl = 0;
无符号整数模拟反馈 = 0;
无符号整数模拟电流 = 0;
无符号整数 ProportionalTerm = 0;
整数 PWM 输出 = 0;
/************************************************* ************************
初始化例程
**************************** *****************************************/
/******* ****************************************************** ************
函数:InitTimer5
说明:初始化 Timer5 为 250uS 定时器,无中断
************************* ************************************************/
void InitTimer5( void )
{
T5CON = 0; // 确保定时器 5 处于复位状态
IFS1bits.T5IF = 0; // 复位定时器 5 中断标志
IPC7bits.T5IP = 5; // 设置 Timer5 中断优先级为 5
PR5 = 9212; // 设置 Timer5 周期寄存器
T5CONbits.TCKPS1 = 0; // 选择 Timer5 输入时钟预分频比 1:1
T5CONbits.TCS = 0; // 选择外部定时器时钟
T5CONbits.TON = 1; // 启用定时器 5 并开始计数
IEC1bits.T5IE = 0; // 禁用定时器 5 中断
}
/****************************************** ******************************
函数:InitPLL()
说明:初始化振荡器和PLL设置并等待锁定。处理器将以 36.85MIPS 运行。
****************************************************** *******************/
void InitPLL()
{
// 7.37MHz / 2 * 40 / 2 FCY = FOSC/2 = 36.85MIPS
CLKDIVbits.PLLPRE = 0; //N1 = 2 VCO 分频器 = /2
PLLFBDbits.PLLDIV = 38;//40x 乘数
CLKDIVbits.PLLPOST = 0; //N2 = 2 PLL 输入分频器 = 2
while(OSCCONbits.LOCK != 1);
}
/****************************************************** ************************ 函数:InitIO()
说明:初始化引脚方向(输入/输出)和电压。
****************************************************** *******************/
void InitIO()
{
TRISAbits.TRISA0 = 1; // 控制电压输入
TRISAbits.TRISA1 = 1; // 反馈电压输入
LATA = 0xFFFF;
TRISBbits.TRISB2 = 1;// 未使用
的 TRISBbits.TRISB3 = 1; // 当前电压输入
TRISBbits.TRISB4 = 1; // 未使用
的 TRISBbits.TRISB5 = 1; // 没用过
TRISBbits.TRISB6 = 1;// 未使用
的 TRISBbits.TRISB7 = 1; // 未使用
的 TRISBbits.TRISB8 = 1; // 未使用
的 TRISBbits.TRISB9 = 1; // 未使用
的 TRISBbits.TRISB10 = 1; // 未使用
的 TRISBbits.TRISB11 = 1; // 未使用
的 TRISBbits.TRISB12 = 1; // 故障输入
TRISBbits.TRISB13 = 0; // 使能输出
TRISBbits.TRISB14 = 0; // PWM1L 输出
TRISBbits.TRISB15 = 0; // PWM1H 输出
LATB = 0x1FFF;
}
/****************************************************** ************************
函数:InitADC()
说明:初始化 ADC 模块以进行 12 位操作
************* ****************************************************** ******/
无效初始化ADC(无效)
{
AD1CON1 = 0;// 清除控制寄存器
AD1CON2 = 0;
AD1CON3 = 0;
AD1CHS0 = 0x0000;// 通道选择 AN0
AD1PCFGL = 0xFFFF; // 模拟输入配置为数字
AD1PCFGLbits.PCFG0 = 0; // AN0 模拟
AD1PCFGLbits.PCFG1 = 0; // AN1 模拟
AD1PCFGLbits.PCFG5 = 0; // AN5 模拟
AD1CON1bits.AD12B = 1; // 12 位,1 通道操作
AD1CON1bits.FORM = 0; // 整数结果
AD1CON1bits.SSRC = 0; //清除样本位开始conv。
AD1CON1bits.ASAM = 0;// 设置采样位时采样
AD1CON2bits.CSCNA = 0; // 禁用通道扫描
AD1CON2bits.VCFG = 0; // AVDD 和 AVSS 是参考
AD1CON3bits.ADRC = 0; // 时钟来自系统时钟
AD1CON3bits.ADCS = 0x2f;// ADC 转换时钟
AD1CON1bits.ADON = 1; // 开启 ADC 模块
}
/****************************************** ******************************
函数:void InitMCPWM(void)
说明:初始化电机控制脉宽调制模块为20KHz。
****************************************************** ******************/
void InitMCPWM(void)
{
P1TCON = 0x8000; // PWM 为自由运行模式,1:1 TCY
PWM1CON1 = 0x0111; // 使能 PWM1L 和 PWM1H
// 将它们配置为独立模式
PWM1CON2 = 0x0000; // 实现 20 kHz
P1DTCON1 = 0x0028; // 2 us 死区时间
P1DTCON2 = 0x0000;
P1FLTACON = 0x0000;// 初始化故障控制
PTPER = FCY/20000 - 1;// 计算周期
P1OVDCON = PWMSTATE_STOPPED; // 禁用 PWM1 输出。
P1DC1 = 0; // 将占空比设置为 0
}
/********************************************** ******************************
程序例程
******************** *************************************************/
/************************************************* ********************
函数:ReadAnalog()
说明:收集模拟值并对误差信号进行比例乘法。如果电流超过 2A +/- 20%,还会测量电机电流并关闭电机驱动器。
****************************************************** *******************/
void ReadAnalog(void)
{
无符号整数采样时间 = 0;
AD1CHS0 = 0x0000;// 通道选择 AN0 (引脚 RA0)
AD1CON1bits.SAMP = 1;
while (SampleTime 《 100) // 为采样时间提供 》5uS
SampleTime++;
AD1CON1bits.SAMP = 0;
而(!AD1CON1bits.DONE);
模拟控制 = ADC1BUF0;// 将转换存储在寄存器
AD1CHS0 = 0x0001; // 通道选择 AN1 (引脚 RA1)
AD1CON1bits.SAMP = 1;
采样时间 = 0;// 提供 》5uS 的采样时间 while (SampleTime 《 100)
SampleTime++;
AD1CON1bits.SAMP = 0;
而(!AD1CON1bits.DONE);
模拟反馈 = ADC1BUF0;// 将转换存储在寄存器
AD1CHS0 = 0x0005; // 通道选择 AN5 (引脚 RB3)
AD1CON1bits.SAMP = 1;
采样时间 = 0;// 提供 》5uS 的采样时间 while (SampleTime 《 100)
SampleTime++;
AD1CON1bits.SAMP = 0;
而(!AD1CON1bits.DONE);
模拟电流 = ADC1BUF0;// 将转换存储在寄存器
ProportionalTerm = 10; // 设置比例值
PWMOutput=(int(ProportionalTerm*(AnalogControl-AnalogFeedback));
// 确保 PWM 信号不超过 100%
if (PWMOutput 》 3685)
PWMOutput = 3685;
if (PWMOutput 《 -3685)
PWMOutput = -3685 ;
if (AnalogCurrent 》 1600) // 1600 大约等于 2A.
PWMOutput = 0;
}
/**************************** *****************************************
函数:MotorControl()
说明:该子程序检查故障条件,如果存在故障,则禁用 H 桥。如果没有故障情况,则 H 桥模块配置为适当的方向,并且 PWMOutput 中的 PWM 信号应用于电机。请注意,PWM 值被反转以应用适当的输出信号,如果发生故障,H 桥将在控制环路计时器结束后重新启用。
****************************************************** *******************/
void MotorControl(void)
{
if (FAULT == 0) // 故障条件下的故障输入 0V
{
PWMOutput = 0; // 如果发生故障,禁用电机输出。
启用 = 0; // 禁用 H 桥
}
if (PWMOutput》0)
P1OVDCON = PWMSTATE_FORWARD;// 设置为正向
if (PWMOutput《0)
{
P1OVDCON = PWMSTATE_REVERSE; // 设置为反向
PWMOutput = -PWMOutput; // 反转 PWM 信号
}
if (PWMOutput == 0)
P1OVDCON = PWMSTATE_STOPPED; // 停止 H 桥
P1DC1 = 3685 - PWMOutput; // 设置 PWM 值
}
/************************************************ ******************************
主程序
********************** ***********************************************/
int main (void)
{
InitPLL(); // 初始化 PLL,等待 lock
InitIO(); // 初始化 i/os
InitADC(); // 初始化 ADC
InitTimer5(); // 初始化一个定时器
初始化MCPWM(); // 初始化 PWM
while (1)
{
asm(“clrwdt”); // 清除看门狗定时器
if (IFS1bits.T5IF == 1) // 检查控制循环定时器
{
IFS1bits.T5IF = 0; // 清除下一个循环的标志
ENABLE = 1; // 启用 H 桥
ReadAnalog(); // 获取模拟读数
MotorControl(); // 设置 PWM 驱动信号
}
}
}
评论
查看更多