3460|2

530

帖子

4

TA的资源

一粒金砂(高级)

楼主
 

[GD32E231 DIY大赛] 05. 自动喂鱼机器人之PWM篇 [复制链接]

 
[GD32E231 DIY大赛] 05. 自动喂鱼机器人之PWM篇

1.舵机基本工作原理

一般机器人控制都离不开舵机控制,这里先简单讲解一下舵机的基本工作原理:

舵机的控制信号为周期是 20ms 的脉宽调制(PWM)信号,其中脉冲宽度从 0.5ms-2.5ms,相对应舵盘的位置为 0-180 度,呈线性变化。也就是说,给它提供一定的脉宽,它的输出轴就会保持在一个相对应的角度上,无论外界转矩怎样改变,直到给它提供一个另外宽度的脉冲信号,它才会改变输出角度到新的对应的位置上。

一般而言,舵机的基准信号都是周期为20ms,宽度为1.5ms。这个基准信号定义的位置为中间位置。其中间位置的脉冲宽度是一定的,那就是1.5ms。

我是参考: https://blog.csdn.net/weixin_38075894/article/details/80027600.
20ms基准频率就是50Hz, 这个一般的单片机都是很容易生成的。
我的机械臂上的舵机型号是MG90S,是一个小舵机,机械臂是4自由度的,因此就是4个。
GD32E231的定时器功能是非常强大的,TIMER2可以同时输出四个通道的PWM,PWM可以设定不同的脉宽。

2.硬件配置

因为GD32E231start开发板,兼容arduino接口,因此我采用了arduino的转接板,转接板仅仅是转接功能,具体如下:
具体的接口配置:
PB4 TIMER2_CH0 D3 PB5 TIMER2_CH1 D4 PB0 TIMER2_CH2 D9 PB1 TIMER2_CH3 D8

3程序如下:

  1. void gpio_config(void);
  2. void pwm_timer_clock_enable(void);
  3. void pwm_timer_config(uint32_t timer);
复制代码
  1. void gpio_config(void)
  2. {
  3. rcu_periph_clock_enable(RCU_GPIOB);
  4. /* configure PB2 output 0 */
  5. gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_2);
  6. gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_2);
  7. gpio_bit_reset(GPIOB, GPIO_PIN_2);//disable opa, ENA is connected to PB2, ENA = 0, diable opa, else, enable ENA, NOT be float
  8. /* configure PB4(TIMER2 CH0) as alternate function */
  9. gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
  10. gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_4);
  11. gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_4);
  12. /* configure PB5(TIMER2 CH1) as alternate function */
  13. gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
  14. gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_5);
  15. gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_5);
  16. /* configure PB0(TIMER2 CH2) as alternate function */
  17. gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0);
  18. gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_0);
  19. gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_0);
  20. /* configure PB1(TIMER2 CH3) as alternate function */
  21. gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
  22. gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_1);
  23. gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_1);
  24. }
复制代码
  1. /*!
  2. \brief enable clock of the TIMER peripheral
  3. \param[in] none
  4. \param[out] none
  5. \retval none
  6. */
  7. void pwm_timer_clock_enable()
  8. {
  9. rcu_periph_clock_enable(RCU_TIMER2);
  10. }
复制代码
  1. void pwm_timer_config(uint32_t timer)
  2. {
  3. /* -----------------------------------------------------------------------
  4. TIMER2CLK is 100KHz
  5. TIMER2 channel0 duty cycle = (25000/ 50000)* 100 = 50%
  6. ----------------------------------------------------------------------- */
  7. timer_oc_parameter_struct timer_ocintpara;
  8. timer_parameter_struct timer_initpara;
  9. timer_deinit(timer);
  10. /* TIMER configuration */
  11. timer_initpara.prescaler = 719;
  12. timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
  13. timer_initpara.counterdirection = TIMER_COUNTER_UP;
  14. timer_initpara.period = 1999;
  15. timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
  16. timer_initpara.repetitioncounter = 0;
  17. timer_init(timer,&timer_initpara);
  18. /* configurate CH0 in PWM mode0 */
  19. timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
  20. timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
  21. timer_channel_output_config(timer,TIMER_CH_0,&timer_ocintpara);
  22. timer_channel_output_pulse_value_config(timer,TIMER_CH_0,150-1);
  23. timer_channel_output_mode_config(timer,TIMER_CH_0,TIMER_OC_MODE_PWM0);
  24. timer_channel_output_shadow_config(timer,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);
  25. timer_auto_reload_shadow_enable(timer);
  26. timer_enable(timer);
  27. delay_1ms(500);
  28. timer_disable(timer);
  29. timer_channel_output_config(timer,TIMER_CH_1,&timer_ocintpara);
  30. timer_channel_output_pulse_value_config(timer,TIMER_CH_1,150-1);
  31. timer_channel_output_mode_config(timer,TIMER_CH_1,TIMER_OC_MODE_PWM0);
  32. timer_channel_output_shadow_config(timer,TIMER_CH_1,TIMER_OC_SHADOW_DISABLE);
  33. timer_auto_reload_shadow_enable(timer);
  34. timer_enable(timer);
  35. delay_1ms(500);
  36. timer_disable(timer);
  37. timer_channel_output_config(timer,TIMER_CH_2,&timer_ocintpara);
  38. timer_channel_output_pulse_value_config(timer,TIMER_CH_2,250-1);
  39. timer_channel_output_mode_config(timer,TIMER_CH_2,TIMER_OC_MODE_PWM0);
  40. timer_channel_output_shadow_config(timer,TIMER_CH_2,TIMER_OC_SHADOW_DISABLE);
  41. timer_auto_reload_shadow_enable(timer);
  42. timer_enable(timer);
  43. delay_1ms(500);
  44. timer_disable(timer);
  45. timer_channel_output_config(timer,TIMER_CH_3,&timer_ocintpara);
  46. timer_channel_output_pulse_value_config(timer,TIMER_CH_3,160-1); //160~200, Claw form close to open
  47. timer_channel_output_mode_config(timer,TIMER_CH_3,TIMER_OC_MODE_PWM0);
  48. timer_channel_output_shadow_config(timer,TIMER_CH_3,TIMER_OC_SHADOW_DISABLE);
  49. timer_auto_reload_shadow_enable(timer);
  50. timer_enable(timer);
  51. delay_1ms(500);
  52. }
