基于STM32F103+TMC2160:86步进电机和驱动一体原理图/PCB图/教程/源码/数据手册等开源分享 资料下载见附件,电脑登入 CUBE界面引脚配置: 定时器1的PWM输出通道1设置: 6 g0 @/ Z- ?1 M! u& F4 w4 v) W: D |
【MCU实战经验】+STM32F107的USB使用
基于STM32F103两轮平衡小车设计(开源)
STM32固件库分享,超全系列整理
STM32F107VCT6官方原理图和PCB
【福利】用STM32库的朋友有福了:STM32F10x_StdPeriph_Lib_V3.5.0chm...
小马哥STM32F103开源小四轴RoboFly全部资料大放送
基于STM32F10xx存储器和系统架构经验分享
基于STM32F1的CAN通信之BH1750
基于STM32F1的CAN通信之OLED
基于STM32F1的CAN通信之之串口IAP
/**
* 函数功能: 定时器中断服务函数$ N1 {/ _- {1 |! F8 ~# @1 I/ l1 |
* 输入参数: 无; L; C! l' R v
* 返 回 值: 无: P/ W/ S; r3 B [5 P H
* 说 明: 实现加减速过程7 d% U. r2 F& _- ?* [5 R
*/; k1 g4 \5 U' j% p6 T$ B3 z, e7 J8 f
void STEPMOTOR_TIMx_IRQHandler(void)//定时器中断处理- S B! ^7 N* s8 K
{ ; e; t' o/ I! z1 E1 _
__IO uint16_t tim_count=0;
// 保存新(下)一个延时周期8 i! _# `( Y% m; R
uint16_t new_step_delay=0;
// 加速过程中最后一次延时(脉冲周期).# _7 J: ?: O* U
__IO static uint16_t last_accel_delay=0;
// 总移动步数计数器# V4 V; H& a( @2 Q. C
__IO static uint32_t step_count = 0;
// 记录new_step_delay中的余数,提高下一步计算的精度
__IO static int32_t rest = 0;8 z# `: ?/ b$ x
//定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲
__IO static uint8_t i=0;
0 s3 O# T: E( A3 O+ G5 F% r( q- F7 t
if(__HAL_TIM_GET_IT_SOURCE(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx) !=RESET)
{
// 清楚定时器中断% _& m |2 e/ ?5 L& \
__HAL_TIM_CLEAR_IT(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx);* X8 u+ f( _% g5 H6 E( N3 Z5 I) m
2 i+ c- I( I9 E; k6 k {6 k
// 设置比较值
tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);
__HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay);/ @; R3 c; ? ?' a2 l
0 N/ }* L+ C- x( b
i++; // 定时器中断次数计数值
if(i==2) // 2次,说明已经输出一个完整脉冲
{
i=0; // 清零定时器中断次数计数值
switch(srd.run_state) // 加减速曲线阶段! ]4 S; w4 l8 l& W
{2 i1 r K- y5 f$ W% b
case STOP:. H' ~) o- g; d5 a' w: S
step_count = 0; // 清零步数计数器
rest = 0; // 清零余值
// 关闭通道
TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_DISABLE); 8 K( k! a+ G+ t! R$ g& w
__HAL_TIM_CLEAR_FLAG(&htimx_STEPMOTOR, STEPMOTOR_TIM_FLAG_CCx);
STEPMOTOR_OUTPUT_DISABLE();( J+ V$ K" w4 Y
MotionStatus = 0; // 电机为停止状态
break;4 Z- O6 O. f+ N6 `* l
; f- C$ w! F& t/ G3 y; N( t2 n$ a
case ACCEL:0 |' C5 A6 b% L$ d! c( k- y8 a: _. M
step_count++; // 步数加12 z9 G0 }) T. O& }
if(srd.dir==CW)
{ 7 V m. s F6 U q+ g; Q {! _
step_position++; // 绝对位置加1
}# [# y/ W' X' Y6 g: N+ M
else; H' n/ V, \% h
{
step_position--; // 绝对位置减12 Y- e% U: F- _* N. S% r
}
srd.accel_count++; // 加速计数值加1
new_step_delay = srd.step_delay - (((2 *srd.step_delay) + rest)/(4 * srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔)! n! p5 I' s% o/ k8 b
rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差* x; `* u( Q5 A- G/ z
if(step_count >= srd.decel_start)// 检查是够应该开始减速4 @0 \% [# |, T% N( D
{& H9 h* ^/ W9 \0 k0 ~
srd.accel_count = srd.decel_val; // 加速计数值为减速阶段计数值的初始值
srd.run_state = DECEL; // 下个脉冲进入减速阶段
}
else if(new_step_delay <= srd.min_delay) // 检查是否到达期望的最大速度
{
last_accel_delay = new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)( F2 k* Q* O8 E+ `
new_step_delay = srd.min_delay; // 使用min_delay(对应最大速度speed)& t6 ?6 p% ?" a4 w7 F- L3 J: N
rest = 0; // 清零余值
srd.run_state = RUN; // 设置为匀速运行状态3 l+ J7 r7 k: b- z6 |- Z- F' x
}
break;! a- E7 W0 ^: o9 Q. J/ N
case RUN:* {/ |! D& N, k& X
step_count++; // 步数加12 \/ G1 I9 r- `. N) M. O
if(srd.dir==CW)
{ / `% l3 A* a8 x3 L( Y V
step_position++; // 绝对位置加1
}. H8 [. b$ C% I- g# j0 W+ t
else3 d( W! l* ~6 k$ t
{
step_position--; // 绝对位置减1
}6 w5 |, G" f' f# a8 m# l
new_step_delay = srd.min_delay; // 使用min_delay(对应最大速度speed)8 P; R! N2 [ S0 }# t+ ?/ ?
if(step_count >= srd.decel_start) // 需要开始减速
{/ x( W# G" P. |, j5 h# }
srd.accel_count = srd.decel_val; // 减速步数做为加速计数值
new_step_delay = last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)
srd.run_state = DECEL; // 状态改变为减速
}6 a% m3 Z- `8 o. K! J" B
break;9 g, R3 A+ V: O& Z
case DECEL:
step_count++; // 步数加1. H% J" P6 b( l1 }
if(srd.dir==CW)
{ 8 P, g: [- K1 u* k3 b5 t
step_position++; // 绝对位置加1* W/ t3 [) q$ U" d( {! T5 B
}: @/ R! C7 P# d3 i# i! A
else+ G' i( ?4 \: }/ p# |# G% u/ r+ m2 Y$ r
{
step_position--; // 绝对位置减1
}* b$ h. L( H" v1 i* M
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);// 计算余数,下次计算补上余数,减少误差, t. z0 @3 k0 [
# `! i% E9 |! o1 A B# c/ `
//检查是否为最后一步( m$ l8 H1 n3 ?; z# t
if(srd.accel_count >= 0)
{' s- n+ C/ X' }
srd.run_state = STOP;
}' M+ x- c+ }% j U( D5 t. I
break;
} 2 R( {4 p& |# u
srd.step_delay = new_step_delay; // 为下个(新的)延时(脉冲周期)赋值
}; ~' t6 W/ d) X; ^" M& W
}6 k$ N" q) Z4 {: Z- R
}
/**
* 函数功能: 相对位置运动:运动给定的步数0 G/ W* u; t: |% u3 V
* 输入参数: step:移动的步数 (正数为顺时针,负数为逆时针).9 A$ }) F6 \* D& N) y4 A+ m
accel 加速度,实际值为accel*0.1*rad/sec^2/ o$ Z" i! R5 X% ?$ h3 t' r, R7 @$ m
decel 减速度,实际值为decel*0.1*rad/sec^24 k. h' V( {3 |3 g4 F3 Z6 q
speed 最大速度,实际值为speed*0.1*rad/sec4 ?2 N4 W+ c& u% t2 v
* 返 回 值: 无
* 说 明: 以给定的步数移动步进电机,先加速到最大速度,然后在合适位置开始
* 减速至停止,使得整个运动距离为指定的步数。如果加减速阶段很短并且4 ^ Z7 d& ?$ Z u* Z4 h6 B0 l5 @
* 速度很慢,那还没达到最大速度就要开始减速
*/
void STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)
{
__IO uint16_t tim_count;
// 达到最大速度时的步数
__IO uint32_t max_s_lim;: m* z3 X% Y/ r7 K( s6 j' x
// 必须要开始减速的步数(如果加速没有达到最大速度)
__IO uint32_t accel_lim;
if(step < 0) // 步数为负数4 p' s( e& [( c
{
srd.dir = CCW; // 逆时针方向旋转/ K J. J3 L( e/ U. m3 Z
STEPMOTOR_DIR_REVERSAL();
step =-step; // 获取步数绝对值
}
else
{
srd.dir = CW; // 顺时针方向旋转
STEPMOTOR_DIR_FORWARD();# D4 n2 u9 N2 }; a1 J- E. `7 Y
}
if(step == 1) // 步数为1
{' M; ~0 e5 O3 M6 {! O* A
srd.accel_count = -1; // 只移动一步, N! X$ c2 g* _7 s. l
srd.run_state = DECEL; // 减速状态.
srd.step_delay = 1000; // 短延时 - q4 P5 A5 m, ?* X2 t- U
}
else if(step != 0) // 如果目标运动步数不为01 i8 Y3 @2 ~1 ?- Q
{
// 我们的驱动器用户手册有详细的计算及推导过程
r) K! T; s, R
// 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
// min_delay = (alpha / tt)/ w
srd.min_delay = (int32_t)(A_T_x10/speed);
& Y5 u' k- A' b4 ~5 v
// 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2$ A0 }$ Q, T1 b) f
// 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);7 w T2 L: ~4 H8 _* \' J# n
3 ]+ D' s8 U; h3 {1 J& ~
// 计算多少步之后达到最大速度的限制
// max_s_lim = speed^2 / (2*alpha*accel)+ L0 i, l s2 C4 @" G
max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));) `) |/ F. m, g j6 v Q
// 如果达到最大速度小于0.5步,我们将四舍五入为0
// 但实际我们必须移动至少一步才能达到想要的速度
if(max_s_lim == 0){
max_s_lim = 1;( l; ?$ b% Z) G# u- P' _3 K! M
}
// n1 = (n1+n2)decel / (accel + decel)4 Y4 F$ {/ I- R9 }6 M5 W
accel_lim = (uint32_t)(step*decel/(accel+decel));3 Q8 ]3 L3 K" G- v+ m
// 我们必须加速至少1步才能才能开始减速.8 ]$ H6 J! D+ m d) \
if(accel_lim == 0){
accel_lim = 1;2 P( {( G6 b8 N4 s& {3 X* B
}
0 P. {) S# D4 U& I
// 使用限制条件我们可以计算出减速阶段步数
if(accel_lim <= max_s_lim){
srd.decel_val = accel_lim - step;: B+ N, a c, a) d
}& ^9 L2 a3 H; V0 B" K3 q
else{
srd.decel_val = -(max_s_lim*accel/decel);4 ^# i" Y. X" D4 P( E" x. m
}
// 当只剩下一步我们必须减速5 `1 x, T" G @* B& h
if(srd.decel_val == 0){
srd.decel_val = -1;% F& `: X: b, O9 [
}
// 计算开始减速时的步数
srd.decel_start = step + srd.decel_val;
0 h& q5 E& y/ O3 d7 a F6 u
// 如果最大速度很慢,我们就不需要进行加速运动
if(srd.step_delay <= srd.min_delay){
srd.step_delay = srd.min_delay;4 ?3 ?; ]9 {# K7 B8 f$ ?
srd.run_state = RUN;
}
else{% i3 w1 M; Y/ b0 |
srd.run_state = ACCEL;% F3 m" ]5 C- B1 Z. a0 z. `6 ^
}
// 复位加速度计数值
srd.accel_count = 0;
}
MotionStatus = 1; // 电机为运动状态
tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);% C* B% j3 t ? L5 q
__HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay); // 设置定时器比较值+ U' X; @ L) Z
TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_ENABLE); // 使能定时器通道
STEPMOTOR_OUTPUT_ENABLE();
}/ x* A' E7 o' _; |
1、机器人和工业驱动器
2、纺织、缝纫机
3、包装机械
4、工厂和实验室自动化+ f* r- g) S" k
5、高速 3D 打印机/ f- D$ L6 W: J5 `: [8 H( M+ g
6、液体处理3 Y# D. q' {1 l$ i- X; D* ?
7、医疗. ]1 t; d; e! B4 }: [9 s. W
8、办公自动化* \0 K0 A- i) i: Q& W
9、有线闭路电视: k: B8 F' n0 u
10、自动取款机、现金回收* q; _5 ~+ F. R- {% m
11、泵和阀门
电机驱动主芯片采用TMC21605 `) q$ i7 u! A9 P; m' _) |
TMC2160和5160区别:5160带UART控制及智能定位控制(如速度控制、位置控制);$ W* L2 z. R4 K: Y! z
TMC2160和TMC260 TMC262区别:以前版本需要通过SPI接口设置细分、电流等,新的TMC2160可通过拨码开关设置;
有条件的输入输出最好加些滤波和保护,输出加脉冲整形(比如加74HC14)
拨码开关ON:设置为高电平1,反之低电平04 P' j" X% m( L" E$ l
细分设置:CFG1、CFG05 U8 V9 O5 j7 u. E) J
CFG1、CFG0:" _& X' p6 Z) ^
11:64细分) i5 G( M) O) H2 g' l% n. v+ {
10:32细分
01:16细分
00:8细分+ g! P2 r: w. J0 `6 e
运行电流设置:CFG4、CFG3、CFG2( [6 a7 Z4 `' R/ O; q
CFG4、CFG3、CFG2:9 ^! ?, }6 c* W( a
111:IRUN=31
110:IRUN=282 H! y1 i/ @ B. M+ C% A; y6 q
101:IRUN=26" i# Z; x9 a3 D: T% s; I T; _+ B
100:IRUN=24
011:IRUN=22
010:IRUN=20
001:IRUN=18
000:IRUN=16% u1 a) ?8 a5 t& }' A' _2 ]/ D
Irms=Vfs/(IRUN/32)/(Rsense*1.414); - J: g8 ]# c4 j: a: B& |
Vfs =325mV,Rsense为0.05欧时,则最大电流为4.5A左右;
CFG5:8 W" z- j. H; q5 C; n
1:SpreadCyle模式,低速、低平稳运行模式0 G4 V' ]: J, { Q" U" e8 o/ d
0:SpreadCyle模式,高速、高运动稳定模式
保持电流设置:CFG6 z1 y: n. d( j2 z# E
CFG6:7 u3 X8 }# P t; U1 y& |5 w- X
1:保持电流=运行电流/2
0:保持电流=运行电流
DIR+STEP接口模式位置控制(无需SPI接口)1 ?! t0 U( d+ M& U) } O& D7 Q
COM端:接24V或12V或5V7 `# F, W6 k2 A6 F( d, S
DRV_ENN、STER、DIR:接集电极开路输出2 E' _5 E8 P4 S6 R$ \* [
为测试方便:$ \+ Q. i+ c* F0 P) N. q, \
COM端:接3.3V
DRV_ENN:使能,接PB147 x4 y4 K2 ?1 j# m. y* O" v4 ?
DIR:方向, PB15
STEP:脉冲,PA8. @. a3 i) `5 }( w6 [, O