MMA7660.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * MMA7760.h
  3. * Library for accelerometer_MMA7760
  4. *
  5. * Copyright (c) 2013 seeed technology inc.
  6. * Author : FrankieChu
  7. * Create Time : Jan 2013
  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 <Arduino.h>
  31. #include <Wire.h>
  32. #include "MMA7660.h"
  33. #define MMA7660TIMEOUT 500 // us
  34. /*Function: Write a byte to the register of the MMA7660*/
  35. void MMA7660::write(uint8_t _register, uint8_t _data) {
  36. Wire.begin();
  37. Wire.beginTransmission(MMA7660_ADDR);
  38. Wire.write(_register);
  39. Wire.write(_data);
  40. Wire.endTransmission();
  41. }
  42. /*Function: Read a byte from the regitster of the MMA7660*/
  43. uint8_t MMA7660::read(uint8_t _register) {
  44. uint8_t data_read;
  45. Wire.begin();
  46. Wire.beginTransmission(MMA7660_ADDR);
  47. Wire.write(_register);
  48. Wire.endTransmission();
  49. Wire.beginTransmission(MMA7660_ADDR);
  50. Wire.requestFrom(MMA7660_ADDR,1);
  51. while(Wire.available())
  52. {
  53. data_read = Wire.read();
  54. }
  55. Wire.endTransmission();
  56. return data_read;
  57. }
  58. // populate lookup table based on the MMA7660 datasheet at http://www.farnell.com/datasheets/1670762.pdf
  59. void MMA7660::initAccelTable() {
  60. int i;
  61. float val, valZ;
  62. for (i = 0, val = 0; i < 32; i++) {
  63. accLookup[i].g = val;
  64. val += 0.047;
  65. }
  66. for (i = 63, val = -0.047; i > 31; i--) {
  67. accLookup[i].g = val;
  68. val -= 0.047;
  69. }
  70. for (i = 0, val = 0, valZ = 90; i < 22; i++) {
  71. accLookup[i].xyAngle = val;
  72. accLookup[i].zAngle = valZ;
  73. val += 2.69;
  74. valZ -= 2.69;
  75. }
  76. for (i = 63, val = -2.69, valZ = -87.31; i > 42; i--) {
  77. accLookup[i].xyAngle = val;
  78. accLookup[i].zAngle = valZ;
  79. val -= 2.69;
  80. valZ += 2.69;
  81. }
  82. for (i = 22; i < 43; i++) {
  83. accLookup[i].xyAngle = 255;
  84. accLookup[i].zAngle = 255;
  85. }
  86. }
  87. void MMA7660::init()
  88. {
  89. initAccelTable();
  90. setMode(MMA7660_STAND_BY);
  91. setSampleRate(AUTO_SLEEP_32);
  92. setMode(MMA7660_ACTIVE);
  93. }
  94. void MMA7660::init(uint8_t interrupts)
  95. {
  96. initAccelTable();
  97. setMode(MMA7660_STAND_BY);
  98. setSampleRate(AUTO_SLEEP_32);
  99. write(MMA7660_INTSU, interrupts);
  100. setMode(MMA7660_ACTIVE);
  101. }
  102. void MMA7660::setMode(uint8_t mode) {
  103. write(MMA7660_MODE,mode);
  104. }
  105. void MMA7660::setSampleRate(uint8_t rate) {
  106. write(MMA7660_SR,rate);
  107. }
  108. /*Function: Get the contents of the registers in the MMA7660*/
  109. /* so as to calculate the acceleration. */
  110. bool MMA7660::getXYZ(int8_t *x,int8_t *y,int8_t *z)
  111. {
  112. START:
  113. unsigned char val[3];
  114. int count = 0;
  115. val[0] = val[1] = val[2] = 64;
  116. while(Wire.available() > 0)
  117. Wire.read();
  118. Wire.requestFrom(MMA7660_ADDR,3);
  119. unsigned long timer_s = micros();
  120. while(Wire.available())
  121. {
  122. if(count < 3)
  123. {
  124. while ( val[count] > 63 ) // reload the damn thing it is bad
  125. {
  126. val[count] = Wire.read();
  127. if(micros()-timer_s > MMA7660TIMEOUT)
  128. {
  129. goto START;
  130. }
  131. }
  132. }
  133. count++;
  134. }
  135. *x = ((int8_t)(val[0]<<2))/4;
  136. *y = ((int8_t)(val[1]<<2))/4;
  137. *z = ((int8_t)(val[2]<<2))/4;
  138. return 1;
  139. }
  140. bool MMA7660::getAcceleration(float *ax,float *ay,float *az)
  141. {
  142. int8_t x,y,z;
  143. if(!getXYZ(&x,&y,&z))return 0;
  144. *ax = x/21.00;
  145. *ay = y/21.00;
  146. *az = z/21.00;
  147. return 1;
  148. }
  149. bool MMA7660::getAcceleration(MMA7660_ACC_DATA *data) {
  150. unsigned char val[3];
  151. int count;
  152. bool error;
  153. unsigned long timer_s = micros();
  154. do {
  155. error = false;
  156. count = 0;
  157. while(Wire.available() > 0) {
  158. Wire.read();
  159. }
  160. Wire.requestFrom(MMA7660_ADDR, 3);
  161. while(Wire.available()) {
  162. if (count < 3) {
  163. val[count] = Wire.read();
  164. if (0x40 & val[count] == 0x40) { // alert bit is set, data is garbage and we have to start over.
  165. error = true;
  166. break;
  167. }
  168. }
  169. count++;
  170. }
  171. if(micros()-timer_s > MMA7660TIMEOUT)return 0;
  172. } while (error);
  173. (*data).x = accLookup[val[0]];
  174. (*data).y = accLookup[val[1]];
  175. (*data).z = accLookup[val[2]];
  176. return 1;
  177. }
  178. bool MMA7660::getAllData(MMA7660_DATA *data) {
  179. int count = 0;
  180. uint8_t val[11] = {0};
  181. while (Wire.available() > 0) {
  182. Wire.read();
  183. }
  184. Wire.requestFrom(MMA7660_ADDR, 11);
  185. while (Wire.available()) {
  186. if (count < 11) {
  187. val[count] = Wire.read();
  188. }
  189. count++;
  190. }
  191. data->X = val[0];
  192. data->Y = val[1];
  193. data->Z = val[2];
  194. data->TILT = val[3];
  195. data->SRST = val[4];
  196. data->SPCNT = val[5];
  197. data->INTSU = val[6];
  198. data->MODE = val[7];
  199. data->SR = val[8];
  200. data->PDET = val[9];
  201. data->PD = val[10];
  202. return 1;
  203. }