Arduino Libraries
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
MMA8452.hpp
Go to the documentation of this file.
1 // Author: Mario S. Könz <mskoenz@gmx.net>
2 // Date: 09.08.2013 19:01:49 CEST
3 // File: MMA8452.hpp
4 
5 /* This program is free software. It comes without any warranty, to
6  * the extent permitted by applicable law. You can redistribute it
7  * and/or modify it under the terms of the Do What The Fuck You Want
8  * To Public License, Version 2, as published by Sam Hocevar. See
9  * http://www.wtfpl.net/ or COPYING for more details. */
10 
11 #ifndef __MMA8452_HEADER
12 #define __MMA8452_HEADER
13 
14 /*
15 MMA8452Q Basic Example Code
16 Nathan Seidle
17 SparkFun Electronics
18 November 5, 2012
19 License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
20 This example code shows how to read the X/Y/Z accelerations and basic functions of the MMA5842. It leaves out
21 all the neat features this IC is capable of (tap, orientation, and inerrupts) and just displays X/Y/Z. See
22 the advanced example code to see more features.
23 Hardware setup:
24 MMA8452 Breakout ------------ Arduino
25 3.3V --------------------- 3.3V
26 SDA -------^^(330)^^------- A4
27 SCL -------^^(330)^^------- A5
28 GND ---------------------- GND
29 The MMA8452 is 3.3V so we recommend using 330 or 1k resistors between a 5V Arduino and the MMA8452 breakout.
30 The MMA8452 has built in pull-up resistors for I2C so you do not need additional pull-ups.
31 */
32 
33 #include <Arduino.h>
34 #include <ustd.hpp>
35 #include <com/i2c.hpp>
36 
37 namespace device {
38  //Define a few of the registers that we will be accessing on the MMA8452
39  uint8_t const OUT_X_MSB = 0x01;
40  #define XYZ_DATA_CFG 0x0E
41  #define WHO_AM_I 0x0D
42  #define CTRL_REG1 0x2A
43 
44  #ifndef MMA8452_ADDRESS
45  #define MMA8452_ADDRESS 0x1D // 0x1D if SA0 is high, 0x1C if low
46  #endif
47  class MMA8452_class {
48  public:
49  //------------------- ctor/init -------------------
50  void init(uint8_t const & g_scale = 2) {
51  delay(100);
52  g_scale_ = g_scale;
53  uint8_t c = read_register(WHO_AM_I); // WHO_AM_I should always be 0x2A
54  ASSERT_MSG(c == 0x2A, "Couldn't connect to MMA8452")
55 
56  standby(); // Must be in standby to change registers
57 
58  byte fsr = g_scale_;
59  if(fsr > 8)
60  fsr = 8;
61  fsr >>= 2; // Neat trick, see page 22. 00 = 2G, 01 = 4A, 10 = 8G
63 
64  //The default data rate is 800Hz and we don't modify it in this example code
65 
66  active(); // Set to active to start reading
67  }
68  void standby() {
69  byte c = read_register(CTRL_REG1);
70  write_register(CTRL_REG1, c & ~(0x01)); //Clear the active bit to go into standby
71  }
72  void active() {
73  byte c = read_register(CTRL_REG1);
74  write_register(CTRL_REG1, c | 0x01); //Set the active bit to begin detection
75  }
76  //------------------- registers -------------------
77  uint8_t read_register(byte address) {
78  uint8_t res;
79  com::i2cout(MMA8452_ADDRESS) << address << ustd::endl(false);
81  return res;
82  }
83 
84  void write_register(byte address, byte data) {
85  com::i2cout(MMA8452_ADDRESS) << address << data << ustd::endl;
86  }
87  //------------------- update -------------------
88  void update() {
90  com::i2cin(MMA8452_ADDRESS) >> raw_data;
91 
92  // Loop to calculate 12-bit ADC and g value for each axis
93  for(int i = 0; i < 3 ; i++) {
94  int g_count = (raw_data[i*2] << 8) | raw_data[(i*2)+1]; //Combine the two 8 bit registers into one 12-bit number
95  g_count >>= 4; //The registers are left align, here we right align the 12-bit integer
96 
97  // If the number is negative, we have to make it so manually (no 12-bit data type)
98  if (raw_data[i*2] > 0x7F) {
99  g_count = ~g_count + 1;
100  g_count *= -1; // Transform into negative 2's complement #
101  }
102 
103  accel[i] = double(g_count) / ((1<<12)/(2*g_scale_));
104  }
105  }
106  //------------------- getter -------------------
107  double const & operator[](uint8_t const & idx) const {
108  ASSERT(idx < 3)
109  return accel[idx];
110  }
111  double const & x() const {
112  return accel[0];
113  }
114  double const & y() const {
115  return accel[1];
116  }
117  double const & z() const {
118  return accel[2];
119  }
120  private:
121  uint8_t g_scale_;
122  double accel[3];
123  uint8_t raw_data[6];
124  };
125 }//end namespace device
126 
127 #endif //__MMA8452_HEADER
void standby()
Definition: MMA8452.hpp:68
#define CTRL_REG1
Definition: MMA8452.hpp:42
#define XYZ_DATA_CFG
Definition: MMA8452.hpp:40
void init(uint8_t const &g_scale=2)
Definition: MMA8452.hpp:50
class com::i2cout_class i2cout
#define ASSERT_MSG(exp, msg)
Definition: ard_assert.hpp:34
double const & x() const
Definition: MMA8452.hpp:111
double const & y() const
Definition: MMA8452.hpp:114
void active()
Definition: MMA8452.hpp:72
struct ustd::endl_class endl
void update()
Definition: MMA8452.hpp:88
uint8_t const OUT_X_MSB
Definition: MMA8452.hpp:39
void write_register(byte address, byte data)
Definition: MMA8452.hpp:84
#define WHO_AM_I
Definition: MMA8452.hpp:41
#define MMA8452_ADDRESS
Definition: MMA8452.hpp:45
double const & z() const
Definition: MMA8452.hpp:117
double const & operator[](uint8_t const &idx) const
Definition: MMA8452.hpp:107
#define ASSERT(exp)
Definition: ard_assert.hpp:33
Definition: MMA8452.hpp:47
uint8_t read_register(byte address)
Definition: MMA8452.hpp:77
class com::i2cin_class i2cin