本帖最后由 子曰好人 于 2018-9-5 08:55 编辑
% D% u; W( E" b7 S* y/ Q+ s) o8 ^2 K( b# h) u
继续做实验,任务3和旋钮控制转速。 首先来看看任务3的要求: 这个可通过代码实现也可以通过上位机实现,已经有坛友做过这样的事情了。通过上位机做就是快速拨弄圆盘,这样系统不能在短时间内反转,造成观测器不能收敛,触发速度反馈错误报警,其实我个人觉得这里也是有过流报警存在的,这就看系统优先响应哪一个报警了。 我这里通过代码来实现task3。 任务3代码: - void task_3(void)
5 O% }" B% L, R3 c& s& }1 G" V - {7 @7 f' [; z) U* D! x* @! X
- MC_ProgramSpeedRampMotor1(-3000/6,1000); //设置-3000rpm的转速,在一秒之内达到- C; g6 k2 B3 W4 N, _7 u% z3 f
- MC_StartMotor1(); //启动电机
0 r3 z& n# M" E5 P8 o( @( \# c3 p) \ - HAL_Delay(500); //运行500ms n7 P# m2 y" q* _) [, e
- while(RUN != MC_GetSTMStateMotor1()); //等待电机处于运行状态,可有可无' Y$ z, J U* g5 ^+ v7 x3 y
- MC_ProgramSpeedRampMotor1(3000/6,1000); //切换到3000rpm转速
6 F4 k! [6 `9 w: w' o7 F - MC_StartMotor1(); //启动电机$ k! M2 ^$ p |! a+ z
- while(MC_SPEED_FDBK != STM_GetFaultState(&STM[M1])); //等待错误触发
# d9 I$ b# g* i9 H: e; L - HAL_Delay(1000); //延时一秒,方便可以在上位机上看见错误是否发生
/ {2 [" ?: q' f - MC_AcknowledgeFaultMotor1(); //清除错误
' h1 Q0 X: E: ?" b5 ?- e: } - HAL_Delay(100); //延时0.1秒
6 Y% c9 v3 d; | - MC_ProgramSpeedRampMotor1(MC_GetLastRampFinalSpeedMotor1(),1000); //重新设置上一次速度值
: l: i1 {- j- p. D( m9 E) V. t - MC_StartMotor1(); //启动电机5 u& z% H+ n/ F# m2 d' _7 {% e
- HAL_Delay(5000); //运行5秒 ]: R5 |( V4 Y+ t1 f3 m( M
- MC_StopMotor1(); //停机
: X1 x7 _" {' f4 [; { - HAL_GPIO_WritePin(LED11_GPIO_Port,LED11_Pin,GPIO_PIN_RESET); //拉低LED引脚,表示任务结束
3 s) {. \8 t$ w2 R% d) k4 s1 ~ - }2 c* b; }0 f9 I+ @0 W, Y
复制代码主函数代码: - /* Infinite loop */5 b' e0 r" |8 l! S, A
- /* USER CODE BEGIN WHILE */
& l; b. M* N% e" A$ ^ - while (1)
$ j. Y, D! Q7 u5 ~ - {
0 ~( d+ X* b) s& v% a - 9 H c' k' j. J. R5 I
- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
+ i. l* D9 N' o. M4 y( O5 x" D- N/ m - {( _9 j* {% `: p& g
- task_3();+ c# R' { |! w
- }- G0 J" M# ?' q( v4 B
- else! q1 C9 O K+ r. c8 n0 E
- {
1 J, K6 K( b+ ~$ B - MC_StopMotor1();" r% R# e: ?- b! u( |* u
- }
N4 G0 n7 o( N- E' C# b& s - /* USER CODE END WHILE */2 h! }2 @( [2 U
复制代码实验现象:
& ?4 d! {& |4 m2 `2 i通过速度变化趋势可以看到任务成功实现了,我对比了PPT的预期结果图,有一些差距。当速度设置为3000rpm时,speed reference并没有跟随代码变为3000。另外,我做了延迟清除错误信息,所以在图中可以看到一截零速状态。 / Y* [8 Q D1 ~! ~
2 _5 v' o4 `+ |' o0 D" n
好了,任务3完成。 --------------------------------------------------------- 现在分享一个开放性实验,旋钮控制转速,我把这个任务定为任务4吧,用旋钮来控制电机转速我觉得才是真正的一个电机控制系统。 由于SDK中并没有考虑旋钮ADC的初始化,所以如果要使用旋钮电位器首先要通过cubemx对ADC进行初始化,在我的第二篇帖子中已经讲过关于套件的硬件资源,也知道了旋钮电位器连接的是PB1引脚。 创建全局变量: - int32_t Speed_Adc = 0;
1 q1 ^+ E8 r4 y4 T" M$ Y - int32_t Speed_ref = 0;
: x+ ?$ H; f' ~0 P3 ]/ E - PWMC_Handle_t * MC_SPEED_REF;4 W3 N( s4 R1 d
复制代码任务4代码: - void task_4(void)" D4 Y- |& L0 t/ H
- {
. ~. N0 x4 u2 \" Z5 K# a7 g - Speed_Adc = R3_1_F30X_ExecRegularConv(MC_SPEED_REF,ADC_CHANNEL_12);. w: R, c5 a) F# i1 r
- Speed_ref = (15500*Speed_Adc)>>16;
; c. r# e8 N4 ^! ^ - if(Speed_ref > 0)' ]3 {" j b5 c
- {
' G. M. v. b- r, d - MC_ProgramSpeedRampMotor1((Speed_ref+1500)/6,1000);
4 z. O, }! z$ ~7 ~1 ~( P - MC_StartMotor1();
% k8 }! Z: w% }; R9 y7 Q- S" m - }
" f- X/ j" G! D7 W# D* y1 K - else
, |0 I" z6 |$ S2 @) | - {! U; D$ v8 e9 c
- MC_StopMotor1();
6 Q6 c0 E* j$ \ - }
: N/ r" o$ O' E. A# l - HAL_Delay(100);5 ^& N3 P2 `6 P5 {3 d+ p
- }
复制代码 主函数代码:
4 w2 v1 j# [+ w7 }: C" p- /* Initialize interrupts */
7 E+ p3 d- w# D5 r H" o5 j - MX_NVIC_Init();
1 r7 l5 ? E$ ?1 B9 [2 h - /* USER CODE BEGIN 2 */
: H8 s# D6 p4 P4 f; H1 o - MC_SPEED_REF = &PWM_Handle_M1._Super;$ b5 M8 J* }1 p4 n' r! q
- /* USER CODE END 2 */" @- N4 z( v$ \
9 t. D" |4 Z% T5 W$ m9 v1 s- /* Infinite loop */
5 x7 f) T% b4 R8 i6 o" @$ e - /* USER CODE BEGIN WHILE */; c+ Y8 O3 L# {3 L7 F
- while (1)
; t( o7 V' i' H1 ~: V+ r - {' c! K: O/ S3 R" B% i O E8 J1 n
- / u8 u& W D. h8 C$ ]
- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))* n# C: t" V. _% e( y$ i) R
- {
6 l' q1 v) I8 U, `& Z s9 H x - task_4();
& ]) Z: c; R# V6 Z - }
6 l+ L% u8 d3 q d2 z+ b/ y+ k - else( W! `& s! K1 @- B
- {( ?1 c% o4 k1 c4 y! e2 w
- MC_ProgramSpeedRampMotor1(0,0);1 t4 v' l5 m% y a& b0 h7 `% V
- MC_StopMotor1();
* P7 a* Q% d* b$ z5 y% E0 F - }
" _" n2 Q- @" [& [# o& e" h' t& q - /* USER CODE END WHILE */
5 N& Q$ T& N2 X/ ^' L/ w8 g
2 X* T& G$ v! E2 I) d$ O* w' b- /* USER CODE BEGIN 3 */; B& O: s3 L7 Z* w1 L) b0 C
- 8 m+ {+ F# `1 X% B" B
- }2 k1 r8 n. p, V# { v) C
- /* USER CODE END 3 */* O" Y; {0 E1 L$ `
复制代码在这里稍微解释一下代码: Speed_Adc是存储ADC采样值的变量,Speed_ref变量通过ADC采样值转化为速度设定值,MC_SPEED_REF是一个指针变量,用于获取ADC初始化设置,R3_1_F30X_ExecRegularConv这个函数在r3_1_f30x_pwm_curr_fdbk,c这个文件中,用于处理规则ADC采样。速度换算这里可以没什么说的。速度设定的时候加1500偏移是有原因的,当设定速度过低的时候电机系统根本不能正常启动,这是我尝试设置的时候所能达到的最低启动速度。 d2 {7 t9 Q- `0 M1 M
实验现象: 从实验结果看来,这份代码默认速度PID能很好的跟踪给定转速。 我发现一个问题,代码里面在电机运行结束之后有些变量好像没有清零,这个问题留到后面在研究吧。
1 N; r6 J% \' C- Y本帖两个任务分享就到这里,欢迎大家留言讨论。& h. b( n1 ~" e( Y/ c7 p
w% S! e1 g1 V& V$ o; s1 {' |. ~
; Y/ P+ i7 D# n4 q
' ]& ^4 s2 Q# u1 K |
看了你发的邮件,新版本的MCSDK生成的代码没有留ADC规则转换的函数接口,可能需要你自己去写了,我把我这边生成的文件发你一份参考吧# r! P, x/ ]; s! ]4 o+ J
1.我之前参考您的函数,如果一直不断在执行转换,会影响电机库的控制时序导致无法开机,后来改为500ms一次,就没有问题。后来检查regular_conversion_manager.c中的内容,发现用户ADC的转换应该是电机库的状态机在调度的,如果连续不断转换或者没有走相应的接口估计会有问题。
2.电机Workbench里面有设置OCP参数,看了原理图应该是通过体验板上面的L6230的内置比较器以及SMT32片内的ADC实现的,但是实际中的程序并没有提供类似的功能。后来查看了代码,OCP保护是通过L6230产生的FO信号进行处理的,不知道我说的是否有偏差,还请指教。
大佬也会有纰漏啊7 p* m" `5 ~! j
/* Infinite loop */
/* USER CODE BEGIN WHILE */2 I( t+ U- @. H6 o2 f
while (1)6 x* y) m# \8 m
{
+ B- v3 d0 J4 ?- Q
if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
{' \$ f# L0 u' E, C" P' N
task_5(); ------>task_3();
}
else
{
MC_StopMotor1();* {: s8 z/ I/ x: E
} 2 B$ T% q5 m# c+ ]. w
/* 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连接也能正常运行
多谢楼主解释了。