Advertisement
Guest User

Untitled

a guest
Jun 18th, 2018
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.63 KB | None | 0 0
  1. #include <Wire.h>
  2. #include <LSM303.h>
  3. #include <L3G.h>
  4. #include "Kalman.h"
  5.  
  6. #define LED 13
  7.  
  8. //You will need to find your own magnetometer calibration values, use the sample code that came with the LSM303 library!!!
  9.  
  10. #define MAG_X_MIN -2752
  11. #define MAG_Y_MIN -3040
  12. #define MAG_Z_MIN -2503
  13. #define MAG_X_MAX +3741
  14. #define MAG_Y_MAX +3053
  15. #define MAG_Z_MAX +3281
  16.  
  17. #define ROLL_LIMIT 90.0f
  18. #define PITCH_LIMIT 180.0f
  19. #define YAW_LIMIT 180.0f
  20.  
  21. Kalman kalmanZ, kalmanX, kalmanY;
  22.  
  23. char report[32];
  24. char inByte;
  25. unsigned long currentTime, lastTime;
  26. float dT;
  27.  
  28. float roll, pitch, yaw; // Roll and pitch calculated from accelerometer, yaw from magnetometer
  29. float gyroXangle, gyroYangle, gyroZangle; // Angle calculated with gyroscope
  30. float gyroXrate, gyroYrate, gyroZrate; // Gyroscope movement rate, in degrees per second
  31. float compAngleX, compAngleY, compAngleZ; // Calculated angle using a complementary filter, YOU WILL NEED TO DO THIS
  32. float kalAngleX, kalAngleY, kalAngleZ; // Calculated angle using a Kalman filter, YOU WILL NEED TO DO THIS
  33.  
  34. LSM303 compass;
  35. L3G gyro;
  36.  
  37. void setup() {
  38. pinMode(LED, OUTPUT);
  39.  
  40. Serial.begin(1000000);
  41. Wire.begin();
  42. Wire.setClock(400000L);
  43.  
  44. compass.init();
  45. compass.enableDefault();
  46. // Set accelerometer data rate to 800Hz
  47. // 0b10010111 = 0x97
  48. compass.writeReg(0x20, 0x97);
  49. // Set magnetometer data rate to 100Hz
  50. // 0b01110100 = 0x74
  51. compass.writeReg(0x24, 0x74);
  52. compass.m_min = (LSM303::vector<int16_t>){MAG_X_MIN, MAG_Y_MIN, MAG_Z_MIN};
  53. compass.m_max = (LSM303::vector<int16_t>){MAG_X_MAX, MAG_Y_MAX, MAG_Z_MAX};
  54.  
  55. if (!gyro.init())
  56. {
  57. Serial.println("Failed to autodetect gyro type!");
  58. while (1);
  59. }
  60. gyro.enableDefault();
  61. // Set gyro data rate to 800Hz
  62. // 0b11111111 = 0xFF
  63. gyro.writeReg(0x20, 0xFF);
  64.  
  65. roll = 0;
  66. pitch = 0;
  67. yaw = 0;
  68.  
  69. lastTime = micros();
  70. compass.read();
  71. updateRollPitch(&compass, &roll, &pitch);
  72. updateYaw(&compass, &yaw);
  73.  
  74. gyroXangle = roll;
  75. gyroYangle = pitch;
  76. gyroZangle = yaw;
  77.  
  78. compAngleX = roll;
  79. compAngleY = pitch;
  80. compAngleZ = yaw;
  81. }
  82.  
  83. void loop() {
  84. currentTime = micros();
  85. compass.read();
  86. gyro.read();
  87. updateRollPitch(&compass, &roll, &pitch);
  88. updateYaw(&compass, &yaw);
  89.  
  90. dT = (currentTime - lastTime) / 1000000.0f;
  91. lastTime = currentTime;
  92.  
  93. gyroXrate = gyroToDegPerSec(gyro.g.x);
  94. gyroYrate = gyroToDegPerSec(gyro.g.y);
  95. gyroZrate = gyroToDegPerSec(gyro.g.z);
  96.  
  97. // Fix xrate and zrate
  98. if (abs(pitch) > 90) gyroXrate = -gyroXrate;
  99. else gyroZrate = -gyroZrate;
  100.  
  101. gyroXangle += gyroXrate * dT;
  102. gyroYangle += gyroYrate * dT;
  103. gyroZangle += gyroZrate * dT;
  104.  
  105. kalmanX.setAngle(roll);
  106. kalmanY.setAngle(roll);
  107. kalmanZ.setAngle(roll);
  108.  
  109. fixAngle(&gyroYangle, &pitch, PITCH_LIMIT);
  110. fixAngle(&gyroZangle, &yaw, YAW_LIMIT);
  111.  
  112. // You will need to calculate these
  113. //compAngleX = 0.98 * (compAngleX + gyroXrate * dT) + 0.02 * roll; // Calculate the angle using a Complimentary filter
  114. //compAngleY = 0.98 * (compAngleY + gyroYrate * dT) + 0.02 * pitch;
  115. //compAngleZ = 0.98 * (compAngleZ + gyroZrate * dT) + 0.02 * yaw;
  116.  
  117. // You will need to calculate these
  118. kalAngleX = kalmanX.getAngle(roll, gyroXrate, dT); // Calculate the angle using a Kalman filter
  119. kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dT);
  120. kalAngleZ = kalmanZ.getAngle(yaw, gyroZrate, dT);
  121.  
  122. if (Serial.available()) respondToSerial();
  123. }
  124.  
  125. void respondToSerial() {
  126. digitalWrite(LED, !digitalRead(LED));
  127. inByte = Serial.read();
  128.  
  129. switch (inByte) {
  130. case 'a':
  131. snprintf(report, sizeof(report), "<A:%d:%d:%d>",
  132. compass.a.x, compass.a.y, compass.a.z);
  133. Serial.print(report);
  134. break;
  135. case 'm':
  136. snprintf(report, sizeof(report), "<M:%d:%d:%d>",
  137. compass.m.x, compass.m.y, compass.m.z);
  138. Serial.print(report);
  139. break;
  140. case 'g':
  141. snprintf(report, sizeof(report), "<G:%d:%d:%d>",
  142. gyro.g.x, gyro.g.y, gyro.g.z);
  143. Serial.print(report);
  144. break;
  145. case 'r':
  146. floatsToSerial('R', roll, pitch, yaw);
  147. break;
  148. case 'd':
  149. floatsToSerial('D', gyroXangle, gyroYangle, gyroZangle);
  150. break;
  151. case 'c':
  152. floatsToSerial('C', compAngleX, compAngleY, compAngleZ);
  153. break;
  154. case 'k':
  155. floatsToSerial('K', kalAngleX, kalAngleY, kalAngleZ);
  156. break;
  157. case 'x':
  158. //RESET ANGLES
  159. gyroXangle = roll;
  160. gyroYangle = pitch;
  161. gyroZangle = yaw;
  162. compAngleX = roll;
  163. compAngleY = pitch;
  164. compAngleZ = yaw;
  165. break;
  166. default:
  167. Serial.print("<E:0:0:0>");
  168. break;
  169. }
  170. }
  171.  
  172. void floatsToSerial(const char tag, float first, float second, float third) {
  173. String output = '<' + String(tag) + ':' + String(first, 3)+ ':' + String(second, 3)+ ':' + String(third, 3) + '>';
  174. Serial.print(output);
  175. }
  176.  
  177. float gyroToDegPerSec(int16_t gyro) {
  178. return gyro * 0.00875f;
  179. }
  180.  
  181. void updateRollPitch(LSM303 *compass, float *roll, float *pitch) {
  182. *roll = atan(compass->a.y / sqrt((float)compass->a.x * (float)compass->a.x + (float)compass->a.z * (float)compass->a.z)) * RAD_TO_DEG;
  183. *pitch = atan2(-compass->a.x, compass->a.z) * RAD_TO_DEG;
  184. }
  185.  
  186. void updateYaw(LSM303 *compass, float *yaw) {
  187. float heading = compass->heading();
  188. if (heading > YAW_LIMIT) heading -= 360.0f;
  189. *yaw = heading;
  190. }
  191.  
  192. void fixAngle(float *angle, float *reference, float limit) {
  193. if (abs(*angle - *reference) > limit * 1.5f) {
  194. if (*angle > *reference) *angle -= 2*limit;
  195. else *angle += 2*limit;
  196. }
  197. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement