bmm150.ino 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * @Author: Sorzn
  3. * @Date: 2019-11-21 19:58:40
  4. * @LastEditTime: 2019-11-22 20:36:35
  5. * @Description: M5Stack project
  6. * @FilePath: /bmm150/bmm150.ino
  7. */
  8. #include <Arduino.h>
  9. #include <Wire.h>
  10. #include "Preferences.h"
  11. #include "M5Stack.h"
  12. #include "math.h"
  13. #include "bmm150.h"
  14. #include "bmm150_defs.h"
  15. Preferences prefs;
  16. struct bmm150_dev dev;
  17. bmm150_mag_data mag_offset;
  18. bmm150_mag_data mag_max;
  19. bmm150_mag_data mag_min;
  20. TFT_eSprite img = TFT_eSprite(&M5.Lcd);
  21. int8_t i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *read_data, uint16_t len)
  22. {
  23. if(M5.I2C.readBytes(dev_id, reg_addr, len, read_data))
  24. {
  25. return BMM150_OK;
  26. }
  27. else
  28. {
  29. return BMM150_E_DEV_NOT_FOUND;
  30. }
  31. }
  32. int8_t i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *read_data, uint16_t len)
  33. {
  34. if(M5.I2C.writeBytes(dev_id, reg_addr, read_data, len))
  35. {
  36. return BMM150_OK;
  37. }
  38. else
  39. {
  40. return BMM150_E_DEV_NOT_FOUND;
  41. }
  42. }
  43. int8_t bmm150_initialization()
  44. {
  45. int8_t rslt = BMM150_OK;
  46. /* Sensor interface over SPI with native chip select line */
  47. dev.dev_id = 0x10;
  48. dev.intf = BMM150_I2C_INTF;
  49. dev.read = i2c_read;
  50. dev.write = i2c_write;
  51. dev.delay_ms = delay;
  52. /* make sure max < mag data first */
  53. mag_max.x = -2000;
  54. mag_max.y = -2000;
  55. mag_max.z = -2000;
  56. /* make sure min > mag data first */
  57. mag_min.x = 2000;
  58. mag_min.y = 2000;
  59. mag_min.z = 2000;
  60. rslt = bmm150_init(&dev);
  61. dev.settings.pwr_mode = BMM150_NORMAL_MODE;
  62. rslt |= bmm150_set_op_mode(&dev);
  63. dev.settings.preset_mode = BMM150_PRESETMODE_ENHANCED;
  64. rslt |= bmm150_set_presetmode(&dev);
  65. return rslt;
  66. }
  67. void bmm150_offset_save()
  68. {
  69. prefs.begin("bmm150", false);
  70. prefs.putBytes("offset", (uint8_t *)&mag_offset, sizeof(bmm150_mag_data));
  71. prefs.end();
  72. }
  73. void bmm150_offset_load()
  74. {
  75. if(prefs.begin("bmm150", true))
  76. {
  77. prefs.getBytes("offset", (uint8_t *)&mag_offset, sizeof(bmm150_mag_data));
  78. prefs.end();
  79. Serial.printf("bmm150 load offset finish.... \r\n");
  80. }
  81. else
  82. {
  83. Serial.printf("bmm150 load offset failed.... \r\n");
  84. }
  85. }
  86. void setup()
  87. {
  88. M5.begin(true, false, true, false);
  89. M5.Power.begin();
  90. Wire.begin(21, 22, 400000);
  91. img.setColorDepth(1);
  92. img.setTextColor(TFT_WHITE);
  93. img.createSprite(320, 240);
  94. img.setBitmapColor(TFT_WHITE, 0);
  95. if(bmm150_initialization() != BMM150_OK)
  96. {
  97. img.fillSprite(0);
  98. img.drawCentreString("BMM150 init failed", 160, 110, 4);
  99. img.pushSprite(0, 0);
  100. for(;;)
  101. {
  102. delay(100);
  103. }
  104. }
  105. bmm150_offset_load();
  106. }
  107. void bmm150_calibrate(uint32_t calibrate_time)
  108. {
  109. uint32_t calibrate_timeout = 0;
  110. calibrate_timeout = millis() + calibrate_time;
  111. Serial.printf("Go calibrate, use %d ms \r\n", calibrate_time);
  112. Serial.printf("running ...");
  113. while (calibrate_timeout > millis())
  114. {
  115. bmm150_read_mag_data(&dev);
  116. if(dev.data.x)
  117. {
  118. mag_min.x = (dev.data.x < mag_min.x) ? dev.data.x : mag_min.x;
  119. mag_max.x = (dev.data.x > mag_max.x) ? dev.data.x : mag_max.x;
  120. }
  121. if(dev.data.y)
  122. {
  123. mag_max.y = (dev.data.y > mag_max.y) ? dev.data.y : mag_max.y;
  124. mag_min.y = (dev.data.y < mag_min.y) ? dev.data.y : mag_min.y;
  125. }
  126. if(dev.data.z)
  127. {
  128. mag_min.z = (dev.data.z < mag_min.z) ? dev.data.z : mag_min.z;
  129. mag_max.z = (dev.data.z > mag_max.z) ? dev.data.z : mag_max.z;
  130. }
  131. delay(100);
  132. }
  133. mag_offset.x = (mag_max.x + mag_min.x) / 2;
  134. mag_offset.y = (mag_max.y + mag_min.y) / 2;
  135. mag_offset.z = (mag_max.z + mag_min.z) / 2;
  136. bmm150_offset_save();
  137. Serial.printf("\n calibrate finish ... \r\n");
  138. Serial.printf("mag_max.x: %.2f x_min: %.2f \t", mag_max.x, mag_min.x);
  139. Serial.printf("y_max: %.2f y_min: %.2f \t", mag_max.y, mag_min.y);
  140. Serial.printf("z_max: %.2f z_min: %.2f \r\n", mag_max.z, mag_min.z);
  141. }
  142. void loop()
  143. {
  144. char text_string[100];
  145. M5.update();
  146. bmm150_read_mag_data(&dev);
  147. float head_dir = atan2(dev.data.x - mag_offset.x, dev.data.y - mag_offset.y) * 180.0 / M_PI;
  148. Serial.printf("Magnetometer data, heading %.2f\n", head_dir);
  149. Serial.printf("MAG X : %.2f \t MAG Y : %.2f \t MAG Z : %.2f \n", dev.data.x, dev.data.y, dev.data.z);
  150. Serial.printf("MID X : %.2f \t MID Y : %.2f \t MID Z : %.2f \n", mag_offset.x, mag_offset.y, mag_offset.z);
  151. img.fillSprite(0);
  152. sprintf(text_string, "MAG X: %.2f", dev.data.x);
  153. img.drawString(text_string, 10, 20, 4);
  154. sprintf(text_string, "MAG Y: %.2f", dev.data.y);
  155. img.drawString(text_string, 10, 50, 4);
  156. sprintf(text_string, "MAG Z: %.2f", dev.data.z);
  157. img.drawString(text_string, 10, 80, 4);
  158. sprintf(text_string, "HEAD Angle: %.2f", head_dir);
  159. img.drawString(text_string, 10, 110, 4);
  160. img.drawCentreString("Press BtnA enter calibrate", 160, 150, 4);
  161. img.pushSprite(0, 0);
  162. if(M5.BtnA.wasPressed())
  163. {
  164. img.fillSprite(0);
  165. img.drawCentreString("Flip + rotate core calibration", 160, 110, 4);
  166. img.pushSprite(0, 0);
  167. bmm150_calibrate(10000);
  168. }
  169. delay(100);
  170. }