学习目标

  1. 了解电机驱动原理
  2. 熟悉原理图
  3. 了解电机驱动芯片的驱动原理
  4. 掌握PWM控制电机转动
  5. 熟悉驱动封装
  6. 掌握逻辑分析仪使用方法

    学习内容

    电机

    采用N20电机,电机上有两个触点,通电就可以转动。我们采用的N20电机的额定电压为6V,最大转速是300RPM(300圈/分钟)
    181.png
    image.png
    image.png
    通电的时候,无论正接还是反接,电机都可以转动,只是转动的方向不同。 :::warning 注意:
  • 减速电机请尽量避免堵转或者超负载,否则会出现崩齿轮损耗。
  • 正反转控制时,不要让齿轮在传动中立刻切换转向,建议在完全停止后切换转向 :::

    原理图

    179.png
    每个电机分别对应一个电机驱动芯片,通过电机驱动芯片进行驱动电机转动。
    电机驱动芯片又是通过两路pwm来控制的。
    以下是电机驱动芯片的真值表:
    180.png
    两个引脚分别对应了采用互补的方式,可以驱动电机,达到电机可以正转反转的效果。
    电机驱动帮助我们解决了正反转动态切换的问题

    驱动编写

    ```c

    ifndef MOTORS_H

    define MOTORS_H

include “Config.h”

void Motors_init();

// 0 -> 100 void Motors_forward(int speed);

// 0 -> 100 void Motors_backward(int speed);

// 0左转 void Motors_left(int speed);

// 0右转 void Motors_right(int speed);

// 原地转 void Motors_around(int speed);

// stop void Motors_stop();

endif

  1. ```c
  2. #include "Motors.h"
  3. #include "STC8H_PWM.h"
  4. #include "GPIO.h"
  5. #define RQ_B P15
  6. #define RQ_F P14
  7. #define PERIOD (MAIN_Fosc / 1000)
  8. typedef struct {
  9. int LQ_speed;
  10. int LH_speed;
  11. int RQ_speed;
  12. int RH_speed;
  13. } MotorCfg;
  14. PWMx_Duty dutyA;
  15. // -100 ------------------ 0 --------------------- 100 Speed
  16. //B_Max 0 F_Max 速度
  17. // 0 -------------------- 50 -------------------- 100 duty
  18. int speed2duty(int speed) {
  19. // speed > 0 前进
  20. // speed < 0 后退
  21. // [-100, 100]
  22. // speed / 2 => [-50, 50]
  23. // speed / 2 + 50 => [ 0, 100]
  24. return speed / 2 + 50;
  25. }
  26. void Motors_config(MotorCfg cfg)
  27. {
  28. PWMx_InitDefine pwmInit;
  29. int LQ_duty = speed2duty(cfg.LQ_speed);
  30. int LH_duty = speed2duty(cfg.LH_speed);
  31. int RQ_duty = speed2duty(cfg.RQ_speed);
  32. int RH_duty = speed2duty(cfg.RH_speed);
  33. // 配置PWM1 - LH 左后
  34. pwmInit.PWM_Mode = CCMRn_PWM_MODE1; //模式, CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
  35. pwmInit.PWM_Duty = PERIOD * LH_duty / 100; //PWM占空比时间, 0~Period
  36. pwmInit.PWM_EnoSelect = (cfg.LH_speed == 0 ? 0 : (ENO1P | ENO1N)); //输出通道选择, ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
  37. PWM_Configuration(PWM1, &pwmInit); //初始化PWM
  38. // 配置PWM2 - RH 右后
  39. pwmInit.PWM_Mode = CCMRn_PWM_MODE2; //模式, CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
  40. pwmInit.PWM_Duty = PERIOD * RH_duty / 100; //PWM占空比时间, 0~Period
  41. pwmInit.PWM_EnoSelect = (cfg.RH_speed == 0 ? 0 : (ENO2P | ENO2N)); //输出通道选择, ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
  42. PWM_Configuration(PWM2, &pwmInit); //初始化PWM
  43. // 配置PWM3 - RQ 右前
  44. pwmInit.PWM_Mode = CCMRn_PWM_MODE1; //模式, CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
  45. pwmInit.PWM_Duty = PERIOD * RQ_duty / 100; //PWM占空比时间, 0~Period
  46. pwmInit.PWM_EnoSelect = (cfg.RQ_speed == 0 ? 0 : (ENO3P | ENO3N)); //输出通道选择, ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
  47. PWM_Configuration(PWM3, &pwmInit);
  48. // 配置PWM4 - LQ 左前
  49. pwmInit.PWM_Mode = CCMRn_PWM_MODE2; //模式, CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
  50. pwmInit.PWM_Duty = PERIOD * LQ_duty / 100; //PWM占空比时间, 0~Period
  51. pwmInit.PWM_EnoSelect = (cfg.LQ_speed == 0 ? 0 : (ENO4P | ENO4N)); //输出通道选择, ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
  52. PWM_Configuration(PWM4, &pwmInit);
  53. // 配置PWMA
  54. pwmInit.PWM_Period = PERIOD - 1; //周期时间, 0~65535
  55. pwmInit.PWM_DeadTime = 0; //死区发生器设置, 0~255
  56. pwmInit.PWM_MainOutEnable= ENABLE; //主输出使能, ENABLE,DISABLE
  57. pwmInit.PWM_CEN_Enable = ENABLE; //使能计数器, ENABLE,DISABLE
  58. PWM_Configuration(PWMA, &pwmInit); //初始化PWM通用寄存器, PWMA,PWMB
  59. // 切换PWM通道
  60. // LH 左后
  61. PWM1_SW(PWM1_SW_P20_P21); //PWM1_SW_P10_P11,PWM1_SW_P20_P21,PWM1_SW_P60_P61
  62. // RH 右后
  63. PWM2_SW(PWM2_SW_P22_P23); //PWM2_SW_P12_P13,PWM2_SW_P22_P23,PWM2_SW_P62_P63
  64. // RQ 右前
  65. PWM3_SW(PWM3_SW_P14_P15); //PWM3_SW_P14_P15,PWM3_SW_P24_P25,PWM3_SW_P64_P65
  66. // LQ 左前
  67. PWM4_SW(PWM4_SW_P16_P17); //PWM4_SW_P16_P17,PWM4_SW_P26_P27,PWM4_SW_P66_P67,PWM4_SW_P34_P33
  68. // 初始化PWMA的中断
  69. NVIC_PWM_Init(PWMA,DISABLE,Priority_0);
  70. }
  71. void Motors_init() {
  72. // 电机IO口
  73. P1_MODE_IO_PU(GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
  74. P2_MODE_IO_PU(GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
  75. }
  76. // 0 -> 100
  77. void Motors_forward(int speed) {
  78. MotorCfg cfg;
  79. cfg.LQ_speed = speed;
  80. cfg.LH_speed = speed;
  81. cfg.RQ_speed = speed;
  82. cfg.RH_speed = speed;
  83. Motors_config(cfg);
  84. }
  85. // 0 -> 100
  86. void Motors_backward(int speed) {
  87. MotorCfg cfg;
  88. cfg.LQ_speed = -speed;
  89. cfg.LH_speed = -speed;
  90. cfg.RQ_speed = -speed;
  91. cfg.RH_speed = -speed;
  92. Motors_config(cfg);
  93. }
  94. // 0左转
  95. void Motors_left(int speed) {
  96. MotorCfg cfg;
  97. cfg.LQ_speed = 0;
  98. cfg.LH_speed = 0;
  99. cfg.RQ_speed = speed;
  100. cfg.RH_speed = speed;
  101. Motors_config(cfg);
  102. }
  103. // 0右转
  104. void Motors_right(int speed) {
  105. MotorCfg cfg;
  106. cfg.LQ_speed = speed;
  107. cfg.LH_speed = speed;
  108. cfg.RQ_speed = 0;
  109. cfg.RH_speed = 0;
  110. Motors_config(cfg);
  111. }
  112. // 原地转
  113. void Motors_around(int speed){
  114. MotorCfg cfg;
  115. cfg.LQ_speed = speed;
  116. cfg.LH_speed = speed;
  117. cfg.RQ_speed = -speed;
  118. cfg.RH_speed = -speed;
  119. Motors_config(cfg);
  120. }
  121. // stop
  122. void Motors_stop() {
  123. MotorCfg cfg;
  124. cfg.LQ_speed = 0;
  125. cfg.LH_speed = 0;
  126. cfg.RQ_speed = 0;
  127. cfg.RH_speed = 0;
  128. Motors_config(cfg);
  129. }

控制逻辑

211.png

  1. 前进:4个轮子同时转动即可
  2. 左转:右侧轮子的转速大于左侧即可
  3. 右转:左侧轮子的转速大于右侧即可

N20电机参数

尺寸图

参数表如下图:
额定电压与真实电压输入的范围要求:

  • 3V电机电压输入范围:1.5V-5V
  • 6V电机电压输入范围:3V-9V
  • 12V电机电压输入范围:6V-12V

参数表
扭矩

练习题

  1. pwm驱动单个电机的启停
  2. pwm驱动多路电机的启停
  3. 实现小车的前进后退转弯等功能