lsm9ds0: Initial implementation

This module implements support for the LSM9DS0 accelerometer,
magnetometer, and gyroscope.

It was developed on the Sparkfun 9DOF sensor block for Intel Edison.

https://www.sparkfun.com/products/13033

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.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
This commit is contained in:
Jon Trulson 2015-07-31 16:17:49 -06:00 committed by Mihai Tudor Panu
parent 03e72e02f8
commit 36b0e1dce0
9 changed files with 2468 additions and 0 deletions

View File

@ -131,6 +131,7 @@ add_executable (pn532-writeurl-example pn532-writeurl.cxx)
add_executable (sainsmartks-example sainsmartks.cxx)
add_executable (mpu60x0-example mpu60x0.cxx)
add_executable (ak8975-example ak8975.cxx)
add_executable (lsm9ds0-example lsm9ds0.cxx)
include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l)
include_directories (${PROJECT_SOURCE_DIR}/src/grove)
@ -236,6 +237,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/grovecircularled)
include_directories (${PROJECT_SOURCE_DIR}/src/rgbringcoder)
include_directories (${PROJECT_SOURCE_DIR}/src/hp20x)
include_directories (${PROJECT_SOURCE_DIR}/src/pn532)
include_directories (${PROJECT_SOURCE_DIR}/src/lsm9ds0)
target_link_libraries (hmc5883l-example hmc5883l ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (groveled-example grove ${CMAKE_THREAD_LIBS_INIT})
@ -368,3 +370,4 @@ target_link_libraries (pn532-writeurl-example pn532 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (sainsmartks-example i2clcd ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (mpu60x0-example mpu9150 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (ak8975-example mpu9150 ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (lsm9ds0-example lsm9ds0 ${CMAKE_THREAD_LIBS_INIT})

83
examples/c++/lsm9ds0.cxx Normal file
View File

@ -0,0 +1,83 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2015 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <iostream>
#include <signal.h>
#include "lsm9ds0.h"
using namespace std;
int shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
//! [Interesting]
// Instantiate an LSM9DS0 using default parameters (bus 1, gyro addr 6b,
// xm addr 1d)
upm::LSM9DS0 *sensor = new upm::LSM9DS0();
sensor->init();
while (shouldRun)
{
sensor->update();
float x, y, z;
sensor->getAccelerometer(&x, &y, &z);
cout << "Accelerometer: ";
cout << "AX: " << x << " AY: " << y << " AZ: " << z << endl;
sensor->getGyroscope(&x, &y, &z);
cout << "Gryoscope: ";
cout << "GX: " << x << " GY: " << y << " GZ: " << z << endl;
sensor->getMagnetometer(&x, &y, &z);
cout << "Magnetometer: ";
cout << "MX = " << x << " MY = " << y << " MZ = " << z << endl;
cout << "Temperature: " << sensor->getTemperature() << endl;
cout << endl;
usleep(500000);
}
//! [Interesting]
cout << "Exiting..." << endl;
delete sensor;
return 0;
}

View File

@ -0,0 +1,77 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2015 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var sensorObj = require('jsupm_lsm9ds0');
// Instantiate an LSM9DS0 using default parameters (bus 1, gyro addr 6b,
// xm addr 1d)
var sensor = new sensorObj.LSM9DS0();
// Initialize the device with default values
sensor.init();
var x = new sensorObj.new_floatp();
var y = new sensorObj.new_floatp();
var z = new sensorObj.new_floatp();
// Output data every half second until interrupted
setInterval(function()
{
sensor.update();
sensor.getAccelerometer(x, y, z);
console.log("Accelerometer: AX: " + sensorObj.floatp_value(x) +
" AY: " + sensorObj.floatp_value(y) +
" AZ: " + sensorObj.floatp_value(z));
sensor.getGyroscope(x, y, z);
console.log("Gyroscope: GX: " + sensorObj.floatp_value(x) +
" AY: " + sensorObj.floatp_value(y) +
" AZ: " + sensorObj.floatp_value(z));
sensor.getMagnetometer(x, y, z);
console.log("Magnetometer: MX: " + sensorObj.floatp_value(x) +
" MY: " + sensorObj.floatp_value(y) +
" MZ: " + sensorObj.floatp_value(z));
console.log("Temperature: " + sensor.getTemperature());
console.log();
}, 500);
// exit on ^C
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting.");
process.exit(0);
});

View File

@ -0,0 +1,71 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2015 Intel Corporation.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import time, sys, signal, atexit
import pyupm_lsm9ds0 as sensorObj
# Instantiate an LSM9DS0 using default parameters (bus 1, gyro addr 6b,
# xm addr 1d)
sensor = sensorObj.LSM9DS0()
## Exit handlers ##
# This function stops python from printing a stacktrace when you hit control-C
def SIGINTHandler(signum, frame):
raise SystemExit
# This function lets you run code on exit
def exitHandler():
print "Exiting"
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
sensor.init()
x = sensorObj.new_floatp()
y = sensorObj.new_floatp()
z = sensorObj.new_floatp()
while (1):
sensor.update()
sensor.getAccelerometer(x, y, z)
print "Accelerometer: AX: ", sensorObj.floatp_value(x),
print " AY: ", sensorObj.floatp_value(y),
print " AZ: ", sensorObj.floatp_value(z)
sensor.getGyroscope(x, y, z)
print "Gyroscope: GX: ", sensorObj.floatp_value(x),
print " GY: ", sensorObj.floatp_value(y),
print " GZ: ", sensorObj.floatp_value(z)
sensor.getMagnetometer(x, y, z)
print "Magnetometer: MX: ", sensorObj.floatp_value(x),
print " MY: ", sensorObj.floatp_value(y),
print " MZ: ", sensorObj.floatp_value(z)
print "Temperature: ", sensor.getTemperature()
print
time.sleep(.5)

View File

@ -0,0 +1,5 @@
set (libname "lsm9ds0")
set (libdescription "gyro, accelerometer and magnometer sensor based on lsm9ds0")
set (module_src ${libname}.cxx)
set (module_h ${libname}.h)
upm_module_init()

View File

@ -0,0 +1,11 @@
%module jsupm_lsm9ds0
%include "../upm.i"
%include "cpointer.i"
%pointer_functions(float, floatp);
%include "lsm9ds0.h"
%{
#include "lsm9ds0.h"
%}

751
src/lsm9ds0/lsm9ds0.cxx Normal file
View File

@ -0,0 +1,751 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2015 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <iostream>
#include <exception>
#include <string.h>
#include "lsm9ds0.h"
using namespace upm;
using namespace std;
LSM9DS0::LSM9DS0(int bus, uint8_t gAddress, uint8_t xmAddress) :
m_i2cG(bus), m_i2cXM(bus), m_gpioG_INT(0), m_gpioG_DRDY(0),
m_gpioXM_GEN1(0), m_gpioXM_GEN2(0)
{
m_gAddr = gAddress;
m_xmAddr = xmAddress;
m_accelX = 0.0;
m_accelY = 0.0;
m_accelZ = 0.0;
m_gyroX = 0.0;
m_gyroY = 0.0;
m_gyroZ = 0.0;
m_magX = 0.0;
m_magY = 0.0;
m_magZ = 0.0;
m_temp = 0.0;
m_accelScale = 0.0;
m_gyroScale = 0.0;
m_magScale = 0.0;
mraa_result_t rv;
if ( (rv = m_i2cG.address(m_gAddr)) != MRAA_SUCCESS)
{
cerr << __FUNCTION__ << ": Could not initialize Gyro i2c address."
<< endl;
mraa_result_print(rv);
throw std::runtime_error(string(__FUNCTION__) +
": Could not initialize Gyro i2c address");
return;
}
if ( (rv = m_i2cXM.address(m_xmAddr)) != MRAA_SUCCESS)
{
cerr << __FUNCTION__ << ": Could not initialize XM i2c address. " << endl;
mraa_result_print(rv);
throw std::runtime_error(string(__FUNCTION__) +
": Could not initialize XM i2c address");
return;
}
}
LSM9DS0::~LSM9DS0()
{
uninstallISR(INTERRUPT_G_INT);
uninstallISR(INTERRUPT_G_DRDY);
uninstallISR(INTERRUPT_XM_GEN1);
uninstallISR(INTERRUPT_XM_GEN2);
}
bool LSM9DS0::init()
{
// Init the gyroscope
// power up
if (!setGyroscopePowerDown(false))
{
cerr << __FUNCTION__ << ": Unable to wake up gyro" << endl;
return false;
}
// enable all axes
if (!setGyroscopeEnableAxes(CTRL_REG1_G_YEN |CTRL_REG1_G_XEN |
CTRL_REG1_G_ZEN))
{
cerr << __FUNCTION__ << ": Unable to enable gyro axes" << endl;
return false;
}
// set gyro ODR
if (!setGyroscopeODR(G_ODR_95_25))
{
cerr << __FUNCTION__ << ": Unable to set gyro ODR" << endl;
return false;
}
// set gyro scale
if (!setGyroscopeScale(G_FS_245))
{
cerr << __FUNCTION__ << ": Unable to set gyro scale" << endl;
return false;
}
// Init the accelerometer
// power up and set ODR
if (!setAccelerometerODR(XM_AODR_100))
{
cerr << __FUNCTION__ << ": Unable to set accel ODR" << endl;
return false;
}
// enable all axes
if (!setAccelerometerEnableAxes(CTRL_REG1_XM_AXEN |CTRL_REG1_XM_AYEN |
CTRL_REG1_XM_AZEN))
{
cerr << __FUNCTION__ << ": Unable to enable accel axes" << endl;
return false;
}
// set scaling rate
if (!setAccelerometerScale(XM_AFS_2))
{
cerr << __FUNCTION__ << ": Unable to set accel scale" << endl;
return false;
}
// temperature sensor
// enable the temperature sensor
if (!enableTemperatureSensor(true))
{
cerr << __FUNCTION__ << ": Unable to enable temp sensor" << endl;
return false;
}
// Init the magnetometer
// set mode (this also powers it up if not XM_MD_POWERDOWN)
if (!setMagnetometerMode(XM_MD_CONTINUOUS))
{
cerr << __FUNCTION__ << ": Unable to set mag scale" << endl;
return false;
}
// turn LPM off
if (!setMagnetometerLPM(false))
{
cerr << __FUNCTION__ << ": Unable to disable mag LPM" << endl;
return false;
}
// set resolution
if (!setMagnetometerResolution(XM_RES_LOW))
{
cerr << __FUNCTION__ << ": Unable to set mag res" << endl;
return false;
}
// set ODR
if (!setMagnetometerODR(XM_ODR_12_5))
{
cerr << __FUNCTION__ << ": Unable to set mag ODR" << endl;
return false;
}
// set scale
if (!setMagnetometerScale(XM_MFS_2))
{
cerr << __FUNCTION__ << ": Unable to set mag scale" << endl;
return false;
}
return true;
}
void LSM9DS0::update()
{
updateGyroscope();
updateAccelerometer();
updateMagnetometer();
updateTemperature();
}
void LSM9DS0::updateGyroscope()
{
uint8_t buffer[6];
memset(buffer, 0, 6);
readRegs(DEV_GYRO, REG_OUT_X_L_G, buffer, 6);
int16_t x, y, z;
x = ( (buffer[1] << 8) | buffer[0] );
y = ( (buffer[3] << 8) | buffer[2] );
z = ( (buffer[5] << 8) | buffer[4] );
m_gyroX = float(x);
m_gyroY = float(y);
m_gyroZ = float(z);
}
void LSM9DS0::updateAccelerometer()
{
uint8_t buffer[6];
memset(buffer, 0, 6);
readRegs(DEV_XM, REG_OUT_X_L_A, buffer, 6);
int16_t x, y, z;
x = ( (buffer[1] << 8) | buffer[0] );
y = ( (buffer[3] << 8) | buffer[2] );
z = ( (buffer[5] << 8) | buffer[4] );
m_accelX = float(x);
m_accelY = float(y);
m_accelZ = float(z);
}
void LSM9DS0::updateMagnetometer()
{
uint8_t buffer[6];
memset(buffer, 0, 6);
readRegs(DEV_XM, REG_OUT_X_L_M, buffer, 6);
int16_t x, y, z;
x = ( (buffer[1] << 8) | buffer[0] );
y = ( (buffer[3] << 8) | buffer[2] );
z = ( (buffer[5] << 8) | buffer[4] );
m_magX = float(x);
m_magY = float(y);
m_magZ = float(z);
}
void LSM9DS0::updateTemperature()
{
uint8_t buffer[2];
memset(buffer, 0, 2);
readRegs(DEV_XM, REG_OUT_TEMP_L_XM, buffer, 2);
// cerr << "HIGH: " << int(buffer[1]) << " LOW: " << int(buffer[0]) << endl;
// 12b signed
int16_t temp = ( (buffer[1] << 8) | (buffer[0] ) );
if (temp & 0x0800)
{
temp &= ~0x0800;
temp *= -1;
}
m_temp = float(temp);
}
uint8_t LSM9DS0::readReg(DEVICE_T dev, uint8_t reg)
{
mraa::I2c *device;
switch(dev)
{
case DEV_GYRO: device = &m_i2cG; break;
case DEV_XM: device = &m_i2cXM; break;
default:
cerr << __FUNCTION__ << ": Internal error, invalid device" << endl;
return 0;
}
return device->readReg(reg);
}
void LSM9DS0::readRegs(DEVICE_T dev, uint8_t reg, uint8_t *buf, int len)
{
mraa::I2c *device;
switch(dev)
{
case DEV_GYRO: device = &m_i2cG; break;
case DEV_XM: device = &m_i2cXM; break;
default:
cerr << __FUNCTION__ << ": Internal error, invalid device" << endl;
return;
}
// We need to set the high bit of the register to enable
// auto-increment mode for reading multiple registers in one go.
device->readBytesReg(reg | m_autoIncrementMode, buf, len);
}
bool LSM9DS0::writeReg(DEVICE_T dev, uint8_t reg, uint8_t val)
{
mraa::I2c *device;
switch(dev)
{
case DEV_GYRO: device = &m_i2cG; break;
case DEV_XM: device = &m_i2cXM; break;
default:
cerr << __FUNCTION__ << ": Internal error, invalid device" << endl;
return false;
}
mraa_result_t rv;
if ((rv = device->writeReg(reg, val)) != MRAA_SUCCESS)
{
cerr << __FUNCTION__ << ": failed:" << endl;
mraa_result_print(rv);
return false;
}
return true;
}
bool LSM9DS0::setGyroscopePowerDown(bool enable)
{
uint8_t reg = readReg(DEV_GYRO, REG_CTRL_REG1_G);
if (enable)
reg &= ~CTRL_REG1_G_PD;
else
reg |= CTRL_REG1_G_PD;
return writeReg(DEV_GYRO, REG_CTRL_REG1_G, reg);
}
bool LSM9DS0::setGyroscopeEnableAxes(uint8_t axes)
{
uint8_t reg = readReg(DEV_GYRO, REG_CTRL_REG1_G);
// filter out any non-axis related data from arg
axes &= (CTRL_REG1_G_YEN | CTRL_REG1_G_XEN | CTRL_REG1_G_ZEN);
// clear them in the register
reg &= ~(CTRL_REG1_G_YEN | CTRL_REG1_G_XEN | CTRL_REG1_G_ZEN);
// now add them
reg |= axes;
return writeReg(DEV_GYRO, REG_CTRL_REG1_G, reg);
}
bool LSM9DS0::setGyroscopeODR(G_ODR_T odr)
{
uint8_t reg = readReg(DEV_GYRO, REG_CTRL_REG1_G);
reg &= ~(_CTRL_REG1_G_ODR_MASK << _CTRL_REG1_G_ODR_SHIFT);
reg |= (odr << _CTRL_REG1_G_ODR_SHIFT);
return writeReg(DEV_GYRO, REG_CTRL_REG1_G, reg);
}
bool LSM9DS0::setGyroscopeScale(G_FS_T scale)
{
uint8_t reg = readReg(DEV_GYRO, REG_CTRL_REG4_G);
reg &= ~(_CTRL_REG4_G_FS_MASK << _CTRL_REG4_G_FS_SHIFT);
reg |= (scale << _CTRL_REG4_G_FS_SHIFT);
if (!writeReg(DEV_GYRO, REG_CTRL_REG4_G, reg))
{
return false;
}
// store scaling factor (mDeg/s/LSB)
switch (scale)
{
case G_FS_245:
m_gyroScale = 8.75;
break;
case G_FS_500:
m_gyroScale = 17.5;
break;
case G_FS_2000:
m_gyroScale = 70.0;
break;
default: // should never occur, but...
m_gyroScale = 0.0; // set a safe, though incorrect value
cerr << __FUNCTION__ << ": internal error, unsupported scale" << endl;
break;
}
return true;
}
bool LSM9DS0::setAccelerometerEnableAxes(uint8_t axes)
{
uint8_t reg = readReg(DEV_XM, REG_CTRL_REG1_XM);
// filter out any non-axis related data from arg
axes &= (CTRL_REG1_XM_AXEN | CTRL_REG1_XM_AYEN | CTRL_REG1_XM_AZEN);
// clear them in the register
reg &= ~(CTRL_REG1_XM_AXEN | CTRL_REG1_XM_AYEN | CTRL_REG1_XM_AZEN);
// now add them
reg |= axes;
return writeReg(DEV_XM, REG_CTRL_REG1_XM, reg);
}
bool LSM9DS0::setAccelerometerODR(XM_AODR_T odr)
{
uint8_t reg = readReg(DEV_XM, REG_CTRL_REG1_XM);
reg &= ~(_CTRL_REG1_XM_AODR_MASK << _CTRL_REG1_XM_AODR_SHIFT);
reg |= (odr << _CTRL_REG1_XM_AODR_SHIFT);
return writeReg(DEV_XM, REG_CTRL_REG1_XM, reg);
}
bool LSM9DS0::setAccelerometerScale(XM_AFS_T scale)
{
uint8_t reg = readReg(DEV_XM, REG_CTRL_REG2_XM);
reg &= ~(_CTRL_REG2_XM_AFS_MASK << _CTRL_REG2_XM_AFS_SHIFT);
reg |= (scale << _CTRL_REG2_XM_AFS_SHIFT);
if (!writeReg(DEV_XM, REG_CTRL_REG2_XM, reg))
{
return false;
}
// store scaling factor
switch (scale)
{
case XM_AFS_2:
m_accelScale = 0.061;
break;
case XM_AFS_4:
m_accelScale = 0.122 ;
break;
case XM_AFS_6:
m_accelScale = 0.183 ;
break;
case XM_AFS_8:
m_accelScale = 0.244 ;
break;
case XM_AFS_16:
m_accelScale = 0.732 ;
break;
default: // should never occur, but...
m_accelScale = 0.0; // set a safe, though incorrect value
cerr << __FUNCTION__ << ": internal error, unsupported scale" << endl;
break;
}
return true;
}
bool LSM9DS0::setMagnetometerResolution(XM_RES_T res)
{
uint8_t reg = readReg(DEV_XM, REG_CTRL_REG5_XM);
reg &= ~(_CTRL_REG5_XM_RES_MASK << _CTRL_REG5_XM_RES_SHIFT);
reg |= (res << _CTRL_REG5_XM_RES_SHIFT);
return writeReg(DEV_XM, REG_CTRL_REG5_XM, reg);
}
bool LSM9DS0::setMagnetometerODR(XM_ODR_T odr)
{
uint8_t reg = readReg(DEV_XM, REG_CTRL_REG5_XM);
reg &= ~(_CTRL_REG5_XM_ODR_MASK << _CTRL_REG5_XM_ODR_SHIFT);
reg |= (odr << _CTRL_REG5_XM_ODR_SHIFT);
return writeReg(DEV_XM, REG_CTRL_REG5_XM, reg);
}
bool LSM9DS0::setMagnetometerMode(XM_MD_T mode)
{
uint8_t reg = readReg(DEV_XM, REG_CTRL_REG7_XM);
reg &= ~(_CTRL_REG7_XM_MD_MASK << _CTRL_REG7_XM_MD_SHIFT);
reg |= (mode << _CTRL_REG7_XM_MD_SHIFT);
return writeReg(DEV_XM, REG_CTRL_REG7_XM, reg);
}
bool LSM9DS0::setMagnetometerLPM(bool enable)
{
uint8_t reg = readReg(DEV_XM, REG_CTRL_REG7_XM);
if (enable)
reg |= CTRL_REG7_XM_MLP;
else
reg &= ~CTRL_REG7_XM_MLP;
return writeReg(DEV_XM, REG_CTRL_REG7_XM, reg);
}
bool LSM9DS0::setMagnetometerScale(XM_MFS_T scale)
{
uint8_t reg = readReg(DEV_XM, REG_CTRL_REG6_XM);
reg &= ~(_CTRL_REG6_XM_MFS_MASK << _CTRL_REG6_XM_MFS_SHIFT);
reg |= (scale << _CTRL_REG6_XM_MFS_SHIFT);
if (!writeReg(DEV_XM, REG_CTRL_REG6_XM, reg))
{
return false;
}
// store scaling factor
switch (scale)
{
case XM_MFS_2:
m_magScale = 0.08;
break;
case XM_MFS_4:
m_magScale = 0.16;
break;
case XM_MFS_8:
m_magScale = 0.32;
break;
case XM_MFS_12:
m_magScale = 0.48;
break;
default: // should never occur, but...
m_magScale = 0.0; // set a safe, though incorrect value
cerr << __FUNCTION__ << ": internal error, unsupported scale" << endl;
break;
}
return true;
}
void LSM9DS0::getAccelerometer(float *x, float *y, float *z)
{
if (x)
*x = (m_accelX * m_accelScale) / 1000.0;
if (y)
*y = (m_accelY * m_accelScale) / 1000.0;
if (z)
*z = (m_accelZ * m_accelScale) / 1000.0;
}
void LSM9DS0::getGyroscope(float *x, float *y, float *z)
{
if (x)
*x = (m_gyroX * m_gyroScale) / 1000.0;
if (y)
*y = (m_gyroY * m_gyroScale) / 1000.0;
if (z)
*z = (m_gyroZ * m_gyroScale) / 1000.0;
}
void LSM9DS0::getMagnetometer(float *x, float *y, float *z)
{
if (x)
*x = (m_magX * m_magScale) / 1000.0;
if (y)
*y = (m_magY * m_magScale) / 1000.0;
if (z)
*z = (m_magZ * m_magScale) / 1000.0;
}
float LSM9DS0::getTemperature()
{
// This might be wrong... The datasheet does not provide enough info
// to calculate the temperature given a specific sensor reading. So
// - with 12b resolution, signed, and 8 degrees/per LSB, we come up
// with the following. Then scale up and we get a number that seems
// pretty close.
return (((m_temp / 2048.0) * 8.0) * 100.0);
}
bool LSM9DS0::enableTemperatureSensor(bool enable)
{
uint8_t reg = readReg(DEV_XM, REG_CTRL_REG5_XM);
if (enable)
reg |= CTRL_REG5_XM_TEMP_EN;
else
reg &= ~CTRL_REG5_XM_TEMP_EN;
return writeReg(DEV_XM, REG_CTRL_REG5_XM, reg);
}
uint8_t LSM9DS0::getGyroscopeStatus()
{
return readReg(DEV_GYRO, REG_STATUS_REG_G);
}
uint8_t LSM9DS0::getMagnetometerStatus()
{
return readReg(DEV_XM, REG_STATUS_REG_M);
}
uint8_t LSM9DS0::getAccelerometerStatus()
{
return readReg(DEV_XM, REG_STATUS_REG_A);
}
uint8_t LSM9DS0::getGyroscopeInterruptConfig()
{
return readReg(DEV_GYRO, REG_INT1_CFG_G);
}
bool LSM9DS0::setGyroscopeInterruptConfig(uint8_t enables)
{
return writeReg(DEV_GYRO, REG_INT1_CFG_G, enables);
}
uint8_t LSM9DS0::getGyroscopeInterruptSrc()
{
return readReg(DEV_GYRO, REG_INT1_SRC_G);
}
uint8_t LSM9DS0::getMagnetometerInterruptControl()
{
return readReg(DEV_XM, REG_INT_CTRL_REG_M);
}
bool LSM9DS0::setMagnetometerInterruptControl(uint8_t enables)
{
return writeReg(DEV_XM, REG_INT_CTRL_REG_M, enables);
}
uint8_t LSM9DS0::getMagnetometerInterruptSrc()
{
return readReg(DEV_XM, REG_INT_SRC_REG_M);
}
uint8_t LSM9DS0::getInterruptGen1()
{
return readReg(DEV_XM, REG_INT_GEN_1_REG);
}
bool LSM9DS0::setInterruptGen1(uint8_t enables)
{
return writeReg(DEV_XM, REG_INT_GEN_1_REG, enables);
}
uint8_t LSM9DS0::getInterruptGen1Src()
{
return readReg(DEV_XM, REG_INT_GEN_1_SRC);
}
uint8_t LSM9DS0::getInterruptGen2()
{
return readReg(DEV_XM, REG_INT_GEN_2_REG);
}
bool LSM9DS0::setInterruptGen2(uint8_t enables)
{
return writeReg(DEV_XM, REG_INT_GEN_2_REG, enables);
}
uint8_t LSM9DS0::getInterruptGen2Src()
{
return readReg(DEV_XM, REG_INT_GEN_2_SRC);
}
void LSM9DS0::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
void (*isr)(void *), void *arg)
{
// delete any existing ISR and GPIO context
uninstallISR(intr);
// greate gpio context
getPin(intr) = new mraa::Gpio(gpio);
getPin(intr)->dir(mraa::DIR_IN);
getPin(intr)->isr(level, isr, arg);
}
void LSM9DS0::uninstallISR(INTERRUPT_PINS_T intr)
{
if (getPin(intr))
{
getPin(intr)->isrExit();
delete getPin(intr);
getPin(intr) = 0;
}
}
mraa::Gpio*& LSM9DS0::getPin(INTERRUPT_PINS_T intr)
{
switch(intr)
{
case INTERRUPT_G_INT:
return m_gpioG_INT;
break;
case INTERRUPT_G_DRDY:
return m_gpioG_DRDY;
break;
case INTERRUPT_XM_GEN1:
return m_gpioXM_GEN1;
break;
case INTERRUPT_XM_GEN2:
return m_gpioXM_GEN2;
break;
default:
throw std::logic_error(string(__FUNCTION__) +
": Invalid interrupt enum passed");
}
}

1452
src/lsm9ds0/lsm9ds0.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,15 @@
%module pyupm_lsm9ds0
%include "../upm.i"
%include "cpointer.i"
%include "stdint.i"
%feature("autodoc", "3");
%pointer_functions(float, floatp);
%include "lsm9ds0.h"
%{
#include "lsm9ds0.h"
%}