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/common.hpp> 28 #include <mraa/i2c.hpp> 29 30 #define AK8975_I2C_BUS 0 31 #define AK8975_DEFAULT_I2C_ADDR 0x0c 32 33 namespace upm { 34 35 /** 36 * @library mpu9150 37 * @sensor ak8975 38 * @comname AK8975 3-axis Magnetometer 39 * @altname AK9875 40 * @type compass 41 * @man grove 42 * @con i2c 43 * 44 * @brief API for the AK8975 magnetometer 45 * 46 * This is a 3-axis magnetometer, which can be used alone, or 47 * coupled with another device (such as the mcu9150 9-axis motion 48 * sensor). 49 * 50 * @snippet ak8975.cxx Interesting 51 */ 52 class AK8975 { 53 public: 54 55 /** 56 * AK8975 registers 57 */ 58 typedef enum { 59 REG_WIA = 0x00, // device id 60 61 REG_INFO = 0x01, // undocumented (AK proprietary data) 62 63 REG_ST1 = 0x02, // status 1 64 65 REG_HXL = 0x03, // magnetometer data, X axis low byte 66 REG_HXH = 0x04, // magnetometer data, X axis high byte 67 REG_HYL = 0x05, 68 REG_HYH = 0x06, 69 REG_HZL = 0x07, 70 REG_HZH = 0x08, 71 72 REG_ST2 = 0x09, // status 2 73 74 REG_CNTL = 0x0a, // control 75 76 // REG_RSV 0x0b reserved 77 78 REG_ASTC = 0x0c, // self test (internal mag field) 79 80 // REG_TS1, REG_TS2 0x0d, 0x0e reserved/factory test 81 82 // REG_I2CDIS 0x0f, I2C disable. Not a good idea to use or support. 83 // write a 0x1b to disable i2c. This requires a power cycle to undo. 84 85 // These registers hold factory calibrated co-efficients needed to 86 // properly compensate for production variations. They can only be 87 // read when device is in fuse mode. They are used to adjust the 88 // measured mag field values. 89 REG_ASAX = 0x10, // X calibration 90 REG_ASAY = 0x11, 91 REG_ASAZ = 0x12 92 } AK8975_REG_T; 93 94 /** 95 * ST1 bits 96 */ 97 typedef enum { 98 ST1_DRDY = 0x01 // data ready bit 99 } ST1_BITS_T; 100 101 /** 102 * ST2 bits 103 */ 104 typedef enum { 105 ST2_DERR = 0x04, // data error 106 ST2_HOFL = 0x08 // measurement overflow 107 } ST2_BITS_T; 108 109 /** 110 * CNTL register, operating mode values 111 */ 112 typedef enum { 113 CNTL_PWRDWN = 0x00, // power down 114 CNTL_MEASURE = 0x01, // single measurement 115 CNTL_SELFTEST = 0x08, 116 CNTL_FUSE_ACCESS = 0x0f // access fuse (coeff) registers 117 } CNTL_MODES_T; 118 119 /** 120 * ASTC (self test control) bits 121 */ 122 typedef enum { 123 ASTC_SELF = 0x40 // enable self test 124 } ASTC_BITS_T; 125 126 /** 127 * ak8975 constructor 128 * 129 * @param bus i2c bus to use 130 * @param address the address for this device 131 */ 132 AK8975(int bus=AK8975_I2C_BUS, uint8_t address=AK8975_DEFAULT_I2C_ADDR); 133 134 /** 135 * AK8975 Destructor 136 */ 137 ~AK8975(); 138 139 /** 140 * set up initial values and start operation 141 * 142 * @param dsr the data sampling rate: one of the DSR_BITS_T values 143 * @return true if successful 144 */ 145 bool init(); 146 147 /** 148 * put the chip into a specific mode 149 * 150 * @param mode one of the CNTL_MODES_T values 151 * @return true if successful 152 */ 153 bool setMode(CNTL_MODES_T mode); 154 155 /** 156 * check to see if the ST1_DRDY bit is set, indicating the device 157 * can accept commands 158 * 159 * @return true if device is ready, false otherwise 160 */ 161 bool isReady(); 162 163 /** 164 * check to see if device is ready and sleep/retry if not. 165 * Returns once device indicates it's ready. 166 * 167 * @return true if device is ready, false if retries exhausted 168 */ 169 bool waitforDeviceReady(); 170 171 /** 172 * take a measurement 173 * 174 * @param selfTest true if we are running a self test, false 175 * (default) otherwise. 176 * @return true if successful, false otherwise 177 */ 178 bool update(bool selfTest=false); 179 180 /** 181 * do a self test sequence. When self test is executed, the 182 * device activates internal calibrated magnets, and measures 183 * them, updating the measurement registers. Once complete, the 184 * data can be read as usual (getMagnetometer()) and the returned 185 * values compared against the following limits to determine 186 * correctness: 187 * 188 * -100 < X < +100; -100 < Y < +100; -1000 < Z < -300 189 * 190 * @return true if successful, false otherwise 191 */ 192 bool selfTest(); 193 194 /** 195 * return the compensated values for the x, y, and z axes. The 196 * unit of measurement is in micro-teslas (uT). 197 * 198 * @param x pointer to returned X axis value 199 * @param y pointer to returned Y axis value 200 * @param z pointer to returned Z axis value 201 */ 202 void getMagnetometer(float *x, float *y, float *z); 203 204 205 protected: 206 /** 207 * compute a compensated magnetometer axis value, based on the raw 208 * axis value and a per-device, per-axis adjustment coefficient 209 * that was read and stored at init() time. 210 * 211 * @param value the raw axis value to compensate 212 * @param adj the adjustment coefficient 213 * @return true if successful 214 */ 215 float adjustValue(float value, float adj); 216 217 // compensation coefficients (factory set) for this device 218 float m_xCoeff; 219 float m_yCoeff; 220 float m_zCoeff; 221 222 // uncompensated magnetometer readings 223 float m_xData; 224 float m_yData; 225 float m_zData; 226 227 private: 228 mraa::I2c m_i2c; 229 uint8_t m_addr; 230 231 }; 232 } 233 234 235