本帖最后由 子曰好人 于 2018-9-5 08:55 编辑
3 p6 a! W& P% d* Q. E! ~: S5 q5 s* ^5 h
继续做实验,任务3和旋钮控制转速。 首先来看看任务3的要求: 这个可通过代码实现也可以通过上位机实现,已经有坛友做过这样的事情了。通过上位机做就是快速拨弄圆盘,这样系统不能在短时间内反转,造成观测器不能收敛,触发速度反馈错误报警,其实我个人觉得这里也是有过流报警存在的,这就看系统优先响应哪一个报警了。 我这里通过代码来实现task3。 任务3代码: - void task_3(void)
1 t7 q/ W4 G# a; b - {. p& F5 F; ]5 \/ |3 V! X
- MC_ProgramSpeedRampMotor1(-3000/6,1000); //设置-3000rpm的转速,在一秒之内达到2 T9 y2 I/ w; ^) i2 s: n: Y
- MC_StartMotor1(); //启动电机
. ]3 Q6 E$ w2 Z: C0 n+ c' u - HAL_Delay(500); //运行500ms2 S5 P7 j( }9 g' S9 [8 h
- while(RUN != MC_GetSTMStateMotor1()); //等待电机处于运行状态,可有可无
, I2 x. }/ t" M( E, e0 \6 i - MC_ProgramSpeedRampMotor1(3000/6,1000); //切换到3000rpm转速
S9 ]+ H3 |. L9 J - MC_StartMotor1(); //启动电机) ^( Q' z: J( q9 q" s$ I
- while(MC_SPEED_FDBK != STM_GetFaultState(&STM[M1])); //等待错误触发
; f8 T' F; Y1 o' y6 s; s - HAL_Delay(1000); //延时一秒,方便可以在上位机上看见错误是否发生1 x1 a% n& R1 D) Q+ x5 i
- MC_AcknowledgeFaultMotor1(); //清除错误
3 z4 B: q- k# T$ ~* B- ^3 H# T9 f - HAL_Delay(100); //延时0.1秒
4 T% f, Q0 [3 S# }$ s - MC_ProgramSpeedRampMotor1(MC_GetLastRampFinalSpeedMotor1(),1000); //重新设置上一次速度值
! H3 p* w( J; @4 c, U* ]" F - MC_StartMotor1(); //启动电机
2 `. e" e; u( y8 `: | e9 G - HAL_Delay(5000); //运行5秒3 ^( F$ G& ?% U1 @
- MC_StopMotor1(); //停机) A2 x6 E# f8 [5 L/ u: e; |7 R% A; w
- HAL_GPIO_WritePin(LED11_GPIO_Port,LED11_Pin,GPIO_PIN_RESET); //拉低LED引脚,表示任务结束$ t% F/ l I3 z4 l( W
- }
2 {! m) G. \* n) ?$ b
复制代码主函数代码: - /* Infinite loop */
5 Z9 D3 P# e6 `5 K4 Q% j" } - /* USER CODE BEGIN WHILE */( v% s5 Y" ?& ]
- while (1) K. ^! O/ V1 e1 B) e
- {
$ Z' b& i& Q* r+ R -
! N" ?; j% G1 h$ S `( E - if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
: ~8 J5 m0 f2 l, A- G8 L - {+ F$ I* _3 Y" v8 ^# K
- task_3();
& `! Q. ?; v3 e; x - }
/ @- P3 _( y) N) K9 w) A$ t - else
0 \3 a8 V0 O7 P3 S1 J% F - {; h1 Y! l9 a6 ~* |
- MC_StopMotor1();* F7 o6 v4 \, @4 ^! {7 z
- }
* M y% O2 `! D: E - /* USER CODE END WHILE */
& W$ D" S! \( Y' w3 b% Q" j( x% r( F
复制代码实验现象:
& M- _- G0 w' |+ H: c; y% \通过速度变化趋势可以看到任务成功实现了,我对比了PPT的预期结果图,有一些差距。当速度设置为3000rpm时,speed reference并没有跟随代码变为3000。另外,我做了延迟清除错误信息,所以在图中可以看到一截零速状态。 ) ^% N* D3 H8 M8 `. C6 W
; Y; K7 T( R! r( L
好了,任务3完成。 --------------------------------------------------------- 现在分享一个开放性实验,旋钮控制转速,我把这个任务定为任务4吧,用旋钮来控制电机转速我觉得才是真正的一个电机控制系统。 由于SDK中并没有考虑旋钮ADC的初始化,所以如果要使用旋钮电位器首先要通过cubemx对ADC进行初始化,在我的第二篇帖子中已经讲过关于套件的硬件资源,也知道了旋钮电位器连接的是PB1引脚。 创建全局变量: - int32_t Speed_Adc = 0;
' T& R" _. R a - int32_t Speed_ref = 0;+ ` t p# i5 }4 J( {: h5 f
- PWMC_Handle_t * MC_SPEED_REF;
* l. H! t( K7 P
复制代码任务4代码: - void task_4(void)+ N) j; W: b' N' R
- {6 [1 }* g: \1 n8 p! Z3 l
- Speed_Adc = R3_1_F30X_ExecRegularConv(MC_SPEED_REF,ADC_CHANNEL_12);
; r- R6 ^' u3 n/ z - Speed_ref = (15500*Speed_Adc)>>16;/ g4 ], n7 i; }. {: I
- if(Speed_ref > 0)9 P3 B7 T6 \& o, O9 r& ]
- {5 \) F6 H6 f4 E5 x- X- O1 @) C
- MC_ProgramSpeedRampMotor1((Speed_ref+1500)/6,1000);
3 ?# r1 z% W4 P - MC_StartMotor1();
2 ]( G2 G* n, k' e- ~; j/ ~ - }
( q8 i5 _! w8 D/ j: j) s4 B - else
+ D, A, Z: u7 M. H5 u - {2 r: ]' \2 G* X
- MC_StopMotor1();/ H5 v" g7 G* S: m8 z' G; P/ v
- }
! b; q; m+ G0 W3 b; q0 @ - HAL_Delay(100);
. u$ v( F) W, Y% s9 \ O! P - }
复制代码 主函数代码:1 V+ I. b! c- F8 [1 B: V& H* [# z
- /* Initialize interrupts *// x+ ~, a3 {3 Z! z9 A+ J$ I3 n4 ]
- MX_NVIC_Init();
% Q) L' Z4 [: {# e - /* USER CODE BEGIN 2 */
/ n5 D, L: w1 }# g4 |% b3 x - MC_SPEED_REF = &PWM_Handle_M1._Super;( H3 ]1 F: o- x, Y8 h4 u1 Y7 s
- /* USER CODE END 2 */0 x; {9 F, A8 i2 s( t
7 d: S/ `# S. |3 d0 e- /* Infinite loop */
. M7 h, B/ H0 a g! R, k7 G6 G - /* USER CODE BEGIN WHILE */4 Q9 q, ^, L6 c) A" R
- while (1)
& R- A- |' r- E# C% `; [8 ? - {
) j7 ~1 ~8 {9 B1 R# ^ - . u, j( G( Y4 l
- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))+ G: T0 J) ~' p5 d; d
- {$ d; M# E- e) ?3 e# b5 `8 ^
- task_4();
2 `. L: O) B0 h# _ - }) d, x( d c9 }' o
- else
& y) @$ e; [2 d% p- t - {6 v! `9 [- b: A8 s
- MC_ProgramSpeedRampMotor1(0,0);
6 y8 Q4 g: G1 P9 ~' }" ~9 r4 V - MC_StopMotor1();+ q* M; W7 Y6 i- Q0 F$ T
- }3 l- R4 F- m* Y2 K
- /* USER CODE END WHILE */
j8 n9 D2 q# }' l6 N/ y
- q4 z7 t! a1 P; N! y- /* USER CODE BEGIN 3 */
( I+ F1 K' `( m' N - $ \$ w+ m% e6 d+ r, B* e
- }8 H* _; @" M# R% b9 w6 G* q+ w U
- /* USER CODE END 3 */; z, j, M: }8 L; A2 \: K, V4 [
复制代码在这里稍微解释一下代码: Speed_Adc是存储ADC采样值的变量,Speed_ref变量通过ADC采样值转化为速度设定值,MC_SPEED_REF是一个指针变量,用于获取ADC初始化设置,R3_1_F30X_ExecRegularConv这个函数在r3_1_f30x_pwm_curr_fdbk,c这个文件中,用于处理规则ADC采样。速度换算这里可以没什么说的。速度设定的时候加1500偏移是有原因的,当设定速度过低的时候电机系统根本不能正常启动,这是我尝试设置的时候所能达到的最低启动速度。 6 V$ ^: ]# b# N% T
实验现象: 从实验结果看来,这份代码默认速度PID能很好的跟踪给定转速。 我发现一个问题,代码里面在电机运行结束之后有些变量好像没有清零,这个问题留到后面在研究吧。
( p) M8 G' L, N& P* T7 ]2 M$ n本帖两个任务分享就到这里,欢迎大家留言讨论。- y ]7 L# i' \; n/ E- w9 T0 |
( B0 j5 L) a; n% ~0 J/ [/ P+ x+ U
( c9 Y' B0 I& `
/ u3 l$ a3 W5 I. h; p. j5 }3 w. C& p, X% C" O
|
看了你发的邮件,新版本的MCSDK生成的代码没有留ADC规则转换的函数接口,可能需要你自己去写了,我把我这边生成的文件发你一份参考吧
% V- t: L* Z8 E8 e9 E
1.我之前参考您的函数,如果一直不断在执行转换,会影响电机库的控制时序导致无法开机,后来改为500ms一次,就没有问题。后来检查regular_conversion_manager.c中的内容,发现用户ADC的转换应该是电机库的状态机在调度的,如果连续不断转换或者没有走相应的接口估计会有问题。
2.电机Workbench里面有设置OCP参数,看了原理图应该是通过体验板上面的L6230的内置比较器以及SMT32片内的ADC实现的,但是实际中的程序并没有提供类似的功能。后来查看了代码,OCP保护是通过L6230产生的FO信号进行处理的,不知道我说的是否有偏差,还请指教。
大佬也会有纰漏啊
/* Infinite loop */
/* USER CODE BEGIN WHILE */6 l/ U; ^ O% L% J
while (1)
{! e( l+ R5 w8 d3 R: j
if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
{6 h! B( s. C! p6 l, X# [
task_5(); ------>task_3();
}, H7 }0 w; b0 d# A! W
else* d7 l5 a! Z9 t
{
MC_StopMotor1();
} 8 B' _! t! K& g9 t- ?* u; }
/* 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连接也能正常运行
多谢楼主解释了。