基于STM32F103+TMC2160:86步进电机和驱动一体原理图/PCB图/教程/源码/数据手册等开源分享 资料下载见附件,电脑登入 CUBE界面引脚配置: 定时器1的PWM输出通道1设置:9 Q5 d1 Z- a; Y2 {" J8 T( N; x; E # ^% E* j+ r! x( V0 g. B/ C |
【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的收发通信经验分享
/**
* 函数功能: 定时器中断服务函数
* 输入参数: 无
* 返 回 值: 无4 ]4 T) e5 ^3 R; |& R1 g& y
* 说 明: 实现加减速过程
*/
void STEPMOTOR_TIMx_IRQHandler(void)//定时器中断处理 K% ]+ J* d' k
{
__IO uint16_t tim_count=0;; x4 A. ~" \; e
// 保存新(下)一个延时周期
uint16_t new_step_delay=0;6 v& y: N3 Y Y, A! C6 ^8 a! s l4 M
// 加速过程中最后一次延时(脉冲周期).8 H* R' q, V7 q$ W8 \# y( W/ l% X
__IO static uint16_t last_accel_delay=0;
// 总移动步数计数器/ Z$ m/ w8 c* y) I8 P9 D8 k
__IO static uint32_t step_count = 0;1 {. ^# d8 L/ J
// 记录new_step_delay中的余数,提高下一步计算的精度
__IO static int32_t rest = 0;
//定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲* I0 E1 L. Z6 [( ]) y( o
__IO static uint8_t i=0;
, P- ]/ G* ~4 b5 F7 k
if(__HAL_TIM_GET_IT_SOURCE(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx) !=RESET)& v+ ?' y# R- l5 Q3 u
{
// 清楚定时器中断/ i* _; r3 f8 D! r% V
__HAL_TIM_CLEAR_IT(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx);
0 r2 d" a$ f. L: D L) p+ J" G
// 设置比较值
tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);( F" D# @: v( b7 A
__HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay);# Y! j- i4 z' M/ o1 u
i++; // 定时器中断次数计数值2 X: |9 L3 U' \4 Z
if(i==2) // 2次,说明已经输出一个完整脉冲, c/ \! A) r$ F. {
{
i=0; // 清零定时器中断次数计数值
switch(srd.run_state) // 加减速曲线阶段/ r3 m/ ]* X/ m2 q
{
case STOP:/ B2 }5 ^' ^5 G" p4 |0 x
step_count = 0; // 清零步数计数器& `; j/ B9 d4 }+ N1 ?
rest = 0; // 清零余值( N: a! M6 m$ o5 o \4 e
// 关闭通道* ^6 j: H& m9 q5 ~# f. O, B4 s0 T
TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_DISABLE); ; {+ {& @, b6 K- B; h
__HAL_TIM_CLEAR_FLAG(&htimx_STEPMOTOR, STEPMOTOR_TIM_FLAG_CCx);
STEPMOTOR_OUTPUT_DISABLE();
MotionStatus = 0; // 电机为停止状态 * v3 Y7 P( r, k9 W0 Z$ v
break;) T2 a4 ]6 Y9 k. W$ i7 S
case ACCEL:
step_count++; // 步数加1! h$ R* X. }' S h2 q
if(srd.dir==CW)
{ V5 \' n G& T/ Y$ j3 O# E, V L
step_position++; // 绝对位置加1
}
else
{; \8 B# P/ V K& T
step_position--; // 绝对位置减1
}# ?" `$ {# z& i- ?( e
srd.accel_count++; // 加速计数值加1
new_step_delay = srd.step_delay - (((2 *srd.step_delay) + rest)/(4 * srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔); [& _" H9 K# ?+ T( Q# E
rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差; o. ?0 D' E5 B' H' j; ~! u
if(step_count >= srd.decel_start)// 检查是够应该开始减速$ G! ~& Y( Z4 z$ p+ A
{( k3 p8 G, w+ l
srd.accel_count = srd.decel_val; // 加速计数值为减速阶段计数值的初始值
srd.run_state = DECEL; // 下个脉冲进入减速阶段 ?( o' X5 Z) k& e! j5 B' I! u: h
}
else if(new_step_delay <= srd.min_delay) // 检查是否到达期望的最大速度5 V' I: N" Y: _& b7 k+ w
{2 `& j6 m- j ^7 n# v, x1 o
last_accel_delay = new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)/ a7 Z, L3 T' H! V
new_step_delay = srd.min_delay; // 使用min_delay(对应最大速度speed)( d) P; {4 s$ R- h
rest = 0; // 清零余值
srd.run_state = RUN; // 设置为匀速运行状态# Q+ H& Q$ c: W% [
}
break;
6 K @- S2 B) f
case RUN:
step_count++; // 步数加1
if(srd.dir==CW)$ w" ~: W& ]* I; ?/ _6 O. C
{
step_position++; // 绝对位置加1
}5 H8 J3 M" F. u% G( O2 M: \
else
{$ {1 `' v6 N3 t
step_position--; // 绝对位置减1# \5 s# w, x+ S5 o
}0 y# W" @7 e; G- Q! n
new_step_delay = srd.min_delay; // 使用min_delay(对应最大速度speed)( B! A: }2 R- h. y
if(step_count >= srd.decel_start) // 需要开始减速1 m' _) S) O ?
{; r9 r! f" W+ k1 v4 Y, ?
srd.accel_count = srd.decel_val; // 减速步数做为加速计数值$ g' @' V# r" E
new_step_delay = last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)
srd.run_state = DECEL; // 状态改变为减速, U i/ J g1 V/ b9 n! O
}. J6 S d6 m, u9 v& |* N: E+ {
break;1 o, A8 k$ `& z; M0 o) B( d0 i
; W8 u: L# Y( `
case DECEL:- h: c; l: ^# K& `
step_count++; // 步数加1
if(srd.dir==CW)
{
step_position++; // 绝对位置加1# o# y8 e' t# e( ]$ L4 A
}
else
{5 Q" Y, a' S8 \$ v
step_position--; // 绝对位置减1
}6 f" t' C6 g" _% k* _# [
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);// 计算余数,下次计算补上余数,减少误差: H b( U. U+ G: ^6 B: q t
0 |! N/ v, U; b. a) @5 S7 Y! u' ~
//检查是否为最后一步
if(srd.accel_count >= 0)1 N$ ~2 l6 q. J7 X( c m
{% _; P% P% t, R) K1 T8 X
srd.run_state = STOP;; _- B7 Y q7 p! t
}/ C3 h# g' w% S; U2 z
break;% L, |8 |/ {+ k
} 4 ]- {. \# X1 x6 Q
srd.step_delay = new_step_delay; // 为下个(新的)延时(脉冲周期)赋值
}4 G6 x& n9 ~2 `$ y8 g q* z
}
}
/**
* 函数功能: 相对位置运动:运动给定的步数
* 输入参数: step:移动的步数 (正数为顺时针,负数为逆时针).
accel 加速度,实际值为accel*0.1*rad/sec^2+ B- ]( i* v% x; }
decel 减速度,实际值为decel*0.1*rad/sec^2) t, n2 q: R* ^4 `3 ~- E/ Y( T
speed 最大速度,实际值为speed*0.1*rad/sec
* 返 回 值: 无
* 说 明: 以给定的步数移动步进电机,先加速到最大速度,然后在合适位置开始. Q2 Z# y" z2 K% f
* 减速至停止,使得整个运动距离为指定的步数。如果加减速阶段很短并且
* 速度很慢,那还没达到最大速度就要开始减速2 J/ D/ T0 O: V" t
*/2 W4 }- `" A1 ~- ~; x
void STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)
{ + f* u3 w3 x1 k* G6 f' v! U8 y
__IO uint16_t tim_count;; ?7 i4 _. j# P
// 达到最大速度时的步数7 ~! e+ o _, Q; f
__IO uint32_t max_s_lim;
// 必须要开始减速的步数(如果加速没有达到最大速度)
__IO uint32_t accel_lim;! t, _8 D0 V i
1 E) q0 ~0 `' ^1 s% w
if(step < 0) // 步数为负数$ z' N) V) y. s
{. T( V& m4 x' t' N+ ] B! A
srd.dir = CCW; // 逆时针方向旋转" K1 }6 @) O5 b# u6 K, x6 I( R
STEPMOTOR_DIR_REVERSAL();
step =-step; // 获取步数绝对值
}
else: @# H9 d9 v' Z
{9 g* R! \- O# f
srd.dir = CW; // 顺时针方向旋转$ \3 F8 i0 f# t9 b2 A
STEPMOTOR_DIR_FORWARD();
}1 l8 u _+ T. Z+ }
9 o' c# C7 H& ^' O" L6 w. P
if(step == 1) // 步数为1
{
srd.accel_count = -1; // 只移动一步# j6 Z" n: Q4 q; `7 j
srd.run_state = DECEL; // 减速状态.
srd.step_delay = 1000; // 短延时
}
else if(step != 0) // 如果目标运动步数不为0/ v B& A, v& n5 l, P; q
{
// 我们的驱动器用户手册有详细的计算及推导过程0 v0 T# i4 n# }# f& R; S' t
# I3 X( F( @% f
// 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
// min_delay = (alpha / tt)/ w0 u: d# O) ^2 e# ` j
srd.min_delay = (int32_t)(A_T_x10/speed);/ X4 n& m1 |: n- e5 c
// 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2
// step_delay = 1/tt * sqrt(2*alpha/accel) y/ M8 j6 j( F7 w7 n1 x/ K5 E
// 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);* b7 ?" Z" h! w7 f, Q
3 g1 i/ A$ z8 f5 x0 o
// 计算多少步之后达到最大速度的限制2 E: {' x! O8 N, H" n2 d0 W
// max_s_lim = speed^2 / (2*alpha*accel)
max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));3 }6 C S& R6 A. e% O
// 如果达到最大速度小于0.5步,我们将四舍五入为0
// 但实际我们必须移动至少一步才能达到想要的速度; ]6 U1 f7 u" P' O. U1 ^8 i
if(max_s_lim == 0){
max_s_lim = 1;
}
// n1 = (n1+n2)decel / (accel + decel)/ u9 B) o; S, h' y' K. {+ v$ N7 L
accel_lim = (uint32_t)(step*decel/(accel+decel));& [) h/ ~/ g. s2 s% W6 H
// 我们必须加速至少1步才能才能开始减速.
if(accel_lim == 0){
accel_lim = 1;
}# H; }2 h1 ?5 D, f: M- z9 q
// 使用限制条件我们可以计算出减速阶段步数. w/ j; c- v; o3 N4 s
if(accel_lim <= max_s_lim){
srd.decel_val = accel_lim - step;0 p9 G4 ?+ X, c/ F, k
}8 Y& j. H; z5 ?( Q" _! W5 `
else{4 Q {8 C$ Y: W% v! Z5 H% x
srd.decel_val = -(max_s_lim*accel/decel);( Q( [7 g/ R+ ~) A+ A8 p
}) d/ h9 h5 g; `1 R1 {* r
// 当只剩下一步我们必须减速
if(srd.decel_val == 0){5 y" c0 \* e( a5 q J
srd.decel_val = -1;! M \- O+ E5 I& B/ ~& X
}9 \" T0 o. X: g. s- X: q" t
+ E9 Y' b% B% u
// 计算开始减速时的步数
srd.decel_start = step + srd.decel_val;. R2 R* b/ L {& G/ ?6 q% @
// 如果最大速度很慢,我们就不需要进行加速运动
if(srd.step_delay <= srd.min_delay){
srd.step_delay = srd.min_delay;( Y+ v# A& b+ b+ |! J( H8 ]
srd.run_state = RUN;
}
else{
srd.run_state = ACCEL;5 k4 t E/ q o% k3 C6 c7 _
} V# p: W6 x1 A3 Z
// 复位加速度计数值1 |6 C8 T; ^; o- @5 \) g
srd.accel_count = 0;
}$ [8 N L9 G0 T- t8 i' ^: {
MotionStatus = 1; // 电机为运动状态% O7 q8 C1 o$ P
tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);
__HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay); // 设置定时器比较值
TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_ENABLE); // 使能定时器通道
STEPMOTOR_OUTPUT_ENABLE();
}
1、机器人和工业驱动器, m* Y. {/ p) i% Z$ _
2、纺织、缝纫机
3、包装机械 G' Q2 Z. d' Y# y# q( X# Y
4、工厂和实验室自动化) m+ }6 g1 H: B/ w0 s; J
5、高速 3D 打印机
6、液体处理
7、医疗9 e/ \" t \- Y$ j. S- d! d
8、办公自动化: H/ Z+ U$ D/ b& p5 _/ H
9、有线闭路电视
10、自动取款机、现金回收
11、泵和阀门
电机驱动主芯片采用TMC2160
TMC2160和5160区别:5160带UART控制及智能定位控制(如速度控制、位置控制);
TMC2160和TMC260 TMC262区别:以前版本需要通过SPI接口设置细分、电流等,新的TMC2160可通过拨码开关设置;, q5 k3 B: ]) g! C- q
) U% y5 h1 r" S3 Y. i, `
有条件的输入输出最好加些滤波和保护,输出加脉冲整形(比如加74HC14)
+ O0 e7 q, H) T6 P
拨码开关ON:设置为高电平1,反之低电平01 L7 l! I' n6 _
细分设置:CFG1、CFG0
CFG1、CFG0:, W4 G- p% y; j* [$ b8 d
11:64细分5 _9 Z* L6 G/ u& Z% J+ f6 C, l
10:32细分
01:16细分/ \; [7 W+ \9 u
00:8细分* R6 U3 w {1 ^: e! ~" \2 D
运行电流设置:CFG4、CFG3、CFG28 Z! i) O3 l/ ~# K
CFG4、CFG3、CFG2:
111:IRUN=31
110:IRUN=28/ S6 [* [" ?0 x& n' E( y- N- [
101:IRUN=26
100:IRUN=24
011:IRUN=22
010:IRUN=20+ l8 F( g% e2 y1 h! d& e
001:IRUN=18
000:IRUN=16$ M. y7 I3 ]' L5 ?
Irms=Vfs/(IRUN/32)/(Rsense*1.414); 6 M9 D) y; ^1 V" v- p
Vfs =325mV,Rsense为0.05欧时,则最大电流为4.5A左右;- @0 P3 P2 m4 I& f* d8 M
CFG5:
1:SpreadCyle模式,低速、低平稳运行模式4 @$ ?( e) ], A
0:SpreadCyle模式,高速、高运动稳定模式7 T# c/ R( ^- k: P2 @7 w
保持电流设置:CFG6: L% e' t! \# P9 ?- [2 L
CFG6:/ Q: L0 ]. o# R. G( n3 `% o
1:保持电流=运行电流/2, _% W) r8 Q" r% `0 J
0:保持电流=运行电流& L, L% N/ K7 W2 J- A* P% o6 ^
DIR+STEP接口模式位置控制(无需SPI接口)
COM端:接24V或12V或5V
DRV_ENN、STER、DIR:接集电极开路输出5 `' P1 D' }# v& q6 B1 V0 J1 z: o0 B
为测试方便:
COM端:接3.3V
DRV_ENN:使能,接PB14
DIR:方向, PB15! {4 e6 R* F- @
STEP:脉冲,PA8- Q/ S# J* k, s4 j7 [* `& ]