本帖最后由 子曰好人 于 2018-9-5 08:55 编辑
9 E5 g0 Q5 M a# F! T, ~0 X/ U# v; [" U' l& V( b
继续做实验,任务3和旋钮控制转速。 首先来看看任务3的要求: 这个可通过代码实现也可以通过上位机实现,已经有坛友做过这样的事情了。通过上位机做就是快速拨弄圆盘,这样系统不能在短时间内反转,造成观测器不能收敛,触发速度反馈错误报警,其实我个人觉得这里也是有过流报警存在的,这就看系统优先响应哪一个报警了。 我这里通过代码来实现task3。 任务3代码: - void task_3(void)3 Q# L! V. ?* }/ j- Z# g0 s& q% v
- {+ w+ ?0 o2 i" ]( _
- MC_ProgramSpeedRampMotor1(-3000/6,1000); //设置-3000rpm的转速,在一秒之内达到4 r6 O$ T8 v% }+ u1 h
- MC_StartMotor1(); //启动电机
* B9 L# t- }: S, f7 H) a |6 d: q! ~ - HAL_Delay(500); //运行500ms; o: l) Q K: ?5 k( d
- while(RUN != MC_GetSTMStateMotor1()); //等待电机处于运行状态,可有可无# T& L i& `+ j. u5 M
- MC_ProgramSpeedRampMotor1(3000/6,1000); //切换到3000rpm转速
" d8 x' _! V$ |! u+ W% J. V - MC_StartMotor1(); //启动电机
, b8 k$ w; q6 m8 _' R - while(MC_SPEED_FDBK != STM_GetFaultState(&STM[M1])); //等待错误触发( i& B) r( F3 S* y+ }: R
- HAL_Delay(1000); //延时一秒,方便可以在上位机上看见错误是否发生% b" K8 c r. x5 C3 F9 h
- MC_AcknowledgeFaultMotor1(); //清除错误
6 }; e) ^: O' u& j - HAL_Delay(100); //延时0.1秒
7 e0 k' ] b3 G/ u - MC_ProgramSpeedRampMotor1(MC_GetLastRampFinalSpeedMotor1(),1000); //重新设置上一次速度值
" h8 X' R; |, F+ |; J" l - MC_StartMotor1(); //启动电机+ X" v8 _- M4 F8 n/ n2 Q5 @& F
- HAL_Delay(5000); //运行5秒
9 h1 O$ \$ h) W# F* ]5 q - MC_StopMotor1(); //停机
0 a% B) K0 z S4 S6 f4 N5 |7 L - HAL_GPIO_WritePin(LED11_GPIO_Port,LED11_Pin,GPIO_PIN_RESET); //拉低LED引脚,表示任务结束" p1 [" f# N7 o7 e
- }1 X# z2 U* h7 W$ T8 X( c
复制代码主函数代码: - /* Infinite loop */8 d1 Y& ^6 Q! I' z) ^
- /* USER CODE BEGIN WHILE */
" G1 R6 \' w$ `& p - while (1)" \* s; m& @5 a( ^' {# M2 k
- {
# y! J1 v; D! i+ h% Y0 D# I - ! K% Z5 X( R0 |% z
- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
( |- ~2 M6 }4 b- Z - {& I% y, o' Y. a3 M
- task_3();7 R' ]/ Y( Q+ U F
- }( y" L4 d( J3 y' X- @3 ^
- else" W2 o n0 Y7 @ }# \
- {( Z' B( A/ @9 q5 H8 v! {
- MC_StopMotor1();
* S& A9 U, t x - }
- F g- a( }4 c, h* v - /* USER CODE END WHILE */1 j( Z- ~4 e) R" [0 C9 N
复制代码实验现象:
9 U' d# t* o' L }' R% n通过速度变化趋势可以看到任务成功实现了,我对比了PPT的预期结果图,有一些差距。当速度设置为3000rpm时,speed reference并没有跟随代码变为3000。另外,我做了延迟清除错误信息,所以在图中可以看到一截零速状态。
' Z, g- E5 A4 X9 o O4 w/ D# V* `9 N2 E1 ~1 H
好了,任务3完成。 --------------------------------------------------------- 现在分享一个开放性实验,旋钮控制转速,我把这个任务定为任务4吧,用旋钮来控制电机转速我觉得才是真正的一个电机控制系统。 由于SDK中并没有考虑旋钮ADC的初始化,所以如果要使用旋钮电位器首先要通过cubemx对ADC进行初始化,在我的第二篇帖子中已经讲过关于套件的硬件资源,也知道了旋钮电位器连接的是PB1引脚。 创建全局变量: - int32_t Speed_Adc = 0;, r3 [( x) X( v/ D: S Y
- int32_t Speed_ref = 0;8 X5 ?$ d- g/ M7 G9 v
- PWMC_Handle_t * MC_SPEED_REF;
: ^7 q/ g% X$ U L
复制代码任务4代码: - void task_4(void) C U- ?) u) O, v
- {
% ]/ J$ b# Z% c* M3 A/ c \; b6 r, N - Speed_Adc = R3_1_F30X_ExecRegularConv(MC_SPEED_REF,ADC_CHANNEL_12);/ Y& \: S" \& j" |( E/ U
- Speed_ref = (15500*Speed_Adc)>>16;3 k! y$ i5 h& W9 E7 U+ \
- if(Speed_ref > 0)' A& a5 {5 z7 ?
- {, e4 u( [5 @, W9 x- N
- MC_ProgramSpeedRampMotor1((Speed_ref+1500)/6,1000);- i7 C o/ i8 Q- D- e" ^& u/ u( z- F
- MC_StartMotor1();0 O* i# E6 y% S1 S' [) g2 f/ c
- }/ r' @' K1 y w2 b. ]3 z
- else9 r& l2 {2 f1 `. i, G# X( E" F$ [
- {
; ~3 q8 W5 Q7 G' ~7 F - MC_StopMotor1();
( M* L) Q- `4 ]5 y4 p - }8 c' V/ O7 h( U) H' |/ X1 w
- HAL_Delay(100);
0 U, J/ t0 `( M5 b5 [6 z+ y - }
复制代码 主函数代码:
9 M" E$ K/ v+ ?# ?) \/ D0 k) T- /* Initialize interrupts */- a" w6 [" \1 p, [0 o
- MX_NVIC_Init();
) R; d# X5 E# r) { - /* USER CODE BEGIN 2 */# _. Z) \- e0 a; ~- a/ A8 |
- MC_SPEED_REF = &PWM_Handle_M1._Super;
! S e; M) W' r; J0 [8 J; E- I' U - /* USER CODE END 2 */
0 X: N* q7 v0 y
' e5 r, ^+ O4 D+ q! I) s0 o4 b6 S- /* Infinite loop */& z& E3 _8 b; e* Y2 Y$ R" p6 r
- /* USER CODE BEGIN WHILE */7 r3 O' Q5 x* g
- while (1)
7 D; b2 E& L7 K% b& s# i* q - {
' ^+ h/ t$ r" `$ M7 @+ o6 u" k! j - 5 O2 _0 K9 P% \6 j5 X
- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))# B9 H ~+ J5 c l* ~6 `" \
- {
3 ]; b J4 ?5 z! r! L4 F+ o3 J- ] - task_4();& v1 y6 k% m5 i' |% o, X Y6 j) ?
- }* t. \$ C$ r! [: A, J* K! E- l
- else
2 n5 b/ a; G3 m7 M8 s2 B - {
' z2 U( G3 c0 d- y4 u7 f - MC_ProgramSpeedRampMotor1(0,0);
$ u7 Y. s4 E1 O2 C. P$ ?" n - MC_StopMotor1();8 D, R+ V# M, y! B& w6 I# T' {
- }
% B; C, k% ]5 v* }* w7 j: Y7 D - /* USER CODE END WHILE */8 c' G5 y; o" s, b
C# \' ?/ f( m2 B4 J- /* USER CODE BEGIN 3 */
! j. Z Y( H2 H
* S3 F, X9 _1 X; j; V- }* D; ^- y. J$ }% m5 h$ ?6 _0 c( Y
- /* USER CODE END 3 */
* t* x$ x2 o& P5 e) w1 C' U
复制代码在这里稍微解释一下代码: Speed_Adc是存储ADC采样值的变量,Speed_ref变量通过ADC采样值转化为速度设定值,MC_SPEED_REF是一个指针变量,用于获取ADC初始化设置,R3_1_F30X_ExecRegularConv这个函数在r3_1_f30x_pwm_curr_fdbk,c这个文件中,用于处理规则ADC采样。速度换算这里可以没什么说的。速度设定的时候加1500偏移是有原因的,当设定速度过低的时候电机系统根本不能正常启动,这是我尝试设置的时候所能达到的最低启动速度。 - z0 T9 x4 A5 z, `
实验现象: 从实验结果看来,这份代码默认速度PID能很好的跟踪给定转速。 我发现一个问题,代码里面在电机运行结束之后有些变量好像没有清零,这个问题留到后面在研究吧。
& i. m; T! Q. e, W* C0 ^4 l本帖两个任务分享就到这里,欢迎大家留言讨论。
; Z; `" @% r. e d8 g$ q7 a, H
9 ^8 E4 Z" [) O& _
) M9 @8 T1 I) r/ X( ]; P' Z- X n
5 R. p# [/ b% W/ C' U5 x
+ O0 w K1 `6 X" B4 }6 }; W( N |
看了你发的邮件,新版本的MCSDK生成的代码没有留ADC规则转换的函数接口,可能需要你自己去写了,我把我这边生成的文件发你一份参考吧
6 ?' X" ~8 i4 G: P9 e; ?
1.我之前参考您的函数,如果一直不断在执行转换,会影响电机库的控制时序导致无法开机,后来改为500ms一次,就没有问题。后来检查regular_conversion_manager.c中的内容,发现用户ADC的转换应该是电机库的状态机在调度的,如果连续不断转换或者没有走相应的接口估计会有问题。: y$ w- v* h w" [; O: b
2.电机Workbench里面有设置OCP参数,看了原理图应该是通过体验板上面的L6230的内置比较器以及SMT32片内的ADC实现的,但是实际中的程序并没有提供类似的功能。后来查看了代码,OCP保护是通过L6230产生的FO信号进行处理的,不知道我说的是否有偏差,还请指教。
大佬也会有纰漏啊- {9 L* H# n/ m- ~) W% ?+ C
) }8 S8 U3 Z3 C: w2 N% X
/* Infinite loop */$ E& K8 k( u4 l4 n
/* USER CODE BEGIN WHILE */
while (1)
{/ ^2 h. W# |$ [
if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
{ z M' p; _2 x, }: h
task_5(); ------>task_3();: |- d4 ~( M' L" W( D& Z
}
else, I: U) s) J( T* y, r8 y
{& w7 j% z. x; j; m( ?2 L6 p( A$ v
MC_StopMotor1();/ ?0 H& p7 d* a) F b! I6 E
}
/* 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连接也能正常运行
多谢楼主解释了。