本帖最后由 子曰好人 于 2018-9-2 10:21 编辑
2 y* X2 Z' l; ^! M
\8 _9 V7 ~- g5 x C8 A: k3 j2 S. v经过前期的准备,可以使用电机套件完成一些实验任务了。 首先是任务1和任务2的要求: 任务一和任务二基于workbench生成的代码来做并不难,因为代码里面提供了很多api函数并且做了很多软件上的保护,可以放心写代码,硬件不会那么容易损坏。
* g8 ]/ G+ D" Q0 L7 b0 }1 ^拿到一份陌生的代码除了了解我前面几篇帖子所说的内容外,在开始写代码前还需要了解api函数。我们可以打开mc_api.h看一看workbench都给我们提供了什么函数。
7 }4 b; K/ [; R. y( ~4 W - /** @addtogroup MCIAPI5 |4 h2 {) D; ]. s! C" j' H
- * @{
: l( d( c. o. H4 @/ y1 A - */( |2 Q5 h9 v& k5 f3 N0 k
3 p2 V8 g+ H% w" S! T0 u0 c- typedef enum {UDRC_STATE_IDLE, UDRC_STATE_REQUESTED, UDRC_STATE_EOC} UDRC_State_t;" Z" H" \! u6 G
- 7 u- D; r" H$ c7 w+ k
- /* Starts Motor 1 */
+ A, [: B' E: C5 ?5 a - bool MC_StartMotor1(void);
0 h' W0 y+ A' ?" l) M% L9 G - ) T! e& B/ {- v- w2 }
- /* Stops Motor 1 */, t9 ^5 H* X* T: D! Q) y
- bool MC_StopMotor1(void);/ M6 a* S" L5 u- v
- ) A2 p! m$ V- X4 Z4 C
- /* Programs a Speed ramp for Motor 1 */
1 M3 ~' Z* u' U( X1 f% h$ ^$ r% i7 u; N8 w - void MC_ProgramSpeedRampMotor1( int16_t hFinalSpeed, uint16_t hDurationms );9 B! V$ c* Y) a5 [
% J2 ]$ F5 @/ ` o* p9 L5 c0 n- /* Programs a Torque ramp for Motor 1 */
4 B7 }+ b3 H, d) T% N - void MC_ProgramTorqueRampMotor1( int16_t hFinalTorque, uint16_t hDurationms );+ [! Y# P; j0 `
- 8 a4 E" B- g! W- L1 d, d. D9 W
- /* Programs a current reference for Motor 1 */
4 W$ h* v$ c4 d - void MC_SetCurrentReferenceMotor1( Curr_Components Iqdref );
4 i! F0 s1 p# x" }
6 F2 E! ~# W R% A* i9 E! m/ n- /* Returns the state of the last submited command for Motor 1 */1 G" D% I( I; x% M( [1 K- d
- MCI_CommandState_t MC_GetCommandStateMotor1( void);
$ d& B5 Q, y: S( t0 r" T& o
0 Y' K# s) g- N) ]( r' q- /* Stops the execution of the current speed ramp for Motor 1 if any *// s2 N5 f+ ^# \
- bool MC_StopSpeedRampMotor1(void);
$ E: Z4 i/ H# W - ) Y8 c3 V! O5 \2 n+ b! k
- /* Returns true if the last submited ramp for Motor 1 has completed, false otherwise */
, P' [$ U! `9 Q - bool MC_HasRampCompletedMotor1(void);
0 D: j' G2 m$ z* x* s& f
: v4 G- b9 u9 [8 u- /* Returns the current mechanical rotor speed reference set for Motor 1, expressed in dHz (tenth of Hertz) */+ W9 a8 Q7 y. X* K
- int16_t MC_GetMecSpeedReferenceMotor1(void);
) N% A; n8 h3 o; b' i. p0 S. } d, | - $ b6 @4 i1 \1 R0 {/ o( s( ~$ q, l
- /* Returns the last computed average mechanical rotor speed for Motor 1, expressed in dHz (tenth of Hertz) */
- v u) ?" H6 ]! B7 s6 t - int16_t MC_GetMecSpeedAverageMotor1(void);
2 Q0 T- M* K- v# |. ^* E$ ^
: @2 Y! L; q0 {) D- /* Returns the final speed of the last ramp programmed for Motor 1, if this ramp was a speed ramp */& ~7 G( D( K7 Y3 k" g
- int16_t MC_GetLastRampFinalSpeedMotor1(void);' K5 m" G9 o F% Y6 a* i
- & d! A! r+ P4 ?5 q
- /* Returns the current Control Mode for Motor 1 (either Speed or Torque) */
' I7 A, g |; E: O* [% Q, I8 B- g8 b - STC_Modality_t MC_GetControlModeMotor1(void);' _: n& H" s* N2 E* {6 f# V
9 B9 g% c" U2 i& H8 `1 }- /* Returns the direction imposed by the last command on Motor 1 */
6 Y5 o8 I3 m( N! m8 J) c2 M - int16_t MC_GetImposedDirectionMotor1(void);
' V% J8 y; z: l2 q s* k
# f K, t7 H" @* J1 c- k- /* Returns the current reliability of the speed sensor used for Motor 1 */
$ @7 }# f1 l2 I9 n - bool MC_GetSpeedSensorReliabilityMotor1(void);4 I2 M8 m1 T2 B, k
- . J- b1 M& g: i3 O
- /* returns the amplitude of the phase current injected in Motor 1 */: ]9 ?/ ^- u. k$ m/ p5 ~
- int16_t MC_GetPhaseCurrentAmplitudeMotor1(void); h9 L% n+ S( B; V& N6 x7 X
+ F9 C' I" v9 n' }- S4 [/ i+ D/ Y7 d- /* returns the amplitude of the phase voltage applied to Motor 1 */
- A* V5 ?. j$ }" |+ a- N' M" k - int16_t MC_GetPhaseVoltageAmplitudeMotor1(void);; @3 ] P) C" x! X. M
- / V: F5 y9 v2 B3 R+ h
- /* returns current Ia and Ib values for Motor 1 */, S/ f, [0 }9 G# Z% k
- Curr_Components MC_GetIabMotor1(void);9 u# P7 }: l+ A" S6 v
( Q3 S& {9 k: j C) k% @: D- /* returns current Ialpha and Ibeta values for Motor 1 */
' Z \: `* v3 m - Curr_Components MC_GetIalphabetaMotor1(void);& C. Q; H4 s6 f" l2 X
- 6 f& V9 ]6 f9 u# O
- /* returns current Iq and Id values for Motor 1 */3 S2 j8 W# L! v9 r; P
- Curr_Components MC_GetIqdMotor1(void);3 ~! C g, u) C2 K- c; `3 m
6 f5 m4 V. o; [- /* returns Iq and Id reference values for Motor 1 */
; J3 I+ F, U- w5 z7 C& E! A2 y) I/ _ - Curr_Components MC_GetIqdrefMotor1(void);
/ s w( G" Q3 q% e - $ W- \% ?' a) B8 Q6 M$ t
- /* returns current Vq and Vd values for Motor 1 */
, x8 W% _2 b; Q& \ - Volt_Components MC_GetVqdMotor1(void);
6 D; w# a. T- E; E6 b3 a, `4 l1 e
9 D6 K" j, V8 t! i( Q; X- /* returns current Valpha and Vbeta values for Motor 1 */: q E- p. D! D* i
- Volt_Components MC_GetValphabetaMotor1(void);
1 O( o2 a4 V, O8 T# d
6 D; O5 A& N4 r$ _8 d- ~- /* returns the electrical angle of the rotor of Motor 1, in DDP format */" k V/ P' q ^8 L+ ?7 d
- int16_t MC_GetElAngledppMotor1(void);" u& v( P, c. I4 S( x
- 4 {) }7 q9 h5 \! T+ H, @
- /* returns the current electrical torque reference for Motor 1 */
$ |0 v( O% D! F2 q7 X - int16_t MC_GetTerefMotor1(void);
4 |9 m! ~6 V, U. [- S) `5 | - : O% M3 J+ n* A* _' }1 |* E
- /* Sets the reference value for Id */9 o/ g" z x$ x V- w7 H" N
- void MC_SetIdrefMotor1( int16_t hNewIdref );
# V% L3 _9 M I, h7 p& a - 9 E3 m, t9 y U4 }
- /* re-initializes Iq and Id references to their default values */, a/ b; p" B# A8 Z0 b: ?
- void MC_Clear_IqdrefMotor1(void);0 L! @5 \+ v, P# _1 P
- 3 J0 ?; m% m7 q
- /* Acknowledge a Motor Control fault on Motor 1 */% T4 U- `+ M# |' n: Y- J
- bool MC_AcknowledgeFaultMotor1( void );, ?6 v1 j' [$ c* w9 u
- 9 a! V- @1 `2 O. z
- /* Returns a bitfiled showing faults that occured since the State Machine of Motor 1 was moved to FAULT_NOW state */
6 n+ |/ ]. S# P; ~7 c5 V - uint16_t MC_GetOccurredFaultsMotor1(void);
; M. V% w. o L5 _ - 7 J2 O, I+ G9 e, }% b
- /* Returns a bitfield showing all current faults on Motor 1 */
6 i* N: W7 h g: ^- p - uint16_t MC_GetCurrentFaultsMotor1(void);
" z: {9 I0 B- b% o; i/ b - / Q8 v0 _( w8 b% o
- /* returns the current state of Motor 1 state machine */
9 H$ \. }5 r5 V0 d3 o' r8 Y - State_t MC_GetSTMStateMotor1(void);: @" }9 U5 \! a( W. {
9 I; }" S' g9 W* Z( N1 h- /* programs a user defined ADC regular conversion */2 B3 t& `# `/ T5 I2 P
- void MC_ProgramRegularConversion(uint8_t bChannel, uint8_t bSampleTime);
0 _: h" l' ~5 G' p, g2 L$ M2 O - 0 ]* h0 v( G' S5 t0 l# F n6 r0 |
- /* Returns the value of the last executed user defined ADC regular conversion */
6 W+ ?$ ?* Z8 S, n3 @+ y - uint16_t MC_GetRegularConversionValue(void);: e. c# I3 K% Q$ t( P5 x
7 @) ]' Q7 X, X: C8 ^- /* Returns the status of the last requested user defined ADC regular conversion */6 S5 ]. R. x- j+ p7 n$ s# e/ D
- UDRC_State_t MC_GetRegularConversionState(void);
复制代码上面这些api函数是对单个电机的操作,包含了启动、调速、调转矩、以及电机各种状态的获取。 看了任务一的要求,个人认为电机控制还是需要与外部交互好一点,电机启停不可控对于大功率的电机控制来说比较危险。 任务一代码: - void task_1(void)5 |7 A3 N+ S$ n$ P$ M% @; V% y
- {
* e# N5 I! @; T - MC_ProgramSpeedRampMotor1(3000/6,1000);' a+ ]& X" D0 f8 i! h
- MC_StartMotor1();" T( n4 ]% X: |, \* ?
- HAL_Delay(10000);( g! {+ j9 q& d
- MC_StopMotor1();
3 w" ~5 C! K8 l - HAL_Delay(10000);
" m; E. P& w" Y% x: A- c+ P - }
复制代码主函数添加的代码: - /* Infinite loop */0 e2 N9 T& R0 F/ K
- /* USER CODE BEGIN WHILE */
: T5 c8 f+ G& |1 p4 Q1 e" l- ^ - while (1)
% s' @5 F. A2 r - {1 Z1 d: t: z. d0 \ h/ K$ `9 Z
- ( x$ ~$ W5 b8 E4 ^+ T" ~
- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
4 c) n: A- t& }2 T! `, @ - {1 |. k! l! |) G! n3 ~
- task_1();7 Q9 B# Y* i R: T! | e; W2 g
- }) x; I+ x, f" p$ J- @. W7 ~# X" w
- else
* s! S: o7 H% y1 L" X4 e$ q8 v - {" u v ]: l1 b5 m; D
- MC_StopMotor1();
/ v! p% T+ }8 p( v# k. i& u - }( K/ ^0 z# N! @$ B" K( [! y
- realspeed = MC_GetMecSpeedAverageMotor1()*6;1 O) N G% a0 U, j* j7 z' h
- /* USER CODE END WHILE */
复制代码按键中断处理函数代码在ui_task.c这个文件中: - void UI_HandleStartStopButton_cb (void)
. n; N2 }( O, D! J. A8 T - {! }5 A( c% N% p
- /* USER CODE BEGIN START_STOP_BTN */
0 w' n3 t# o3 x V# Q - HAL_GPIO_TogglePin(LED11_GPIO_Port,LED11_Pin);) a# v0 Y+ W8 ]
- /* USER CODE END START_STOP_BTN */0 V: k. \) E, L8 S0 [5 A( E6 ?# ]
- }
4 f1 Y3 N/ E* s% x, w! U: T
复制代码这样可以通过按键来控制任务的运行并且可以通过led的亮灭来观察系统所处的状态。LED11是驱动板上的一颗led,引脚号是PB2,可以通过cubemx来设置初始化代码。 通过monitor可以看到速度变化曲线图: ok,任务一完成。 -------------------------------------------------------------
- Y6 V; d" O' c 任务二代码: - void task_2(void)1 N) d8 `7 u" m% U) Y' u
- {4 S+ W% o" X7 W8 [. t {# `
- int16_t Speed_Kp,Speed_Ki;& i x& Z, N: w
- MCT_Handle_t * pMctHdl;, J, e& \" j& @0 r! t% |
- MC_ProgramSpeedRampMotor1(3000/6,1000);" F/ M T7 J6 G1 {$ R5 R5 |
- MC_StartMotor1();$ Z2 F5 m7 }- \0 ]: s, ?6 ~8 u8 I
- HAL_Delay(3000);; l0 Y- _' n+ e" i/ P+ J% g
- MC_StopMotor1();1 |1 v( S7 u$ y' D8 i( h$ P
- HAL_Delay(1000);
1 ?' A# X3 g- a9 S N - pMctHdl = GetMCT(M1);7 \, q4 b( ?9 _( k; b, ~
- Speed_Kp = PID_GetKP(pMctHdl->pPIDSpeed);
. h/ O! o0 j4 @6 G - Speed_Ki = PID_GetKI(pMctHdl->pPIDSpeed);8 w% x5 P0 J3 A1 x5 T; y' ^3 W
- PID_SetKP(pMctHdl->pPIDSpeed,Speed_Kp*2);, X y( i( a5 i k
- PID_SetKI(pMctHdl->pPIDSpeed,Speed_Ki*2);; V8 {, g* \8 q* n9 k; |
- MC_ProgramSpeedRampMotor1(3000/6,1000);7 ]. f( f$ ?$ N) U$ j$ O& S7 A
- MC_StartMotor1();
* k# g5 l+ i1 e' W: n* q0 K) c - HAL_Delay(3000);7 K4 V$ B3 I6 {8 C6 q
- MC_StopMotor1();
y1 T8 N. m" ?2 g* k; q - HAL_Delay(1000);4 `: Q0 R* \+ h7 y( |7 T4 v
- PID_SetKP(pMctHdl->pPIDSpeed,Speed_Kp/2);
1 s6 m3 p0 M8 v; c3 B - PID_SetKI(pMctHdl->pPIDSpeed,Speed_Ki/2);
* T- V( L8 U( y- }1 Q - MC_ProgramSpeedRampMotor1(3000/6,1000);# T2 ~ B/ Q5 R0 d' p R7 x) L% P
- MC_StartMotor1();
+ g2 r3 F7 `# ~( y - HAL_Delay(3000);$ Z5 A3 k8 }; e+ |5 M" r
- MC_StopMotor1();
$ l q) b+ O, d c - HAL_GPIO_WritePin(LED11_GPIO_Port,LED11_Pin,GPIO_PIN_RESET);
* x! u2 h1 U* L: I, U - }
复制代码主函数代码和任务一相同,只是把task_1()改成task_2()就行了。最后一行把LED引脚拉低是为了让代码只运行一次,多次运行可以通过按键进行操作。 可以看到和预期结果是一致的,原始PI调节速度快,有超调现象;Kp、Ki同时增大一倍的时候,调节加快了,并且超调现象被抑制了;当Kp、Ki同时缩小一倍时可以看到虽然调节很快,但是有严重的超调现象。 / n; G7 d! c) J
2 _1 ?2 k+ {' p
通过monitor的图形显示速度波形极大的方便调试PID的过程,ST考虑得真周到。
6 N: Y. V/ @' U5 o' E i; _ 我在这里有个疑问,这个plotter只能显示参考速度的波形吗,还能不能添加其他变量来查看系统某个变量的变化趋势呢。之前我一直是用的Jscope,但是Jscope需要连接Jlink来查看,对于这款套件来说需要额外连接Jlink调试器,有一点点麻烦。后面调试有必要我还是会使用Jscope来查看一些变量的波形,并且分享到论坛。
& z. O/ i( Z) n N9 s N8 F! ]* v+ x( O
任务一和任务二已完成,欢迎大家留言讨论。$ T7 C* n$ j9 p4 c
! m m) m# G, U2 k2 Y
5 C* }) h+ K" j" P; g* a" K! u- s. K
0 I4 E% m9 A8 M' \0 R/ G
|
/* Programs a Speed ramp for Motor 1 */" [, I# J# n; q6 R
void MC_ProgramSpeedRampMotor1( int16_t hFinalSpeed, uint16_t hDurationms );# v3 M) w* d7 c" q8 V( F& a
这个函数的第二个参数你改过吗,第二个参数就是达到目标值的时间,越小加速度越快# P( `( U' k3 x1 [/ U
( }! w) F4 m9 r/ S
考虑另外一个问题,电机惯性较大,电机驱动板的驱动能力有限,也许最多就只能10+s才能达到目标转速
1.在我的程序里按键的作用起的是传递信号的作用,按键中断中翻转LED11引脚,主函数通过读取LED11引脚电平值做是否启动任务的判断。
2.在我的代码里启停是可控的,通过LED11引脚电平来判断是否执行task1。另外,task1的要求就是延时不断启停,我这样写是没有问题的
直接扔好几个问题,还没完全看过来' g) S* d# m: Z- | |+ k, K9 J
回复20#和21#:
User_label那个自己想写什么名字无所谓,根据自己喜好就OK3 Z& ?3 Q1 a% F/ C
回复22#和23#:
不用跟我的代码完全一样,这个只是我用于控制实验进行与否的一种方式,你也可以通过其他方式来做
好的,有时间我去了解一下通讯协议的代码,尝试显示其他变量。另外一个就是觉得plotter采样率有点低,Jscope采样率1kHz在好些时候都显得不太够用。
我没试过其他电压,一直用的12V,你是不是正负极接反了
不是,我是从24V慢慢升上去的,
我后面尝试一下高电压再给你反馈吧,主要是现在我也没有高电压的电机,所以一直用的12V
好的,还是小心点吧
上电40V驱动板坏了,底板还是好的,这个可能需要告知一下ST了
板子和上位机通讯协议是啥
我还没看,你可以去串口中断函数中了解通信协议
正常呀,这属于C语言基本功,MCT_Handle_t这个结构体在mc_tuning.h中定义的,你要在其他文件中使用当然要包含定义这个结构体的头文件嘛
那就好,我还以为是我工程建立的有问题