基于STM32F103+TMC2160:86步进电机和驱动一体原理图/PCB图/教程/源码/数据手册等开源分享 资料下载见附件,电脑登入 CUBE界面引脚配置: 定时器1的PWM输出通道1设置:+ `. \; `+ u) U& i3 s* \ 3 B1 k" O/ m! Y- u0 R |
【MCU实战经验】+STM32F103的uCOSII详细移植
小马哥STM32F103开源小四轴RoboFly全部资料大放送
在高容量 STM32F103xx 微控制器中实现 ADPCM 算法
STM32F103标准库开发---SPI实验---读写 W25Q128 外部 Flash
RT-Thread在STM32F103RC上移植
STM32固件库分享,超全系列整理
【原创】STM32F103的SPI2的配置函数,DMA发送和接收!
【源代码】STM32F103C8T6最小板搞定CMSIS-DAP和SWO功能
【福利】用STM32库的朋友有福了:STM32F10x_StdPeriph_Lib_V3.5.0chm...
基于STM32F103做CAN的收发通信经验分享
/**# ^7 {: L. g* D
* 函数功能: 定时器中断服务函数) o2 u; v" c) i, Z F' A1 I5 ^
* 输入参数: 无
* 返 回 值: 无
* 说 明: 实现加减速过程
*/9 e+ S# Y5 n. G+ ~& g! g
void STEPMOTOR_TIMx_IRQHandler(void)//定时器中断处理
{ 9 G: z/ \9 t5 Q; [8 O6 L$ g
__IO uint16_t tim_count=0;
// 保存新(下)一个延时周期
uint16_t new_step_delay=0;9 S( G, {+ @( j k- h' E
// 加速过程中最后一次延时(脉冲周期).9 T2 G! K8 w4 c. I. b. @
__IO static uint16_t last_accel_delay=0;) i4 j" [2 ?8 g1 Q
// 总移动步数计数器
__IO static uint32_t step_count = 0;
// 记录new_step_delay中的余数,提高下一步计算的精度
__IO static int32_t rest = 0;3 V B7 v; j! J) c$ m; Y
//定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲: Y( f0 [0 K/ _/ L+ Y8 A6 U2 }
__IO static uint8_t i=0;
0 _4 |/ M0 _5 H9 R. S5 K
if(__HAL_TIM_GET_IT_SOURCE(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx) !=RESET)9 \6 s# E; j1 D
{
// 清楚定时器中断
__HAL_TIM_CLEAR_IT(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx);9 B* e& T* ^$ v+ G
// 设置比较值0 ]( C2 \) g9 r, ?9 F. \6 Y6 _
tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);
__HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay);7 g0 A+ n( C9 ^2 b6 @, q, v9 A/ B2 O
i++; // 定时器中断次数计数值2 [. i2 x- e0 w, j3 P1 c* W
if(i==2) // 2次,说明已经输出一个完整脉冲
{& N1 W) ?9 P' j7 | X! C
i=0; // 清零定时器中断次数计数值
switch(srd.run_state) // 加减速曲线阶段
{! k7 ^; F: m7 a6 N" S+ v
case STOP:" c# |1 f! ^5 T( @" g7 O
step_count = 0; // 清零步数计数器/ P5 i; L" p5 b4 ]5 k
rest = 0; // 清零余值4 @; ?& d2 L0 b# R6 `: e
// 关闭通道
TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_DISABLE); " T5 `3 E9 W* R2 `1 N" Q4 K' d
__HAL_TIM_CLEAR_FLAG(&htimx_STEPMOTOR, STEPMOTOR_TIM_FLAG_CCx);9 R5 n; N: [$ c" W" K( D
STEPMOTOR_OUTPUT_DISABLE();2 i' ]7 m, r: w2 @) f0 ]$ R. ]
MotionStatus = 0; // 电机为停止状态
break;
: u. ]3 M0 ]0 M; V
case ACCEL:
step_count++; // 步数加1' f6 x' O: X7 C/ Z8 H$ ?* T) Y
if(srd.dir==CW)
{ 3 o, }# U$ C$ S# F2 ~
step_position++; // 绝对位置加1, s& v8 i _# [$ B7 B
}1 n! o2 N8 j) C/ ^1 V
else
{
step_position--; // 绝对位置减1* G; g# ^# I7 H% g+ a, J6 u% l5 o* I
}( v) ?0 f4 v9 k2 H- @* x
srd.accel_count++; // 加速计数值加1
new_step_delay = srd.step_delay - (((2 *srd.step_delay) + rest)/(4 * srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔)
rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差; _! _" a4 j# ?' ]0 A9 u
if(step_count >= srd.decel_start)// 检查是够应该开始减速, q, `( H) T$ a/ u
{
srd.accel_count = srd.decel_val; // 加速计数值为减速阶段计数值的初始值
srd.run_state = DECEL; // 下个脉冲进入减速阶段
}! H2 W" E9 ]& G& {1 y
else if(new_step_delay <= srd.min_delay) // 检查是否到达期望的最大速度3 @, J% h# B+ Z: `! _- J, ]
{
last_accel_delay = new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)0 i3 q9 m+ u1 X! f# {! J* Y/ R
new_step_delay = srd.min_delay; // 使用min_delay(对应最大速度speed)/ R0 F' w6 Z9 a$ o" G
rest = 0; // 清零余值, d( T1 ~8 D8 F+ p7 p% q
srd.run_state = RUN; // 设置为匀速运行状态, Y5 _; _: p$ t# [2 ~' Z
}) v8 `1 ^8 C% I/ f1 W9 `
break;
case RUN:
step_count++; // 步数加1: o5 q1 P$ H. R- J
if(srd.dir==CW)
{
step_position++; // 绝对位置加1
}
else9 q! F0 g: x7 O5 r" Q% d) {
{" \) R8 R+ T4 L7 Z! j- s# H9 b
step_position--; // 绝对位置减1/ d' z( x' Z' P
}9 k$ d7 w- b/ n
new_step_delay = srd.min_delay; // 使用min_delay(对应最大速度speed)# X; t, @& G* J. f
if(step_count >= srd.decel_start) // 需要开始减速! J. W* I& F! F7 L, f4 S
{
srd.accel_count = srd.decel_val; // 减速步数做为加速计数值
new_step_delay = last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)
srd.run_state = DECEL; // 状态改变为减速
}
break;
0 Y: f3 v+ ], }# I7 o4 T( y9 ]
case DECEL:
step_count++; // 步数加1& @& `7 z6 o& p+ M
if(srd.dir==CW)
{
step_position++; // 绝对位置加14 D8 y& B$ f# n# p( c
}
else
{
step_position--; // 绝对位置减1
}# n+ g) u7 X V/ a3 @
srd.accel_count++;
new_step_delay = srd.step_delay - (((2 * srd.step_delay) + rest)/(4 * srd.accel_count + 1)); //计算新(下)一步脉冲周期(时间间隔)
rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差) n6 y6 ^; C, |. ?8 l
//检查是否为最后一步3 a5 c6 J$ b& l: M# e1 N
if(srd.accel_count >= 0)- Y. I' y$ s1 H6 y) Q. l
{
srd.run_state = STOP;: Y& k: R$ U3 n- }. V3 L) b
}# k# e) q9 x5 N& r* Y
break;3 _* B! b) y+ p! P
}
srd.step_delay = new_step_delay; // 为下个(新的)延时(脉冲周期)赋值- {, w, X# ?* U4 ?8 w
}
}
}' @. W6 W, p' Y& x
/**
* 函数功能: 相对位置运动:运动给定的步数
* 输入参数: step:移动的步数 (正数为顺时针,负数为逆时针).
accel 加速度,实际值为accel*0.1*rad/sec^2
decel 减速度,实际值为decel*0.1*rad/sec^2
speed 最大速度,实际值为speed*0.1*rad/sec" J4 l7 [; a8 b3 J
* 返 回 值: 无/ T8 ?% C2 L/ ]' d
* 说 明: 以给定的步数移动步进电机,先加速到最大速度,然后在合适位置开始
* 减速至停止,使得整个运动距离为指定的步数。如果加减速阶段很短并且) A7 p" D* }3 ]6 @: |
* 速度很慢,那还没达到最大速度就要开始减速
*// d; O$ t2 v# ]0 W4 I( R0 Y" ^! i
void STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)7 y+ j$ I7 D5 W$ y0 A2 i
{ 2 n# V* B5 H0 _! T$ z. f( M
__IO uint16_t tim_count;
// 达到最大速度时的步数1 c) c7 @8 [, e/ k7 k; Y
__IO uint32_t max_s_lim;
// 必须要开始减速的步数(如果加速没有达到最大速度)
__IO uint32_t accel_lim;
8 P2 d4 K7 P: Z3 B
if(step < 0) // 步数为负数7 Z% s4 O" U2 S% q* W# J% T2 q6 C" X
{
srd.dir = CCW; // 逆时针方向旋转
STEPMOTOR_DIR_REVERSAL();
step =-step; // 获取步数绝对值% A9 [* Z9 } J# ?
}
else
{
srd.dir = CW; // 顺时针方向旋转
STEPMOTOR_DIR_FORWARD();
}
+ {) v* s% N! u7 L# z( V4 M6 V" [- g
if(step == 1) // 步数为1 k9 S9 T6 t: J* ^
{
srd.accel_count = -1; // 只移动一步
srd.run_state = DECEL; // 减速状态.
srd.step_delay = 1000; // 短延时 ' y8 z( [ ^# m/ M* J
}
else if(step != 0) // 如果目标运动步数不为0# ]4 m5 B# n$ E! P
{
// 我们的驱动器用户手册有详细的计算及推导过程
7 h3 N3 F2 U0 e
// 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
// min_delay = (alpha / tt)/ w6 m' N8 S; A: j
srd.min_delay = (int32_t)(A_T_x10/speed);0 W8 [) v; ]. l0 t1 [1 g& v$ d" ~
// 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2# j& g/ l. x) B4 G
// step_delay = 1/tt * sqrt(2*alpha/accel)
// step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100
srd.step_delay = (int32_t)((T1_FREQ_148 * sqrt(A_SQ / accel))/10);
8 _, N9 `7 t6 W8 v& M
// 计算多少步之后达到最大速度的限制1 B8 Y& {: a6 f' n: ~
// max_s_lim = speed^2 / (2*alpha*accel)
max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));* J/ ?9 k, Z2 H5 {7 S; q" H
// 如果达到最大速度小于0.5步,我们将四舍五入为0 S1 _1 |, @- A! i$ ?+ k0 N2 _
// 但实际我们必须移动至少一步才能达到想要的速度1 |2 N. K' n' @8 ^' C
if(max_s_lim == 0){- v5 q2 |' h; U% p) m
max_s_lim = 1;5 G4 W: m3 T' u5 Z0 d
}* \9 R+ k" e5 W
// n1 = (n1+n2)decel / (accel + decel)3 b. ^, ]' Q- B: |( l8 j9 K* z
accel_lim = (uint32_t)(step*decel/(accel+decel));/ U" D' u* W( W: B% V( f9 p
// 我们必须加速至少1步才能才能开始减速.: N* w( {& {* V+ w$ @+ D/ T5 c' t; Q
if(accel_lim == 0){" I" S% G; U- v# V% M1 d6 X. w% X( u
accel_lim = 1;" S& t* t6 |" k. l$ w
}9 ]+ m+ j3 \4 r
/ _' Q# h3 ]. n1 {& \
// 使用限制条件我们可以计算出减速阶段步数* D* b5 l l/ u2 v" G
if(accel_lim <= max_s_lim){
srd.decel_val = accel_lim - step;
}
else{
srd.decel_val = -(max_s_lim*accel/decel);( ~4 [9 \' r. v) D
}
// 当只剩下一步我们必须减速/ p0 p4 a& y1 l9 y
if(srd.decel_val == 0){
srd.decel_val = -1;4 P Q A; O& q% r j! k
}
// 计算开始减速时的步数
srd.decel_start = step + srd.decel_val;. j9 x$ I- [" a) E
// 如果最大速度很慢,我们就不需要进行加速运动
if(srd.step_delay <= srd.min_delay){
srd.step_delay = srd.min_delay;
srd.run_state = RUN;
}% ^3 L* k+ c5 I/ n. I7 q
else{7 c2 l" t, H& ?/ U
srd.run_state = ACCEL;' `# t6 o! B7 q" O- p
}
// 复位加速度计数值! t+ a& o, P6 u1 e
srd.accel_count = 0;
}
MotionStatus = 1; // 电机为运动状态
tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);
__HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay); // 设置定时器比较值# j0 P9 l5 w& W/ {
TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_ENABLE); // 使能定时器通道
STEPMOTOR_OUTPUT_ENABLE();
}$ t9 `' H6 y, C, C2 J! _
1、机器人和工业驱动器8 P9 a C4 T9 {9 E* @
2、纺织、缝纫机
3、包装机械
4、工厂和实验室自动化' l! ^ I+ K: S( }
5、高速 3D 打印机
6、液体处理2 l7 t" }9 g/ S2 w& g* p
7、医疗# _0 Q( O; m" G9 j& J
8、办公自动化$ @" U0 T( J, z; R( }* Z
9、有线闭路电视
10、自动取款机、现金回收7 l M6 @: a; F$ B" @( Y7 j6 `
11、泵和阀门
电机驱动主芯片采用TMC2160) L0 l" t( s6 p
TMC2160和5160区别:5160带UART控制及智能定位控制(如速度控制、位置控制);! p9 p- @! T0 ^: @
TMC2160和TMC260 TMC262区别:以前版本需要通过SPI接口设置细分、电流等,新的TMC2160可通过拨码开关设置;4 l' Y; g( |7 J+ `# W
有条件的输入输出最好加些滤波和保护,输出加脉冲整形(比如加74HC14)
拨码开关ON:设置为高电平1,反之低电平05 [% t+ a4 H) o
细分设置:CFG1、CFG0
CFG1、CFG0:: F1 ^. d5 ^. F1 L% g
11:64细分
10:32细分
01:16细分
00:8细分
运行电流设置:CFG4、CFG3、CFG2
CFG4、CFG3、CFG2:4 _! k2 V; y* T& T
111:IRUN=31# O: i+ w% a# V/ C
110:IRUN=28
101:IRUN=26$ ~8 D2 x" d. q# A7 b/ A2 j
100:IRUN=24
011:IRUN=22
010:IRUN=20
001:IRUN=18
000:IRUN=16( e) a% z. h: J0 [
Irms=Vfs/(IRUN/32)/(Rsense*1.414); + p3 V! @. w1 l' l: B. E3 }
Vfs =325mV,Rsense为0.05欧时,则最大电流为4.5A左右;$ L* x5 i3 Y) w- a( ]1 F8 y3 I% w
CFG5:
1:SpreadCyle模式,低速、低平稳运行模式! _; X8 ? f; g& {
0:SpreadCyle模式,高速、高运动稳定模式
保持电流设置:CFG6
CFG6:
1:保持电流=运行电流/2
0:保持电流=运行电流
DIR+STEP接口模式位置控制(无需SPI接口)
COM端:接24V或12V或5V
DRV_ENN、STER、DIR:接集电极开路输出
为测试方便:' S( Q+ Q8 p7 u/ A6 j
COM端:接3.3V5 o/ n5 C) p3 w
DRV_ENN:使能,接PB140 {5 P3 i8 E, r+ \
DIR:方向, PB15( [. Z2 C+ b0 f) z) H9 P# q
STEP:脉冲,PA8