Accelerometer_Compass_LSM303D.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * A library for LSM303D based Acc&Compass Grove
  3. *
  4. * Copyright (c) 2012 Seeed Technology Limited
  5. * Website : www.seeed.cc
  6. * Author : Jacky Zhang
  7. * Create Time: Dec 2014
  8. * Change Log :
  9. *
  10. * The MIT License (MIT)
  11. *
  12. * Permission is hereby granted, free of charge, to any person obtaining a copy
  13. * of this software and associated documentation files (the "Software"), to deal
  14. * in the Software without restriction, including without limitation the rights
  15. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  16. * copies of the Software, and to permit persons to whom the Software is
  17. * furnished to do so, subject to the following conditions:
  18. *
  19. * The above copyright notice and this permission notice shall be included in
  20. * all copies or substantial portions of the Software.
  21. *
  22. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  25. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  26. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  28. * THE SOFTWARE.
  29. */
  30. #include <Accelerometer_Compass_LSM303D.h>
  31. #include <Wire.h>
  32. /* LSM303 Address definitions */
  33. #define LSM303D_ADDR 0x1E // assuming SA0 grounded
  34. /* LSM303 Register definitions */
  35. #define TEMP_OUT_L 0x05
  36. #define TEMP_OUT_H 0x06
  37. #define STATUS_REG_M 0x07
  38. #define OUT_X_L_M 0x08
  39. #define OUT_X_H_M 0x09
  40. #define OUT_Y_L_M 0x0A
  41. #define OUT_Y_H_M 0x0B
  42. #define OUT_Z_L_M 0x0C
  43. #define OUT_Z_H_M 0x0D
  44. #define WHO_AM_I 0x0F
  45. #define INT_CTRL_M 0x12
  46. #define INT_SRC_M 0x13
  47. #define INT_THS_L_M 0x14
  48. #define INT_THS_H_M 0x15
  49. #define OFFSET_X_L_M 0x16
  50. #define OFFSET_X_H_M 0x17
  51. #define OFFSET_Y_L_M 0x18
  52. #define OFFSET_Y_H_M 0x19
  53. #define OFFSET_Z_L_M 0x1A
  54. #define OFFSET_Z_H_M 0x1B
  55. #define REFERENCE_X 0x1C
  56. #define REFERENCE_Y 0x1D
  57. #define REFERENCE_Z 0x1E
  58. #define CTRL_REG0 0x1F
  59. #define CTRL_REG1 0x20
  60. #define CTRL_REG2 0x21
  61. #define CTRL_REG3 0x22
  62. #define CTRL_REG4 0x23
  63. #define CTRL_REG5 0x24
  64. #define CTRL_REG6 0x25
  65. #define CTRL_REG7 0x26
  66. #define STATUS_REG_A 0x27
  67. #define OUT_X_L_A 0x28
  68. #define OUT_X_H_A 0x29
  69. #define OUT_Y_L_A 0x2A
  70. #define OUT_Y_H_A 0x2B
  71. #define OUT_Z_L_A 0x2C
  72. #define OUT_Z_H_A 0x2D
  73. #define FIFO_CTRL 0x2E
  74. #define FIFO_SRC 0x2F
  75. #define IG_CFG1 0x30
  76. #define IG_SRC1 0x31
  77. #define IG_THS1 0x32
  78. #define IG_DUR1 0x33
  79. #define IG_CFG2 0x34
  80. #define IG_SRC2 0x35
  81. #define IG_THS2 0x36
  82. #define IG_DUR2 0x37
  83. #define CLICK_CFG 0x38
  84. #define CLICK_SRC 0x39
  85. #define CLICK_THS 0x3A
  86. #define TIME_LIMIT 0x3B
  87. #define TIME_LATENCY 0x3C
  88. #define TIME_WINDOW 0x3D
  89. #define ACT_THS 0x3E
  90. #define ACT_DUR 0x3F
  91. #define MAG_SCALE_2 0x00//full-scale is +/-2Gauss
  92. #define MAG_SCALE_4 0x20//+/-4Gauss
  93. #define MAG_SCALE_8 0x40//+/-8Gauss
  94. #define MAG_SCALE_12 0x60//+/-12Gauss
  95. char LSM303D::init()
  96. {
  97. char rtn = -1;
  98. Wire.begin(); // Start up I2C, required for LSM303 communication
  99. if(read(WHO_AM_I) != 0x49) return rtn; // return wrong if no LSM303D was found
  100. write(0x57, CTRL_REG1); // 0x57 = ODR=50hz, all accel axes on
  101. write((3<<6)|(0<<3), CTRL_REG2); // set full-scale
  102. write(0x00, CTRL_REG3); // no interrupt
  103. write(0x00, CTRL_REG4); // no interrupt
  104. write((4<<2), CTRL_REG5); // 0x10 = mag 50Hz output rate
  105. write(MAG_SCALE_2, CTRL_REG6); //magnetic scale = +/-1.3Gauss
  106. write(0x00, CTRL_REG7); // 0x00 = continouous conversion mode
  107. rtn = 0;
  108. return rtn;
  109. }
  110. unsigned char LSM303D::read(unsigned char address)
  111. {
  112. char temp;
  113. Wire.beginTransmission(LSM303D_ADDR);
  114. Wire.write(address);
  115. Wire.endTransmission();
  116. Wire.requestFrom(LSM303D_ADDR, 1);
  117. while(!Wire.available());
  118. temp = Wire.read();
  119. Wire.endTransmission();
  120. return temp;
  121. }
  122. void LSM303D::write(unsigned char data, unsigned char address)
  123. {
  124. Wire.beginTransmission(LSM303D_ADDR);
  125. Wire.write(address);
  126. Wire.write(data);
  127. Wire.endTransmission();
  128. }
  129. char LSM303D::isMagReady()
  130. {
  131. char temp;
  132. temp = read(STATUS_REG_M) & 0x03;
  133. return temp;
  134. }
  135. void LSM303D::getMag(int * rawValues)
  136. {
  137. rawValues[X] = ((int)read(OUT_X_H_M) << 8) | (read(OUT_X_L_M));
  138. rawValues[Y] = ((int)read(OUT_Y_H_M) << 8) | (read(OUT_Y_L_M));
  139. rawValues[Z] = ((int)read(OUT_Z_H_M) << 8) | (read(OUT_Z_L_M));
  140. }
  141. void LSM303D::getAccel(int * rawValues)
  142. {
  143. rawValues[X] = ((int)read(OUT_X_H_A) << 8) | (read(OUT_X_L_A));
  144. rawValues[Y] = ((int)read(OUT_Y_H_A) << 8) | (read(OUT_Y_L_A));
  145. rawValues[Z] = ((int)read(OUT_Z_H_A) << 8) | (read(OUT_Z_L_A));
  146. }
  147. float LSM303D::getHeading(int * magValue)
  148. {
  149. // see section 1.2 in app note AN3192
  150. float heading = 180*atan2(magValue[Y], magValue[X])/PI; // assume pitch, roll are 0
  151. if (heading <0)
  152. heading += 360;
  153. return heading;
  154. }
  155. float LSM303D::getTiltHeading(int * magValue, float * accelValue)
  156. {
  157. // see appendix A in app note AN3192
  158. float pitch = asin(-accelValue[X]);
  159. float roll = asin(accelValue[Y]/cos(pitch));
  160. float xh = magValue[X] * cos(pitch) + magValue[Z] * sin(pitch);
  161. float yh = magValue[X] * sin(roll) * sin(pitch) + magValue[Y] * cos(roll) - magValue[Z] * sin(roll) * cos(pitch);
  162. float zh = -magValue[X] * cos(roll) * sin(pitch) + magValue[Y] * sin(roll) + magValue[Z] * cos(roll) * cos(pitch);
  163. float heading = 180 * atan2(yh, xh)/PI;
  164. if (yh >= 0)
  165. return heading;
  166. else
  167. return (360 + heading);
  168. }
  169. LSM303D Lsm303d;