mirror of
https://github.com/eclipse/upm.git
synced 2025-03-16 05:27:28 +03:00

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>
234 lines
6.7 KiB
C++
234 lines
6.7 KiB
C++
/*
|
|
* 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.
|
|
*/
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <mraa/i2c.hpp>
|
|
|
|
#define AK8975_I2C_BUS 0
|
|
#define AK8975_DEFAULT_I2C_ADDR 0x0c
|
|
|
|
namespace upm {
|
|
|
|
/**
|
|
* @library mpu9150
|
|
* @sensor ak8975
|
|
* @comname AK8975 3-axis Magnetometer
|
|
* @altname AK9875
|
|
* @type compass
|
|
* @man grove
|
|
* @con i2c
|
|
*
|
|
* @brief API for the AK8975 magnetometer
|
|
*
|
|
* This is a 3-axis magnetometer, which can be used alone, or
|
|
* coupled with another device (such as the mcu9150 9-axis motion
|
|
* sensor).
|
|
*
|
|
* @snippet ak8975.cxx Interesting
|
|
*/
|
|
class AK8975 {
|
|
public:
|
|
|
|
/**
|
|
* AK8975 registers
|
|
*/
|
|
typedef enum {
|
|
REG_WIA = 0x00, // device id
|
|
|
|
REG_INFO = 0x01, // undocumented (AK proprietary data)
|
|
|
|
REG_ST1 = 0x02, // status 1
|
|
|
|
REG_HXL = 0x03, // magnetometer data, X axis low byte
|
|
REG_HXH = 0x04, // magnetometer data, X axis high byte
|
|
REG_HYL = 0x05,
|
|
REG_HYH = 0x06,
|
|
REG_HZL = 0x07,
|
|
REG_HZH = 0x08,
|
|
|
|
REG_ST2 = 0x09, // status 2
|
|
|
|
REG_CNTL = 0x0a, // control
|
|
|
|
// REG_RSV 0x0b reserved
|
|
|
|
REG_ASTC = 0x0c, // self test (internal mag field)
|
|
|
|
// REG_TS1, REG_TS2 0x0d, 0x0e reserved/factory test
|
|
|
|
// REG_I2CDIS 0x0f, I2C disable. Not a good idea to use or support.
|
|
// write a 0x1b to disable i2c. This requires a power cycle to undo.
|
|
|
|
// These registers hold factory calibrated co-efficients needed to
|
|
// properly compensate for production variations. They can only be
|
|
// read when device is in fuse mode. They are used to adjust the
|
|
// measured mag field values.
|
|
REG_ASAX = 0x10, // X calibration
|
|
REG_ASAY = 0x11,
|
|
REG_ASAZ = 0x12
|
|
} AK8975_REG_T;
|
|
|
|
/**
|
|
* ST1 bits
|
|
*/
|
|
typedef enum {
|
|
ST1_DRDY = 0x01 // data ready bit
|
|
} ST1_BITS_T;
|
|
|
|
/**
|
|
* ST2 bits
|
|
*/
|
|
typedef enum {
|
|
ST2_DERR = 0x04, // data error
|
|
ST2_HOFL = 0x08 // measurement overflow
|
|
} ST2_BITS_T;
|
|
|
|
/**
|
|
* CNTL register, operating mode values
|
|
*/
|
|
typedef enum {
|
|
CNTL_PWRDWN = 0x00, // power down
|
|
CNTL_MEASURE = 0x01, // single measurement
|
|
CNTL_SELFTEST = 0x08,
|
|
CNTL_FUSE_ACCESS = 0x0f // access fuse (coeff) registers
|
|
} CNTL_MODES_T;
|
|
|
|
/**
|
|
* ASTC (self test control) bits
|
|
*/
|
|
typedef enum {
|
|
ASTC_SELF = 0x40 // enable self test
|
|
} ASTC_BITS_T;
|
|
|
|
/**
|
|
* ak8975 constructor
|
|
*
|
|
* @param bus i2c bus to use
|
|
* @param address the address for this device
|
|
*/
|
|
AK8975(int bus=AK8975_I2C_BUS, uint8_t address=AK8975_DEFAULT_I2C_ADDR);
|
|
|
|
/**
|
|
* AK8975 Destructor
|
|
*/
|
|
~AK8975();
|
|
|
|
/**
|
|
* set up initial values and start operation
|
|
*
|
|
* @param dsr the data sampling rate: one of the DSR_BITS_T values
|
|
* @return true if successful
|
|
*/
|
|
bool init();
|
|
|
|
/**
|
|
* put the chip into a specific mode
|
|
*
|
|
* @param mode one of the CNTL_MODES_T values
|
|
* @return true if successful
|
|
*/
|
|
bool setMode(CNTL_MODES_T mode);
|
|
|
|
/**
|
|
* check to see if the ST1_DRDY bit is set, indicating the device
|
|
* can accept commands
|
|
*
|
|
* @return true if device is ready, false otherwise
|
|
*/
|
|
bool isReady();
|
|
|
|
/**
|
|
* check to see if device is ready and sleep/retry if not.
|
|
* Returns once device indicates it's ready.
|
|
*
|
|
* @return true if device is ready, false if retries exhausted
|
|
*/
|
|
bool waitforDeviceReady();
|
|
|
|
/**
|
|
* take a measurement
|
|
*
|
|
* @param selfTest true if we are running a self test, false
|
|
* (default) otherwise.
|
|
* @return true if successful, false otherwise
|
|
*/
|
|
bool update(bool selfTest=false);
|
|
|
|
/**
|
|
* do a self test sequence. When self test is executed, the
|
|
* device activates internal calibrated magnets, and measures
|
|
* them, updating the measurement registers. Once complete, the
|
|
* data can be read as usual (getMagnetometer()) and the returned
|
|
* values compared against the following limits to determine
|
|
* correctness:
|
|
*
|
|
* -100 < X < +100; -100 < Y < +100; -1000 < Z < -300
|
|
*
|
|
* @return true if successful, false otherwise
|
|
*/
|
|
bool selfTest();
|
|
|
|
/**
|
|
* return the compensated values for the x, y, and z axes. The
|
|
* unit of measurement is in micro-teslas (uT).
|
|
*
|
|
* @param x pointer to returned X axis value
|
|
* @param y pointer to returned Y axis value
|
|
* @param z pointer to returned Z axis value
|
|
*/
|
|
void getMagnetometer(float *x, float *y, float *z);
|
|
|
|
|
|
protected:
|
|
/**
|
|
* compute a compensated magnetometer axis value, based on the raw
|
|
* axis value and a per-device, per-axis adjustment coefficient
|
|
* that was read and stored at init() time.
|
|
*
|
|
* @param value the raw axis value to compensate
|
|
* @param adj the adjustment coefficient
|
|
* @return true if successful
|
|
*/
|
|
float adjustValue(float value, float adj);
|
|
|
|
// compensation coefficients (factory set) for this device
|
|
float m_xCoeff;
|
|
float m_yCoeff;
|
|
float m_zCoeff;
|
|
|
|
// uncompensated magnetometer readings
|
|
float m_xData;
|
|
float m_yData;
|
|
float m_zData;
|
|
|
|
private:
|
|
mraa::I2c m_i2c;
|
|
uint8_t m_addr;
|
|
|
|
};
|
|
}
|
|
|
|
|