1.背景
前几天找出个步进电机,用l298n驱动测试了一下,具体见上篇文章简单的步进电机驱动调试。但是l298n无法实现细分控制,在低速转动时,声音比较大,且振动厉害,因此想着尝试一下细分控制效果。于是花十二块大洋某宝购买了一块t“mc2209步进电机超静音驱动模块”来测试一下。
2.硬件及连接
2.1硬件
art-pi、tmc2209模块、dc12v电源。
2.2接口连接
tmc2009模块的接口连接如下:
3.原理介绍
3.1 tmc2209模块介绍
tmc2209是triaminic推出的一款步进电机驱动模块。驱动模块静音且高精度,可以实现高达1/256步细分控制,实现更平滑静音的步进电机控制。模块内嵌12.5 mhz的内部振荡器,简单串行数据传输的uart。性价比较高的步进电机驱动模块。
3.2 tmc2209规格
工作电压:5.5 – 38v
最大内部时钟频率:12.5 mhz
每相最大电流:2 a
峰值输出电流:2.8a
逻辑工作电压:3/5v
3.3 tmc2209针脚定义
3.4 微步细分配置
1)硬件细分配置
tmc2209模块提供了硬件微步配置,通过ms1和ms2可以实现1/8、1/16、1/32、1/64的细分控制,具体如下:
2)软件细分配置
如果想实现更高的细分控制,则需要通过usart口进行配置,具体如下:
(测试中,测试完完善进来)
4.程序代码
4.1 tmc2209初始化
//硬件微步设置
void micro_step_set(rt_uint8_t step)
{
switch (step) {
case 8:
rt_pin_write(ms1_pin, pin_low);
rt_pin_write(ms2_pin, pin_low);
break;
case 16:
rt_pin_write(ms1_pin, pin_high);
rt_pin_write(ms2_pin, pin_high);
break;
case 32:
rt_pin_write(ms1_pin, pin_high);
rt_pin_write(ms2_pin, pin_low);
break;
case 64:
rt_pin_write(ms1_pin, pin_low);
rt_pin_write(ms2_pin, pin_high);
break;
default:
break;
}
}
static int tmc2209_init(void)
{
rt_pin_mode(en_pin, pin_mode_output);
rt_pin_mode(ms1_pin, pin_mode_output);
rt_pin_mode(ms2_pin, pin_mode_output);
rt_pin_mode(step_pin, pin_mode_output);
rt_pin_mode(dir_pin, pin_mode_output);
rt_pin_write(en_pin, pin_low);
micro_step_set(micro_step);
hwtimer_init();
return 0;
}
init_app_export(tmc2209_init);
4.2 pwm设置
这里采用了pwm(art-pi默认的pwm5通道1)来输出脉冲信号控制步进电机的转动速度,下面是使用函数:
int pwm_set(rt_uint16_t fre, rt_uint8_t duty_cycle)
{
rt_uint32_t period = 0;
rt_uint32_t pulse = 0;
pwm_dev = (struct rt_device_pwm )rt_device_find(pwm_dev_name);
if (pwm_dev == rt_null)
{
rt_kprintf(pwm sample run failed! can't find %s device!n, pwm_dev_name);
return rt_error;
}
period = 1000000000 / fre;
pulse = period * duty_cycle / 100;
/ 设置pwm周期和脉冲宽度默认值 /
rt_pwm_set(pwm_dev, pwm_dev_channel, period, pulse);
/ 使能设备 */
rt_pwm_enable(pwm_dev, pwm_dev_channel);
return 0;
}
4.3 定时器配置
这里采用硬件定时器(art-pi默认tim13,ps:settings虽然可以直接配置,但是cubemx默认没配置tim13,所以直接使用还是不行,需要cubemx配置后才能使用)来控制pwm输出指定的脉冲数量,通过计算步进电机转动的角度所需要的脉冲个数,以及转动速度计算的脉冲时间,计算出定时器的计时时间,超时后停止pwm输出,并禁止tmc2209(不禁止的话电机会发热)。
#define hwtimer_dev_name timer13 /* 定时器名称 /
/ 定时器超时回调函数 /
static rt_err_t timeout_cb(rt_device_t dev, rt_size_t size)
{
rt_pwm_disable(pwm_dev, pwm_dev_channel);//停止pwm输出
rt_pin_write(en_pin, pin_high);//禁止tmc2209
return 0;
}
int hwtimer_init(void)
{
rt_err_t ret = rt_eok;
rt_hwtimer_mode_t mode; / 定时器模式 /
rt_uint32_t freq = 1000000; / 计数频率 /
/ 查找定时器设备 /
hw_dev = rt_device_find(hwtimer_dev_name);
if (hw_dev == rt_null)
{
rt_kprintf(hwtimer sample run failed! can't find %s device!n, hwtimer_dev_name);
return rt_error;
}
/ 以读写方式打开设备 /
ret = rt_device_open(hw_dev, rt_device_oflag_rdwr);
if (ret != rt_eok)
{
rt_kprintf(open %s device failed!n, hwtimer_dev_name);
return ret;
}
/ 设置超时回调函数 /
rt_device_set_rx_indicate(hw_dev, timeout_cb);
/ 设置计数频率(若未设置该项,默认为1mhz 或 支持的最小计数频率) /
rt_device_control(hw_dev, hwtimer_ctrl_freq_set, &freq);
/ 设置模式为周期性定时器(若未设置,默认是hwtimer_mode_oneshot)*/
mode = hwtimer_mode_oneshot;
ret = rt_device_control(hw_dev, hwtimer_ctrl_mode_set, &mode);
if (ret != rt_eok)
{
rt_kprintf(set mode failed! ret is :%dn, ret);
return ret;
}
return ret;
}
int hwtimer_start(rt_hwtimerval_t timeout)
{
if (rt_device_write(hw_dev, 0, &timeout, sizeof(timeout)) != sizeof(timeout))
{
rt_kprintf(set timeout value failedn);
return rt_error;
}
return rt_eok;
}
4.4 步进电机控制
这里采用了两种方式来输出脉冲及数量,一种是通过延时和翻转dir管脚电平实现,一种是通过定时器和pwm来实现。
/*
dir:电机转动方向,0 正转;1 反转
speed:电机转动速度:0-300r/min,注意不同的电机最高转速不一样
angle:电机转动角度:°
/
void turn_control(rt_uint8_t dir, rt_uint16_t speed, float_t angle)
{
rt_uint32_t pulse_num = 0;//脉冲数量
rt_uint16_t delay_time = 0;
rt_uint16_t pulse_fre = 0;//脉冲频率
rt_hwtimerval_t timeout_value;
float_t temp = 0.0;
temp = (angle / (360.0 / 200.0 / micro_step));
float_t t = 1000000 / ((360.0 / (360.0 / 200.0 / micro_step)) / 60.0 * speed);
pulse_num = temp;
delay_time = t / 2;
pulse_fre = 1000000 / t;
timeout_value.sec = 0;
timeout_value.usec = t * pulse_num;
//rt_kprintf(%dn, pulse_num);
//rt_kprintf(%dn, delay_time);
//rt_kprintf(%dn, pulse_fre);
//rt_kprintf(%dn, timeout_value.usec);
rt_pin_write(en_pin, pin_low);
//设置电机转动方向
if(dir == 0)
rt_pin_write(dir_pin, pin_high);
if(dir == 1)
rt_pin_write(dir_pin, pin_low);
pwm_set(pulse_fre, 50);//设置pwm频率并输出
hwtimer_start(timeout_value);//设置定时时间并启动定时器
/ for (int i = 0; i < pulse_num; ++i) {
rt_pin_write(step_pin, pin_low);
//rt_thread_mdelay(speed);
rt_hw_us_delay(delay_time);
rt_pin_write(step_pin, pin_high);
//rt_thread_mdelay(speed);
rt_hw_us_delay(delay_time);
}
rt_pin_write(en_pin, pin_high);*/
}
4.5 msh控制台
这里把电机控制加入msh指令,可以通过控制台来手动实现电机任意控制测试:
static void step_motor_turn(int argc, char**argv)
{
if (argc < 3)
{
rt_kprintf(please input'step_motor_turn direction speed angle'n);
return;
}
if (!rt_strcmp(argv[1], forward))
{
turn_control(0, atof(argv[2]), atof(argv[3]));
}
else if (!rt_strcmp(argv[1], reverse))
{
turn_control(1, atoi(argv[2]), atof(argv[3]));
}
else
{
rt_kprintf(please input'step_motor_turn direction speed angle'n);
}
}
msh_cmd_export(step_motor_turn, step_motor_turn );
5.总结
电机的转动确实非常安静,完全听不到声音,在低速控制时转动也比较平滑,完全感受不到振动。性价比不错,有需要做步进电机控制的小伙伴可以参考使用。
一种可编程宽带放大器的设计
aigo固态硬盘S500的上手体验:花小钱带来大满足
AN-653: 改善高动态范围均方根射频功率检波器的温度稳定性和线性度
DM7276/DM7275高精度直流电压计的功能特性及特点
英国首个人工智能技术开发出的药物即将进入临床测试阶段 AI制药将获突破
Art-Pi+TMC2209步进电机细分控制测试
电动汽车的平台化
华为智慧屏V65尊爵版开启预售 售价7999元
将socket程序从linux移植到windows上
重磅!新材料技术应用大会即将召开!齐聚30+院士聚焦材料前沿
FedEx着手区块链争端解决平台试点计划
2018年MCU的涨价潮已成定局,今年恐将缺货一整
有媒体报道称,内存和闪存价格将分别上涨30%、20%
TCL液晶彩电IPL32C电源与逆变器板维修
燃气表智能化标准的详细解读
几种数字卫星接收机开关电源典型故障检修
前端技术是什么
iPhone8发布会正在直播:iPhone8外观、配色、性能全面升级,银色、金色、灰色无腮红金
浅析应用于智能楼宇的物联网新技术
Zynq Petalinux编译用户自定义系统