你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

No.4 电机套件实验任务一和任务二

[复制链接]
子曰好人 发布时间:2018-9-2 10:18
本帖最后由 子曰好人 于 2018-9-2 10:21 编辑

经过前期的准备,可以使用电机套件完成一些实验任务了。
首先是任务1和任务2的要求:
task1.png
task2.png
任务一和任务二基于workbench生成的代码来做并不难,因为代码里面提供了很多api函数并且做了很多软件上的保护,可以放心写代码,硬件不会那么容易损坏。

拿到一份陌生的代码除了了解我前面几篇帖子所说的内容外,在开始写代码前还需要了解api函数。我们可以打开mc_api.h看一看workbench都给我们提供了什么函数。
  1. /** @addtogroup MCIAPI
  2.   * @{
  3.   */

  4. typedef enum {UDRC_STATE_IDLE, UDRC_STATE_REQUESTED, UDRC_STATE_EOC} UDRC_State_t;

  5. /* Starts Motor 1 */
  6. bool MC_StartMotor1(void);

  7. /* Stops Motor 1 */
  8. bool MC_StopMotor1(void);

  9. /* Programs a Speed ramp for Motor 1 */
  10. void MC_ProgramSpeedRampMotor1( int16_t hFinalSpeed, uint16_t hDurationms );

  11. /* Programs a Torque ramp for Motor 1 */
  12. void MC_ProgramTorqueRampMotor1( int16_t hFinalTorque, uint16_t hDurationms );

  13. /* Programs a current reference for Motor 1 */
  14. void MC_SetCurrentReferenceMotor1( Curr_Components Iqdref );

  15. /* Returns the state of the last submited command for Motor 1 */
  16. MCI_CommandState_t  MC_GetCommandStateMotor1( void);

  17. /* Stops the execution of the current speed ramp for Motor 1 if any */
  18. bool MC_StopSpeedRampMotor1(void);

  19. /* Returns true if the last submited ramp for Motor 1 has completed, false otherwise */
  20. bool MC_HasRampCompletedMotor1(void);

  21. /* Returns the current mechanical rotor speed reference set for Motor 1, expressed in dHz (tenth of Hertz) */
  22. int16_t MC_GetMecSpeedReferenceMotor1(void);

  23. /* Returns the last computed average mechanical rotor speed for Motor 1, expressed in dHz (tenth of Hertz) */
  24. int16_t MC_GetMecSpeedAverageMotor1(void);

  25. /* Returns the final speed of the last ramp programmed for Motor 1, if this ramp was a speed ramp */
  26. int16_t MC_GetLastRampFinalSpeedMotor1(void);

  27. /* Returns the current Control Mode for Motor 1 (either Speed or Torque) */
  28. STC_Modality_t MC_GetControlModeMotor1(void);

  29. /* Returns the direction imposed by the last command on Motor 1 */
  30. int16_t MC_GetImposedDirectionMotor1(void);

  31. /* Returns the current reliability of the speed sensor used for Motor 1 */
  32. bool MC_GetSpeedSensorReliabilityMotor1(void);

  33. /* returns the amplitude of the phase current injected in Motor 1 */
  34. int16_t MC_GetPhaseCurrentAmplitudeMotor1(void);

  35. /* returns the amplitude of the phase voltage applied to Motor 1 */
  36. int16_t MC_GetPhaseVoltageAmplitudeMotor1(void);

  37. /* returns current Ia and Ib values for Motor 1 */
  38. Curr_Components MC_GetIabMotor1(void);

  39. /* returns current Ialpha and Ibeta values for Motor 1 */
  40. Curr_Components MC_GetIalphabetaMotor1(void);

  41. /* returns current Iq and Id values for Motor 1 */
  42. Curr_Components MC_GetIqdMotor1(void);

  43. /* returns Iq and Id reference values for Motor 1 */
  44. Curr_Components MC_GetIqdrefMotor1(void);

  45. /* returns current Vq and Vd values for Motor 1 */
  46. Volt_Components MC_GetVqdMotor1(void);

  47. /* returns current Valpha and Vbeta values for Motor 1 */
  48. Volt_Components MC_GetValphabetaMotor1(void);

  49. /* returns the electrical angle of the rotor of Motor 1, in DDP format */
  50. int16_t MC_GetElAngledppMotor1(void);

  51. /* returns the current electrical torque reference for Motor 1 */
  52. int16_t MC_GetTerefMotor1(void);

  53. /* Sets the reference value for Id */
  54. void MC_SetIdrefMotor1( int16_t hNewIdref );

  55. /* re-initializes Iq and Id references to their default values */
  56. void MC_Clear_IqdrefMotor1(void);

  57. /* Acknowledge a Motor Control fault on Motor 1 */
  58. bool MC_AcknowledgeFaultMotor1( void );

  59. /* Returns a bitfiled showing faults that occured since the State Machine of Motor 1 was moved to FAULT_NOW state */
  60. uint16_t MC_GetOccurredFaultsMotor1(void);

  61. /* Returns a bitfield showing all current faults on Motor 1 */
  62. uint16_t MC_GetCurrentFaultsMotor1(void);

  63. /* returns the current state of Motor 1 state machine */
  64. State_t  MC_GetSTMStateMotor1(void);

  65. /* programs a user defined ADC regular conversion */
  66. void MC_ProgramRegularConversion(uint8_t bChannel, uint8_t bSampleTime);

  67. /* Returns the value of the last executed user defined ADC regular conversion */
  68. uint16_t MC_GetRegularConversionValue(void);

  69. /* Returns the status of the last requested user defined ADC regular conversion */
  70. UDRC_State_t MC_GetRegularConversionState(void);
