Browse Source

mpu9150: rewrite from scratch

This driver has been rewritten from scratch.  It is implemented as 3
seperate drivers now (but all included as part of the mpu9150 UPM
library):

AK8975 (Magnetometer)
MPU60X0 (Accelerometer, Gyroscope, and Temperature sensor)
MPU9150 (composed of AK8975 and MPU60X0)

Each driver can be used independently and includes examples in
C++/JS/Python.

Commonly used capabilities are supported, and methods/register
definitions exist to easily implement any desired functionality that
is missing.  Interrupt support has also been added.

Scaling support has also been properly implemented for both the
Accelerometer and Gyroscope.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
Jon Trulson 9 years ago
parent
commit
03e72e02f8

+ 4
- 0
examples/c++/CMakeLists.txt View File

@@ -129,6 +129,8 @@ add_executable (hp20x-example hp20x.cxx)
129 129
 add_executable (pn532-example pn532.cxx)
130 130
 add_executable (pn532-writeurl-example pn532-writeurl.cxx)
131 131
 add_executable (sainsmartks-example sainsmartks.cxx)
132
+add_executable (mpu60x0-example mpu60x0.cxx)
133
+add_executable (ak8975-example ak8975.cxx)
132 134
 
133 135
 include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l)
134 136
 include_directories (${PROJECT_SOURCE_DIR}/src/grove)
@@ -364,3 +366,5 @@ target_link_libraries (hp20x-example hp20x ${CMAKE_THREAD_LIBS_INIT})
364 366
 target_link_libraries (pn532-example pn532 ${CMAKE_THREAD_LIBS_INIT})
365 367
 target_link_libraries (pn532-writeurl-example pn532 ${CMAKE_THREAD_LIBS_INIT})
366 368
 target_link_libraries (sainsmartks-example i2clcd ${CMAKE_THREAD_LIBS_INIT})
369
+target_link_libraries (mpu60x0-example mpu9150 ${CMAKE_THREAD_LIBS_INIT})
370
+target_link_libraries (ak8975-example mpu9150 ${CMAKE_THREAD_LIBS_INIT})

+ 72
- 0
examples/c++/ak8975.cxx View File

@@ -0,0 +1,72 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2015 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+#include <unistd.h>
26
+#include <iostream>
27
+#include <signal.h>
28
+#include "mpu9150.h"
29
+
30
+using namespace std;
31
+
32
+int shouldRun = true;
33
+
34
+void sig_handler(int signo)
35
+{
36
+  if (signo == SIGINT)
37
+    shouldRun = false;
38
+}
39
+
40
+
41
+int main(int argc, char **argv)
42
+{
43
+  signal(SIGINT, sig_handler);
44
+//! [Interesting]
45
+
46
+  upm::AK8975 *sensor = new upm::AK8975();
47
+
48
+  sensor->init();
49
+
50
+  while (shouldRun)
51
+    {
52
+      sensor->update();
53
+      
54
+      float x, y, z;
55
+      
56
+      sensor->getMagnetometer(&x, &y, &z);
57
+      cout << "Magnetometer:  ";
58
+      cout << "MX = " << x << " MY = " << y << " MZ = " << z << endl;
59
+
60
+      cout << endl;
61
+
62
+      usleep(500000);
63
+    }
64
+
65
+//! [Interesting]
66
+
67
+  cout << "Exiting..." << endl;
68
+  
69
+  delete sensor;
70
+  
71
+  return 0;
72
+}

+ 77
- 0
examples/c++/mpu60x0.cxx View File

@@ -0,0 +1,77 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2015 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+#include <unistd.h>
26
+#include <iostream>
27
+#include <signal.h>
28
+#include "mpu9150.h"
29
+
30
+using namespace std;
31
+
32
+int shouldRun = true;
33
+
34
+void sig_handler(int signo)
35
+{
36
+  if (signo == SIGINT)
37
+    shouldRun = false;
38
+}
39
+
40
+
41
+int main(int argc, char **argv)
42
+{
43
+  signal(SIGINT, sig_handler);
44
+//! [Interesting]
45
+
46
+  upm::MPU60X0 *sensor = new upm::MPU60X0();
47
+
48
+  sensor->init();
49
+
50
+  while (shouldRun)
51
+    {
52
+      sensor->update();
53
+      
54
+      float x, y, z;
55
+      
56
+      sensor->getAccelerometer(&x, &y, &z);
57
+      cout << "Accelerometer: ";
58
+      cout << "AX: " << x << " AY: " << y << " AZ: " << z << endl;
59
+
60
+      sensor->getGyroscope(&x, &y, &z);
61
+      cout << "Gryoscope:     ";
62
+      cout << "GX: " << x << " GY: " << y << " GZ: " << z << endl;
63
+      
64
+      cout << "Temperature:   " << sensor->getTemperature() << endl;
65
+      cout << endl;
66
+
67
+      usleep(500000);
68
+    }
69
+
70
+//! [Interesting]
71
+
72
+  cout << "Exiting..." << endl;
73
+  
74
+  delete sensor;
75
+  
76
+  return 0;
77
+}

+ 53
- 31
examples/c++/mpu9150.cxx View File

