M5Bala.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "M5Bala.h"
  2. #include "M5Stack.h"
  3. #define MPU9250_ID 0x71
  4. #define MPU6050_ID 0x68
  5. M5Bala::M5Bala() {
  6. wire = &Wire;
  7. }
  8. M5Bala::M5Bala(TwoWire &w) {
  9. wire = &w;
  10. }
  11. void M5Bala::begin() {
  12. // IMU
  13. imu_CalcInit();
  14. // Motor
  15. setMotor(0, 0);
  16. // PID param
  17. K1 = 60;
  18. K2 = 24;
  19. K5 = 0;
  20. K3 = 8.5;
  21. K4 = 5.2;
  22. // K5 = 8;
  23. loop_interval = 0;
  24. left_offset = 0;
  25. right_offset = 0;
  26. forward_offset = 0;
  27. for (int i = 0; i < 128; i++) {
  28. imu_update();
  29. }
  30. pitch = imu_getAngleX();
  31. }
  32. uint8_t M5Bala::i2c_readByte(uint8_t address, uint8_t subAddress) {
  33. uint8_t data;
  34. M5.I2C.readByte(address, subAddress, &data);
  35. return data; // Return data read from slave register
  36. }
  37. void M5Bala::setMotor(int16_t pwm0, int16_t pwm1) {
  38. // Value range
  39. int16_t m0 = constrain(pwm0, -255, 255);
  40. int16_t m1 = constrain(pwm1, -255, 255);
  41. // Dead zone
  42. if (((m0 > 0) && (m0 < DEAD_ZONE)) || ((m0 < 0) && (m0 > -DEAD_ZONE))) m0 = 0;
  43. if (((m1 > 0) && (m1 < DEAD_ZONE)) || ((m1 < 0) && (m1 > -DEAD_ZONE))) m1 = 0;
  44. // Same value
  45. static int16_t pre_m0, pre_m1;
  46. if ((m0 == pre_m0) && (m1 == pre_m1))
  47. return;
  48. pre_m0 = m0;
  49. pre_m1 = m1;
  50. uint8_t i2c_out_buff[4];
  51. i2c_out_buff[0] = m0 & 0xff;
  52. i2c_out_buff[1] = (m0 >> 8) & 0xff;
  53. i2c_out_buff[2] = (m1 >> 0) & 0xff;
  54. i2c_out_buff[3] = (m1 >> 8) & 0xff;
  55. M5.I2C.writeBytes(M5GO_WHEEL_ADDR, MOTOR_CTRL_ADDR, i2c_out_buff, 4);
  56. }
  57. void M5Bala::readEncder() {
  58. static float _speed_input0 = 0, _speed_input1 = 0;
  59. int16_t rx_buf[2];
  60. M5.I2C.readBytes(M5GO_WHEEL_ADDR, ENCODER_ADDR, 4, (uint8_t *)rx_buf);
  61. // filter
  62. _speed_input0 *= 0.9;
  63. _speed_input0 += 0.1 * rx_buf[0];
  64. _speed_input1 *= 0.9;
  65. _speed_input1 += 0.1 * rx_buf[1];
  66. speed_input0 = constrain((int16_t)(-_speed_input0), -255, 255);
  67. speed_input1 = constrain((int16_t)(_speed_input1), -255, 255);
  68. }
  69. void M5Bala::PIDCompute() {
  70. static float last_angle;
  71. static int16_t last_wheel;
  72. float angle, angle_velocity;
  73. int16_t wheel, wheel_velocity;
  74. int16_t torque, speed_diff, speed_diff_adjust;
  75. angle = pitch;
  76. angle_velocity = angle - last_angle;
  77. last_angle = angle;
  78. wheel = (speed_input0 + speed_input1) / 2; /* wheel = read_encoder()-profiler() */
  79. wheel_velocity = wheel - last_wheel;
  80. last_wheel = wheel;
  81. torque = (angle_velocity * K1) + (angle * K2)
  82. + (wheel_velocity * K3) + (wheel * K4);
  83. speed_diff = (speed_input0 - speed_input1);
  84. speed_diff_adjust = (K5 * speed_diff);
  85. pwm_out0 = torque - speed_diff_adjust;
  86. pwm_out1 = torque;
  87. pwm_out0 = constrain(pwm_out0, -255, 255);
  88. pwm_out1 = constrain(pwm_out1, -255, 255);
  89. }
  90. void M5Bala::run() {
  91. if (micros() >= loop_interval) {
  92. loop_interval = micros() + 10000;
  93. // Attitude sample
  94. imu_update();
  95. pitch = imu_getAngleX() + angle_offset;
  96. // Car down
  97. if (abs(pitch) > 45) {
  98. setMotor(0, 0);
  99. return;
  100. }
  101. // Encoder sample
  102. readEncder();
  103. // PID Compute
  104. PIDCompute();
  105. // Motor out
  106. setMotor(pwm_out0 + forward_offset + left_offset,
  107. pwm_out1 + forward_offset + right_offset);
  108. }
  109. }
  110. void M5Bala::stop() {
  111. left_offset = 0;
  112. right_offset = 0;
  113. }
  114. void M5Bala::move(int16_t speed, uint16_t duration) {
  115. forward_offset = -speed;
  116. if (duration != 0) {
  117. delay(duration);
  118. stop();
  119. }
  120. }
  121. void M5Bala::turn(int16_t speed, uint16_t duration) {
  122. if (speed > 0) {
  123. left_offset = speed;
  124. right_offset = 0;
  125. } else if (speed < 0) {
  126. left_offset = 0;
  127. right_offset = -speed;
  128. }
  129. if (duration != 0) {
  130. delay(duration);
  131. stop();
  132. }
  133. }
  134. void M5Bala::rotate(int16_t speed, uint16_t duration) {
  135. left_offset = speed;
  136. right_offset = -speed;
  137. if (duration != 0) {
  138. delay(duration);
  139. stop();
  140. }
  141. }