• 机器人微控制器编程(CoCube)-强化实践


    之前的案例,可以进一步扩展:


    机器人微控制器编程(CoCube)-突破边界

    从AD到电压;电压和电量,什么关系:

    锂电池电压和电量之间,有一定的对应关系,通过对开路电压的测量,可以大致得出电池的剩余电量。不过用电压测量电量的方式有一定的不稳定性,例如放电电流、环境温度、循环、放电平台、电极材料等,都会给最后结果的准确与否带来影响。
    电压和电量的对应关系是:100%----4.20V、90%-----4.06V、80%-----3.98V、70%-----3.92V、60%-----3.87V、50%-----3.82V、40%-----3.79V、30%-----3.77V、20%-----3.74V、10%-----3.68V、5%------3.45V、0%------3.00V。锂电池能够实现用电压测量剩余电量,主要是因为这种电池有一个很独特的性质:在电池放电时,电池电压会随着电量的流失而逐渐降低,从而形成了一种正相关的关系,并且有一定的斜率。因此我们能够依据剩余电量估算出大概的电压,反之亦然。 

    进一步:

    电量和机器人任务状态的关系:

    充电:检测是否满电

    工作:检测电量是否在范围内,执行任务

    低电:机器人进入低功耗和准备充电模式

    哪些由机器人做,哪些由服务器做?


    卡尔曼滤波:

    MPU6050数据进一步扩展

    机器人微控制器编程(CoCube)-深度融合

     


     

    1. #include
    2. #include
    3. #include // Source: https://github.com/TKJElectronics/KalmanFilter
    4. #define RESTRICT_PITCH // Comment out to restrict roll to ±90deg instead - please read: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf
    5. MPU6050 mpu6050(Wire);
    6. Kalman kalmanX; // Create the Kalman instances
    7. Kalman kalmanY;
    8. uint32_t timer;
    9. /* IMU Data */
    10. double accX, accY, accZ;
    11. double gyroX, gyroY, gyroZ;
    12. int16_t tempRaw;
    13. double gyroXangle, gyroYangle; // Angle calculate using the gyro only
    14. double compAngleX, compAngleY; // Calculated angle using a complementary filter
    15. double kalAngleX, kalAngleY; // Calculated angle using a Kalman filter
    16. // TODO: Make calibration routine
    17. void setup() {
    18. Serial.begin(115200);
    19. Wire.begin();
    20. mpu6050.begin();
    21. mpu6050.calcGyroOffsets(true);
    22. delay(1000); // Wait for sensor to stabilize
    23. /* Set kalman and gyro starting angle */
    24. mpu6050.update();
    25. accX = mpu6050.getAccX();
    26. accY = mpu6050.getAccY();
    27. accZ = mpu6050.getAccZ();
    28. // Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf eq. 25 and eq. 26
    29. // atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2
    30. // It is then converted from radians to degrees
    31. #ifdef RESTRICT_PITCH // Eq. 25 and 26
    32. double roll = atan2(accY, accZ) * RAD_TO_DEG;
    33. double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
    34. #else // Eq. 28 and 29
    35. double roll = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
    36. double pitch = atan2(-accX, accZ) * RAD_TO_DEG;
    37. #endif
    38. kalmanX.setAngle(roll); // Set starting angle
    39. kalmanY.setAngle(pitch);
    40. gyroXangle = roll;
    41. gyroYangle = pitch;
    42. compAngleX = roll;
    43. compAngleY = pitch;
    44. timer = micros();
    45. }
    46. void loop() {
    47. /* Update all the values */
    48. mpu6050.update();
    49. accX = mpu6050.getAccX();
    50. accY = mpu6050.getAccY();
    51. accZ = mpu6050.getAccZ();
    52. tempRaw = mpu6050.getTemp();
    53. gyroX = mpu6050.getGyroX();
    54. gyroY = mpu6050.getGyroY();
    55. gyroZ = mpu6050.getGyroZ();
    56. double dt = (double)(micros() - timer) / 1000000; // Calculate delta time
    57. timer = micros();
    58. // Source: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf eq. 25 and eq. 26
    59. // atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2
    60. // It is then converted from radians to degrees
    61. #ifdef RESTRICT_PITCH // Eq. 25 and 26
    62. double roll = atan2(accY, accZ) * RAD_TO_DEG;
    63. double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
    64. #else // Eq. 28 and 29
    65. double roll = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
    66. double pitch = atan2(-accX, accZ) * RAD_TO_DEG;
    67. #endif
    68. double gyroXrate = gyroX / 131.0; // Convert to deg/s
    69. double gyroYrate = gyroY / 131.0; // Convert to deg/s
    70. #ifdef RESTRICT_PITCH
    71. // This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees
    72. if ((roll < -90 && kalAngleX > 90) || (roll > 90 && kalAngleX < -90)) {
    73. kalmanX.setAngle(roll);
    74. compAngleX = roll;
    75. kalAngleX = roll;
    76. gyroXangle = roll;
    77. } else
    78. kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter
    79. if (abs(kalAngleX) > 90)
    80. gyroYrate = -gyroYrate; // Invert rate, so it fits the restriced accelerometer reading
    81. kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt);
    82. #else
    83. // This fixes the transition problem when the accelerometer angle jumps between -180 and 180 degrees
    84. if ((pitch < -90 && kalAngleY > 90) || (pitch > 90 && kalAngleY < -90)) {
    85. kalmanY.setAngle(pitch);
    86. compAngleY = pitch;
    87. kalAngleY = pitch;
    88. gyroYangle = pitch;
    89. } else
    90. kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt); // Calculate the angle using a Kalman filter
    91. if (abs(kalAngleY) > 90)
    92. gyroXrate = -gyroXrate; // Invert rate, so it fits the restriced accelerometer reading
    93. kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt); // Calculate the angle using a Kalman filter
    94. #endif
    95. gyroXangle += gyroXrate * dt; // Calculate gyro angle without any filter
    96. gyroYangle += gyroYrate * dt;
    97. //gyroXangle += kalmanX.getRate() * dt; // Calculate gyro angle using the unbiased rate
    98. //gyroYangle += kalmanY.getRate() * dt;
    99. compAngleX = 0.93 * (compAngleX + gyroXrate * dt) + 0.07 * roll; // Calculate the angle using a Complimentary filter
    100. compAngleY = 0.93 * (compAngleY + gyroYrate * dt) + 0.07 * pitch;
    101. // Reset the gyro angle when it has drifted too much
    102. if (gyroXangle < -180 || gyroXangle > 180)
    103. gyroXangle = kalAngleX;
    104. if (gyroYangle < -180 || gyroYangle > 180)
    105. gyroYangle = kalAngleY;
    106. /* Print Data */
    107. #if 0 // Set to 1 to activate
    108. Serial.print(accX); Serial.print("\t");
    109. Serial.print(accY); Serial.print("\t");
    110. Serial.print(accZ); Serial.print("\t");
    111. Serial.print(gyroX); Serial.print("\t");
    112. Serial.print(gyroY); Serial.print("\t");
    113. Serial.print(gyroZ); Serial.print("\t");
    114. Serial.print("\t");
    115. #endif
    116. Serial.print(roll); Serial.print("\t");
    117. Serial.print(gyroXangle); Serial.print("\t");
    118. Serial.print(compAngleX); Serial.print("\t");
    119. Serial.print(kalAngleX); Serial.print("\t");
    120. Serial.print("\t");
    121. Serial.print(pitch); Serial.print("\t");
    122. Serial.print(gyroYangle); Serial.print("\t");
    123. Serial.print(compAngleY); Serial.print("\t");
    124. Serial.print(kalAngleY); Serial.print("\t");
    125. #if 0 // Set to 1 to print the temperature
    126. Serial.print("\t");
    127. double temperature = (double)tempRaw / 340.0 + 36.53;
    128. Serial.print(temperature); Serial.print("\t");
    129. #endif
    130. Serial.print("\r\n");
    131. }

  • 相关阅读:
    TiDB 工具下载
    Ubuntu 22.04安装深度学习框架PyTorch-GPU版
    call apply bind
    Dubbo+Zookeeper入门实例
    D*算法(C++/MATLAB)
    Jmeter —— 常用的几种断言方法(基本用法)
    jvm内存分配与回收策略
    【计算机图形学】光线追踪 Ray Tracing
    宝塔的安装与查看
    VPS是干嘛用的?有哪些知名牌子?与云服务器有什么区别?
  • 原文地址:https://blog.csdn.net/ZhangRelay/article/details/126278292