@@ -1,6 +1,6 @@
1 1
 /*
2
- * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
3
- * Copyright (c) 2014 Intel Corporation.
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2015 Intel Corporation.
4 4
  *
5 5
  * Permission is hereby granted, free of charge, to any person obtaining
6 6
  * a copy of this software and associated documentation files (the
@@ -24,36 +24,58 @@
24 24
 
25 25
 #include <unistd.h>
26 26
 #include <iostream>
27
+#include <signal.h>
27 28
 #include "mpu9150.h"
28 29
 
29
-int
30
-main(int argc, char **argv)
30
+using namespace std;
31
+
32
+int shouldRun = true;
33
+
34
+void sig_handler(int signo)
31 35
 {
32
-    //! [Interesting]
33
-    upm::Vector3D data;
34
-    upm::MPU9150 *sensor = new upm::MPU9150(0, ADDR);
35
-    sensor->getData ();
36
-    sensor->getAcceleromter (&data);
37
-    std::cout << "*************************************************" << std::endl;
38
-    std::cout << "DEVICE ID (" << (int) sensor->getDeviceID () << ")" << std::endl;
39
-    std::cout << "*************************************************" << std::endl;
40
-    std::cout << "ACCELEROMETER :: X (" << data.axisX << ")" << " Y (" << data.axisY << ")"
41
-                << " Z (" << data.axisZ << ")" << std::endl;
42
-
43
-    sensor->getGyro (&data);
44
-    std::cout << "GYRO :: X (" << data.axisX << ")" << " Y (" << data.axisY << ")"
45
-                << " Z (" << data.axisZ << ")" << std::endl;
46
-
47
-    sensor->getMagnometer (&data);
48
-    std::cout << "MAGNOMETER :: X (" << data.axisX << ")" << " Y (" << data.axisY << ")"
49
-                << " Z (" << data.axisZ << ")" << std::endl;
50
-    std::cout << "TEMPERATURE (" << sensor->getTemperature () << ")" << std::endl;
51
-    std::cout << "*************************************************" << std::endl;
52
-    //! [Interesting]
53
-
54
-    std::cout << "exiting application" << std::endl;
55
-
56
-    delete sensor;
57
-
58
-    return 0;
36
+  if (signo == SIGINT)
37
+    shouldRun = false;
38
+}
39
+
40
+
41
+int main(int argc, char **argv)
42
+{
43
+  signal(SIGINT, sig_handler);
44
+//! [Interesting]
45
+
46
+  upm::MPU9150 *sensor = new upm::MPU9150();
47
+
48
+  sensor->init();
49
+
50
+  while (shouldRun)
51
+    {
52
+      sensor->update();
53
+      
54
+      float x, y, z;
55
+      
56
+      sensor->getAccelerometer(&x, &y, &z);
57
+      cout << "Accelerometer: ";
58
+      cout << "AX: " << x << " AY: " << y << " AZ: " << z << endl;
59
+
60
+      sensor->getGyroscope(&x, &y, &z);
61
+      cout << "Gryoscope:     ";
62
+      cout << "GX: " << x << " GY: " << y << " GZ: " << z << endl;
63
+      
64
+      sensor->getMagnetometer(&x, &y, &z);
65
+      cout << "Magnetometer:  ";
66
+      cout << "MX = " << x << " MY = " << y << " MZ = " << z << endl;
67
+
68
+      cout << "Temperature:   " << sensor->getTemperature() << endl;
69
+      cout << endl;
70
+
71
+      usleep(500000);
72
+    }
73
+
74
+//! [Interesting]
75
+
76
+  cout << "Exiting..." << endl;
77
+  
78
+  delete sensor;
79
+  
80
+  return 0;
59 81
 }

+ 64
- 0
examples/javascript/ak8975.js View File

@@ -0,0 +1,64 @@
1
+/*jslint node:true, vars:true, bitwise:true, unparam:true */
2
+/*jshint unused:true */
3
+
4
+/*
5
+ * Author: Jon Trulson <jtrulson@ics.com>
6
+ * Copyright (c) 2015 Intel Corporation.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining
9
+ * a copy of this software and associated documentation files (the
10
+ * "Software"), to deal in the Software without restriction, including
11
+ * without limitation the rights to use, copy, modify, merge, publish,
12
+ * distribute, sublicense, and/or sell copies of the Software, and to
13
+ * permit persons to whom the Software is furnished to do so, subject to
14
+ * the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be
17
+ * included in all copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+
29
+var sensorObj = require('jsupm_mpu9150');
30
+
31
+// Instantiate an AK8975 on default I2C bus and address
32
+var sensor = new sensorObj.AK8975();
33
+
34
+// Initialize the device with default values
35
+sensor.init();
36
+
37
+var x = new sensorObj.new_floatp();
38
+var y = new sensorObj.new_floatp();
39
+var z = new sensorObj.new_floatp();
40
+
41
+// Output data every half second until interrupted
42
+setInterval(function()
43
+{
44
+    sensor.update();
45
+    
46
+    sensor.getMagnetometer(x, y, z);
47
+    console.log("Magnetometer:  MX: " + sensorObj.floatp_value(x) + 
48
+                " MY: " + sensorObj.floatp_value(y) + 
49
+                " MZ: " + sensorObj.floatp_value(z));
50
+
51
+    console.log();
52
+
53
+}, 500);
54
+
55
+// exit on ^C
56
+process.on('SIGINT', function()
57
+{
58
+    sensor = null;
59
+    sensorObj.cleanUp();
60
+    sensorObj = null;
61
+    console.log("Exiting.");
62
+    process.exit(0);
63
+});
64
+

+ 71
- 0
examples/javascript/mpu60x0.js View File

@@ -0,0 +1,71 @@
1
+/*jslint node:true, vars:true, bitwise:true, unparam:true */
2
+/*jshint unused:true */
3
+
4
+/*
5
+ * Author: Jon Trulson <jtrulson@ics.com>
6
+ * Copyright (c) 2015 Intel Corporation.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining
9
+ * a copy of this software and associated documentation files (the
10
+ * "Software"), to deal in the Software without restriction, including
11
+ * without limitation the rights to use, copy, modify, merge, publish,
12
+ * distribute, sublicense, and/or sell copies of the Software, and to
13
+ * permit persons to whom the Software is furnished to do so, subject to
14
+ * the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be
17
+ * included in all copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+
29
+var sensorObj = require('jsupm_mpu9150');
30
+
31
+// Instantiate an MPU60X0 on default I2C bus and address
32
+var sensor = new sensorObj.MPU60X0();
33
+
34
+// Initialize the device with default values
35
+sensor.init();
36
+
37
+var x = new sensorObj.new_floatp();
38
+var y = new sensorObj.new_floatp();
39
+var z = new sensorObj.new_floatp();
40
+
41
+// Output data every half second until interrupted
42
+setInterval(function()
43
+{
44
+    sensor.update();
45
+    
46
+    sensor.getAccelerometer(x, y, z);
47
+    console.log("Accelerometer: AX: " + sensorObj.floatp_value(x) + 
48
+                " AY: " + sensorObj.floatp_value(y) + 
49
+                " AZ: " + sensorObj.floatp_value(z));
50
+
51
+    sensor.getGyroscope(x, y, z);
52
+    console.log("Gyroscope:     GX: " + sensorObj.floatp_value(x) + 
53
+                " AY: " + sensorObj.floatp_value(y) + 
54
+                " AZ: " + sensorObj.floatp_value(z));
55
+ 
56
+    console.log("Temperature:   " + sensor.getTemperature());
57
+ 
58
+    console.log();
59
+
60
+}, 500);
61
+
62
+// exit on ^C
63
+process.on('SIGINT', function()
64
+{
65
+    sensor = null;
66
+    sensorObj.cleanUp();
67
+    sensorObj = null;
68
+    console.log("Exiting.");
69
+    process.exit(0);
70
+});
71
+

+ 76
- 0
examples/javascript/mpu9150.js View File

@@ -0,0 +1,76 @@
1
+/*jslint node:true, vars:true, bitwise:true, unparam:true */
2
+/*jshint unused:true */
3
+
4
+/*
5
+ * Author: Jon Trulson <jtrulson@ics.com>
6
+ * Copyright (c) 2015 Intel Corporation.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining
9
+ * a copy of this software and associated documentation files (the
10
+ * "Software"), to deal in the Software without restriction, including
11
+ * without limitation the rights to use, copy, modify, merge, publish,
12
+ * distribute, sublicense, and/or sell copies of the Software, and to
13
+ * permit persons to whom the Software is furnished to do so, subject to
14
+ * the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be
17
+ * included in all copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+
29
+var sensorObj = require('jsupm_mpu9150');
30
+
31
+// Instantiate an MPU9105 on default I2C bus and address
32
+var sensor = new sensorObj.MPU9150();
33
+
34
+// Initialize the device with default values
35
+sensor.init();
36
+
37
+var x = new sensorObj.new_floatp();
38
+var y = new sensorObj.new_floatp();
39
+var z = new sensorObj.new_floatp();
40
+
41
+// Output data every half second until interrupted
42
+setInterval(function()
43
+{
44
+    sensor.update();
45
+    
46
+    sensor.getAccelerometer(x, y, z);
47
+    console.log("Accelerometer: AX: " + sensorObj.floatp_value(x) + 
48
+                " AY: " + sensorObj.floatp_value(y) + 
49
+                " AZ: " + sensorObj.floatp_value(z));
50
+
51
+    sensor.getGyroscope(x, y, z);
52
+    console.log("Gyroscope:     GX: " + sensorObj.floatp_value(x) + 
53
+                " AY: " + sensorObj.floatp_value(y) + 
54
+                " AZ: " + sensorObj.floatp_value(z));
55
+ 
56
+    sensor.getMagnetometer(x, y, z);
57
+    console.log("Magnetometer:  MX: " + sensorObj.floatp_value(x) + 
58
+                " MY: " + sensorObj.floatp_value(y) + 
59
+                " MZ: " + sensorObj.floatp_value(z));
60
+
61
+    console.log("Temperature:   " + sensor.getTemperature());
62
+ 
63
+    console.log();
64
+
65
+}, 500);
66
+
67
+// exit on ^C
68
+process.on('SIGINT', function()
69
+{
70
+    sensor = null;
71
+    sensorObj.cleanUp();
72
+    sensorObj = null;
73
+    console.log("Exiting.");
74
+    process.exit(0);
75
+});
76
+

+ 59
- 0
examples/python/ak8975.py View File

@@ -0,0 +1,59 @@
1
+#!/usr/bin/python
2
+# Author: Jon Trulson <jtrulson@ics.com>
3
+# Copyright (c) 2015 Intel Corporation.
4
+#
5
+# Permission is hereby granted, free of charge, to any person obtaining
6
+# a copy of this software and associated documentation files (the
7
+# "Software"), to deal in the Software without restriction, including
8
+# without limitation the rights to use, copy, modify, merge, publish,
9
+# distribute, sublicense, and/or sell copies of the Software, and to
10
+# permit persons to whom the Software is furnished to do so, subject to
11
+# the following conditions:
12
+#
13
+# The above copyright notice and this permission notice shall be
14
+# included in all copies or substantial portions of the Software.
15
+#
16
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+import time, sys, signal, atexit
25
+import pyupm_mpu9150 as sensorObj
26
+
27
+# Instantiate an AK8975 on I2C bus 0
28
+sensor = sensorObj.AK8975()
29
+
30
+## Exit handlers ##
31
+# This function stops python from printing a stacktrace when you hit control-C
32
+def SIGINTHandler(signum, frame):
33
+	raise SystemExit
34
+
35
+# This function lets you run code on exit
36
+def exitHandler():
37
+	print "Exiting"
38
+	sys.exit(0)
39
+
40
+# Register exit handlers
41
+atexit.register(exitHandler)
42
+signal.signal(signal.SIGINT, SIGINTHandler)
43
+
44
+sensor.init()
45
+
46
+x = sensorObj.new_floatp()
47
+y = sensorObj.new_floatp()
48
+z = sensorObj.new_floatp()
49
+
50
+while (1):
51
+        sensor.update()
52
+        sensor.getMagnetometer(x, y, z)
53
+        print "Magnetometer:  MX: ", sensorObj.floatp_value(x), 
54
+        print " MY: ", sensorObj.floatp_value(y),
55
+        print " MZ: ", sensorObj.floatp_value(z)
56
+
57
+        print
58
+
59
+	time.sleep(.5)

+ 65
- 0
examples/python/mpu60x0.py View File

@@ -0,0 +1,65 @@
1
+#!/usr/bin/python
2
+# Author: Jon Trulson <jtrulson@ics.com>
3
+# Copyright (c) 2015 Intel Corporation.
4
+#
5
+# Permission is hereby granted, free of charge, to any person obtaining
6
+# a copy of this software and associated documentation files (the
7
+# "Software"), to deal in the Software without restriction, including
8
+# without limitation the rights to use, copy, modify, merge, publish,
9
+# distribute, sublicense, and/or sell copies of the Software, and to
10
+# permit persons to whom the Software is furnished to do so, subject to
11
+# the following conditions:
12
+#
13
+# The above copyright notice and this permission notice shall be
14
+# included in all copies or substantial portions of the Software.
15
+#
16
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+import time, sys, signal, atexit
25
+import pyupm_mpu9150 as sensorObj
26
+
27
+# Instantiate an MPU60X0 on I2C bus 0
28
+sensor = sensorObj.MPU60X0()
29
+
30
+## Exit handlers ##
31
+# This function stops python from printing a stacktrace when you hit control-C
32
+def SIGINTHandler(signum, frame):
33
+	raise SystemExit
34
+
35
+# This function lets you run code on exit
36
+def exitHandler():
37
+	print "Exiting"
38
+	sys.exit(0)
39
+
40
+# Register exit handlers
41
+atexit.register(exitHandler)
42
+signal.signal(signal.SIGINT, SIGINTHandler)
43
+
44
+sensor.init()
45
+
46
+x = sensorObj.new_floatp()
47
+y = sensorObj.new_floatp()
48
+z = sensorObj.new_floatp()
49
+
50
+while (1):
51
+        sensor.update()
52
+        sensor.getAccelerometer(x, y, z)
53
+        print "Accelerometer: AX: ", sensorObj.floatp_value(x), 
54
+        print " AY: ", sensorObj.floatp_value(y),
55
+        print " AZ: ", sensorObj.floatp_value(z)
56
+
57
+        sensor.getGyroscope(x, y, z)
58
+        print "Gyroscope:     GX: ", sensorObj.floatp_value(x), 
59
+        print " GY: ", sensorObj.floatp_value(y),
60
+        print " GZ: ", sensorObj.floatp_value(z)
61
+
62
+        print "Temperature:  ", sensor.getTemperature()
63
+        print
64
+
65
+	time.sleep(.5)

+ 70
- 0
examples/python/mpu9150.py View File

@@ -0,0 +1,70 @@
1
+#!/usr/bin/python
2
+# Author: Jon Trulson <jtrulson@ics.com>
3
+# Copyright (c) 2015 Intel Corporation.
4
+#
5
+# Permission is hereby granted, free of charge, to any person obtaining
6
+# a copy of this software and associated documentation files (the
7
+# "Software"), to deal in the Software without restriction, including
8
+# without limitation the rights to use, copy, modify, merge, publish,
9
+# distribute, sublicense, and/or sell copies of the Software, and to
10
+# permit persons to whom the Software is furnished to do so, subject to
11
+# the following conditions:
12
+#
13
+# The above copyright notice and this permission notice shall be
14
+# included in all copies or substantial portions of the Software.
15
+#
16
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+import time, sys, signal, atexit
25
+import pyupm_mpu9150 as sensorObj
26
+
27
+# Instantiate an MPU9150 on I2C bus 0
28
+sensor = sensorObj.MPU9150()
29
+
30
+## Exit handlers ##
31
+# This function stops python from printing a stacktrace when you hit control-C
32
+def SIGINTHandler(signum, frame):
33
+	raise SystemExit
34
+
35
+# This function lets you run code on exit
36
+def exitHandler():
37
+	print "Exiting"
38
+	sys.exit(0)
39
+
40
+# Register exit handlers
41
+atexit.register(exitHandler)
42
+signal.signal(signal.SIGINT, SIGINTHandler)
43
+
44
+sensor.init()
45
+
46
+x = sensorObj.new_floatp()
47
+y = sensorObj.new_floatp()
48
+z = sensorObj.new_floatp()
49
+
50
+while (1):
51
+        sensor.update()
52
+        sensor.getAccelerometer(x, y, z)
53
+        print "Accelerometer: AX: ", sensorObj.floatp_value(x), 
54
+        print " AY: ", sensorObj.floatp_value(y),
55
+        print " AZ: ", sensorObj.floatp_value(z)
56
+
57
+        sensor.getGyroscope(x, y, z)
58
+        print "Gyroscope:     GX: ", sensorObj.floatp_value(x), 
59
+        print " GY: ", sensorObj.floatp_value(y),
60
+        print " GZ: ", sensorObj.floatp_value(z)
61
+
62
+        sensor.getMagnetometer(x, y, z)
63
+        print "Magnetometer:  MX: ", sensorObj.floatp_value(x), 
64
+        print " MY: ", sensorObj.floatp_value(y),
65
+        print " MZ: ", sensorObj.floatp_value(z)
66
+
67
+        print "Temperature:  ", sensor.getTemperature()
68
+        print
69
+
70
+	time.sleep(.5)

+ 3
- 3
src/mpu9150/CMakeLists.txt View File

@@ -1,5 +1,5 @@
1 1
 set (libname "mpu9150")
2
-set (libdescription "giro, acceleromter and magnometer sensor based on mpu9150")
3
-set (module_src ${libname}.cxx)
4
-set (module_h ${libname}.h)
2
+set (libdescription "gyro, acceleromter and magnometer sensor based on mpu9150")
3
+set (module_src ${libname}.cxx ak8975.cxx mpu60x0.cxx)
4
+set (module_h ${libname}.h ak8975.h mpu60x0.h)
5 5
 upm_module_init()

+ 232
- 0
src/mpu9150/ak8975.cxx View File

@@ -0,0 +1,232 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2015 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+#include <unistd.h>
26
+#include <iostream>
27
+#include <string>
28
+
29
+#include "ak8975.h"
30
+
31
+using namespace upm;
32
+using namespace std;
33
+
34
+
35
+AK8975::AK8975(int bus, uint8_t address):
36
+  m_i2c(bus)
37
+{
38
+  m_addr = address;
39
+  m_xCoeff = 0.0;
40
+  m_yCoeff = 0.0;
41
+  m_zCoeff = 0.0;
42
+
43
+  mraa_result_t rv;
44
+  if ( (rv = m_i2c.address(m_addr)) != MRAA_SUCCESS)
45
+    {
46
+      cerr << __FUNCTION__ << ": Could not initialize i2c address. " << endl;
47
+      mraa_result_print(rv);
48
+      return;
49
+    }
50
+}
51
+
52
+AK8975::~AK8975()
53
+{
54
+}
55
+
56
+bool AK8975::init()
57
+{
58
+  // we put the device in 'fuse mode', and then read the compensation
59
+  // coefficients and store them.
60
+
61
+  // first, set power down mode
62
+
63
+  if (!setMode(CNTL_PWRDWN))
64
+    {
65
+      cerr << __FUNCTION__ << ": Unable to set PWRDWN mode" << endl;
66
+      return false;
67
+    }
68
+
69
+  if (!setMode(CNTL_FUSE_ACCESS))
70
+    {
71
+      cerr << __FUNCTION__ << ": Unable to set FUSE mode" << endl;
72
+      return false;
73
+    }
74
+
75
+  // Read each byte and store
76
+  m_xCoeff = (float)m_i2c.readReg(REG_ASAX);
77
+  m_yCoeff = (float)m_i2c.readReg(REG_ASAY);
78
+  m_zCoeff = (float)m_i2c.readReg(REG_ASAZ);
79
+
80
+  // now, place back in power down mode
81
+  if (!setMode(CNTL_PWRDWN))
82
+    {
83
+      cerr << __FUNCTION__ << ": Unable to reset PWRDWN mode" << endl;
84
+      return false;
85
+    }
86
+
87
+  return true;
88
+}
89
+
90
+bool AK8975::setMode(CNTL_MODES_T mode)
91
+{
92
+  mraa_result_t rv;
93
+  if ((rv = m_i2c.writeReg(REG_CNTL, mode)) != MRAA_SUCCESS)
94
+    {
95
+      cerr << __FUNCTION__ << ": failed:" << endl;
96
+      mraa_result_print(rv);
97
+      return false;
98
+    } 
99
+
100
+  // sleep at least 100us for for mode transition to complete
101
+  usleep(150);
102
+
103
+  return true;
104
+}
105
+
106
+bool AK8975::isReady()
107
+{
108
+  uint8_t rdy = m_i2c.readReg(REG_ST1);
109
+  
110
+  if (rdy & ST1_DRDY)
111
+    return true;
112
+
113
+  return false;
114
+}
115
+
116
+bool AK8975::waitforDeviceReady()
117
+{
118
+  const int maxRetries = 20;
119
+
120
+  int retries = 0;
121
+
122
+  while (retries < maxRetries)
123
+    {
124
+      if (isReady())
125
+        return true;
126
+
127
+      usleep(5000);
128
+      retries++;
129
+    }
130
+  
131
+  cerr << __FUNCTION__ << ": timeout waiting for device to become ready"
132
+       << endl;
133
+
134
+  return false;
135
+}
136
+
137
+bool AK8975::update(bool selfTest)
138
+{
139
+  // this flag (selfTest) is used so that we can read values without
140
+  // specifically taking a measurement.  For example, selfTest will
141
+  // pass true to this method so that the test results aren't
142
+  // overwritten by a measurement.
143
+  if (!selfTest)
144
+    {
145
+      // First set measurement mode (take a measurement)
146
+      if (!setMode(CNTL_MEASURE))
147
+        {
148
+          cerr << __FUNCTION__ << ": Unable to set MEASURE mode" << endl;
149
+          return false;
150
+        }
151
+    }
152
+
153
+  if (!waitforDeviceReady())
154
+    return false;
155
+
156
+  // hope it worked.  Now read out the values and store them (uncompensated)
157
+  uint8_t data[6];
158
+  m_i2c.readBytesReg(REG_HXL, data, 6);
159
+
160
+  int16_t x, y, z;
161
+  x = ( (data[1] << 8) | data[0] );
162
+  y = ( (data[3] << 8) | data[2] );
163
+  z = ( (data[5] << 8) | data[4] );
164
+
165
+  m_xData = float(x);
166
+  m_yData = float(y);
167
+  m_zData = float(z);
168
+
169
+  return true;
170
+}
171
+
172
+bool AK8975::selfTest()
173
+{
174
+  mraa_result_t rv;
175
+
176
+  // set power down first
177
+  if (!setMode(CNTL_PWRDWN))
178
+    {
179
+      cerr << __FUNCTION__ << ": Unable to set PWRDWN mode" << endl;
180
+      return false;
181
+    }
182
+
183
+  // enable self test bit
184
+  if ((rv = m_i2c.writeReg(REG_ASTC, ASTC_SELF)) != MRAA_SUCCESS)
185
+    {
186
+      cerr << __FUNCTION__ << ": failed to enable self test:" << endl;
187
+      mraa_result_print(rv);
188
+      return false;
189
+    } 
190
+  
191
+  // now set self test mode
192
+  if (!setMode(CNTL_SELFTEST))
193
+    {
194
+      cerr << __FUNCTION__ << ": Unable to set SELFTEST mode" << endl;
195
+      return false;
196
+    }
197
+  
198
+  // now update current data (without enabling a measurement)
199
+  update(true);
200
+  
201
+  // Now, reset self test register
202
+  uint8_t reg = m_i2c.readReg(REG_ASTC);
203
+  reg &= ~ASTC_SELF;
204
+  if ((rv = m_i2c.writeReg(REG_ASTC, reg)) != MRAA_SUCCESS)
205
+    {
206
+      cerr << __FUNCTION__ << ": failed to disable self test:" << endl;
207
+      mraa_result_print(rv);
208
+      return false;
209
+    } 
210
+
211
+  // after self-test measurement, device transitions to power down mode
212
+  return true;
213
+}
214
+
215
+float AK8975::adjustValue(float value, float adj)
216
+{
217
+  // apply the proper compensation to value.  This equation is taken
218
+  // from the AK8975 datasheet, section 8.3.11
219
+
220
+  return ( value * ((((adj - 128.0) * 0.5) / 128.0) + 1.0) );
221
+} 
222
+
223
+void AK8975::getMagnetometer(float *x, float *y, float *z)
224
+{
225
+  if (x)
226
+    *x = adjustValue(m_xData, m_xCoeff);
227
+  if (y)
228
+    *y = adjustValue(m_yData, m_yCoeff);
229
+  if (z)
230
+    *z = adjustValue(m_zData, m_zCoeff);
231
+}
232
+

+ 233
- 0
src/mpu9150/ak8975.h View File

@@ -0,0 +1,233 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2015 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+#pragma once
25
+
26
+#include <string>
27
+#include <mraa/i2c.hpp>
28
+
29
+#define AK8975_I2C_BUS 0
30
+#define AK8975_DEFAULT_I2C_ADDR 0x0c
31
+
32
+namespace upm {
33
+  
34
+  /**
35
+   * @library mpu9150
36
+   * @sensor ak8975
37
+   * @comname AK8975 3-axis Magnetometer
38
+   * @altname AK9875
39
+   * @type compass
40
+   * @man grove
41
+   * @con i2c
42
+   *
43
+   * @brief API for the AK8975 magnetometer
44
+   *
45
+   * This is a 3-axis magnetometer, which can be used alone, or
46
+   * coupled with another device (such as the mcu9150 9-axis motion
47
+   * sensor). 
48
+   *
49
+   * @snippet ak8975.cxx Interesting
50
+   */
51
+  class AK8975 {
52
+  public:
53
+
54
+    /**
55
+     * AK8975 registers
56
+     */
57
+    typedef enum {
58
+      REG_WIA                   = 0x00, // device id
59
+
60
+      REG_INFO                  = 0x01, // undocumented (AK proprietary data)
61
+
62
+      REG_ST1                   = 0x02, // status 1
63
+
64
+      REG_HXL                   = 0x03, // magnetometer data, X axis low byte
65
+      REG_HXH                   = 0x04, // magnetometer data, X axis high byte
66
+      REG_HYL                   = 0x05,
67
+      REG_HYH                   = 0x06,
68
+      REG_HZL                   = 0x07,
69
+      REG_HZH                   = 0x08,
70
+
71
+      REG_ST2                   = 0x09, // status 2
72
+
73
+      REG_CNTL                  = 0x0a, // control
74
+
75
+      // REG_RSV 0x0b reserved
76
+
77
+      REG_ASTC                  = 0x0c, // self test (internal mag field)
78
+
79
+      // REG_TS1, REG_TS2 0x0d, 0x0e reserved/factory test
80
+
81
+      // REG_I2CDIS 0x0f, I2C disable.  Not a good idea to use or support.
82
+      //  write a 0x1b to disable i2c.  This requires a power cycle to undo.
83
+
84
+      // These registers hold factory calibrated co-efficients needed to
85
+      // properly compensate for production variations.  They can only be
86
+      // read when device is in fuse mode.  They are used to adjust the
87
+      // measured mag field values.
88
+      REG_ASAX                  = 0x10, // X calibration
89
+      REG_ASAY                  = 0x11,
90
+      REG_ASAZ                  = 0x12
91
+    } AK8975_REG_T;
92
+    
93
+    /**
94
+     * ST1 bits
95
+     */
96
+    typedef enum {
97
+      ST1_DRDY                  = 0x01 // data ready bit
98
+    } ST1_BITS_T;
99
+    
100
+    /**
101
+     * ST2 bits
102
+     */
103
+    typedef enum {
104
+      ST2_DERR                  = 0x04, // data error
105
+      ST2_HOFL                  = 0x08  // measurement overflow
106
+    } ST2_BITS_T;
107
+    
108
+    /**
109
+     * CNTL register, operating mode values
110
+     */
111
+    typedef enum {
112
+      CNTL_PWRDWN               = 0x00, // power down
113
+      CNTL_MEASURE              = 0x01, // single measurement
114
+      CNTL_SELFTEST             = 0x08,
115
+      CNTL_FUSE_ACCESS          = 0x0f  // access fuse (coeff) registers
116
+    } CNTL_MODES_T;
117
+    
118
+    /**
119
+     * ASTC (self test control) bits
120
+     */
121
+    typedef enum {
122
+      ASTC_SELF                 = 0x40 // enable self test
123
+    } ASTC_BITS_T;
124
+
125
+    /**
126
+     * ak8975 constructor
127
+     *
128
+     * @param bus i2c bus to use
129
+     * @param address the address for this device
130
+     */
131
+    AK8975(int bus=AK8975_I2C_BUS, uint8_t address=AK8975_DEFAULT_I2C_ADDR);
132
+
133
+    /**
134
+     * AK8975 Destructor
135
+     */
136
+    ~AK8975();
137
+    
138
+    /**
139
+     * set up initial values and start operation
140
+     *
141
+     * @param dsr the data sampling rate: one of the DSR_BITS_T values
142
+     * @return true if successful
143
+     */
144
+    bool init();
145
+
146
+    /**
147
+     * put the chip into a specific mode
148
+     *
149
+     * @param mode one of the CNTL_MODES_T values
150
+     * @return true if successful
151
+     */
152
+    bool setMode(CNTL_MODES_T mode);
153
+
154
+    /**
155
+     * check to see if the ST1_DRDY bit is set, indicating the device
156
+     * can accept commands
157
+     *
158
+     * @return true if device is ready, false otherwise
159
+     */
160
+    bool isReady();
161
+
162
+    /**
163
+     * check to see if device is ready and sleep/retry if not.
164
+     * Returns once device indicates it's ready.
165
+     *
166
+     * @return true if device is ready, false if retries exhausted
167
+     */
168
+    bool waitforDeviceReady();
169
+
170
+    /**
171
+     * take a measurement
172
+     *
173
+     * @param selfTest true if we are running a self test, false
174
+     * (default) otherwise.
175
+     * @return true if successful, false otherwise
176
+     */
177
+    bool update(bool selfTest=false);
178
+
179
+    /**
180
+     * do a self test sequence.  When self test is executed, the
181
+     * device activates internal calibrated magnets, and measures
182
+     * them, updating the measurement registers.  Once complete, the
183
+     * data can be read as usual (getMagnetometer()) and the returned
184
+     * values compared against the following limits to determine
185
+     * correctness:
186
+     *
187
+     * -100 < X < +100; -100 < Y < +100; -1000 < Z < -300
188
+     *
189
+     * @return true if successful, false otherwise
190
+     */
191
+    bool selfTest();
192
+
193
+    /**
194
+     * return the compensated values for the x, y, and z axes.  The
195
+     * unit of measurement is in micro-teslas (uT).
196
+     *
197
+     * @param x pointer to returned X axis value
198
+     * @param y pointer to returned Y axis value
199
+     * @param z pointer to returned Z axis value
200
+     */
201
+    void getMagnetometer(float *x, float *y, float *z);
202
+
203
+
204
+  protected:
205
+    /**
206
+     * compute a compensated magnetometer axis value, based on the raw
207
+     * axis value and a per-device, per-axis adjustment coefficient
208
+     * that was read and stored at init() time.
209
+     *
210
+     * @param value the raw axis value to compensate
211
+     * @param adj the adjustment coefficient 
212
+     * @return true if successful
213
+     */
214
+    float adjustValue(float value, float adj);
215
+
216
+    // compensation coefficients (factory set) for this device
217
+    float m_xCoeff;
218
+    float m_yCoeff;
219
+    float m_zCoeff;
220
+
221
+    // uncompensated magnetometer readings
222
+    float m_xData;
223
+    float m_yData;
224
+    float m_zData;
225
+
226
+  private:
227
+    mraa::I2c m_i2c;
228
+    uint8_t m_addr;
229
+
230
+  };
231
+}
232
+
233
+