复制代码
然后,如果要改变特定通道的PWM宽度,可以用timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0, value)函数.
由于舵机瞬态电流比较大,务必增大电流或者制作专用驱动电路,否则GD32E231会因为电压瞬间降低而引起复位。
我这里采用5V 3A的供电加上USB供电,并且在程序中,平滑PWM值的改变,才勉强实现系统的稳定工作。
可以采用这种法法来实现舵机平滑切换:
  1. /*!
  2. \brief config the specific steering motor 0,1,2,3
  3. \param[in] motor_tag: 0,1,2,3; pulse: 50~250, mid=150 0.5ms~2.5ms
  4. \param[out] none
  5. \retval none
  6. */
  7. void control_motor(uint8_t motor_tag, uint32_t pulse)
  8. {
  9. uint8_t i;
  10. if(motor_tag == 0)
  11. {
  12. if(pulse>=current_value[0])
  13. {
  14. for(i=current_value[0];i <= pulse; i++) //in case of big current to pulse MCU system
  15. {
  16. timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,i-1);
  17. delay_1ms(20);
  18. }
  19. }
  20. else
  21. {
  22. for(i=current_value[0];i >= pulse; i--) //in case of big current to pulse MCU system
  23. {
  24. timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_0,i-1);
  25. delay_1ms(20);
  26. }
  27. }
  28. current_value[0] = pulse;
  29. }
  30. else if (motor_tag == 1)
  31. {
  32. if(pulse>=current_value[1])
  33. {
  34. for(i=current_value[1];i <= pulse; i++) //in case of big current to pulse MCU system
  35. {
  36. timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,i-1);
  37. delay_1ms(20);
  38. }
  39. }
  40. else
  41. {
  42. for(i=current_value[1];i >= pulse; i--) //in case of big current to pulse MCU system
  43. {
  44. timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,i-1);
  45. delay_1ms(20);
  46. }
  47. }
  48. current_value[1] = pulse;
  49. }
  50. else if (motor_tag == 2)
  51. {
  52. if(pulse>=current_value[2])
  53. {
  54. for(i=current_value[2];i <= pulse; i++) //in case of big current to pulse MCU system
  55. {
  56. timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,i-1);
  57. delay_1ms(30);
  58. }
  59. }
  60. else
  61. {
  62. for(i=current_value[2];i >= pulse; i--) //in case of big current to pulse MCU system
  63. {
  64. timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_2,i-1);
  65. delay_1ms(30);
  66. }
  67. }
  68. current_value[2] = pulse;
  69. }
  70. else if (motor_tag == 3)
  71. {
  72. if(pulse>=current_value[3])
  73. {
  74. for(i=current_value[3];i <= pulse; i++) //in case of big current to pulse MCU system
  75. {
  76. timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_3,i-1);
  77. delay_1ms(20);
  78. }
  79. }
  80. else
  81. {
  82. for(i=current_value[3];i >= pulse; i--) //in case of big current to pulse MCU system
  83. {
  84. timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_3,i-1);
  85. delay_1ms(50);
  86. }
  87. }
  88. current_value[3] = pulse;
  89. }
  90. }
复制代码
主函数中:
  1. pwm_timer_clock_enable();
  2. pwm_timer_config(TIMER2);
复制代码

最新回复

好资料,谢谢分享!  详情 回复 发表于 2019-5-26 08:19
点赞 关注(1)
 
 

回复
举报

172

帖子

0

TA的资源

宇宙尘埃

沙发
 
谢谢分享!
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

板凳
 

好资料,谢谢分享!
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表