复制代码
上面这些api函数是对单个电机的操作,包含了启动、调速、调转矩、以及电机各种状态的获取。
看了任务一的要求,个人认为电机控制还是需要与外部交互好一点,电机启停不可控对于大功率的电机控制来说比较危险。
任务一代码:
  1. void task_1(void)
  2. {
  3.     MC_ProgramSpeedRampMotor1(3000/6,1000);
  4.     MC_StartMotor1();
  5.     HAL_Delay(10000);
  6.     MC_StopMotor1();
  7.     HAL_Delay(10000);
  8. }
复制代码
主函数添加的代码:
  1. /* Infinite loop */
  2.   /* USER CODE BEGIN WHILE */
  3.   while (1)
  4.   {
  5.       
  6.       if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
  7.       {
  8.               task_1();
  9.       }
  10.       else
  11.       {
  12.             MC_StopMotor1();
  13.       }
  14.       realspeed = MC_GetMecSpeedAverageMotor1()*6;
  15.   /* USER CODE END WHILE */
复制代码
按键中断处理函数代码在ui_task.c这个文件中:
  1. void UI_HandleStartStopButton_cb (void)
  2. {
  3. /* USER CODE BEGIN START_STOP_BTN */
  4.   HAL_GPIO_TogglePin(LED11_GPIO_Port,LED11_Pin);
  5. /* USER CODE END START_STOP_BTN */
  6. }
复制代码
这样可以通过按键来控制任务的运行并且可以通过led的亮灭来观察系统所处的状态。LED11是驱动板上的一颗led,引脚号是PB2,可以通过cubemx来设置初始化代码。
通过monitor可以看到速度变化曲线图:
任务一速度变化截图.png
ok,任务一完成。
-------------------------------------------------------------
任务二代码:
  1. void task_2(void)
  2. {
  3.         int16_t Speed_Kp,Speed_Ki;
  4.         MCT_Handle_t * pMctHdl;
  5.         MC_ProgramSpeedRampMotor1(3000/6,1000);
  6.         MC_StartMotor1();
  7.         HAL_Delay(3000);
  8.         MC_StopMotor1();
  9.         HAL_Delay(1000);
  10.      pMctHdl = GetMCT(M1);
  11.      Speed_Kp = PID_GetKP(pMctHdl->pPIDSpeed);
  12.      Speed_Ki = PID_GetKI(pMctHdl->pPIDSpeed);
  13.      PID_SetKP(pMctHdl->pPIDSpeed,Speed_Kp*2);
  14.      PID_SetKI(pMctHdl->pPIDSpeed,Speed_Ki*2);
  15.      MC_ProgramSpeedRampMotor1(3000/6,1000);
  16.      MC_StartMotor1();
  17.      HAL_Delay(3000);
  18.      MC_StopMotor1();
  19.      HAL_Delay(1000);
  20.      PID_SetKP(pMctHdl->pPIDSpeed,Speed_Kp/2);
  21.      PID_SetKI(pMctHdl->pPIDSpeed,Speed_Ki/2);
  22.      MC_ProgramSpeedRampMotor1(3000/6,1000);
  23.      MC_StartMotor1();
  24.      HAL_Delay(3000);
  25.      MC_StopMotor1();   
  26.         HAL_GPIO_WritePin(LED11_GPIO_Port,LED11_Pin,GPIO_PIN_RESET);
  27. }
复制代码
主函数代码和任务一相同,只是把task_1()改成task_2()就行了。最后一行把LED引脚拉低是为了让代码只运行一次,多次运行可以通过按键进行操作。
任务2速度截图.png
可以看到和预期结果是一致的,原始PI调节速度快,有超调现象;Kp、Ki同时增大一倍的时候,调节加快了,并且超调现象被抑制了;当Kp、Ki同时缩小一倍时可以看到虽然调节很快,但是有严重的超调现象。

通过monitor的图形显示速度波形极大的方便调试PID的过程,ST考虑得真周到。

我在这里有个疑问,这个plotter只能显示参考速度的波形吗,还能不能添加其他变量来查看系统某个变量的变化趋势呢。之前我一直是用的Jscope,但是Jscope需要连接Jlink来查看,对于这款套件来说需要额外连接Jlink调试器,有一点点麻烦。后面调试有必要我还是会使用Jscope来查看一些变量的波形,并且分享到论坛。

任务一和任务二已完成,欢迎大家留言讨论。




收藏 2 评论27 发布时间:2018-9-2 10:18

举报

27个回答
子曰好人 回答时间:2019-7-23 09:13:07
jeff1996 发表于 2019-7-22 16:34
楼主。 我按照你任务1的程序。 但是我的电机加速到3000RPM需要10多秒。 怎么设置都是10多秒,很奇怪。 请问 ...

/* Programs a Speed ramp for Motor 1 */
void MC_ProgramSpeedRampMotor1( int16_t hFinalSpeed, uint16_t hDurationms );
这个函数的第二个参数你改过吗,第二个参数就是达到目标值的时间,越小加速度越快

考虑另外一个问题,电机惯性较大,电机驱动板的驱动能力有限,也许最多就只能10+s才能达到目标转速
子曰好人 回答时间:2019-3-13 10:16:47
gatsby32 发表于 2019-3-13 09:42
老哥  这个task是写在main函数里面吗  ?这个按键中断有什么作用啊?麻烦老哥给我解解惑,第一次学这些 很 ...

1.在我的程序里按键的作用起的是传递信号的作用,按键中断中翻转LED11引脚,主函数通过读取LED11引脚电平值做是否启动任务的判断。
2.在我的代码里启停是可控的,通过LED11引脚电平来判断是否执行task1。另外,task1的要求就是延时不断启停,我这样写是没有问题的
子曰好人 回答时间:2019-3-28 17:05:01
gatsby32 发表于 2019-3-28 16:52
老哥 这两个函数的内容不一样 ,为了完成实验一 我需要把这个内容改成和你一样的吗
...

直接扔好几个问题,还没完全看过来
回复20#和21#:
User_label那个自己想写什么名字无所谓,根据自己喜好就OK
回复22#和23#:
不用跟我的代码完全一样,这个只是我用于控制实验进行与否的一种方式,你也可以通过其他方式来做
freeelectron 回答时间:2018-9-2 18:27:19
这个只显示了速度波形,其实要想显示更多东西,就在通讯协议里面加就好了,ST这个是串口的,板子和上位机通讯协议已经固定了,想要显示更多可以自己搞个上位机;
子曰好人 回答时间:2018-9-2 19:05:16
freeelectron 发表于 2018-9-2 18:27
这个只显示了速度波形,其实要想显示更多东西,就在通讯协议里面加就好了,ST这个是串口的,板子和上位机通 ...

好的,有时间我去了解一下通讯协议的代码,尝试显示其他变量。另外一个就是觉得plotter采样率有点低,Jscope采样率1kHz在好些时候都显得不太够用。
FF_胖子 回答时间:2018-9-14 09:20:41
这套板最大可以承受多大的电压,官方给的不是8-48V吗,但是我的刚到40V下面那个nucle板就烧了
子曰好人 回答时间:2018-9-14 09:29:48
ff321 发表于 2018-9-14 09:20
这套板最大可以承受多大的电压,官方给的不是8-48V吗,但是我的刚到40V下面那个nucle板就烧了
...

我没试过其他电压,一直用的12V,你是不是正负极接反了
FF_胖子 回答时间:2018-9-14 09:47:12
子曰好人 发表于 2018-9-14 09:29
我没试过其他电压,一直用的12V,你是不是正负极接反了

不是,我是从24V慢慢升上去的,
子曰好人 回答时间:2018-9-14 10:04:26
ff321 发表于 2018-9-14 09:47
不是,我是从24V慢慢升上去的,

我后面尝试一下高电压再给你反馈吧,主要是现在我也没有高电压的电机,所以一直用的12V
FF_胖子 回答时间:2018-9-14 10:57:54
子曰好人 发表于 2018-9-14 10:04
我后面尝试一下高电压再给你反馈吧,主要是现在我也没有高电压的电机,所以一直用的12V ...

好的,还是小心点吧
子曰好人 回答时间:2018-9-14 18:52:52
ff321 发表于 2018-9-14 10:57
好的,还是小心点吧

上电40V驱动板坏了,底板还是好的,这个可能需要告知一下ST了
VernonBacon 回答时间:2018-9-19 09:21:24
freeelectron 发表于 2018-9-2 18:27
这个只显示了速度波形,其实要想显示更多东西,就在通讯协议里面加就好了,ST这个是串口的,板子和上位机通 ...

板子和上位机通讯协议是啥
子曰好人 回答时间:2018-9-19 09:37:38
vernonvb 发表于 2018-9-19 09:21
板子和上位机通讯协议是啥

我还没看,你可以去串口中断函数中了解通信协议
mozartc 回答时间:2018-9-20 13:21:39
MCT_Handle_t* 这个类型的指针,会报错,没有定义,然后我加上mc_tuning.h就可以了,楼主你有遇到吗?
子曰好人 回答时间:2018-9-20 14:08:31
mozartc 发表于 2018-9-20 13:21
MCT_Handle_t* 这个类型的指针,会报错,没有定义,然后我加上mc_tuning.h就可以了,楼主你有遇到吗? ...

正常呀,这属于C语言基本功,MCT_Handle_t这个结构体在mc_tuning.h中定义的,你要在其他文件中使用当然要包含定义这个结构体的头文件嘛
mozartc 回答时间:2018-9-20 14:12:20
子曰好人 发表于 2018-9-20 14:08
正常呀,这属于C语言基本功,MCT_Handle_t这个结构体在mc_tuning.h中定义的,你要在其他文件中使用当然要 ...

那就好,我还以为是我工程建立的有问题
gatsby32 回答时间:2019-3-11 10:49:32
老哥  cubemax怎么初试化引脚啊,你能把你的任务一和任务二的工程发给我我吗,我不知道task这些函数要添加在哪里 ,我以前没学过这些东西 ,是个菜鸟 ,望老哥多多指教啊
12下一页

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版