+ 17
- 0
src/mpu9150/jsupm_mpu9150.i View File

@@ -1,8 +1,25 @@
1 1
 %module jsupm_mpu9150
2 2
 %include "../upm.i"
3
+%include "cpointer.i"
4
+
5
+%pointer_functions(float, floatp);
3 6
 
4 7
 %{
5 8
     #include "mpu9150.h"
6 9
 %}
7 10
 
11
+%include "ak8975.h"
12
+%{
13
+    #include "ak8975.h"
14
+%}
15
+
16
+%include "mpu60x0.h"
17
+%{
18
+    #include "mpu60x0.h"
19
+%}
20
+
8 21
 %include "mpu9150.h"
22
+%{
23
+    #include "mpu9150.h"
24
+%}
25
+

+ 405
- 0
src/mpu9150/mpu60x0.cxx View File

@@ -0,0 +1,405 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2015 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+#include <unistd.h>
26
+#include <iostream>
27
+#include <string.h>
28
+
29
+#include "mpu60x0.h"
30
+
31
+using namespace upm;
32
+using namespace std;
33
+
34
+
35
+MPU60X0::MPU60X0(int bus, uint8_t address) :
36
+  m_i2c(bus), m_gpioIRQ(0)
37
+{
38
+  m_addr = address;
39
+
40
+  m_accelX = 0.0;
41
+  m_accelY = 0.0;
42
+  m_accelZ = 0.0;
43
+  
44
+  m_gyroX = 0.0;
45
+  m_gyroY = 0.0;
46
+  m_gyroZ = 0.0;
47
+  
48
+  m_temp = 0.0;
49
+
50
+  m_accelScale = 1.0;
51
+  m_gyroScale = 1.0;
52
+
53
+  mraa_result_t rv;
54
+  if ( (rv = m_i2c.address(m_addr)) != MRAA_SUCCESS)
55
+    {
56
+      cerr << __FUNCTION__ << ": Could not initialize i2c address. " << endl;
57
+      mraa_result_print(rv);
58
+      return;
59
+    }
60
+}
61
+
62
+MPU60X0::~MPU60X0()
63
+{
64
+  uninstallISR();
65
+}
66
+
67
+bool MPU60X0::init()
68
+{
69
+  // first, take the device out of sleep mode
70
+  if (!setSleep(false))
71
+    {
72
+      cerr << __FUNCTION__ << ": Unable to wake up device" << endl;
73
+      return false;
74
+    }
75
+
76
+  // set the clock source to use the gyroscope PLL rather than the
77
+  // internal clock for stability
78
+  if (!setClockSource(PLL_XG))
79
+    {
80
+      cerr << __FUNCTION__ << ": Unable to set clock source" << endl;
81
+      return false;
82
+    }
83
+
84
+  usleep(5000);
85
+
86
+  // enable temperature measurement (default on power up, but let's be sure)
87
+  enableTemperatureSensor(true);
88
+
89
+  // set the gyro and accel scale bits to reasonable values
90
+  setGyroscopeScale(FS_500);
91
+  setAccelerometerScale(AFS_2);
92
+
93
+  // enable the DLPF
94
+  setDigitalLowPassFilter(DLPF_94_98);
95
+
96
+  // let things stabilize...
97
+  usleep(100000);
98
+
99
+  return true;
100
+}
101
+
102
+
103
+void MPU60X0::update()
104
+{
105
+  // read all of the sensor registers - accel, gyro, and temp
106
+  uint8_t buffer[14];
107
+
108
+  memset(buffer, 0, 14);
109
+  readRegs(REG_ACCEL_XOUT_H, buffer, 14);
110
+
111
+  int16_t ax, ay, az;
112
+  int16_t temp;
113
+  int16_t gx, gy, gz;
114
+
115
+  ax =  ( (buffer[0] << 8) | buffer[1] );
116
+  ay =  ( (buffer[2] << 8) | buffer[3] );
117
+  az =  ( (buffer[4] << 8) | buffer[5] );
118
+
119
+  temp = ( (buffer[6] << 8) | buffer[7] );
120
+
121
+  gx =  ( (buffer[8] << 8) | buffer[9] );
122
+  gy =  ( (buffer[10] << 8) | buffer[11] );
123
+  gz =  ( (buffer[12] << 8) | buffer[13] );
124
+
125
+  // now stash them
126
+  m_accelX = float(ax);
127
+  m_accelY = float(ay);
128
+  m_accelZ = float(az);
129
+
130
+  m_temp = float(temp);
131
+
132
+  m_gyroX = float(gx);
133
+  m_gyroY = float(gy);
134
+  m_gyroZ = float(gz);
135
+}
136
+
137
+uint8_t MPU60X0::readReg(uint8_t reg)
138
+{
139
+  return m_i2c.readReg(reg);
140
+}
141
+
142
+void MPU60X0::readRegs(uint8_t reg, uint8_t *buf, int len)
143
+{
144
+  m_i2c.readBytesReg(reg, buf, len);
145
+}
146
+
147
+bool MPU60X0::writeReg(uint8_t reg, uint8_t val)
148
+{
149
+  mraa_result_t rv;
150
+  if ((rv = m_i2c.writeReg(reg, val)) != MRAA_SUCCESS)
151
+    {
152
+      cerr << __FUNCTION__ << ": failed:" << endl;
153
+      mraa_result_print(rv);
154
+      return false;
155
+    } 
156
+  
157
+  return true;
158
+}
159
+
160
+bool MPU60X0::setSleep(bool enable)
161
+{
162
+  uint8_t reg = readReg(REG_PWR_MGMT_1);
163
+
164
+  if (enable)
165
+    reg |= PWR_SLEEP;
166
+  else
167
+    reg &= ~PWR_SLEEP;
168
+
169
+  return writeReg(REG_PWR_MGMT_1, reg);
170
+}
171
+
172
+bool MPU60X0::setClockSource(CLKSEL_T clk)
173
+{
174
+  uint8_t reg = readReg(REG_PWR_MGMT_1);
175
+
176
+  reg &= ~(_CLKSEL_MASK << _CLKSEL_SHIFT);
177
+
178
+  reg |= (clk << _CLKSEL_SHIFT);
179
+
180
+  return writeReg(REG_PWR_MGMT_1, reg);
181
+}
182
+
183
+bool MPU60X0::setGyroscopeScale(FS_SEL_T scale)
184
+{
185
+  uint8_t reg = readReg(REG_GYRO_CONFIG);
186
+
187
+  reg &= ~(_FS_SEL_MASK << _FS_SEL_SHIFT);
188
+
189
+  reg |= (scale << _FS_SEL_SHIFT);
190
+
191
+  if (!writeReg(REG_GYRO_CONFIG, reg))
192
+    {
193
+      return false;
194
+    }
195
+
196
+  // store scaling factor
197
+
198
+  switch (scale)
199
+    {
200
+    case FS_250:
201
+      m_gyroScale = 131.0;
202
+      break;
203
+
204
+    case FS_500:
205
+      m_gyroScale = 65.5;
206
+      break;
207
+
208
+    case FS_1000:
209
+      m_gyroScale = 32.8;
210
+      break;
211
+
212
+    case FS_2000:
213
+      m_gyroScale = 16.4;
214
+      break;
215
+
216
+    default: // should never occur, but...
217
+      m_gyroScale = 1.0;        // set a safe, though incorrect value
218
+      cerr << __FUNCTION__ << ": internal error, unsupported scale" << endl;
219
+      break;
220
+    }
221
+
222
+  return true;
223
+}
224
+
225
+bool MPU60X0::setAccelerometerScale(AFS_SEL_T scale)
226
+{
227
+  uint8_t reg = readReg(REG_ACCEL_CONFIG);
228
+
229
+  reg &= ~(_AFS_SEL_MASK << _AFS_SEL_SHIFT);
230
+
231
+  reg |= (scale << _AFS_SEL_SHIFT);
232
+
233
+  if (!writeReg(REG_ACCEL_CONFIG, reg))
234
+    {
235
+      return false;
236
+    }
237
+
238
+  // store scaling factor
239
+  
240
+  switch (scale)
241
+    {
242
+    case AFS_2:
243
+      m_accelScale = 16384.0;
244
+      break;
245
+
246
+    case AFS_4:
247
+      m_accelScale = 8192.0;
248
+      break;
249
+
250
+    case AFS_8:
251
+      m_accelScale = 4096.0;
252
+      break;
253
+
254
+    case AFS_16:
255
+      m_accelScale = 2048.0;
256
+      break;
257
+
258
+    default: // should never occur, but...
259
+      m_accelScale = 1.0;        // set a safe, though incorrect value
260
+      cerr << __FUNCTION__ << ": internal error, unsupported scale" << endl;
261
+      break;
262
+    }
263
+
264
+  return true;
265
+}
266
+
267
+bool MPU60X0::setDigitalLowPassFilter(DLPF_CFG_T dlp)
268
+{
269
+  uint8_t reg = readReg(REG_CONFIG);
270
+
271
+  reg &= ~(_CONFIG_DLPF_MASK << _CONFIG_DLPF_SHIFT);
272
+
273
+  reg |= (dlp << _CONFIG_DLPF_SHIFT);
274
+
275
+  return writeReg(REG_CONFIG, reg);
276
+}
277
+
278
+bool MPU60X0::setSampleRateDivider(uint8_t div)
279
+{
280
+  return writeReg(REG_SMPLRT_DIV, div);
281
+}
282
+
283
+uint8_t MPU60X0::getSampleRateDivider()
284
+{
285
+  return readReg(REG_SMPLRT_DIV);
286
+}
287
+
288
+void MPU60X0::getAccelerometer(float *x, float *y, float *z)
289
+{
290
+  if (x)
291
+    *x = m_accelX / m_accelScale;
292
+
293
+  if (y)
294
+    *y = m_accelY / m_accelScale;
295
+
296
+  if (z)
297
+    *z = m_accelZ / m_accelScale;
298
+}
299
+
300
+void MPU60X0::getGyroscope(float *x, float *y, float *z)
301
+{
302
+  if (x)
303
+    *x = m_gyroX / m_gyroScale;
304
+
305
+  if (y)
306
+    *y = m_gyroY / m_gyroScale;
307
+
308
+  if (z)
309
+    *z = m_gyroZ / m_gyroScale;
310
+}
311
+
312
+float MPU60X0::getTemperature()
313
+{
314
+  // this equation is taken from the datasheet
315
+  return (m_temp / 340.0) + 36.53;
316
+}
317
+
318
+bool MPU60X0::enableTemperatureSensor(bool enable)
319
+{
320
+  uint8_t reg = readReg(REG_PWR_MGMT_1);
321
+
322
+  if (enable)
323
+    reg &= ~TEMP_DIS;
324
+  else
325
+    reg |= TEMP_DIS;
326
+
327
+  return writeReg(REG_PWR_MGMT_1, reg);
328
+}
329
+
330
+bool MPU60X0::setExternalSync(EXT_SYNC_SET_T val)
331
+{
332
+  uint8_t reg = readReg(REG_CONFIG);
333
+
334
+  reg &= ~(_CONFIG_EXT_SYNC_SET_MASK << _CONFIG_EXT_SYNC_SET_SHIFT);
335
+
336
+  reg |= (val << _CONFIG_EXT_SYNC_SET_SHIFT);
337
+
338
+  return writeReg(REG_CONFIG, reg);
339
+}
340
+
341
+bool MPU60X0::enableI2CBypass(bool enable)
342
+{
343
+  uint8_t reg = readReg(REG_INT_PIN_CFG);
344
+
345
+  if (enable)
346
+    reg |= I2C_BYPASS_ENABLE;
347
+  else
348
+    reg &= ~I2C_BYPASS_ENABLE;
349
+
350
+  return writeReg(REG_INT_PIN_CFG, reg);
351
+}
352
+
353
+bool MPU60X0::setMotionDetectionThreshold(uint8_t thr)
354
+{
355
+  return writeReg(REG_MOT_THR, thr);
356
+}
357
+
358
+uint8_t MPU60X0::getInterruptStatus()
359
+{
360
+  return readReg(REG_INT_STATUS);
361
+}
362
+
363
+bool MPU60X0::setInterruptEnables(uint8_t enables)
364
+{
365
+  return writeReg(REG_INT_ENABLE, enables);
366
+}
367
+
368
+uint8_t MPU60X0::getInterruptEnables()
369
+{
370
+  return readReg(REG_INT_ENABLE);
371
+}
372
+
373
+bool MPU60X0::setInterruptPinConfig(uint8_t cfg)
374
+{
375
+  return writeReg(REG_INT_PIN_CFG, cfg);
376
+}
377
+
378
+uint8_t MPU60X0::getInterruptPinConfig()
379
+{
380
+  return readReg(REG_INT_PIN_CFG);
381
+}
382
+
383
+void MPU60X0::installISR(int gpio, mraa::Edge level, 
384
+                         void (*isr)(void *), void *arg)
385
+{
386
+  // delete any existing ISR and GPIO context
387
+  uninstallISR();
388
+
389
+  // greate gpio context
390
+  m_gpioIRQ = new mraa::Gpio(gpio);
391
+
392
+  m_gpioIRQ->dir(mraa::DIR_IN);
393
+  m_gpioIRQ->isr(level, isr, arg);
394
+}
395
+
396
+void MPU60X0::uninstallISR()
397
+{
398
+  if (m_gpioIRQ)
399
+    {
400
+      m_gpioIRQ->isrExit();
401
+      delete m_gpioIRQ;
402
+      
403
+      m_gpioIRQ = 0;
404
+    }
405
+}

