diff --git a/README.md b/README.md index 8e33d906..e4eb07a8 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Temperature Sensors: Compass/Gyro/Magnometer Sensors: * upm::Hmc5883l * upm::MPU9150 + * upm::LSM303 Atmospheric Pressure Sensors: * upm::GY65 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 820bf58e..4b720c80 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -35,6 +35,7 @@ add_executable (mq5-example mq5-example.cxx) add_executable (mq9-example mq9-example.cxx) add_executable (tcs3414cs-example tcs3414cs-example.cxx) add_executable (th02-example th02-example.cxx) +add_executable (lsm303-example lsm303.cxx) include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l) include_directories (${PROJECT_SOURCE_DIR}/src/grove) @@ -64,6 +65,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/ecs1030) include_directories (${PROJECT_SOURCE_DIR}/src/gas) include_directories (${PROJECT_SOURCE_DIR}/src/tcs3414cs) include_directories (${PROJECT_SOURCE_DIR}/src/th02) +include_directories (${PROJECT_SOURCE_DIR}/src/lsm303) target_link_libraries (compass hmc5883l ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (groveled grove ${CMAKE_THREAD_LIBS_INIT}) @@ -102,3 +104,4 @@ target_link_libraries (mq5-example gas ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (mq9-example gas ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (tcs3414cs-example tcs3414cs ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (th02-example th02 ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries (lsm303-example lsm303 ${CMAKE_THREAD_LIBS_INIT}) diff --git a/examples/lsm303.cxx b/examples/lsm303.cxx new file mode 100644 index 00000000..d578e187 --- /dev/null +++ b/examples/lsm303.cxx @@ -0,0 +1,44 @@ +/* + * Author: Brendan Le Foll + * Copyright (c) 2014 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 + +//! [Interesting] +#include "lsm303.h" + +int +main(int argc, char **argv) +{ + upm::LSM303 *sensor = new upm::LSM303(0); + + std::cout << sensor->getHeading() << std::endl; + + sensor->getAcceleration(); + uint8_t* accel = sensor->getRawAccelData(); + + std::cout << "X " << (int)accel[0] << " - Y " << (int)accel[1] << " - Z " << (int)accel[2] << std::endl; + + return 0; +} +//! [Interesting] diff --git a/examples/python/lsm303.py b/examples/python/lsm303.py new file mode 100644 index 00000000..69d77382 --- /dev/null +++ b/examples/python/lsm303.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +# Author: Brendan Le Foll +# Copyright (c) 2014 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 pyupm_lsm303 as lsm303 + +x = lsm303.LSM303(0) +x.getCoordinates() +x.getHeading() diff --git a/src/lsm303/CMakeLists.txt b/src/lsm303/CMakeLists.txt new file mode 100644 index 00000000..d97e58bb --- /dev/null +++ b/src/lsm303/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "lsm303") +set (libdescription "upm lsm303") +set (module_src ${libname}.cxx) +set (module_h ${libname}.h) +upm_module_init() diff --git a/src/lsm303/jsupm_lsm303.i b/src/lsm303/jsupm_lsm303.i new file mode 100644 index 00000000..f87e7f7e --- /dev/null +++ b/src/lsm303/jsupm_lsm303.i @@ -0,0 +1,8 @@ +%module jsupm_lsm303 +%include "../upm.i" + +%{ + #include "lsm303.h" +%} + +%include "lsm303.h" diff --git a/src/lsm303/lsm303.cxx b/src/lsm303/lsm303.cxx new file mode 100644 index 00000000..2f30e87d --- /dev/null +++ b/src/lsm303/lsm303.cxx @@ -0,0 +1,156 @@ +/* + * Author: Brendan Le Foll + * Copyright (c) 2014 Intel Corporation. + * + * Code based on LSM303DLH sample by Jim Lindblom SparkFun Electronics + * and the CompensatedCompass.ino by Frankie Chu from SeedStudio + * + * 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 +#include +#include + +#include "lsm303.h" + +using namespace upm; + +LSM303::LSM303(int bus, int addrMag, int addrAcc) +{ + mraa_result_t ret = MRAA_SUCCESS; + + m_addrMag = addrMag; + m_addrAcc = addrAcc; + + m_i2c = mraa_i2c_init(bus); + + buf[0] = CTRL_REG1_A; + buf[1] = 0x27; + ret = mraa_i2c_address(m_i2c, m_addrAcc); + ret = mraa_i2c_write(m_i2c, buf, 2); + + // 0x27 = normal power mode, all accel axes on + buf[0] = CTRL_REG1_A; + buf[1] = 0x27; + ret = mraa_i2c_address(m_i2c, m_addrAcc); + ret = mraa_i2c_write(m_i2c, buf, 2); + + // scale == 2, can be 4 or 8 + buf[0] = CTRL_REG4_A; + buf[1] = 0x00; + ret = mraa_i2c_address(m_i2c, m_addrAcc); + ret = mraa_i2c_write(m_i2c, buf, 2); + + // 0x14 = mag 30Hz output rate + buf[0] = CRA_REG_M; + buf[1] = 0x14; + ret = mraa_i2c_address(m_i2c, m_addrMag); + ret = mraa_i2c_write(m_i2c, buf, 2); + + // magnetic scale = +/-1.3Gaussmagnetic scale = +/-1.3Gauss + buf[0] = CRB_REG_M; + buf[1] = 0x20; // MAG_SCALE_1_3; + ret = mraa_i2c_address(m_i2c, m_addrMag); + ret = mraa_i2c_write(m_i2c, buf, 2); + + // 0x00 = continouous conversion mode + buf[0] = MR_REG_M; + buf[1] = 0x00; + ret = mraa_i2c_address(m_i2c, m_addrMag); + ret = mraa_i2c_write(m_i2c, buf, 2); +} + +LSM303::~LSM303() { + mraa_i2c_stop(m_i2c); +} + +float +LSM303::getHeading() +{ + if (getCoordinates() != MRAA_SUCCESS) { + return -1; + } + + float heading = 180 * atan2(coor[Y], coor[X])/M_PI; + + if (heading < 0) + heading += 360; + + return heading; +} + +uint8_t* +LSM303::getRawAccelData() +{ + return &accel[0]; +} + +uint8_t* +LSM303::getRawCoorData() +{ + return &coor[0]; +} + +mraa_result_t +LSM303::getCoordinates() +{ + mraa_result_t ret = MRAA_SUCCESS; + + memset(&buf[0], 0, sizeof(uint8_t)*6); + ret = mraa_i2c_address(m_i2c, m_addrMag); + ret = mraa_i2c_write_byte(m_i2c, OUT_X_H_M); + ret = mraa_i2c_address(m_i2c, m_addrMag); + int num = mraa_i2c_read(m_i2c, buf, 6); + if (num != 6) { + return ret; + } + // convert to coordinates + for (int i=0; i<3; i++) { + coor[i] = (buf[0*i] << 8) | buf[1*i]; + } + // note that coor array is in XZY order + //printf("X=%x, Y=%x, Z=%x\n", coor[X], coor[Y], coor[Z]); + + return ret; +} + +// helper function that writes a value to the acc and then reads +int +LSM303::readThenWrite(uint8_t reg) +{ + mraa_i2c_address(m_i2c, m_addrAcc); + mraa_i2c_write_byte(m_i2c, reg); + mraa_i2c_address(m_i2c, m_addrAcc); + return (int) mraa_i2c_read_byte(m_i2c); +} + +mraa_result_t +LSM303::getAcceleration() +{ + mraa_result_t ret = MRAA_SUCCESS; + + accel[2] = (readThenWrite(OUT_X_L_A) << 8) | (readThenWrite(OUT_X_H_A)); + accel[0] = (readThenWrite(OUT_Y_L_A) << 8) | (readThenWrite(OUT_Y_H_A)); + accel[1] = (readThenWrite(OUT_Z_L_A) << 8) | (readThenWrite(OUT_Z_H_A)); + //printf("X=%x, Y=%x, Z=%x\n", accel[X], accel[Y], accel[Z]); + + return ret; +} diff --git a/src/lsm303/lsm303.h b/src/lsm303/lsm303.h new file mode 100644 index 00000000..e607f24b --- /dev/null +++ b/src/lsm303/lsm303.h @@ -0,0 +1,129 @@ +/* + * Author: Brendan Le Foll + * Copyright (c) 2014 Intel Corporation. + * + * Code based on LSM303DLH sample by Jim Lindblom SparkFun Electronics + * and the CompensatedCompass.ino by Frankie Chu from SeedStudio + * + * 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. + */ +#pragma once + +#include +#include +#include + +namespace upm { + +/* LSM303 Address definitions */ +#define LSM303_MAG 0x1E // assuming SA0 grounded +#define LSM303_ACC 0x18 // assuming SA0 grounded + +/* LSM303 Register definitions */ +#define CTRL_REG1_A 0x20 +#define CTRL_REG2_A 0x21 +#define CTRL_REG3_A 0x22 +#define CTRL_REG4_A 0x23 +#define CTRL_REG5_A 0x24 + +#define CRA_REG_M 0x00 +#define CRB_REG_M 0x01 + +#define MR_REG_M 0x02 +#define OUT_X_H_M 0x03 + +#define OUT_X_L_A 0x28 +#define OUT_X_H_A 0x29 +#define OUT_Y_L_A 0x2A +#define OUT_Y_H_A 0x2B +#define OUT_Z_L_A 0x2C +#define OUT_Z_H_A 0x2D + +#define X 0 +#define Z 1 +#define Y 2 + +/** + * @brief C++ API for LSM303 + * + * This file defines the LSM303DLH 3-axis magnetometer/3-axis accelerometer. + * This module was tested with the SeedStudio Grove [6-Axis Accelerometer&Compass] + * (http://www.seeedstudio.com/wiki/Grove_-_6-Axis_Accelerometer%26Compass) + * module that is used over i2c. The magnometer and acceleromter are accessed + * at two seperate i2c addresses. + * + * @snippet lsm303.cxx Interesting + * @image html lsm303.jpeg + */ +class LSM303 { + public: + /** + * Instanciates a LSM303 object + * + * @param i2c bus + * @param addr magometer + * @param addr accelerometer + */ + LSM303 (int bus, int addrMag=LSM303_MAG, int addrAcc=LSM303_ACC); + + /** + * LSM303 object destructor + */ + ~LSM303 (); + + /** + * Get Current Heading, headings <0 indicate an error occured + * + * @return float + */ + float getHeading(); + + /** + * Get the coordinates in XYZ order + */ + mraa_result_t getCoordinates(); + + /** + * Get accelerometer values + */ + mraa_result_t getAcceleration(); + + /** + * Get the raw coordinate data, this will get updated when getCoordinates() is called + */ + uint8_t* getRawCoorData(); + + /** + * Get the raw accelerometer data, this will get updated when getAcceleration() is called + */ + uint8_t* getRawAccelData(); + + private: + int readThenWrite(uint8_t reg); + + mraa_i2c_context m_i2c; + int m_addrMag; + int m_addrAcc; + uint8_t buf[6]; + uint8_t coor[3]; + uint8_t accel[3]; +}; + +} diff --git a/src/lsm303/pyupm_lsm303.i b/src/lsm303/pyupm_lsm303.i new file mode 100644 index 00000000..20ded881 --- /dev/null +++ b/src/lsm303/pyupm_lsm303.i @@ -0,0 +1,9 @@ +%module pyupm_lsm303 +%include "../upm.i" + +%feature("autodoc", "3"); + +%include "lsm303.h" +%{ + #include "lsm303.h" +%}