本帖最后由 子曰好人 于 2018-9-5 08:55 编辑
3 D5 k3 ~: K* F3 I1 I# \- R) N, b8 R' \9 s0 |' ^+ M* V2 m
继续做实验,任务3和旋钮控制转速。 首先来看看任务3的要求: 这个可通过代码实现也可以通过上位机实现,已经有坛友做过这样的事情了。通过上位机做就是快速拨弄圆盘,这样系统不能在短时间内反转,造成观测器不能收敛,触发速度反馈错误报警,其实我个人觉得这里也是有过流报警存在的,这就看系统优先响应哪一个报警了。 我这里通过代码来实现task3。 任务3代码: - void task_3(void)
6 N4 D' ?, q0 o3 x+ C - {( r( y. c' K, |% L( H0 H3 W
- MC_ProgramSpeedRampMotor1(-3000/6,1000); //设置-3000rpm的转速,在一秒之内达到
2 i, `8 ~) s: b - MC_StartMotor1(); //启动电机( r9 B" k' Y/ i4 b" m6 |' X8 N
- HAL_Delay(500); //运行500ms& ` g8 A: S+ G9 p( V9 p& ^; r
- while(RUN != MC_GetSTMStateMotor1()); //等待电机处于运行状态,可有可无
# L& y2 o. w9 w% O# \# d - MC_ProgramSpeedRampMotor1(3000/6,1000); //切换到3000rpm转速6 C0 @( |. Y. _1 d( {$ R. w, N
- MC_StartMotor1(); //启动电机
- G \0 \: T, a - while(MC_SPEED_FDBK != STM_GetFaultState(&STM[M1])); //等待错误触发
6 t8 X) C7 T0 `# ?5 y7 u - HAL_Delay(1000); //延时一秒,方便可以在上位机上看见错误是否发生
( [( Z. R) H& P8 r - MC_AcknowledgeFaultMotor1(); //清除错误
S- F4 o/ b! u8 U8 ~ - HAL_Delay(100); //延时0.1秒
+ q# g- I# t I C - MC_ProgramSpeedRampMotor1(MC_GetLastRampFinalSpeedMotor1(),1000); //重新设置上一次速度值/ R( a4 N3 W+ e0 h
- MC_StartMotor1(); //启动电机3 [7 J2 m3 ?$ y2 x- y4 S' w
- HAL_Delay(5000); //运行5秒
( j- u8 @: ?# W" B# e - MC_StopMotor1(); //停机
* n1 i. J' B/ E0 u- a7 C - HAL_GPIO_WritePin(LED11_GPIO_Port,LED11_Pin,GPIO_PIN_RESET); //拉低LED引脚,表示任务结束
c6 R* ~ Z$ O. Q - }
/ g1 E4 o4 a0 p3 e* m8 h
复制代码主函数代码: - /* Infinite loop */* T. [1 ~+ s: U$ M: K8 e( l
- /* USER CODE BEGIN WHILE */( Q7 E. ] e9 D+ R# e6 _. }0 i" S
- while (1)
% L1 l/ \6 \0 {; e7 s; G/ t - {/ T# |3 X, e, L& d! H
- # e2 d- ?( t9 Q) t
- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
; R( S" q. ]& t: n - {( E1 ^ m2 P( Y, t
- task_3();/ T9 ~1 Z# j; h0 G4 n9 B; m
- }9 L1 m! I4 R) [1 r! r6 }. x; y0 m
- else
7 M1 r# g; P2 v4 B - {
3 I8 `7 l3 W5 ~ - MC_StopMotor1();( Z- t, ]3 c: P3 \3 |: Y
- } 1 r$ |4 c6 [) o' N8 u& @
- /* USER CODE END WHILE */
) F( i. F" k+ s
复制代码实验现象:
+ y9 Z) b( ^; u0 J
通过速度变化趋势可以看到任务成功实现了,我对比了PPT的预期结果图,有一些差距。当速度设置为3000rpm时,speed reference并没有跟随代码变为3000。另外,我做了延迟清除错误信息,所以在图中可以看到一截零速状态。 9 T' @; e6 n9 D0 F+ f
. K9 m0 m- p \8 }& Z' f
好了,任务3完成。 --------------------------------------------------------- 现在分享一个开放性实验,旋钮控制转速,我把这个任务定为任务4吧,用旋钮来控制电机转速我觉得才是真正的一个电机控制系统。 由于SDK中并没有考虑旋钮ADC的初始化,所以如果要使用旋钮电位器首先要通过cubemx对ADC进行初始化,在我的第二篇帖子中已经讲过关于套件的硬件资源,也知道了旋钮电位器连接的是PB1引脚。 创建全局变量: - int32_t Speed_Adc = 0;
( R5 J0 f9 V3 Q" n' L/ s - int32_t Speed_ref = 0;% q1 ~/ x, K+ q% G& |. d+ t6 d
- PWMC_Handle_t * MC_SPEED_REF;
! L7 t Y1 A# C/ T/ A9 K5 _
复制代码任务4代码: - void task_4(void)
3 g9 t! O# ^% K0 o. u% q - {
$ E) f6 z7 g' e# \0 ^ - Speed_Adc = R3_1_F30X_ExecRegularConv(MC_SPEED_REF,ADC_CHANNEL_12);
3 J& R1 {' @, I - Speed_ref = (15500*Speed_Adc)>>16;. m. m2 v. q7 `: Q
- if(Speed_ref > 0)( N4 U' [0 _+ F8 k8 E* U
- {
3 b$ Q! p* A' ?2 X, Y9 `7 v - MC_ProgramSpeedRampMotor1((Speed_ref+1500)/6,1000);* Q8 K e; w# B `/ J0 x" G
- MC_StartMotor1(); Q5 J: V( ]+ |, g0 w+ B9 i6 T+ ^
- }& g$ X$ M* ^: t# q/ q0 T; J
- else3 M; M+ q8 x# w
- {$ s9 [6 E+ @) n, s3 P. b( R& s
- MC_StopMotor1();0 b( W4 z$ w; _9 O- F
- }
9 q/ _) C) A2 V) _ - HAL_Delay(100);6 v2 U& T* I2 s- l$ W
- }
复制代码 主函数代码:6 ^3 A/ I& E+ _! q. y( H
- /* Initialize interrupts */
' J% o Q) m+ U* N - MX_NVIC_Init();; d. H# H; m# y1 O+ ~( H
- /* USER CODE BEGIN 2 */, f8 a y/ p5 A- ^( r8 m, q
- MC_SPEED_REF = &PWM_Handle_M1._Super;& l1 @% X; x4 }
- /* USER CODE END 2 */4 R0 a! n& o% w7 g- U( S
% R/ d( ~9 w z- g3 V7 F3 c- /* Infinite loop */0 c7 W7 y5 N. T, B
- /* USER CODE BEGIN WHILE */
. W8 E0 I# F2 m2 @ - while (1)
6 c. u* ? ?& _1 z' c) l - {1 B% a" [3 j, ]4 d2 m# m
- . H6 ?3 G4 H# ?& \. C3 M
- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))+ m# `- M# I0 u4 \9 W9 a
- {4 x, h# b, G1 r8 E2 D8 ?8 ?
- task_4();
; O1 O4 [5 }7 i0 V; M - }. Q7 f: K" E* [) ~1 v0 @. U
- else
6 i9 _% I( q3 B* _; k2 n - { P& @7 E1 p6 ~, a u5 p
- MC_ProgramSpeedRampMotor1(0,0);
) h) x1 z* G" h, E9 m. }* s - MC_StopMotor1();
' `5 v' F/ e( ?! Q8 v - }% e+ \. R1 E# J( ?8 @
- /* USER CODE END WHILE */
2 I9 H `: A8 x5 q. w; r5 w* T# v5 i
, Q: n- B' I8 \, I% j: O- /* USER CODE BEGIN 3 */
; y, q3 z/ M6 f0 p4 x - ' [' @ |' C- z! C- ^6 i# {# |
- }
5 {$ V- x5 s1 P# z9 V" Y - /* USER CODE END 3 */) G6 s' D9 U% A6 k" _( C- \' s
复制代码在这里稍微解释一下代码: Speed_Adc是存储ADC采样值的变量,Speed_ref变量通过ADC采样值转化为速度设定值,MC_SPEED_REF是一个指针变量,用于获取ADC初始化设置,R3_1_F30X_ExecRegularConv这个函数在r3_1_f30x_pwm_curr_fdbk,c这个文件中,用于处理规则ADC采样。速度换算这里可以没什么说的。速度设定的时候加1500偏移是有原因的,当设定速度过低的时候电机系统根本不能正常启动,这是我尝试设置的时候所能达到的最低启动速度。
3 l" v5 k( R o. c- K2 N# X实验现象: 从实验结果看来,这份代码默认速度PID能很好的跟踪给定转速。 我发现一个问题,代码里面在电机运行结束之后有些变量好像没有清零,这个问题留到后面在研究吧。 * e. ^9 b- ]3 p, ^6 `: x8 ~; ]" V# n
本帖两个任务分享就到这里,欢迎大家留言讨论。
8 R, X/ Q$ c$ @) ~
+ \, l7 B: F( U# |) l. }9 J) c. C
4 y: t( m; j& a& H) O. g
0 F! d7 J& ~7 @3 z
( t$ \: c* E0 i: ~ |
看了你发的邮件,新版本的MCSDK生成的代码没有留ADC规则转换的函数接口,可能需要你自己去写了,我把我这边生成的文件发你一份参考吧: Y# G5 r) s& G d- }! V
! e3 a& I1 g3 r: Z) C1 j. B
1.我之前参考您的函数,如果一直不断在执行转换,会影响电机库的控制时序导致无法开机,后来改为500ms一次,就没有问题。后来检查regular_conversion_manager.c中的内容,发现用户ADC的转换应该是电机库的状态机在调度的,如果连续不断转换或者没有走相应的接口估计会有问题。7 \$ ?% B1 s1 J1 b( V$ s1 w2 m! m
2.电机Workbench里面有设置OCP参数,看了原理图应该是通过体验板上面的L6230的内置比较器以及SMT32片内的ADC实现的,但是实际中的程序并没有提供类似的功能。后来查看了代码,OCP保护是通过L6230产生的FO信号进行处理的,不知道我说的是否有偏差,还请指教。
大佬也会有纰漏啊
/* Infinite loop */" B K, J& \# o& E' L& S; a8 W1 u
/* USER CODE BEGIN WHILE */3 e% O+ ~( Y2 W# E
while (1)
{
if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
{# [, V8 W/ M+ x+ C8 r E& T% O8 P
task_5(); ------>task_3();8 F' n7 I+ @- n& e
}
else, W+ T3 O: B$ q* A
{
MC_StopMotor1();
} % @/ \% P3 a% ~- i8 n( f5 Q
/* USER CODE END WHILE */
不好意思,感谢指正
去研究一下电机库生成的故障触发机制代码,也许就能明白了,搞清楚是怎么回事之后就能自定义故障报警了
在r3_1_f30x_pwm_curr_fdbk.c这个文件里面,要调用这个函数需要包含头文件r3_1_f30x_pwm_curr_fdbk.h
手误写错了,已更正
15500是电机能达到的最大转速,Speed_Adc的最大值是4096,ADC采样值和速度参考值的换算方式为:(Spped_ref-0)/(Speed_Adc-0)=15500/4096=15500>>16;
没遇到过,我的一直是正常的呀,没有USB连接也能正常运行
多谢楼主解释了。