本帖最后由 子曰好人 于 2018-9-5 08:55 编辑
- Z2 H, j' ^- Y* O+ M. K+ X s9 j* h2 V& U( m
继续做实验,任务3和旋钮控制转速。 首先来看看任务3的要求: 这个可通过代码实现也可以通过上位机实现,已经有坛友做过这样的事情了。通过上位机做就是快速拨弄圆盘,这样系统不能在短时间内反转,造成观测器不能收敛,触发速度反馈错误报警,其实我个人觉得这里也是有过流报警存在的,这就看系统优先响应哪一个报警了。 我这里通过代码来实现task3。 任务3代码: - void task_3(void)7 W" X( G Y% D8 m" m
- {
7 N0 }0 B5 V! ~; u/ o7 d, E; A - MC_ProgramSpeedRampMotor1(-3000/6,1000); //设置-3000rpm的转速,在一秒之内达到
' `" A3 E+ C- Q. f6 ?; M' x* i$ N - MC_StartMotor1(); //启动电机
: r9 d) A/ r% N, K9 ^5 \ - HAL_Delay(500); //运行500ms
& s. _' M3 d- } {% o) }. j: h' X - while(RUN != MC_GetSTMStateMotor1()); //等待电机处于运行状态,可有可无1 h ?" G2 w" L+ }3 j/ ^
- MC_ProgramSpeedRampMotor1(3000/6,1000); //切换到3000rpm转速- [ s) R6 F! h
- MC_StartMotor1(); //启动电机
* c% p" x$ z" I# q H8 y - while(MC_SPEED_FDBK != STM_GetFaultState(&STM[M1])); //等待错误触发
0 o9 ^/ [9 w6 l% @- i2 X - HAL_Delay(1000); //延时一秒,方便可以在上位机上看见错误是否发生
9 y: Z' }) C l# g, }3 q3 N3 b# } - MC_AcknowledgeFaultMotor1(); //清除错误
4 I+ g' G5 U- |% j - HAL_Delay(100); //延时0.1秒
. }; u/ K$ L1 ^7 s, h - MC_ProgramSpeedRampMotor1(MC_GetLastRampFinalSpeedMotor1(),1000); //重新设置上一次速度值3 z, w! _9 Z' a/ |' t- L) n& {
- MC_StartMotor1(); //启动电机
4 l0 Y L8 d: E/ ? - HAL_Delay(5000); //运行5秒" b9 E& z* m$ m: j+ u+ G% ]" [3 w
- MC_StopMotor1(); //停机# A7 K, _) p4 m1 V- c
- HAL_GPIO_WritePin(LED11_GPIO_Port,LED11_Pin,GPIO_PIN_RESET); //拉低LED引脚,表示任务结束
% g. m$ N+ ~! Z( b - }
7 L$ y# q- |7 B; e( x2 o, Y
复制代码主函数代码: - /* Infinite loop */" c! q* J" I! T3 \* Z! M0 Z, \
- /* USER CODE BEGIN WHILE */) v% }9 R$ A1 R0 F
- while (1)) E- k- D+ d' u; G4 ?4 `- N
- {& r+ i3 d8 G p, n$ b+ L2 V: D
- * q8 N+ e" m; }* i1 G0 v
- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
8 \4 J1 |# u, }4 k, f2 a - {+ q" t3 S# h- g% }0 ]% r P
- task_3();
! [4 A! O% |4 C4 E# ]! ?- w* C - }
: T" S J2 z" w3 a - else+ x X$ @7 e% _4 v
- {
: j. ^& M" u" ]6 c9 B9 ` - MC_StopMotor1();
$ u+ [2 Y- ]1 t9 q# L8 O2 c2 f - } - X# K( B; @0 ~/ `" t ?, _
- /* USER CODE END WHILE */% ^# [. ?2 P* M) O
复制代码实验现象:
6 c) B' ]3 x/ b5 P- ]2 |5 g
通过速度变化趋势可以看到任务成功实现了,我对比了PPT的预期结果图,有一些差距。当速度设置为3000rpm时,speed reference并没有跟随代码变为3000。另外,我做了延迟清除错误信息,所以在图中可以看到一截零速状态。
% ]! r, N$ w1 R" r1 z; j9 n+ A3 w( }: `( q. M# {
好了,任务3完成。 --------------------------------------------------------- 现在分享一个开放性实验,旋钮控制转速,我把这个任务定为任务4吧,用旋钮来控制电机转速我觉得才是真正的一个电机控制系统。 由于SDK中并没有考虑旋钮ADC的初始化,所以如果要使用旋钮电位器首先要通过cubemx对ADC进行初始化,在我的第二篇帖子中已经讲过关于套件的硬件资源,也知道了旋钮电位器连接的是PB1引脚。 创建全局变量: - int32_t Speed_Adc = 0;& O, Q( K* {6 C% }
- int32_t Speed_ref = 0;
% T9 X! s' e7 h$ G. W3 v0 n5 D P. u - PWMC_Handle_t * MC_SPEED_REF;
6 ?. a$ v) u5 F9 A
复制代码任务4代码: - void task_4(void)
+ \) G: u' d7 l( q- M3 I - {/ L, W8 N& |0 p' V1 H% E, m$ f
- Speed_Adc = R3_1_F30X_ExecRegularConv(MC_SPEED_REF,ADC_CHANNEL_12);
$ y! M5 b: n) ^7 M9 c1 D - Speed_ref = (15500*Speed_Adc)>>16;4 c2 b2 J3 `+ A1 j) T& c+ S
- if(Speed_ref > 0)
8 y, A ^: f# Q7 @ - {
2 w1 b3 z4 G( g8 P3 N* v, O' | - MC_ProgramSpeedRampMotor1((Speed_ref+1500)/6,1000);
F% |# Z! U" f, ^8 k' V Z - MC_StartMotor1();* \3 j8 b+ L; P9 t+ d
- }
2 d9 o: l; R' s* z; z1 A- p0 ?! e - else
2 }1 V* ?- j# h& A: d3 }/ U) I - {
, G, e/ q; X& g6 Q: X3 B - MC_StopMotor1();
. P( t0 ^2 u f: G0 `7 S - } D( t$ }* J; M% y0 f( Y8 Z
- HAL_Delay(100);* j' {) ]2 h, o4 j6 e% f s8 `$ @
- }
复制代码 主函数代码:
; Z, l, S' |8 z7 y5 P9 q7 u- /* Initialize interrupts */
- m# b" H, G1 s! o l& c - MX_NVIC_Init();6 s' ?& l, ]) W+ |" y
- /* USER CODE BEGIN 2 */& z* h D% N+ h. h' L
- MC_SPEED_REF = &PWM_Handle_M1._Super;
* _" P+ n- ]+ b - /* USER CODE END 2 */0 h+ Z/ L6 n& J6 I: \$ X
- 2 q( {1 T& a, _" _. L4 O, _* g
- /* Infinite loop */& Y: P: ^8 Y" L
- /* USER CODE BEGIN WHILE */* C; J7 W. r+ _" K+ H
- while (1)
B9 y e( Z2 x9 j2 g H. F( I& w - {
3 m+ N& @& G5 ]$ A* d: C1 F - # z! y# {* |6 ^( @4 t& z1 |+ K
- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
# M/ N( v1 ~# E6 Z. `8 O0 S+ l - {
; I; W. x# N* A; Y- R% K - task_4();0 U2 B6 c- r! ~. l
- }; D+ g2 ^/ a3 o# \ F! X; O
- else
4 E2 r- } n8 q& Y1 K" H - {
3 e2 C7 b+ B6 l& F$ O - MC_ProgramSpeedRampMotor1(0,0);8 R* w/ i N5 k. P
- MC_StopMotor1();" K8 R, e- E# f2 ?
- }
2 i* O% H7 [3 M - /* USER CODE END WHILE */7 z- S/ C! q1 [. `
- T7 ~/ c7 ~. I: q5 A% F. N
- /* USER CODE BEGIN 3 */9 R5 o) R# h7 s% O5 |. r
3 z$ O" Y- M4 \4 w+ S) A2 R" Q @- }# x7 ~' o' ^3 A0 M: M+ V' t+ Z4 ^
- /* USER CODE END 3 */3 v1 u/ Z0 Z" m& j) g+ B$ A7 w8 J
复制代码在这里稍微解释一下代码: Speed_Adc是存储ADC采样值的变量,Speed_ref变量通过ADC采样值转化为速度设定值,MC_SPEED_REF是一个指针变量,用于获取ADC初始化设置,R3_1_F30X_ExecRegularConv这个函数在r3_1_f30x_pwm_curr_fdbk,c这个文件中,用于处理规则ADC采样。速度换算这里可以没什么说的。速度设定的时候加1500偏移是有原因的,当设定速度过低的时候电机系统根本不能正常启动,这是我尝试设置的时候所能达到的最低启动速度。
q' L: a3 I0 K m) n实验现象: 从实验结果看来,这份代码默认速度PID能很好的跟踪给定转速。 我发现一个问题,代码里面在电机运行结束之后有些变量好像没有清零,这个问题留到后面在研究吧。
) k9 p4 ~% t+ p2 `* J8 z本帖两个任务分享就到这里,欢迎大家留言讨论。
* s/ g, V% Q& P2 m/ A 1 p: u: P1 R/ W' }
5 n" T5 S1 V. L; V* v) f- n8 S7 }( x' d
3 I0 W* x- e G9 F7 i+ \- [) Q6 V |
看了你发的邮件,新版本的MCSDK生成的代码没有留ADC规则转换的函数接口,可能需要你自己去写了,我把我这边生成的文件发你一份参考吧
* i- f& s2 }& ~! F+ s
1.我之前参考您的函数,如果一直不断在执行转换,会影响电机库的控制时序导致无法开机,后来改为500ms一次,就没有问题。后来检查regular_conversion_manager.c中的内容,发现用户ADC的转换应该是电机库的状态机在调度的,如果连续不断转换或者没有走相应的接口估计会有问题。( e- z3 ^/ F" b8 @7 a" \
2.电机Workbench里面有设置OCP参数,看了原理图应该是通过体验板上面的L6230的内置比较器以及SMT32片内的ADC实现的,但是实际中的程序并没有提供类似的功能。后来查看了代码,OCP保护是通过L6230产生的FO信号进行处理的,不知道我说的是否有偏差,还请指教。
大佬也会有纰漏啊
/* Infinite loop */7 c& P2 q" f( I
/* USER CODE BEGIN WHILE */' ^4 z# p$ J' f! k8 a, r( H* o l8 p7 D
while (1)! q; `: _* @' o0 w; B3 y+ k" W
{
: v( C3 ^7 O% e; T* j4 O
if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
{
task_5(); ------>task_3();6 m5 U1 y4 j% h
}0 B; |" `% l; r; e
else0 }, M2 Z: O5 ? a
{
MC_StopMotor1();
}
/* 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连接也能正常运行
多谢楼主解释了。