当前位置:   article > 正文

第 8 章 机器人底盘Arduino端编码器驱动(自学二刷笔记)

第 8 章 机器人底盘Arduino端编码器驱动(自学二刷笔记)

重要参考:

课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ

讲义链接:Introduction · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程

8.4.3 底盘实现_02Arduino端编码器驱动

测速是整个PID闭环控制中的必须环节,我们必须修改代码适配当前AB相编码器,虽然需要重写功能,但是测速部分内容已经封装,只需要实现编码器计数即可,大致实现流程如下:

  1. ROSArduinoBridge.ino 中需要注释之前的编码器驱动,添加自定义编码器驱动;
  2. encoder_driver.h 中设置编码器引脚并声明初始化函数以及中断函数;
  3. encoder_driver.ino 中实现编码器计数以及重置函数;
  4. ROSArduinoBridge.ino 中 setup 函数调用编码器初始化函数。
  5. 测试
1.定义编码器驱动

ROSArduinoBridge.ino需要添加编码器宏定义,代码如下:

  1. #define USE_BASE // Enable the base controller code
  2. //#undef USE_BASE // Disable the base controller code
  3. /* Define the motor controller and encoder library you are using */
  4. #ifdef USE_BASE
  5. /* The Pololu VNH5019 dual motor driver shield */
  6. //#define POLOLU_VNH5019
  7. /* The Pololu MC33926 dual motor driver shield */
  8. //#define POLOLU_MC33926
  9. /* The RoboGaia encoder shield */
  10. //#define ROBOGAIA
  11. /* Encoders directly attached to Arduino board */
  12. //#define ARDUINO_ENC_COUNTER
  13. #define ARDUINO_MY_COUNTER
  14. /* L298 Motor driver*/
  15. //#define L298_MOTOR_DRIVER
  16. #define L298P_MOTOR_DRIVER
  17. #endif

先去除 #define L298P_MOTOR_DRIVER 的注释,否则后续编译会抛出异常。

2.修改encoder_driver.h文件

修改后内容如下:

  1. /* *************************************************************
  2. Encoder driver function definitions - by James Nugen
  3. ************************************************************ */
  4. #ifdef ARDUINO_ENC_COUNTER
  5. //below can be changed, but should be PORTD pins;
  6. //otherwise additional changes in the code are required
  7. #define LEFT_ENC_PIN_A PD2 //pin 2
  8. #define LEFT_ENC_PIN_B PD3 //pin 3
  9. //below can be changed, but should be PORTC pins
  10. #define RIGHT_ENC_PIN_A PC4 //pin A4
  11. #define RIGHT_ENC_PIN_B PC5 //pin A5
  12. #elif defined ARDUINO_MY_COUNTER
  13. #define LEFT_A 21
  14. #define LEFT_B 20
  15. #define RIGHT_A 18
  16. #define RIGHT_B 19
  17. void initEncoders();
  18. void leftEncoderEventA();
  19. void leftEncoderEventB();
  20. void rightEncoderEventA();
  21. void rightEncoderEventB();
  22. #endif
  23. long readEncoder(int i);
  24. void resetEncoder(int i);
  25. void resetEncoders();
3.修改encoder_driver.ino 文件

