BMM150class.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include "BMM150class.h"
  2. BMM150class::BMM150class()
  3. {
  4. }
  5. int8_t i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *read_data, uint16_t len)
  6. {
  7. if (M5.I2C.readBytes(dev_id, reg_addr, len, read_data))
  8. {
  9. return BMM150_OK;
  10. }
  11. else
  12. {
  13. return BMM150_E_DEV_NOT_FOUND;
  14. }
  15. }
  16. int8_t i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *read_data, uint16_t len)
  17. {
  18. if (M5.I2C.writeBytes(dev_id, reg_addr, read_data, len))
  19. {
  20. return BMM150_OK;
  21. }
  22. else
  23. {
  24. return BMM150_E_DEV_NOT_FOUND;
  25. }
  26. }
  27. int8_t BMM150class::bmm150_initialization()
  28. {
  29. int8_t rslt = BMM150_OK;
  30. /* Sensor interface over SPI with native chip select line */
  31. dev.dev_id = 0x10;
  32. dev.intf = BMM150_I2C_INTF;
  33. dev.read = i2c_read;
  34. dev.write = i2c_write;
  35. dev.delay_ms = delay;
  36. /* make sure max < mag data first */
  37. mag_max.x = -2000;
  38. mag_max.y = -2000;
  39. mag_max.z = -2000;
  40. /* make sure min > mag data first */
  41. mag_min.x = 2000;
  42. mag_min.y = 2000;
  43. mag_min.z = 2000;
  44. rslt = bmm150_init(&dev);
  45. dev.settings.pwr_mode = BMM150_NORMAL_MODE;
  46. rslt |= bmm150_set_op_mode(&dev);
  47. dev.settings.preset_mode = BMM150_PRESETMODE_ENHANCED;
  48. rslt |= bmm150_set_presetmode(&dev);
  49. return rslt;
  50. }
  51. void BMM150class::bmm150_offset_save()
  52. {
  53. prefs.begin("bmm150", false);
  54. prefs.putBytes("offset", (uint8_t *)&mag_offset, sizeof(bmm150_mag_data));
  55. // added soft-iron scale
  56. prefs.putBytes("scale", (uint8_t *)&mag_scale, sizeof(bmm150_mag_data));
  57. prefs.end();
  58. }
  59. void BMM150class::bmm150_offset_load()
  60. {
  61. if (prefs.begin("bmm150", true))
  62. {
  63. prefs.getBytes("offset", (uint8_t *)&mag_offset, sizeof(bmm150_mag_data));
  64. // added soft iron distortion scaling
  65. prefs.getBytes("scale", (uint8_t *)&mag_scale, sizeof(bmm150_mag_data));
  66. prefs.end();
  67. Serial.printf("bmm150 load offset finish.... \r\n");
  68. }
  69. else
  70. {
  71. Serial.printf("bmm150 load offset failed.... \r\n");
  72. }
  73. }
  74. /*
  75. void BMM150class::setup()
  76. {
  77. M5.begin(true, false, true, false);
  78. Wire.begin(21, 22, 400000);
  79. M5.Lcd.fillScreen(BLACK);
  80. M5.Lcd.setTextColor(WHITE);
  81. if (bmm150_initialization() != BMM150_OK)
  82. {
  83. // img.fillSprite(0);
  84. // img.drawCentreString("BMM150 init failed", 160, 110, 4);
  85. // img.pushSprite(0, 0);
  86. M5.Lcd.setCursor(0, 10);
  87. M5.Lcd.print("BMM150 init failed");
  88. for (;;)
  89. {
  90. delay(100);
  91. }
  92. }
  93. bmm150_offset_load();
  94. }
  95. */
  96. void BMM150class::bmm150_calibrate(uint32_t calibrate_time)
  97. {
  98. uint32_t calibrate_timeout = 0;
  99. float avg_chord;
  100. calibrate_timeout = millis() + calibrate_time;
  101. Serial.printf("Go calibrate, use %d ms \r\n", calibrate_time);
  102. Serial.printf("running ...");
  103. while (calibrate_timeout > millis())
  104. {
  105. bmm150_read_mag_data(&dev);
  106. if (dev.data.x)
  107. {
  108. mag_min.x = (dev.data.x < mag_min.x) ? dev.data.x : mag_min.x;
  109. mag_max.x = (dev.data.x > mag_max.x) ? dev.data.x : mag_max.x;
  110. }
  111. if (dev.data.y)
  112. {
  113. mag_max.y = (dev.data.y > mag_max.y) ? dev.data.y : mag_max.y;
  114. mag_min.y = (dev.data.y < mag_min.y) ? dev.data.y : mag_min.y;
  115. }
  116. if (dev.data.z)
  117. {
  118. mag_min.z = (dev.data.z < mag_min.z) ? dev.data.z : mag_min.z;
  119. mag_max.z = (dev.data.z > mag_max.z) ? dev.data.z : mag_max.z;
  120. }
  121. delay(100);
  122. }
  123. mag_offset.x = (mag_max.x + mag_min.x) / 2;
  124. mag_offset.y = (mag_max.y + mag_min.y) / 2;
  125. mag_offset.z = (mag_max.z + mag_min.z) / 2;
  126. // added soft iron calibration
  127. mag_chord.x = (mag_max.x - mag_min.x) / 2;
  128. mag_chord.y = (mag_max.y - mag_min.y) / 2;
  129. mag_chord.z = (mag_max.z - mag_min.z) / 2;
  130. avg_chord = (mag_chord.x + mag_chord.y + mag_chord.z)/3;
  131. mag_scale.x = avg_chord / mag_chord.x;
  132. mag_scale.y = avg_chord / mag_chord.y;
  133. mag_scale.z = avg_chord / mag_chord.z;
  134. bmm150_offset_save();
  135. Serial.printf("\n calibrate finish ... \r\n");
  136. // Serial.printf("mag_max.x: %.2f x_min: %.2f \t", mag_max.x, mag_min.x);
  137. // Serial.printf("y_max: %.2f y_min: %.2f \t", mag_max.y, mag_min.y);
  138. // Serial.printf("z_max: %.2f z_min: %.2f \r\n", mag_max.z, mag_min.z);
  139. }
  140. void BMM150class::Init(void)
  141. {
  142. Wire.begin(21, 22, 400000);
  143. M5.Lcd.fillScreen(BLACK);
  144. M5.Lcd.setTextColor(WHITE);
  145. if (bmm150_initialization() != BMM150_OK)
  146. {
  147. M5.Lcd.setCursor(0, 10);
  148. M5.Lcd.print("BMM150 init failed");
  149. for (;;)
  150. {
  151. delay(100);
  152. }
  153. }
  154. bmm150_offset_load();
  155. Serial.printf("MID X : %.2f \t MID Y : %.2f \t MID Z : %.2f \n", mag_offset.x, mag_offset.y, mag_offset.z);
  156. Serial.printf("SCALE X : %.2f \t SCALE Y : %.2f \t SCALE Z : %.2f \n", mag_scale.x, mag_scale.y, mag_scale.z);
  157. M5.Lcd.setCursor(0, 10);
  158. M5.Lcd.printf("offset X, Y, Z: %5.4f %5.4f %5.4f \n", mag_offset.x, mag_offset.y, mag_offset.z);
  159. M5.Lcd.setCursor(0, 20);
  160. M5.Lcd.printf("scale X, Y, Z: %5.4f %5.4f %5.4f \n", mag_scale.x, mag_scale.y, mag_scale.z);
  161. delay(3000); // see preset data 3 sec.
  162. }
  163. void BMM150class::getMagnetData(float *mx, float *my, float *mz)
  164. {
  165. bmm150_read_mag_data(&dev);
  166. // float head_dir = atan2(dev.data.x - mag_offset.x, dev.data.y - mag_offset.y) * 180.0 / M_PI;
  167. *mx = dev.data.x;
  168. *my = dev.data.y;
  169. *mz = dev.data.z;
  170. }
  171. void BMM150class::getMagnetOffset(float *mx, float *my, float *mz)
  172. {
  173. bmm150_offset_load();
  174. *mx = mag_offset.x;
  175. *my = mag_offset.y;
  176. *mz = mag_offset.z;
  177. }
  178. void BMM150class::getMagnetScale(float *mx, float *my, float *mz)
  179. {
  180. bmm150_offset_load();
  181. *mx = mag_scale.x;
  182. *my = mag_scale.y;
  183. *mz = mag_scale.z;
  184. }