+ 934
- 0
src/mpu9150/mpu60x0.h View File

@@ -0,0 +1,934 @@
1
+/*
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2015 Intel Corporation.
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files (the
7
+ * "Software"), to deal in the Software without restriction, including
8
+ * without limitation the rights to use, copy, modify, merge, publish,
9
+ * distribute, sublicense, and/or sell copies of the Software, and to
10
+ * permit persons to whom the Software is furnished to do so, subject to
11
+ * the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+#pragma once
25
+
26
+#include <string>
27
+#include <mraa/i2c.hpp>
28
+#include <mraa/gpio.hpp>
29
+
30
+#define MPU60X0_I2C_BUS 0
31
+#define MPU60X0_DEFAULT_I2C_ADDR 0x68
32
+
33
+namespace upm {
34
+  
35
+  /**
36
+   * @library mpu9150
37
+   * @sensor mpu60x0
38
+   * @comname MPU60X0 3-axis Gyroscope and 3-axis Accelerometer
39
+   * @type accelerometer compass
40
+   * @man seeed
41
+   * @con i2c gpio
42
+   *
43
+   * @brief API for the MPU60X0 3-axis Gyroscope and 3-axis Accelerometer
44
+   *
45
+   * The MPU60X0 devices provide the world’s first integrated 6-axis
46
+   * motion processor solution that eliminates the package-level
47
+   * gyroscope and accelerometer cross-axis misalignment associated
48
+   * with discrete solutions. The devices combine a 3-axis gyroscope
49
+   * and a 3-axis accelerometer on the same silicon die.
50
+   *
51
+   * While not all of the functionality of this device is supported
52
+   * initially, methods and register definitions are provided that
53
+   * should allow an end user to implement whatever features are
54
+   * required.
55
+   *
56
+   * @snippet mpu60x0.cxx Interesting
57
+   */
58
+  class MPU60X0 {
59
+  public:
60
+
61
+    // NOTE: These enums were composed from both the mpu6050 and
62
+    // mpu9150 register maps, since this driver was written using an
63
+    // mpu9150, but we'd like this module to be usable with a
64
+    // standalone mpu60x0.
65
+    //
66
+    // Registers and bitfields marked with an '*' in their
67
+    // comment indicate registers or bit fields present in the mpu9150
68
+    // register map, but not in the original mpu6050 register map.  If
69
+    // using this module on a standalone mpu6050, you should avoid
70
+    // using those registers or bitfields marked with an *.
71
+
72
+    /**
73
+     * MPU60X0 registers
74
+     */
75
+    typedef enum {
76
+      REG_SELF_TEST_X           = 0x0d,
77
+      REG_SELF_TEST_Y           = 0x0e,
78
+      REG_SELF_TEST_Z           = 0x0f,
79
+      REG_SELF_TEST_A           = 0x10,
80
+
81
+      REG_SMPLRT_DIV            = 0x19, // sample rate divider
82
+
83
+      REG_CONFIG                = 0x1a,
84
+      REG_GYRO_CONFIG           = 0x1b,
85
+      REG_ACCEL_CONFIG          = 0x1c,
86
+
87
+      REG_FF_THR                = 0x1d, // *freefall threshold
88
+      REG_FF_DUR                = 0x1e, // *freefall duration
89
+
90
+      REG_MOT_THR               = 0x1f, // motion threshold
91
+      REG_MOT_DUR               = 0x20, // *motion duration
92
+
93
+      REG_ZRMOT_THR             = 0x21, // *zero motion threshhold
94
+      REG_ZRMOT_DUR             = 0x22, // *zero motion duration
95
+
96
+      REG_FIFO_EN               = 0x23,
97
+
98
+      REG_I2C_MST_CTRL          = 0x24, // I2C master control
99
+
100
+      REG_I2C_SLV0_ADDR         = 0x25, // I2C slave 0
101
+      REG_I2C_SLV0_REG          = 0x26,
102
+      REG_I2C_SLV0_CTRL         = 0x27,
103
+
104
+      REG_I2C_SLV1_ADDR         = 0x28, // I2C slave 1
105
+      REG_I2C_SLV1_REG          = 0x29,
106
+      REG_I2C_SLV1_CTRL         = 0x2a,
107
+
108
+      REG_I2C_SLV2_ADDR         = 0x2b, // I2C slave 2
109
+      REG_I2C_SLV2_REG          = 0x2c,
110
+      REG_I2C_SLV2_CTRL         = 0x2d,
111
+
112
+      REG_I2C_SLV3_ADDR         = 0x2e, // I2C slave 3
113
+      REG_I2C_SLV3_REG          = 0x2f,
114
+      REG_I2C_SLV3_CTRL         = 0x30,
115
+
116
+      REG_I2C_SLV4_ADDR         = 0x31, // I2C slave 4
117
+      REG_I2C_SLV4_REG          = 0x32,
118
+      REG_I2C_SLV4_DO           = 0x33,
119
+      REG_I2C_SLV4_CTRL         = 0x34,
120
+      REG_I2C_SLV4_DI           = 0x35,
121
+
122
+      REG_I2C_MST_STATUS        = 0x36, // I2C master status
123
+
124
+      REG_INT_PIN_CFG           = 0x37, // interrupt pin config/i2c bypass
125
+      REG_INT_ENABLE            = 0x38,
126
+
127
+      // 0x39 reserved
128
+
129
+      REG_INT_STATUS            = 0x3a, // interrupt status
130
+
131
+      REG_ACCEL_XOUT_H          = 0x3b, // accelerometer outputs
132
+      REG_ACCEL_XOUT_L          = 0x3c,
133
+
134
+      REG_ACCEL_YOUT_H          = 0x3d,
135
+      REG_ACCEL_YOUT_L          = 0x3e,
136
+
137
+      REG_ACCEL_ZOUT_H          = 0x3f,
138
+      REG_ACCEL_ZOUT_L          = 0x40,
139
+
140
+      REG_TEMP_OUT_H            = 0x41, // temperature output
141
+      REG_TEMP_OUT_L            = 0x42,
142
+
143
+      REG_GYRO_XOUT_H           = 0x43, // gyro outputs
144
+      REG_GYRO_XOUT_L           = 0x44,
145
+
146
+      REG_GYRO_YOUT_H           = 0x45,
147
+      REG_GYRO_YOUT_L           = 0x46,
148
+
149
+      REG_GYRO_ZOUT_H           = 0x47,
150
+      REG_GYRO_ZOUT_L           = 0x48,
151
+
152
+      REG_EXT_SENS_DATA_00      = 0x49, // external sensor data
153
+      REG_EXT_SENS_DATA_01      = 0x4a,
154
+      REG_EXT_SENS_DATA_02      = 0x4b,
155
+      REG_EXT_SENS_DATA_03      = 0x4c,
156
+      REG_EXT_SENS_DATA_04      = 0x4d,
157
+      REG_EXT_SENS_DATA_05      = 0x4e,
158
+      REG_EXT_SENS_DATA_06      = 0x4f,
159
+      REG_EXT_SENS_DATA_07      = 0x50,
160
+      REG_EXT_SENS_DATA_08      = 0x51,
161
+      REG_EXT_SENS_DATA_09      = 0x52,
162
+      REG_EXT_SENS_DATA_10      = 0x53,
163
+      REG_EXT_SENS_DATA_11      = 0x54,
164
+      REG_EXT_SENS_DATA_12      = 0x55,
165
+      REG_EXT_SENS_DATA_13      = 0x56,
166
+      REG_EXT_SENS_DATA_14      = 0x57,
167
+      REG_EXT_SENS_DATA_15      = 0x58,
168
+      REG_EXT_SENS_DATA_16      = 0x59,
169
+      REG_EXT_SENS_DATA_17      = 0x5a,
170
+      REG_EXT_SENS_DATA_18      = 0x5b,
171
+      REG_EXT_SENS_DATA_19      = 0x5c,
172
+      REG_EXT_SENS_DATA_20      = 0x5d,
173
+      REG_EXT_SENS_DATA_21      = 0x5e,
174
+      REG_EXT_SENS_DATA_22      = 0x5f,
175
+      REG_EXT_SENS_DATA_23      = 0x60,
176
+
177
+      REG_MOT_DETECT_STATUS     = 0x61, // *
178
+
179
+      // 0x62 reserved
180
+
181
+      REG_I2C_SLV0_DO           = 0x63, // I2C slave data outs
182
+      REG_I2C_SLV1_DO           = 0x64,
183
+      REG_I2C_SLV2_DO           = 0x65,
184
+      REG_I2C_SLV3_DO           = 0x66,
185
+
186
+      REG_I2C_MST_DELAY_CTRL    = 0x67,
187
+
188
+      REG_SIGNAL_PATH_RESET     = 0x68, // signal path resets
189
+
190
+      REG_MOT_DETECT_CTRL       = 0x69,
191
+
192
+      REG_USER_CTRL             = 0x6a,
193
+
194
+      REG_PWR_MGMT_1            = 0x6b, // power management
195
+      REG_PWR_MGMT_2            = 0x6c,
196
+
197
+      // 0x6d-0x71 reserved
198
+
199
+      REG_FIFO_COUNTH           = 0x72,
200
+      REG_FIFO_COUNTL           = 0x73,
201
+
202
+      REG_FIFO_R_W              = 0x74,
203
+
204
+      REG_WHO_AM_I              = 0x75
205
+    } MPU60X0_REG_T;
206
+    
207
+    /**
208
+     * CONFIG bits
209
+     */
210
+    typedef enum {
211
+      CONFIG_DLPF_CFG0            = 0x01, // digital low-pass filter config
212
+      CONFIG_DLPF_CFG1            = 0x02,
213
+      CONFIG_DLPF_CFG2            = 0x04,
214
+      _CONFIG_DLPF_SHIFT          = 0,
215
+      _CONFIG_DLPF_MASK           = 7,
216
+
217
+      CONFIG_EXT_SYNC_SET0        = 0x08, // FSYNC pin config
218
+      CONFIG_EXT_SYNC_SET1        = 0x10,
219
+      CONFIG_EXT_SYNC_SET2        = 0x20,
220
+      _CONFIG_EXT_SYNC_SET_SHIFT  = 3,
221
+      _CONFIG_EXT_SYNC_SET_MASK   = 7
222
+    } CONFIG_BITS_T;
223
+
224
+    /**
225
+     * CONFIG DLPF_CFG values
226
+     */
227
+    typedef enum {
228
+      DLPF_260_256                = 0, // accel/gyro bandwidth (Hz)
229
+      DLPF_184_188                = 1,
230
+      DLPF_94_98                  = 2,
231
+      DLPF_44_42                  = 3,
232
+      DLPF_21_20                  = 4,
233
+      DLPF_10_10                  = 5,
234
+      DLPF_5_5                    = 6,
235
+      DLPF_RESERVED               = 7
236
+    } DLPF_CFG_T;
237
+
238
+    /**
239
+     * CONFIG EXT_SYNC_SET values
240
+     */
241
+    typedef enum {
242
+      EXT_SYNC_DISABLED           = 0,
243
+      EXT_SYNC_TEMP_OUT           = 1,
244
+      EXT_SYNC_GYRO_XOUT          = 2,
245
+      EXT_SYNC_GYRO_YOUT          = 3,
246
+      EXT_SYNC_GYRO_ZOUT          = 4,
247
+      EXT_SYNC_ACCEL_XOUT         = 5,
248
+      EXT_SYNC_ACCEL_YOUT         = 6,
249
+      EXT_SYNC_ACCEL_ZOUT         = 7
250
+    } EXT_SYNC_SET_T;
251
+
252
+    /**
253
+     * GYRO_CONFIG bits
254
+     */
255
+    typedef enum {
256
+      // 0x01-0x04 reserved
257
+      FS_SEL0                          = 0x08, // gyro full scale range
258
+      FS_SEL1                          = 0x10,
259
+      _FS_SEL_SHIFT                    = 3,
260
+      _FS_SEL_MASK                     = 3,
261
+
262
+      ZG_ST                            = 0x20, // gyro self test bits
263
+      YG_ST                            = 0x40,
264
+      XG_ST                            = 0x80
265
+    } GRYO_CONFIG_BITS_T;
266
+
267
+    /**
268
+     * GYRO FS_SEL values
269
+     */
270
+    typedef enum {
271
+      FS_250                           = 0, // 250 deg/s, 131 LSB deg/s
272
+      FS_500                           = 1, // 500 deg/s, 65.5 LSB deg/s
273
+      FS_1000                          = 2, // 1000 deg/s, 32.8 LSB deg/s
274
+      FS_2000                          = 3  // 2000 deg/s, 16.4 LSB deg/s
275
+    } FS_SEL_T;
276
+
277
+    /**
278
+     * ACCEL_CONFIG bits
279
+     */
280
+    typedef enum {
281
+      // 0x01-0x04 reserved
282
+      AFS_SEL0                         = 0x08, // accel full scale range
283
+      AFS_SEL1                         = 0x10,
284
+      _AFS_SEL_SHIFT                   = 3,
285
+      _AFS_SEL_MASK                    = 3,
286
+
287
+      ZA_ST                            = 0x20, // gyro self test bits
288
+      YA_ST                            = 0x40,
289
+      XA_ST                            = 0x80
290
+    } ACCEL_CONFIG_BITS_T;
291
+
292
+    /**
293
+     * ACCEL AFS_SEL (full scaling) values
294
+     */
295
+    typedef enum {
296
+      AFS_2                            = 0, // 2g, 16384 LSB/g
297
+      AFS_4                            = 1, // 4g, 8192 LSB/g
298
+      AFS_8                            = 2, // 8g, 4096 LSB/g
299
+      AFS_16                           = 3  // 16g, 2048 LSB/g
300
+    } AFS_SEL_T;
301
+
302
+    /**
303
+     * REG_FIFO_EN bits
304
+     */
305
+    typedef enum {
306
+      SLV0_FIFO_EN                     = 0x01,
307
+      SLV1_FIFO_EN                     = 0x02,
308
+      SLV2_FIFO_EN                     = 0x04,
309
+
310
+      ACCEL_FIFO_EN                    = 0x08,
311
+
312
+      ZG_FIFO_EN                       = 0x10,
313
+      YG_FIFO_EN                       = 0x20,
314
+      XG_FIFO_EN                       = 0x40,
315
+
316
+      TEMP_FIFO_EN                     = 0x80
317
+    } FIFO_EN_BITS_T;
318
+
319
+    /**
320
+     * REG_I2C_MST_CTRL bits
321
+     */
322
+    typedef enum {
323
+      I2C_MST_CLK0                     = 0x01,
324
+      I2C_MST_CLK1                     = 0x02,
325
+      I2C_MST_CLK2                     = 0x04,
326
+      I2C_MST_CLK3                     = 0x08,
327
+      _I2C_MST_CLK_SHIFT               = 0,
328
+      _I2C_MST_CLK_MASK                = 15,
329
+
330
+      I2C_MST_P_NSR                    = 0x10,
331
+
332
+      SLV_3_FIFO_EN                    = 0x20,
333
+
334
+      WAIT_FOR_ES                      = 0x40,
335
+
336
+      MULT_MST_EN                      = 0x80
337
+    } I2C_MST_CTRL_BITS_T;
338
+
339
+    /**
340
+     * I2C_MST_CLK values
341
+     */
342
+    typedef enum {
343
+      MST_CLK_348                      = 0, // 348Khz
344
+      MST_CLK_333                      = 1,
345
+      MST_CLK_320                      = 2,
346
+      MST_CLK_308                      = 3,
347
+      MST_CLK_296                      = 4,
348
+      MST_CLK_286                      = 5,
349
+      MST_CLK_276                      = 6,
350
+      MST_CLK_267                      = 7,
351
+      MST_CLK_258                      = 8,
352
+      MST_CLK_500                      = 9,
353
+      MST_CLK_471                      = 10,
354
+      MST_CLK_444                      = 11,
355
+      MST_CLK_421                      = 12,
356
+      MST_CLK_400                      = 13,
357
+      MST_CLK_381                      = 14,
358
+      MST_CLK_364                      = 15
359
+    } I2C_MST_CLK_T;
360
+
361
+    /**
362
+     * REG_I2C SLV0-SLV4 _ADDR bits
363
+     */
364
+    typedef enum {
365
+      I2C_SLV_ADDR0                    = 0x01,
366
+      I2C_SLV_ADDR1                    = 0x02,
367
+      I2C_SLV_ADDR2                    = 0x04,
368
+      I2C_SLV_ADDR3                    = 0x08,
369
+      I2C_SLV_ADDR4                    = 0x10,
370
+      I2C_SLV_ADDR5                    = 0x20,
371
+      I2C_SLV_ADDR6                    = 0x40,
372
+      _I2C_SLV_ADDR_SHIFT              = 0,
373
+      _I2C_SLV_ADDR_MASK               = 127,
374
+
375
+      I2C_SLV_RW                       = 0x80
376
+    } I2C_SLV_ADDR_BITS_T;
377
+
378
+    /**
379
+     * REG_I2C SLV0-SLV3 _CTRL bits
380
+     */
381
+    typedef enum {
382
+      I2C_SLV_LEN0                     = 0x01,
383
+      I2C_SLV_LEN1                     = 0x02,
384
+      I2C_SLV_LEN2                     = 0x04,
385
+      I2C_SLV_LEN3                     = 0x08,
386
+      _I2C_SLV_LEN_SHIFT               = 0,
387
+      _I2C_SLV_LEN_MASK                = 15,
388
+
389
+      I2C_SLV_GRP                      = 0x10,
390
+      I2C_SLV_REG_DIS                  = 0x20,
391
+      I2C_SLV_BYTE_SW                  = 0x40,
392
+      I2C_SLV_EN                       = 0x80
393
+    } I2C_SLV_CTRL_BITS_T;
394
+
395
+    /**
396
+     * REG_I2C_SLV4_CTRL bits, these are different from the SLV0-SLV3
397
+     * CRTL bits.
398
+     *
399
+     * MST_DLY is not enumerated in the register map.  It configures
400
+     * the reduced access rate of i2c slaves relative to the sample
401
+     * rate. When a slave’s access rate is decreased relative to the
402
+     * Sample Rate, the slave is accessed every 
403
+     * 1 / (1 + I2C_MST_DLY) samples
404
+     */
405
+    typedef enum {
406
+      I2C_MST_DLY0                     = 0x01,
407
+      I2C_MST_DLY1                     = 0x02,
408
+      I2C_MST_DLY2                     = 0x04,
409
+      I2C_MST_DLY3                     = 0x08,
410
+      I2C_MST_DLY4                     = 0x10,
411
+      _I2C_MST_DLY_SHIFT               = 0,
412
+      _I2C_MST_DLY_MASK                = 31,
413
+
414
+      I2C_SLV4_REG_DIS                 = 0x20,
415
+      I2C_SLV4_INT_EN                  = 0x40,
416
+      I2C_SLV4_EN                      = 0x80
417
+    } I2C_SLV4_CTRL_BITS_T;
418
+
419
+    /**
420
+     * REG_I2C_MST_STATUS bits
421
+     */
422
+    typedef enum {
423
+      I2C_SLV0_NACK                    = 0x01,
424
+      I2C_SLV1_NACK                    = 0x02,
425
+      I2C_SLV2_NACK                    = 0x04,
426
+      I2C_SLV3_NACK                    = 0x08,
427
+      I2C_SLV4_NACK                    = 0x10,
428
+
429
+      I2C_LOST_ARB                     = 0x20,
430
+      I2C_SLV4_DONE                    = 0x40,
431
+      PASS_THROUGH                     = 0x80
432
+    } I2C_MST_STATUS_BITS_T;
433
+    
434
+    /**
435
+     * REG_INT_PIN_CFG bits
436
+     */
437
+    typedef enum {
438
+      CLKOUT_EN                        = 0x01, // *
439
+
440
+      I2C_BYPASS_ENABLE                = 0x02,
441
+
442
+      FSYNC_INT_EN                     = 0x04,
443
+      FSYNC_INT_LEVEL                  = 0x08,
444
+
445
+      INT_RD_CLEAR                     = 0x10,
446
+
447
+      LATCH_INT_EN                     = 0x20,
448
+
449
+      INT_OPEN                         = 0x40,
450
+      INT_LEVEL                        = 0x80
451
+    } INT_PIN_CFG_BITS_T;
452
+    
453
+    /**
454
+     * REG_INT_ENABLE bits
455
+     */
456
+    typedef enum {
457
+      DATA_RDY_EN                      = 0x01, // *
458
+
459
+      // 0x02, 0x04 reserved
460
+
461
+      I2C_MST_INT_EN                   = 0x08,
462
+
463
+      FIFO_OFLOW_EN                    = 0x10,
464
+
465
+      ZMOT_EN                          = 0x20, // *zero motion
466
+      MOT_EN                           = 0x40,
467
+      FF_EN                            = 0x80  // *freefall
468
+    } INT_ENABLE_BITS_T;
469
+    
470
+    /**
471
+     * REG_INT_STATUS bits
472
+     */
473
+    typedef enum {
474
+      DATA_RDY_INT                     = 0x01,
475
+
476
+      // 0x02, 0x04 reserved
477
+
478
+      I2C_MST_INT                      = 0x08,
479
+
480
+      FIFO_OFLOW_INT                   = 0x10,
481
+
482
+      ZMOT_INT                         = 0x20, // *zero motion
483
+      MOT_INT                          = 0x40,
484
+      FF_INT                           = 0x80  // *freefall
485
+    } INT_STATUS_BITS_T;
486
+    
487
+    /**
488
+     * REG_MOT_DETECT_STATUS bits (mpu9150 only)
489
+     */
490
+    typedef enum {
491
+      MOT_ZRMOT                        = 0x01, // *
492
+
493
+      // 0x02 reserved
494
+
495
+      MOT_ZPOS                         = 0x04, // *
496
+      MOT_ZNEG                         = 0x08, // *
497
+
498
+      MOT_YPOS                         = 0x10, // *
499
+      MOT_YNEG                         = 0x20, // *
500
+
501
+      MOT_XPOS                         = 0x40, // *
502
+      MOT_XNEG                         = 0x80, // *
503
+    } MOT_DETECT_STATUS_BITS_T;
504
+    
505
+    /**
506
+     * REG_MST_DELAY_CTRL bits
507
+     */
508
+    typedef enum {
509
+      I2C_SLV0_DLY_EN                  = 0x01,
510
+      I2C_SLV1_DLY_EN                  = 0x02,
511
+      I2C_SLV2_DLY_EN                  = 0x04,
512
+      I2C_SLV3_DLY_EN                  = 0x08,
513
+      I2C_SLV4_DLY_EN                  = 0x10,
514
+
515
+      // 0x20, 0x40, reserved
516
+
517
+      DELAY_ES_SHADOW                  = 0x80
518
+    } MST_DELAY_CTRL_BITS_T;
519
+    
520
+    /**
521
+     * REG_SIGNAL_PATH_RESET bits
522
+     */
523
+    typedef enum {
524
+      TEMP_RESET                       = 0x01,
525
+      ACCEL_RESET                      = 0x02,
526
+      GYRO_RESET                       = 0x04
527
+
528
+      // 0x08-0x80 reserved
529
+    } SIGNAL_PATH_RESET_BITS_T;
530
+    
531
+    /**
532
+     * REG_MOT_DETECT_CTRL bits
533
+     */
534
+    typedef enum {
535
+      MOT_COUNT0                       = 0x01, // *
536
+      MOT_COUNT1                       = 0x02, // *
537
+      _MOT_COUNT_SHIFT                 = 0,
538
+      _MOT_COUNT_MASK                  = 3,
539
+
540
+      FF_COUNT0                        = 0x04, // *
541
+      FF_COUNT1                        = 0x08, // *
542
+      _FF_COUNT_SHIFT                  = 2,
543
+      _FF_COUNT_MASK                   = 3,
544
+
545
+      ACCEL_ON_DELAY0                  = 0x10,
546
+      ACCEL_ON_DELAY1                  = 0x20,
547
+      _ACCEL_ON_DELAY_SHIFT            = 4,
548
+      _ACCEL_ON_DELAY_MASK             = 3
549
+      // 0x40,0x80 reserved
550
+    } MOT_DETECT_CTRL_BITS_T;
551
+    
552
+    /**
553
+     * MOT_COUNT or FF_COUNT values (mpu9150 only)
554
+     */
555
+    typedef enum {
556
+      COUNT_0                          = 0, // Reset
557
+      COUNT_1                          = 1, // counter decrement 1
558
+      COUNT_2                          = 2, // counter decrement 2
559
+      COUNT_4                          = 3  // counter decrement 4
560
+    } MOT_FF_COUNT_T;
561
+
562
+    /**
563
+     * ACCEL_ON_DELAY values
564
+     */
565
+    typedef enum {
566
+      ON_DELAY_0                       = 0, // no delay
567
+      ON_DELAY_1                       = 1, // add 1ms
568
+      ON_DELAY_2                       = 2, // add 2ms
569
+      ON_DELAY_3                       = 3  // add 3ms
570
+    } ACCEL_ON_DELAY_T;
571
+
572
+    /**
573
+     * REG_USER_CTRL bits
574
+     */
575
+    typedef enum {
576
+      SIG_COND_RESET                   = 0x01,
577
+      I2C_MST_RESET                    = 0x02,
578
+      FIFO_RESET                       = 0x04,
579
+
580
+      // 0x08 reserved
581
+
582
+      I2C_IF_DIS                       = 0x10,
583
+      I2C_MST_EN                       = 0x20,
584
+      FIFO_EN                          = 0x40
585
+
586
+      /// 0x80 reserved
587
+    } USER_CTRL_BITS_T;
588
+    
589
+    /**
590
+     * REG_PWR_MGMT_1 bits
591
+     */
592
+    typedef enum {
593
+      CLKSEL0                          = 0x01,
594
+      CLKSEL1                          = 0x02,
595
+      CLKSEL2                          = 0x04,
596
+      _CLKSEL_SHIFT                    = 0,
597
+      _CLKSEL_MASK                     = 7,
598
+
599
+      TEMP_DIS                         = 0x08,
600
+
601
+      // 0x10 reserved
602
+
603
+      PWR_CYCLE                        = 0x20,
604
+      PWR_SLEEP                        = 0x40,
605
+      DEVICE_RESET                     = 0x80
606
+    } PWR_MGMT_1_BITS_T;
607
+    
608
+    /**
609
+     * CLKSEL values
610
+     */
611
+    typedef enum {
612
+      INT_8MHZ                         = 0, // internal 8Mhz osc
613
+      PLL_XG                           = 1, // PLL X axis gyro
614
+      PLL_YG                           = 2, // PLL Y axis gyro
615
+      PLL_ZG                           = 3, // PLL Z axis gyro
616
+      PLL_EXT_32KHZ                    = 4, // PLL with external 32.768Khz ref
617
+      PLL_EXT_19MHZ                    = 5, // PLL with external 19.2Mhz ref
618
+      // 6 - reserved
619
+      CLK_STOP                         = 7  // stops clk
620
+    } CLKSEL_T;
621
+
622
+    /**
623
+     * REG_PWR_MGMT_2 bits
624
+     */
625
+    typedef enum {
626
+      STBY_ZG                          = 0x01,
627
+      STBY_YG                          = 0x02,
628
+      STBY_XG                          = 0x04,
629
+      STBY_ZA                          = 0x08,
630
+      STBY_YA                          = 0x10,
631
+      STBY_XA                          = 0x20,
632
+
633
+      LP_WAKE_CTRL0                    = 0x40,
634
+      LP_WAKE_CTRL1                    = 0x80,
635
+      _LP_WAKE_CTRL_SHIFT              = 6,
636
+      _LP_WAKE_CTRL_MASK               = 3
637
+    } PWR_MGMT_2_BITS_T;
638
+    
639
+    /**
640
+     * LP_WAKE_CTRL values
641
+     */
642
+    typedef enum {
643
+      LP_WAKE_1_25                     = 0, // wakeup feq: 1.25hz
644
+      LP_WAKE_5                        = 1, // 5hz
645
+      LP_WAKE_20                       = 2, // 20hz
646
+      LP_WAKE_40                       = 3, // 40hz
647
+    } LP_WAKE_CRTL_T;
648
+
649
+
650
+    /**
651
+     * mpu60x0 constructor
652
+     *
653
+     * @param bus i2c bus to use
654
+     * @param address the address for this device
655
+     */
656
+    MPU60X0(int bus=MPU60X0_I2C_BUS, uint8_t address=MPU60X0_DEFAULT_I2C_ADDR);
657
+
658
+    /**
659
+     * MPU60X0 Destructor
660
+     */
661
+    ~MPU60X0();
662
+    
663
+    /**
664
+     * set up initial values and start operation
665
+     *
666
+     * @return true if successful
667
+     */
668
+    bool init();
669
+
670
+    /**
671
+     * take a measurement and store the current sensor values
672
+     * internally.  Note, these user facing registers are only updated
673
+     * from the internal device sensor values when the i2c serial
674
+     * traffic is 'idle'.  So, if you are reading the values too fast,
675
+     * the bus may never be idle, and you will just end up reading
676
+     * the same values over and over.
677
+     *
678
+     * Unfortunately, it is is not clear how long 'idle' actually
679
+     * means, so if you see this behavior, reduce the rate at which
680
+     * you are calling update().
681
+     *
682
+     */
683
+    void update();
684
+
685
+    /**
686
+     * read a register
687
+     *
688
+     * @param reg the register to read
689
+     * @return the value of the register
690
+     */
691
+    uint8_t readReg(uint8_t reg);
692
+
693
+    /**
694
+     * read contiguous refister into a buffer
695
+     *
696
+     * @param reg the register to start reading at
697
+     * @param buf the buffer to store the results
698
+     * @param len the number of registers to read
699
+     * @return the value of the register
700
+     */
701
+    void readRegs(uint8_t reg, uint8_t *buf, int len);
702
+
703
+    /**
704
+     * write to a register
705
+     *
706
+     * @param reg the register to write to
707
+     * @param val the value to write
708
+     * @return true if successful, false otherwise
709
+     */
710
+    bool writeReg(uint8_t reg, uint8_t val);
711
+
712
+    /**
713
+     * enable or disable device sleep
714
+     *
715
+     * @param enable true to put device to sleep, false to wake up
716
+     * @return true if successful, false otherwise
717
+     */
718
+    bool setSleep(bool enable);
719
+
720
+    /**
721
+     * specify the clock source for the device to use
722
+     *
723
+     * @param clk one of the CLKSEL_T values
724
+     * @return true if successful, false otherwise
725
+     */
726
+    bool setClockSource(CLKSEL_T clk);
727
+
728
+    /**
729
+     * set the scaling mode of the gyroscope
730
+     *
731
+     * @param scale one of the FS_SEL_T values
732
+     * @return true if successful, false otherwise
733
+     */
734
+    bool setGyroscopeScale(FS_SEL_T scale);
735
+
736
+    /**
737
+     * set the scaling mode of the accelerometer
738
+     *
739
+     * @param scale one of the AFS_SEL_T values
740
+     * @return true if successful, false otherwise
741
+     */
742
+    bool setAccelerometerScale(AFS_SEL_T scale);
743
+
744
+    /**
745
+     * set the Low Pass Digital filter.  This enables filtering (if
746
+     * non-0) of the accelerometer and gyro outputs.
747
+     *
748
+     * @param scale one of the DLPF_CFG_T values
749
+     * @return true if successful, false otherwise
750
+     */
751
+    bool setDigitalLowPassFilter(DLPF_CFG_T dlp);
752
+
753
+    /**
754
+     * set the sample rate divider.  This register specifies the
755
+     * divider from the gyro output rate used to generate the Sample
756
+     * Rate.  The sensor registor output, FIFO output, DMP sampling
757
+     * and motion detection are all based on the Sample Rate.
758
+     *
759
+     * The Sample Rate is generated by dividing the gyro output rate
760
+     * by this register:
761
+     *
762
+     * Sample Rate = Gyro output rate / (1 + sample rate divider).
763
+     *
764
+     * The Gyro output rate is 8Khz when the Digital Low Pass Filter
765
+     * (DLPF) is 0 or 7 (DLPF_260_256 or DLPF_RESERVED), and 1Khz
766
+     * otherwise.
767
+     *
768
+     * @param scale one of the DLPF_CFG_T values
769
+     * @return true if successful, false otherwise
770
+     */
771
+    bool setSampleRateDivider(uint8_t div);
772
+
773
+    /**
774
+     * get the current Sample Rate divider
775
+     *
776
+     * @return the current sample rate divider
777
+     */
778
+    uint8_t getSampleRateDivider();
779
+
780
+    /**
781
+     * get the accelerometer values
782
+     *
783
+     * @param x the returned x value, if arg is non-NULL
784
+     * @param y the returned y value, if arg is non-NULL
785
+     * @param z the returned z value, if arg is non-NULL
786
+     * @return true if successful, false otherwise
787
+     */
788
+    void getAccelerometer(float *x, float *y, float *z);
789
+
790
+    /**
791
+     * get the gyroscope values
792
+     *
793
+     * @param x the returned x value, if arg is non-NULL
794
+     * @param y the returned y value, if arg is non-NULL
795
+     * @param z the returned z value, if arg is non-NULL
796
+     * @return true if successful, false otherwise
797
+     */
798
+    void getGyroscope(float *x, float *y, float *z);
799
+
800
+    /**
801
+     * get the temperature value
802
+     *
803
+     * @return the temperature value in degrees Celcius
804
+     */
805
+    float getTemperature();
806
+
807
+    /**
808
+     * enable onboard temperature measurement sensor
809
+     *
810
+     * @param enable true to enable temperature sensor, false to disable
811
+     * @return true if successful, false otherwise
812
+     */
813
+    bool enableTemperatureSensor(bool enable);
814
+
815
+    /**
816
+     * configure external sync.  An external signal connected to the
817
+     * FSYNC pin can be sampled by configuring EXT_SYNC_SET.  Signal
818
+     * changes to the FSYNC pin are latched so that short strobes may
819
+     * be captured. The latched FSYNC signal will be sampled at the
820
+     * Sampling Rate, as defined in register 25. After sampling, the
821
+     * latch will reset to the current FSYNC signal state.
822
+     *
823
+     * The sampled value will be reported in place of the least
824
+     * significant bit in a sensor data register determined by the
825
+     * value of EXT_SYNC_SET
826
+     *
827
+     * @param val one of the EXT_SYNC_SET_T values
828
+     * @return true if successful, false otherwise
829
+     */
830
+    bool setExternalSync(EXT_SYNC_SET_T val);
831
+
832
+    /**
833
+     * enable I2C Bypass.  Enabling this feature allows devices on the
834
+     * MPU60X0 auxillary I2C bus to be visible on the MCU's I2C bus.
835
+     *
836
+     * @param enable true to I2C bypass
837
+     * @return true if successful, false otherwise
838
+     */
839
+    bool enableI2CBypass(bool enable);
840
+
841
+    /**
842
+     * set the motion detection threshold for interrupt generation.
843
+     * Motion is detected when the absolute value of any of the
844
+     * accelerometer measurements exceeds this Motion detection
845
+     * threshold.
846
+     *
847
+     * @param thr threshold
848
+     * @return true if successful, false otherwise
849
+     */
850
+    bool setMotionDetectionThreshold(uint8_t thr);
851
+
852
+    /**
853
+     * return the interrupt status register.
854
+     *
855
+     * @return the interrupt status word (see INT_STATUS_BITS_T)
856
+     */
857
+    uint8_t getInterruptStatus();
858
+
859
+    /**
860
+     * set the interrupt enables
861
+     *
862
+     * @param enables bitmask of INT_ENABLE_BITS_T values to enable
863
+     * @return true if successful, false otherwise
864
+     */
865
+    bool setInterruptEnables(uint8_t enables);
866
+
867
+    /**
868
+     * get the current interrupt enables register
869
+     *
870
+     * @return bitmask of INT_ENABLE_BITS_T values
871
+     */
872
+    uint8_t getInterruptEnables();
873
+
874
+    /**
875
+     * set the interrupt pin configuration
876
+     *
877
+     * @param cfg bitmask of INT_PIN_CFG_BITS_T values
878
+     * @return true if successful, false otherwise
879
+     */
880
+    bool setInterruptPinConfig(uint8_t cfg);
881
+
882
+    /**
883
+     * get the current interrupt pin configuration
884
+     *
885
+     * @return bitmask of INT_PIN_CFG_BITS_T values
886
+     */
887
+    uint8_t getInterruptPinConfig();
888
+    
889
+    /**
890
+     * install an interrupt handler.
891
+     *
892
+     * @param gpio gpio pin to use as interrupt pin
893
+     * @param level the interrupt trigger level (one of mraa::Edge
894
+     * values).  Make sure that you have configured the interrupt pin
895
+     * (setInterruptPinConfig()) properly for whatever level you
896
+     * choose.
897
+     * @param isr the interrupt handler, accepting a void * argument
898
+     * @param arg the argument to pass the the interrupt handler
899
+     */
900
+    void installISR(int gpio, mraa::Edge level, void (*isr)(void *), void *arg);
901
+
902
+    /**
903
+     * uninstall a previously installed interrupt handler
904
+     *
905
+     */
906
+    void uninstallISR();
907
+
908
+  protected:
909
+    // uncompensated accelerometer and gyroscope values
910
+    float m_accelX;
911
+    float m_accelY;
912
+    float m_accelZ;
913
+
914
+    float m_gyroX;
915
+    float m_gyroY;
916
+    float m_gyroZ;
917
+
918
+    // uncompensated temperature value
919
+    float m_temp;
920
+
921
+    // accelerometer and gyro scaling factors, depending on their Full
922
+    // Scale settings.
923
+    float m_accelScale;
924
+    float m_gyroScale;
925
+
926
+  private:
927
+    mraa::I2c m_i2c;
928
+    uint8_t m_addr;
929
+
930
+    mraa::Gpio *m_gpioIRQ;
931
+  };
932
+}
933
+
934
+

+ 57
- 181
src/mpu9150/mpu9150.cxx View File

@@ -1,9 +1,6 @@
1 1
 /*
2
- * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
3
- * Copyright (c) 2014 Intel Corporation.
4
- *
5
- * Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
6
- * 8/24/2011 by Jeff Rowberg <jeff@rowberg.net>
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2015 Intel Corporation.
7 4
  *
8 5
  * Permission is hereby granted, free of charge, to any person obtaining
9 6
  * a copy of this software and associated documentation files (the
@@ -32,195 +29,74 @@
32 29
 #include "mpu9150.h"
33 30
 
34 31
 using namespace upm;
32
+using namespace std;
35 33
 
36
-MPU9150::MPU9150 (int bus, int devAddr) {
37
-    m_name = "MPU9150";
38
-
39
-    m_i2cAddr = devAddr;
40
-    m_bus = bus;
41
-
42
-    m_i2Ctx = mraa_i2c_init(m_bus);
43
-
44
-    mraa_result_t ret = mraa_i2c_address(m_i2Ctx, m_i2cAddr);
45
-    if (ret != MRAA_SUCCESS) {
46
-        fprintf(stderr, "Messed up i2c bus\n");
47
-    }
48
-
49
-    initSensor ();
34
+MPU9150::MPU9150 (int bus, int address, int magAddress) :
35
+  m_mag(0), MPU60X0(bus, address)
36
+{
37
+  m_magAddress = magAddress;
38
+  m_i2cBus = bus;
50 39
 }
51 40
 
52
-MPU9150::~MPU9150() {
53
-    mraa_i2c_stop(m_i2Ctx);
41
+MPU9150::~MPU9150()
42
+{
43
+  if (m_mag)
44
+    delete m_mag;
54 45
 }
55 46
 
56
-mraa_result_t
57
-MPU9150::initSensor () {
58
-    uint8_t regData = 0x0;
59
-
60
-    // setClockSource
61
-    updateRegBits ( MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT,
62
-                    MPU6050_PWR1_CLKSEL_LENGTH, MPU6050_CLOCK_PLL_XGYRO);
63
-    // setFullScaleGyroRange
64
-    updateRegBits ( MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT,
65
-                    MPU6050_GCONFIG_FS_SEL_LENGTH, MPU6050_GYRO_FS_250);
66
-    // setFullScaleAccelRange
67
-    updateRegBits ( MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT,
68
-                    MPU6050_ACONFIG_AFS_SEL_LENGTH, MPU6050_ACCEL_FS_2);
69
-    // setSleepEnabled
70
-    i2cReadReg_N (MPU6050_RA_PWR_MGMT_1, 0x1, &regData);
71
-    regData &= ~(1 << MPU6050_PWR1_SLEEP_BIT);
72
-    i2cWriteReg (MPU6050_RA_PWR_MGMT_1, regData);
73
-
74
-    return MRAA_SUCCESS;
75
-}
76
-
77
-uint8_t
78
-MPU9150::getDeviceID () {
79
-    uint8_t regData = 0x0;
80
-    getRegBits (MPU6050_RA_WHO_AM_I, MPU6050_WHO_AM_I_BIT, MPU6050_WHO_AM_I_LENGTH, &regData);
81
-    return regData;
82
-}
83
-
84
-void
85
-MPU9150::getData () {
86
-    uint8_t buffer[14];
87
-
88
-    for (int i = 0; i < SMOOTH_TIMES; i++) {
89
-        i2cReadReg_N (MPU6050_RA_ACCEL_XOUT_H, 14, buffer);
90
-        axisAcceleromter.rawData.axisX  = (((int16_t)buffer[0]) << 8)  | buffer[1];
91
-        axisAcceleromter.rawData.axisY  = (((int16_t)buffer[2]) << 8)  | buffer[3];
92
-        axisAcceleromter.rawData.axisZ  = (((int16_t)buffer[4]) << 8)  | buffer[5];
93
-        axisAcceleromter.sumData.axisX  += (double) axisAcceleromter.rawData.axisX / 16384;
94
-        axisAcceleromter.sumData.axisY  += (double) axisAcceleromter.rawData.axisY / 16384;
95
-        axisAcceleromter.sumData.axisZ  += (double) axisAcceleromter.rawData.axisZ / 16384;
96
-
97
-        axisGyroscope.rawData.axisX     = (((int16_t)buffer[8]) << 8)  | buffer[9];
98
-        axisGyroscope.rawData.axisY     = (((int16_t)buffer[10]) << 8) | buffer[11];
99
-        axisGyroscope.rawData.axisZ     = (((int16_t)buffer[12]) << 8) | buffer[13];
100
-        axisGyroscope.sumData.axisX     += (double) axisAcceleromter.rawData.axisX * 250 / 32768;
101
-        axisGyroscope.sumData.axisY     += (double) axisAcceleromter.rawData.axisY * 250 / 32768;
102
-        axisGyroscope.sumData.axisZ     += (double) axisAcceleromter.rawData.axisZ * 250 / 32768;
103
-
104
-        i2cWriteReg (MPU6050_RA_INT_PIN_CFG, 0x02);
105
-        usleep (10000);
106
-        m_i2cAddr = MPU9150_RA_MAG_ADDRESS;
107
-        i2cWriteReg (0x0A, 0x01);
108
-        usleep (10000);
109
-        i2cReadReg_N (MPU9150_RA_MAG_XOUT_L, 6, buffer);
110
-        m_i2cAddr = ADDR;
111
-
112
-        axisMagnetomer.rawData.axisX  = (((int16_t)buffer[0]) << 8)  | buffer[1];
113
-        axisMagnetomer.rawData.axisY  = (((int16_t)buffer[2]) << 8)  | buffer[3];
114
-        axisMagnetomer.rawData.axisZ  = (((int16_t)buffer[4]) << 8)  | buffer[5];
115
-        axisMagnetomer.sumData.axisX  += (double) axisMagnetomer.rawData.axisX * 1200 / 4096;
116
-        axisMagnetomer.sumData.axisY  += (double) axisMagnetomer.rawData.axisY * 1200 / 4096;
117
-        axisMagnetomer.sumData.axisZ  += (double) axisMagnetomer.rawData.axisZ * 1200 / 4096;
47
+bool MPU9150::init()
48
+{
49
+  // init the gyro/accel component
50
+  if (!MPU60X0::init())
51
+    {
52
+      cerr << __FUNCTION__ << ": Unable to init MPU60X0" << endl;
53
+      return false;
118 54
     }
119 55
 
120
-    axisAcceleromter.data.axisX = axisAcceleromter.sumData.axisX / SMOOTH_TIMES;
121
-    axisAcceleromter.data.axisY = axisAcceleromter.sumData.axisY / SMOOTH_TIMES;
122
-    axisAcceleromter.data.axisZ = axisAcceleromter.sumData.axisZ / SMOOTH_TIMES;
123
-
124
-    axisGyroscope.data.axisX = axisGyroscope.sumData.axisX / SMOOTH_TIMES;
125
-    axisGyroscope.data.axisY = axisGyroscope.sumData.axisY / SMOOTH_TIMES;
126
-    axisGyroscope.data.axisZ = axisGyroscope.sumData.axisZ / SMOOTH_TIMES;
127
-
128
-    axisMagnetomer.data.axisX = axisMagnetomer.sumData.axisX / SMOOTH_TIMES;
129
-    axisMagnetomer.data.axisY = axisMagnetomer.sumData.axisY / SMOOTH_TIMES;
130
-    axisMagnetomer.data.axisZ = axisMagnetomer.sumData.axisZ / SMOOTH_TIMES;
131
-}
132
-
133
-mraa_result_t
134
-MPU9150::getAcceleromter (Vector3D * data) {
135
-    data->axisX = axisAcceleromter.data.axisX;
136
-    data->axisY = axisAcceleromter.data.axisY;
137
-    data->axisZ = axisAcceleromter.data.axisZ;
138
-
139
-    return MRAA_SUCCESS;
140
-}
141
-
142
-mraa_result_t
143
-MPU9150::getGyro (Vector3D * data) {
144
-    data->axisX = axisGyroscope.data.axisX;
145
-    data->axisY = axisGyroscope.data.axisY;
146
-    data->axisZ = axisGyroscope.data.axisZ;
147
-
148
-    return MRAA_SUCCESS;
149
-}
150
-
151
-mraa_result_t
152
-MPU9150::getMagnometer (Vector3D * data) {
153
-    data->axisX = axisMagnetomer.data.axisX;
154
-    data->axisY = axisMagnetomer.data.axisY;
155
-    data->axisZ = axisMagnetomer.data.axisZ;
156
-
157
-    return MRAA_SUCCESS;
158
-}
159
-
160
-float
161
-MPU9150::getTemperature () {
162
-    uint8_t buffer[2];
163
-    uint16_t tempRaw = 0;
164
-
165
-    updateRegBits (MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_TEMP_DIS_BIT, 0x1, 0x0);
166
-    i2cReadReg_N (MPU6050_RA_TEMP_OUT_H, 2, buffer);
167
-    tempRaw = (((int16_t)buffer[0]) << 8) | buffer[1];
168
-
169
-    return (float)tempRaw / 340.0 + 35.0;
170
-}
171
-
172
-/*
173
- * **************
174
- *  private area
175
- * **************
176
- */
177
-uint16_t
178
-MPU9150::i2cReadReg_N (int reg, unsigned int len, uint8_t * buffer) {
179
-    int readByte = 0;
180
-    mraa_i2c_address(m_i2Ctx, m_i2cAddr);
181
-    mraa_i2c_write_byte(m_i2Ctx, reg);
182
-
183
-    mraa_i2c_address(m_i2Ctx, m_i2cAddr);
184
-    readByte = mraa_i2c_read(m_i2Ctx, buffer, len);
185
-    return readByte;
186
-}
56
+  // Now, we need to enable I2C bypass on the MPU60X0 component.  This
57
+  // will allow us to access the AK8975 Magnetometer on I2C addr 0x0c.
58
+  if (!enableI2CBypass(true))
59
+    {
60
+      cerr << __FUNCTION__ << ": Unable to enable I2C bypass" << endl;
61
+      return false;
62
+    }
187 63
 
188
-mraa_result_t
189
-MPU9150::i2cWriteReg (uint8_t reg, uint8_t value) {
190
-    mraa_result_t error = MRAA_SUCCESS;
64
+  // Now that we've done that, create an AK8975 instance and
65
+  // initialize it.
66
+  m_mag = new AK8975(m_i2cBus, m_magAddress);
191 67
 
192
-    uint8_t data[2] = { reg, value };
193
-    error = mraa_i2c_address (m_i2Ctx, m_i2cAddr);
194
-    error = mraa_i2c_write (m_i2Ctx, data, 2);
68
+  if (!m_mag->init())
69
+    {
70
+      cerr << __FUNCTION__ << ": Unable to init magnetometer" << endl;
71
+      delete m_mag;
72
+      m_mag = 0;
73
+      return false;
74
+    }
195 75
 
196
-    return error;
76
+  return true;
197 77
 }
198 78
 
199
-int
200
-MPU9150::updateRegBits (uint8_t reg, uint8_t bitStart, uint8_t length, uint16_t data) {
201
-    uint8_t regData;
79
+void MPU9150::update()
80
+{
81
+  MPU60X0::update();
202 82
 
203
-    if (i2cReadReg_N (reg, 0x1, &regData) != 0) {
204
-        uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
205
-        data <<= (bitStart - length + 1); // shift data into correct position
206
-        data &= mask; // zero all non-important bits in data
207
-        regData &= ~(mask); // zero all important bits in existing byte
208
-        regData |= data; // combine data with existing byte
209
-        return i2cWriteReg (reg, regData);
210
-    } else {
211
-        return 0x0;
212
-    }
83
+  if (m_mag)
84
+    m_mag->update();
213 85
 }
214 86
 
215
-uint8_t
216
-MPU9150::getRegBits (uint8_t reg, uint8_t bitStart, uint8_t length, uint8_t * data) {
217
-    uint8_t count = 0;
218
-    uint8_t regData;
219
-    if (i2cReadReg_N (reg, 0x1, &regData) != 0) {
220
-        uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1);
221
-        regData &= mask;
222
-        regData >>= (bitStart - length + 1);
223
-        *data = regData;
224
-    }
225
-    return count;
87
+void MPU9150::getMagnetometer(float *x, float *y, float *z)
88
+{
89
+  float mx, my, mz;
90
+
91
+  if (!m_mag)
92
+    mx = my = mz = 0.0;
93
+  else
94
+    m_mag->getMagnetometer(&mx, &my, &mz);
95
+  
96
+  if (x)
97
+    *x = mx;
98
+  if (y)
99
+    *y = my;
100
+  if (z)
101
+    *z = mz;
226 102
 }

+ 92
- 183
src/mpu9150/mpu9150.h View File

@@ -1,9 +1,6 @@
1 1
 /*
2
- * Author: Yevgeniy Kiveisha <yevgeniy.kiveisha@intel.com>
3
- * Copyright (c) 2014 Intel Corporation.
4
- *
5
- * Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
6
- * 8/24/2011 by Jeff Rowberg <jeff@rowberg.net>
2
+ * Author: Jon Trulson <jtrulson@ics.com>
3
+ * Copyright (c) 2015 Intel Corporation.
7 4
  *
8 5
  * Permission is hereby granted, free of charge, to any person obtaining
9 6
  * a copy of this software and associated documentation files (the
@@ -24,188 +21,100 @@
24 21
  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 22
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 23
  */
24
+
27 25
 #pragma once
28 26
 
29
-#include <string>
30
-#include <mraa/i2c.h>
31
-
32
-#define MPU6050_ADDRESS_AD0_LOW             0x68 // address pin low (GND), default for InvenSense evaluation board
33
-#define MPU6050_ADDRESS_AD0_HIGH            0x69 // address pin high (VCC)
34
-#define ADDR                                MPU6050_ADDRESS_AD0_LOW // device address
35
-
36
-// registers address
37
-#define MPU6050_CLOCK_PLL_XGYRO             0x01
38
-#define MPU6050_GYRO_FS_250                 0x00
39
-#define MPU6050_ACCEL_FS_2                  0x00
40
-#define MPU6050_RA_INT_PIN_CFG              0x37
41
-
42
-#define MPU6050_RA_ACCEL_XOUT_H             0x3B
43
-#define MPU6050_RA_ACCEL_XOUT_L             0x3C
44
-#define MPU6050_RA_ACCEL_YOUT_H             0x3D
45
-#define MPU6050_RA_ACCEL_YOUT_L             0x3E
46
-#define MPU6050_RA_ACCEL_ZOUT_H             0x3F
47
-#define MPU6050_RA_ACCEL_ZOUT_L             0x40
48
-#define MPU6050_RA_TEMP_OUT_H               0x41
49
-#define MPU6050_RA_TEMP_OUT_L               0x42
50
-#define MPU6050_RA_GYRO_XOUT_H              0x43
51
-#define MPU6050_RA_GYRO_XOUT_L              0x44
52
-#define MPU6050_RA_GYRO_YOUT_H              0x45
53
-#define MPU6050_RA_GYRO_YOUT_L              0x46
54
-#define MPU6050_RA_GYRO_ZOUT_H              0x47
55
-#define MPU6050_RA_GYRO_ZOUT_L              0x48
56
-
57
-#define MPU6050_RA_CONFIG                   0x1A
58
-#define MPU6050_CFG_DLPF_CFG_BIT            2
59
-#define MPU6050_CFG_DLPF_CFG_LENGTH         3
60
-
61
-#define MPU6050_RA_GYRO_CONFIG              0x1B
62
-#define MPU6050_GCONFIG_FS_SEL_BIT          4
63
-#define MPU6050_GCONFIG_FS_SEL_LENGTH       2
64
-
65
-#define MPU6050_RA_ACCEL_CONFIG             0x1C
66
-#define MPU6050_ACONFIG_AFS_SEL_BIT         4
67
-#define MPU6050_ACONFIG_AFS_SEL_LENGTH      2
68
-
69
-// magnotometer
70
-#define MPU9150_RA_MAG_ADDRESS              0x0C
71
-#define MPU9150_RA_MAG_XOUT_L               0x03
72
-
73
-#define MPU6050_RA_PWR_MGMT_1               0x6B
74
-#define MPU6050_PWR1_CLKSEL_BIT             2
75
-#define MPU6050_PWR1_CLKSEL_LENGTH          3
76
-#define MPU6050_PWR1_SLEEP_BIT              6
77
-
78
-#define MPU6050_RA_INT_PIN_CFG              0x37
79
-
80
-// temperature
81
-#define MPU6050_PWR1_TEMP_DIS_BIT           3
82
-#define MPU6050_RA_WHO_AM_I                 0x75
83
-#define MPU6050_WHO_AM_I_BIT                6
84
-#define MPU6050_WHO_AM_I_LENGTH             6
85
-
86
-#define SMOOTH_TIMES                        10.0
87
-
88
-#define HIGH               1
89
-#define LOW                0
27
+#include "mpu60x0.h"
28
+#include "ak8975.h"
29
+
30
+#define MPU9150_I2C_BUS 0
31
+#define MPU9150_DEFAULT_I2C_ADDR  MPU60X0_DEFAULT_I2C_ADDR
32
+
90 33
 
91 34
 namespace upm {
92 35
 
93
-struct Vector3DRaw {
94
-    uint16_t axisX;
95
-    uint16_t axisY;
96
-    uint16_t axisZ;
97
-};
98
-
99
-struct Vector3D {
100
-    double axisX;
101
-    double axisY;
102
-    double axisZ;
103
-};
104
-
105
-struct AxisData {
106
-    Vector3DRaw rawData;
107
-    Vector3D    sumData;
108
-    Vector3D    data;
109
-};
110
-
111
-/**
112
- * @brief MPU9150 accelerometer library
113
- * @defgroup mpu9150 libupm-mpu9150
114
- * @ingroup seeed i2c accelerometer compass
115
- */
116
-/**
117
- * @library mpu9150
118
- * @sensor mpu9150
119
- * @comname MPU9150 Inertial Measurement Unit
120
- * @altname Grove IMU 9DOF
121
- * @type accelerometer compass
122
- * @man seeed
123
- * @web http://www.seeedstudio.com/wiki/Grove_-_IMU_9DOF_v1.0
124
- * @con i2c
125
- *
126
- * @brief API for MPU9150 chip (Accelerometer, Gyro and Magnometer Sensor)
127
- *
128
- * This file defines the MPU9150 interface for libmpu9150
129
- *
130
- * @image html mpu9150.jpg
131
- * @snippet mpu9150.cxx Interesting
132
- */
133
-class MPU9150 {
134
-    public:
135
-        /**
136
-         * Instanciates a MPU9150 object
137
-         *
138
-         * @param bus number of used bus
139
-         * @param devAddr addres of used i2c device
140
-         */
141
-        MPU9150 (int bus=0, int devAddr=0x68);
142
-
143
-        /**
144
-         * MPU9150 object destructor, basicaly it close i2c connection.
145
-         */
146
-        ~MPU9150 ();
147
-
148
-        /**
149
-         * Initiate MPU9150 chips
150
-         */
151
-        mraa_result_t initSensor ();
152
-
153
-        /**
154
-         * Get identity of the device
155
-         */
156
-        uint8_t getDeviceID ();
157
-
158
-        /**
159
-         * Get the Accelerometer, Gyro and Compass data from the chip and
160
-         * save it in private section.
161
-         */
162
-        void getData ();
163
-
164
-        /**
165
-         * @param data structure with 3 axis (x,y,z)
166
-         */
167
-        mraa_result_t getAcceleromter (Vector3D * data);
168
-
169
-        /**
170
-         * @param data structure with 3 axis (x,y,z)
171
-         */
172
-        mraa_result_t getGyro (Vector3D * data);
173
-
174
-        /**
175
-         * @param data structure with 3 axis (x,y,z)
176
-         */
177
-        mraa_result_t getMagnometer (Vector3D * data);
178
-
179
-        /**
180
-         * Read on die temperature from the chip
181
-         */
182
-        float getTemperature ();
183
-
184
-        /**
185
-         * Return name of the component
186
-         */
187
-        std::string name()
188
-        {
189
-            return m_name;
190
-        }
191
-
192
-    private:
193
-        std::string m_name;
194
-
195
-        int m_i2cAddr;
196
-        int m_bus;
197
-        mraa_i2c_context m_i2Ctx;
198
-
199
-        AxisData axisMagnetomer;
200
-        AxisData axisAcceleromter;
201
-        AxisData axisGyroscope;
202
-
203
-        uint16_t i2cReadReg_N (int reg, unsigned int len, uint8_t * buffer);
204
-        mraa_result_t i2cWriteReg (uint8_t reg, uint8_t value);
205
-        int updateRegBits (uint8_t reg, uint8_t bitStart,
206
-                                    uint8_t length, uint16_t data);
207
-        uint8_t getRegBits (uint8_t reg, uint8_t bitStart,
208
-                                    uint8_t length, uint8_t * data);
209
-};
36
+  /**
37
+   * @brief MPU9150 accelerometer library
38
+   * @defgroup mpu9150 libupm-mpu9150
39
+   * @ingroup seeed i2c gpio accelerometer compass
40
+   */
41
+
42
+  /**
43
+   * @library mpu9150
44
+   * @sensor mpu9150
45
+   * @comname MPU9150 Inertial Measurement Unit
46
+   * @altname Grove IMU 9DOF
47
+   * @type accelerometer compass
48
+   * @man seeed
49
+   * @web http://www.seeedstudio.com/wiki/Grove_-_IMU_9DOF_v1.0
50
+   * @con i2c gpio
51
+   *
52
+   * @brief API for MPU9150 chip (Accelerometer, Gyro and Magnometer Sensor)
53
+   *
54
+   * This file defines the MPU9150 interface for libmpu9150
55
+   *
56
+   * @image html mpu9150.jpg
57
+   * @snippet mpu9150.cxx Interesting
58
+   */
59
+
60
+  class MPU9150: public MPU60X0
61
+  {
62
+  public:
63
+    /**
64
+     * MPU9150 constructor
65
+     *
66
+     * @param bus i2c bus to use
67
+     * @param address the address for this device
68
+     * @param magAddress the address of the connected magnetometer
69
+     */
70
+    MPU9150 (int bus=MPU9150_I2C_BUS, int address=MPU9150_DEFAULT_I2C_ADDR,
71
+             int magAddress=AK8975_DEFAULT_I2C_ADDR);
72
+
73
+    /**
74
+     * MPU9150 Destructor
75
+     */
76
+    ~MPU9150 ();
77
+
78
+    /**
79
+     * set up initial values and start operation
80
+     *
81
+     * @return true if successful
82
+     */
83
+    bool init();
84
+
85
+    /**
86
+     * take a measurement and store the current sensor values
87
+     * internally.  Note, these user facing registers are only updated
88
+     * from the internal device sensor values when the i2c serial
89
+     * traffic is 'idle'.  So, if you are reading the values too fast,
90
+     * the bus may never be idle, and you will just end up reading
91
+     * the same values over and over.
92
+     *
93
+     * Unfortunately, it is is not clear how long 'idle' actually
94
+     * means, so if you see this behavior, reduce the rate at which
95
+     * you are calling update().
96
+     */
97
+    void update();
98
+
99
+    /**
100
+     * return the compensated values for the x, y, and z axes.  The
101
+     * unit of measurement is in micro-teslas (uT).
102
+     *
103
+     * @param x pointer to returned X axis value
104
+     * @param y pointer to returned Y axis value
105
+     * @param z pointer to returned Z axis value
106
+     */
107
+    void getMagnetometer(float *x, float *y, float *z);
108
+
109
+
110
+  protected:
111
+    // magnetometer instance
112
+    AK8975* m_mag;
113
+
114
+
115
+  private:
116
+    int m_i2cBus;
117
+    uint8_t m_magAddress;
118
+  };
210 119
 
211 120
 }

+ 14
- 0
src/mpu9150/pyupm_mpu9150.i View File

@@ -1,11 +1,25 @@
1 1
 %module pyupm_mpu9150
2 2
 %include "../upm.i"
3
+%include "cpointer.i"
3 4
 
4 5
 %include "stdint.i"
5 6
 
6 7
 %feature("autodoc", "3");
7 8
 
9
+%pointer_functions(float, floatp);
10
+
11
+%include "ak8975.h"
12
+%{
13
+    #include "ak8975.h"
14
+%}
15
+
16
+%include "mpu60x0.h"
17
+%{
18
+    #include "mpu60x0.h"
19
+%}
20
+
8 21
 %include "mpu9150.h"
9 22
 %{
10 23
     #include "mpu9150.h"
11 24
 %}
25
+