本帖最后由 子曰好人 于 2018-9-5 08:55 编辑 % \0 u/ j2 s% Z% b
; P5 b& I' }! B: E5 D4 t& h
继续做实验,任务3和旋钮控制转速。 首先来看看任务3的要求: 这个可通过代码实现也可以通过上位机实现,已经有坛友做过这样的事情了。通过上位机做就是快速拨弄圆盘,这样系统不能在短时间内反转,造成观测器不能收敛,触发速度反馈错误报警,其实我个人觉得这里也是有过流报警存在的,这就看系统优先响应哪一个报警了。 我这里通过代码来实现task3。 任务3代码: - void task_3(void)
8 m9 K0 r9 a/ A) J1 k5 M - { _4 P/ B. B' j/ ?. g: Q8 \9 r
- MC_ProgramSpeedRampMotor1(-3000/6,1000); //设置-3000rpm的转速,在一秒之内达到
! ^' G e' K+ u4 ^ - MC_StartMotor1(); //启动电机0 I% b$ t, ?- F. O* X2 `. _0 C
- HAL_Delay(500); //运行500ms- H- s( O' |) J+ d8 a1 s
- while(RUN != MC_GetSTMStateMotor1()); //等待电机处于运行状态,可有可无
4 a U2 m: Q* L( ~7 \5 ^! ^1 P - MC_ProgramSpeedRampMotor1(3000/6,1000); //切换到3000rpm转速
; ?9 q. y) W- w( ?& P" B' A+ k - MC_StartMotor1(); //启动电机
h7 s/ E# z% |8 v0 }; G - while(MC_SPEED_FDBK != STM_GetFaultState(&STM[M1])); //等待错误触发
1 z, w! {& Y/ O' ` - HAL_Delay(1000); //延时一秒,方便可以在上位机上看见错误是否发生
* O) K- {) q& N& E7 i! }; ? - MC_AcknowledgeFaultMotor1(); //清除错误
/ p1 r* h" a6 {$ E* g* n - HAL_Delay(100); //延时0.1秒
% ^6 W4 g1 X% _/ t* N/ r' c6 Q - MC_ProgramSpeedRampMotor1(MC_GetLastRampFinalSpeedMotor1(),1000); //重新设置上一次速度值, x9 Q6 H( `; D! E
- MC_StartMotor1(); //启动电机2 J" b0 v! r8 n/ h' q5 E( m
- HAL_Delay(5000); //运行5秒( z; Q8 i/ ?4 T0 s' F! i# e0 t+ h# z
- MC_StopMotor1(); //停机: l3 q: T7 w1 \* D M& e$ M; _1 @( s
- HAL_GPIO_WritePin(LED11_GPIO_Port,LED11_Pin,GPIO_PIN_RESET); //拉低LED引脚,表示任务结束
$ z, u& h" q+ I5 E" X0 i - }
8 R+ i1 [; H0 r# E* z2 ]
复制代码主函数代码: - /* Infinite loop */; n- A- g- r' G
- /* USER CODE BEGIN WHILE */2 m* Y9 c1 X+ [& C
- while (1): E/ Y& @9 C# Z+ J; B* S
- {9 Y+ F) [: y, P( `8 u% [
-
d' d3 l+ J! T! \# R: h - if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))6 ^: F. X+ U6 [+ P$ n- e
- {, m9 Y2 W! M( B; h8 ]. H" c
- task_3();
0 t1 U5 M2 |- a! R - }
9 C' v- L5 h! m: X0 [( [ - else
|+ s/ e" D; q! i - {3 D1 r: N4 g7 |, A& w9 a' x3 u
- MC_StopMotor1();; o# N; E! n A0 I) e8 _6 a# c
- }
# |+ ?# Y: M6 ?# D - /* USER CODE END WHILE */: B* U" r& Q3 x1 a
复制代码实验现象:
% w7 X' R8 A, L3 |6 {通过速度变化趋势可以看到任务成功实现了,我对比了PPT的预期结果图,有一些差距。当速度设置为3000rpm时,speed reference并没有跟随代码变为3000。另外,我做了延迟清除错误信息,所以在图中可以看到一截零速状态。
) Q* j7 {+ |8 F( ^& L' ]
4 h1 I4 j( g8 b, ], m: N* Y, U好了,任务3完成。
--------------------------------------------------------- 现在分享一个开放性实验,旋钮控制转速,我把这个任务定为任务4吧,用旋钮来控制电机转速我觉得才是真正的一个电机控制系统。 由于SDK中并没有考虑旋钮ADC的初始化,所以如果要使用旋钮电位器首先要通过cubemx对ADC进行初始化,在我的第二篇帖子中已经讲过关于套件的硬件资源,也知道了旋钮电位器连接的是PB1引脚。 创建全局变量: - int32_t Speed_Adc = 0;
5 J/ p" w$ H0 p - int32_t Speed_ref = 0;
8 e# F; Y V* M4 M) e - PWMC_Handle_t * MC_SPEED_REF;
, P6 [4 l4 X) R/ v; J, ]# J$ c
复制代码任务4代码: - void task_4(void)
+ B$ N/ D( M! |; P - {
, l+ Y& F; [! C - Speed_Adc = R3_1_F30X_ExecRegularConv(MC_SPEED_REF,ADC_CHANNEL_12);
& k' {" a. E' q6 N3 R - Speed_ref = (15500*Speed_Adc)>>16;
! `' k5 {6 b: u1 j0 i - if(Speed_ref > 0)
0 M0 K% B% w U) U - {; c& O" @ u% V
- MC_ProgramSpeedRampMotor1((Speed_ref+1500)/6,1000);. C+ z _4 s4 B, [( W; K
- MC_StartMotor1();+ Z; ?& d* m2 O
- }
( r; C% p+ l# \- M$ W - else
1 t5 a9 P& K4 u8 w# P - {
2 Q# y& V! }! s% Y - MC_StopMotor1();5 ? H9 ?$ t& y+ a
- }) ~" N! Y" v+ V% g" B, S
- HAL_Delay(100);
/ w" Z# \0 F8 }! H/ Q1 D - }
复制代码 主函数代码:
. |* |: A, ^0 {/ B# p$ O1 s8 y0 G: B- /* Initialize interrupts */! j( B/ ?8 }* ` C
- MX_NVIC_Init();
) Y$ |8 _8 z, s. K - /* USER CODE BEGIN 2 */
* W) @, U# P! q - MC_SPEED_REF = &PWM_Handle_M1._Super;, e$ h( x& Y& g
- /* USER CODE END 2 */; V( O! ]$ y% q/ Q0 ^
3 }; K1 K2 |4 `! t+ ?- /* Infinite loop */
8 j3 |6 ^: D5 g- X% H) u: z& \& b - /* USER CODE BEGIN WHILE */
& a, p) m# i5 O; Y/ N - while (1)
& ^2 H% t; d* B7 ^, u# ^# I) Q - {
( Y. L' m0 `: ? u
' R3 }0 ~& Z. _" l3 D0 R- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin)): T. _! ]8 M: |0 P$ F& B4 |4 V2 P
- {# z2 ^0 c" C$ V, `5 k O
- task_4();
3 p' C7 E N+ h2 b, b - }# e9 _" E9 i9 h
- else
* J8 z' H- C6 w! P, V! d7 G Y - {4 K5 w# k u% y0 b" C
- MC_ProgramSpeedRampMotor1(0,0);8 ~0 _" {6 K) `" H, m2 z
- MC_StopMotor1();
1 ~ O5 R0 h& G - }
6 `, e( h) o! @/ m - /* USER CODE END WHILE */
, l) B) X. T$ \
* c" U5 `) {2 Q b1 g- /* USER CODE BEGIN 3 */
$ Q- p0 a& `1 j; @& S+ _ - # h' ?9 v( C. b+ {) j/ M' D
- }
6 H1 j$ D' W/ e - /* USER CODE END 3 */1 {" A/ X6 c( H( E, g& e5 m( @5 K
复制代码在这里稍微解释一下代码: Speed_Adc是存储ADC采样值的变量,Speed_ref变量通过ADC采样值转化为速度设定值,MC_SPEED_REF是一个指针变量,用于获取ADC初始化设置,R3_1_F30X_ExecRegularConv这个函数在r3_1_f30x_pwm_curr_fdbk,c这个文件中,用于处理规则ADC采样。速度换算这里可以没什么说的。速度设定的时候加1500偏移是有原因的,当设定速度过低的时候电机系统根本不能正常启动,这是我尝试设置的时候所能达到的最低启动速度。
3 t: H3 a" M5 D3 L. O9 d5 ^实验现象: 从实验结果看来,这份代码默认速度PID能很好的跟踪给定转速。 我发现一个问题,代码里面在电机运行结束之后有些变量好像没有清零,这个问题留到后面在研究吧。 1 O: w6 t5 I5 ^5 i$ g' v5 \1 U
本帖两个任务分享就到这里,欢迎大家留言讨论。& e' b. K1 r8 k8 R- n. q% p
. a; c% d8 P! @! Z. T6 R( ^6 W. N; l R; y4 X- }
* o3 K! ?- P# z& R- P) \
$ k* F6 s$ s. F% x% r
|
看了你发的邮件,新版本的MCSDK生成的代码没有留ADC规则转换的函数接口,可能需要你自己去写了,我把我这边生成的文件发你一份参考吧
1.我之前参考您的函数,如果一直不断在执行转换,会影响电机库的控制时序导致无法开机,后来改为500ms一次,就没有问题。后来检查regular_conversion_manager.c中的内容,发现用户ADC的转换应该是电机库的状态机在调度的,如果连续不断转换或者没有走相应的接口估计会有问题。- c$ B: H0 A* e: q0 ^& t
2.电机Workbench里面有设置OCP参数,看了原理图应该是通过体验板上面的L6230的内置比较器以及SMT32片内的ADC实现的,但是实际中的程序并没有提供类似的功能。后来查看了代码,OCP保护是通过L6230产生的FO信号进行处理的,不知道我说的是否有偏差,还请指教。
大佬也会有纰漏啊
+ b+ k- M& z) [% ~4 K) Y( @, t( S
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)" F" M) d# o. c
{
if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
{
task_5(); ------>task_3();
}
else" ]) X. V! N4 h& L/ G: O# r7 M+ I9 H* |! T
{. H( I0 k& S5 ]' _+ ~
MC_StopMotor1();
} ; I, l4 s Z8 Y* N7 g8 K
/* 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连接也能正常运行
多谢楼主解释了。