直流有刷空心杯驱动
- 空心杯电机
- 一、原理图
- 二、有刷电机代码
- 总结
空心杯电机
心杯电动机属于直流永磁的伺服、控制电动机,也可以将其归类为微特电机。空心杯电动机具有突出的节能特性、灵敏方便的控制特性和稳定的运行特性,技术先进性十分明显。作为高效率的能量转换装置,在很多领域代表了电动机的发展方向。空心杯电动机在结构上突破了传统电机的转子结构形式,采用的是无铁芯转子,也叫空心杯型转子。这种新颖的转子结构彻底消除了由于铁芯形成涡流而造成的电能损耗。同时其重量和转动惯量大幅降低,从而减少了转子自身的机械能损耗。由于转子的结构变化而使电动机的运转特性得到了极大改善,不但具有突出的节能特点,更为重要的是具备了铁芯电动机所无法达到的控制和拖动特性。空心杯电机分为有刷和无刷两种,有刷空心杯电机转子无铁芯,无刷空心杯电机定子无铁芯。绕组采用三角形接法。空心杯电动机主要有以下特性:
1、节能特性:能量转换效率很高,其最大效率一般在70%以上,部分产品可达到90%以上(铁芯电动机一般在70%)。
2、控制特性:起动、制动迅速,响应极快,机械时间常数小于28毫秒,部分产品可以达到10毫秒以内(铁芯电动机一般在100毫秒以上);在推荐运行区域内的高速运转状态下,可以方便地对转速进行灵敏的调节。
3、拖动特性:运行稳定性十分可靠,转速的波动很小,作为微型电动机其转速波动能够容易的控制在2%以内。
另外,空心杯电动机的能量密度大幅度提高,与同等功率的铁芯电动机相比,其重量、体积减轻1/3-1/2
由于空心杯电动机克服了有铁芯电动机不可逾越的技术障碍,而且其突出的特点集中在电动机的主要性能方面,使其具备了广阔的应用领域。尤其是随着工业技术的飞速发展,对电动机的伺服特性不断提出更高的期望和要求,使空心杯电动机在很多应用场合拥有不可替代的地位。
空心杯电动机的应用,从军事、高科技领域进入大工业和民用领域后,十多年来得到迅速的发展,尤其是在工业发达国家,已经涉及到大部分行业和许多产品。
1、需要快速响应的随动系统。如导弹的飞行方向快速调节,高倍率光驱的随动控制,快速自动调焦,高灵敏的记录和检测设备,工业机器人,仿生义肢等,空心杯电动机能很好地满足其技术要求。
2、对驱动元件要求平稳持久拖动的产品。如各类便携式的仪器仪表,个人随身装备,野外作业的仪器设备,电动车等,同样一组电源,供电时间可以延长一倍以上。
3、各种飞行器,包括航空、航天、航模等。利用空心杯电动机重量轻,体积小,能耗低的优点,可以最大限度地减轻飞行器的重量。
4、各种各样的民用电器、工业产品。采用空心杯电动机作为执行元件,可以使产品档次提高,性能优越。
5、利用其能量转换效率高的优势,也作为发电机使用;利用其线性运行特性,也作为测速发电机使用;配上减速器,也可以作为力矩电动机使用。
随着工业技术进步,各种机电设备严格的技术条件对伺服电动机提出越来越高的技术要求,同时,空心杯电动机的应用范围已经完全脱离了高端产品的局限性,正在迅速地扩大在一般民用等低端产品上的应用范围,以广泛提升产品品质。据有关资料统计,在工业发达国家已经有100多种民用产品上成熟应用了空心杯电动机 [2] 。
空心杯电机应用于移液枪中,原因在于直径小可以做到16mm,转速高,带减速箱后扭矩加大可以带动丝杆做移液操作,电机屁股后端加编码器可以实现位置,速度,电流三环控制。国外高端移液枪使用步进电机,空心杯有刷电机及直线电机的都有产品。其中基于直线电机的8.5mm方案最具科技感,目前在国内没有销售。
国内做空心杯电机的商家有鸣志,万至达,鑫宝达,鼎智,五颗星等。空心杯电机包括有刷和无刷两种类型。国外的品牌如Maxon,其配套驱动器价格贵。
本文基于TI DRV8876有刷伺服芯片,开发有刷驱动器,实现对空心杯有刷电机的闭环位置控制。
一、原理图
DRV8876适用于24V,2A以内直流有刷伺服电机驱动,应用于移液枪项目中非常合适。单片机中编写有刷电机控制环路实现位置环,速度环,电流环。
二、有刷电机代码
代码如下(示例):
volatile int g_timx_encode_count = 0; /* 溢出次数 */
uint8_t g_run_flag = 0;
/** * @brief 电机停止 * @param 无 * @retval 无 */
void dcmotor_stop(void)
{
TIM4->CCR1 = 0;
TIM4->CCR2 = 0;
HAL_TIM_PWM_Stop(&htim4,TIM_CHANNEL_1);
HAL_TIM_PWM_Stop(&htim4,TIM_CHANNEL_2);
}
void dcmotor_dir(uint8_t para)
{
HAL_TIM_PWM_Stop(&htim4,TIM_CHANNEL_1);
HAL_TIM_PWM_Stop(&htim4,TIM_CHANNEL_2);
if (para == 0) /* 正转 */
{
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);
}
else if (para == 1) /* 反转 */
{
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_2);
}
}
/** * @brief 电机速度设置 * @param para:比较寄存器值 * @retval 无 */
void dcmotor_speed(uint16_t para)
{
if (para < (__HAL_TIM_GetAutoreload(&htim4) - 0x0F)) /* 限速 */
{
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_1, para);
}
}
/** * @brief 电机控制 * @param para: pwm比较值 ,正数电机为正转,负数为反转 * @note 根据传入的参数控制电机的转向和速度 * @retval 无 */
void motor_pwm_set(float para)
{
int val = (int)para;
if (val >= 0)
{
// dcmotor_dir(0); /* 正转 */
// dcmotor_speed(val);
// if (val < (__HAL_TIM_GetAutoreload(&htim4) - 0x0F)) /* 限速 */
// {
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);
HAL_TIM_PWM_Stop(&htim4,TIM_CHANNEL_2);
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_1, val);
// }
}
else
{
// dcmotor_dir(1); /* 反转 */
// dcmotor_speed(-val);
val = -val;
// if (val < (__HAL_TIM_GetAutoreload(&htim4) - 0x0F)) /* 限速 */
// {
HAL_TIM_PWM_Stop(&htim4,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_2);
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_2, val);
// }
}
}
/************************************* 第三部分 编码器测速 ****************************************************/
Motor_TypeDef g_motor_data; /*电机参数变量*/
ENCODE_TypeDef g_encode; /*编码器参数变量*/
/** * @brief 电机速度计算 * @param encode_now:当前编码器总的计数值 * ms:计算速度的间隔,中断1ms进入一次,例如ms = 5即5ms计算一次速度 * @retval 无 */
void speed_computer(int32_t encode_now, uint8_t ms)
{
uint8_t i = 0, j = 0;
float temp = 0.0;
static uint8_t sp_count = 0, k = 0;
static float speed_arr[10] = {
0.0}; /* 存储速度进行滤波运算 */
if (sp_count == ms) /* 计算一次速度 */
{
/* 计算电机转速 第一步 :计算ms毫秒内计数变化量 第二步 ;计算1min内计数变化量:g_encode.speed * ((1000 / ms) * 60 , 第三步 :除以编码器旋转一圈的计数次数(倍频倍数 * 编码器分辨率) 第四步 :除以减速比即可得出电机转速 */
g_encode.encode_now = encode_now; /* 取出编码器当前计数值 */
g_encode.speed = (g_encode.encode_now - g_encode.encode_old); /* 计算编码器计数值的变化量 */
speed_arr[k++] = (float)(g_encode.speed * ((1000 / ms) * 60.0) / REDUCTION_RATIO / ROTO_RATIO ); /* 保存电机转速 */
g_encode.encode_old = g_encode.encode_now; /* 保存当前编码器的值 */
/* 累计10次速度值,后续进行滤波*/
if (k == 10)
{
for (i = 10; i >= 1; i--) /* 冒泡排序*/
{
for (j = 0; j < (i - 1); j++)
{
if (speed_arr[j] > speed_arr[j + 1]) /* 数值比较 */
{
temp = speed_arr[j]; /* 数值换位 */
speed_arr[j] = speed_arr[j + 1];
speed_arr[j + 1] = temp;
}
}
}
temp = 0.0;
for (i = 2; i < 8; i++) /* 去除两边高低数据 */
{
temp += speed_arr[i]; /* 将中间数值累加 */
}
temp = (float)(temp / 6); /*求速度平均值*/
/* 一阶低通滤波 * 公式为:Y(n)= qX(n) + (1-q)Y(n-1) * 其中X(n)为本次采样值;Y(n-1)为上次滤波输出值;Y(n)为本次滤波输出值,q为滤波系数 * q值越小则上一次输出对本次输出影响越大,整体曲线越平稳,但是对于速度变化的响应也会越慢 */
g_motor_data.speed = (float)( ((float)0.48 * temp) + (g_motor_data.speed * (float)0.52) );
k = 0;
}
sp_count = 0;
}
sp_count ++;
}
/** * @brief 获取编码器的值 * @param 无 * @retval 编码器值 */
int gtim_get_encode(void)
{
return ( int32_t )__HAL_TIM_GET_COUNTER(&htim3) + g_timx_encode_count * 65536; /* 总的编码器值 = 当前计数值 + 之前累计编码器的值 */
}
void SPEED_LOOP(void)
{
static uint8_t val = 0;
int Encode_now = gtim_get_encode(); /* 获取编码器值,用于计算速度 */
speed_computer(Encode_now, 1); /* 中位平均值滤除编码器抖动数据,5ms计算一次速度 */
if (val % SMAPLSE_PID_SPEED == 0) /* 进行一次pid计算 */
{
if (g_run_flag) /* 判断电机是否启动了 */
{
g_motor_data.location = (float)Encode_now; /* 获取当前编码器总计数值,用于位置闭环控制 */
integral_limit(&g_location_pid , 10000 ,-10000); /* 位置环积分限幅 */
integral_limit(&g_speed_pid , 10000 ,-10000); /* 速度环积分限幅 */
integral_limit(&g_current_pid , 10000 ,-10000); /* 电流环积分限幅 */
// if( (g_location_pid.Error <= 2) && (g_location_pid.Error >= -2) ) /* 设置闭环死区 */
// {
// g_location_pid.Error = 0; /* 偏差太小了,直接清零 */
// g_location_pid.SumError = 0; /* 清除积分 */
// }
//
// g_motor_data.motor_pwm = increment_pid_ctrl(&g_location_pid, g_motor_data.location); /* 位置环PID控制(最外环) */
//
// if (g_motor_data.motor_pwm >= 2000) /* 限制外环输出(目标速度) */
// {
// g_motor_data.motor_pwm = 2000;
// }
// else if (g_motor_data.motor_pwm <= -2000)
// {
// g_motor_data.motor_pwm = -2000;
// }
//
// g_speed_pid.SetPoint = g_motor_data.motor_pwm; /* 设置目标速度,外环输出作为内环输入 */
g_motor_data.motor_pwm = increment_pid_ctrl(&g_speed_pid, g_motor_data.speed); /* 速度环PID控制(次外环) */
// if ( g_motor_data.motor_pwm > 0) /* 判断速度环输出值是否为正数 */
// {
// dcmotor_dir(0); /* 输出为正数,设置电机正转 */
// }
// else
// {
// g_motor_data.motor_pwm = -g_motor_data.motor_pwm; /* 输出取反 */
// dcmotor_dir(1); /* 设置电机反转 */
// }
// if (g_motor_data.motor_pwm >= 100) /* 限制外环输出(目标电流) */
// {
// g_motor_data.motor_pwm = 100;
// }
g_current_pid.SetPoint = g_motor_data.motor_pwm; /* 设置目标电流,外环输出作为内环输入 */
g_motor_data.motor_pwm = increment_pid_ctrl(&g_current_pid, g_motor_data.current); /* 电流环PID控制(内环) */
if (g_motor_data.motor_pwm >= 3600) /* 限制外环输出(目标速度) */
{
g_motor_data.motor_pwm = 3600;
}
else if (g_motor_data.motor_pwm <= -3600)
{
g_motor_data.motor_pwm = -3600;
}
motor_pwm_set(g_motor_data.motor_pwm); /* 设置占空比 */
}
val = 0;
}
val ++;
}
总结
本文实现了直流有刷空心杯电机的位置,速度,电流三环控制。有兴趣的朋友可以合作交流技术。
今天的文章直流无刷空心杯电机_0408空心杯最低驱动电压分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/58709.html