主要添加内容如下:

  1. #elif defined ARDUINO_MY_COUNTER
  2. volatile long left_count = 0L;
  3. volatile long right_count = 0L;
  4. void initEncoders(){
  5. pinMode(LEFT_A,INPUT); // 21 --- 2
  6. pinMode(LEFT_B,INPUT); // 20 --- 3
  7. pinMode(RIGHT_A,INPUT);// 18 --- 5
  8. pinMode(RIGHT_B,INPUT);// 19 --- 4
  9. attachInterrupt(2,leftEncoderEventA,CHANGE);
  10. attachInterrupt(3,leftEncoderEventB,CHANGE);
  11. attachInterrupt(5,rightEncoderEventA,CHANGE);
  12. attachInterrupt(4,rightEncoderEventB,CHANGE);
  13. }
  14. void leftEncoderEventA(){
  15. if(digitalRead(LEFT_A) == HIGH){
  16. if(digitalRead(LEFT_B) == HIGH){
  17. left_count++;
  18. } else {
  19. left_count--;
  20. }
  21. } else {
  22. if(digitalRead(LEFT_B) == LOW){
  23. left_count++;
  24. } else {
  25. left_count--;
  26. }
  27. }
  28. }
  29. void leftEncoderEventB(){
  30. if(digitalRead(LEFT_B) == HIGH){
  31. if(digitalRead(LEFT_A) == LOW){
  32. left_count++;
  33. } else {
  34. left_count--;
  35. }
  36. } else {
  37. if(digitalRead(LEFT_A) == HIGH){
  38. left_count++;
  39. } else {
  40. left_count--;
  41. }
  42. }
  43. }
  44. void rightEncoderEventA(){
  45. if(digitalRead(RIGHT_A) == HIGH){
  46. if(digitalRead(RIGHT_B) == HIGH){
  47. right_count++;
  48. } else {
  49. right_count--;
  50. }
  51. } else {
  52. if(digitalRead(RIGHT_B) == LOW){
  53. right_count++;
  54. } else {
  55. right_count--;
  56. }
  57. }
  58. }
  59. void rightEncoderEventB(){
  60. if(digitalRead(RIGHT_B) == HIGH){
  61. if(digitalRead(RIGHT_A) == LOW){
  62. right_count++;
  63. } else {
  64. right_count--;
  65. }
  66. } else {
  67. if(digitalRead(RIGHT_A) == HIGH){
  68. right_count++;
  69. } else {
  70. right_count--;
  71. }
  72. }
  73. }
  74. long readEncoder(int i) {
  75. if (i == LEFT) return left_count;
  76. else return right_count;
  77. }
  78. /* Wrap the encoder reset function */
  79. void resetEncoder(int i) {
  80. if (i == LEFT){
  81. left_count=0L;
  82. return;
  83. } else {
  84. right_count=0L;
  85. return;
  86. }
  87. }
4.ROSArduinoBridge.ino 实现初始化

setup 添加语句:initEncoders();

  1. void setup() {
  2. Serial.begin(BAUDRATE);
  3. // Initialize the motor controller if used */
  4. #ifdef USE_BASE
  5. #ifdef ARDUINO_ENC_COUNTER
  6. //set as inputs
  7. DDRD &= ~(1<<LEFT_ENC_PIN_A);
  8. DDRD &= ~(1<<LEFT_ENC_PIN_B);
  9. DDRC &= ~(1<<RIGHT_ENC_PIN_A);
  10. DDRC &= ~(1<<RIGHT_ENC_PIN_B);
  11. //enable pull up resistors
  12. PORTD |= (1<<LEFT_ENC_PIN_A);
  13. PORTD |= (1<<LEFT_ENC_PIN_B);
  14. PORTC |= (1<<RIGHT_ENC_PIN_A);
  15. PORTC |= (1<<RIGHT_ENC_PIN_B);
  16. // tell pin change mask to listen to left encoder pins
  17. PCMSK2 |= (1 << LEFT_ENC_PIN_A)|(1 << LEFT_ENC_PIN_B);
  18. // tell pin change mask to listen to right encoder pins
  19. PCMSK1 |= (1 << RIGHT_ENC_PIN_A)|(1 << RIGHT_ENC_PIN_B);
  20. // enable PCINT1 and PCINT2 interrupt in the general interrupt mask
  21. PCICR |= (1 << PCIE1) | (1 << PCIE2);
  22. #elif defined ARDUINO_MY_COUNTER
  23. initEncoders();
  24. #endif
  25. initMotorController();
  26. resetPID();
  27. #endif
  28. /* Attach servos if used */
  29. #ifdef USE_SERVOS
  30. int i;
  31. for (i = 0; i < N_SERVOS; i++) {
  32. servos[i].initServo(
  33. servoPins[i],
  34. stepDelay[i],
  35. servoInitPosition[i]);
  36. }
  37. #endif
  38. }
5.测试

编译并上传程序,打开串口监视器,然后旋转车轮,在串口监视器中录入 e 即可查看左右编码器计数,录入命令 r 可以重置计数。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/608303
推荐阅读
相关标签
  

闽ICP备14008679号