Jeremiah Mattison / Rm3100

Dependents:   Hello_RM3100 RM3100

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Rm3100.hpp Source File

Rm3100.hpp

00001 #ifndef RM3100_HPP
00002 #define RM3100_HPP
00003 
00004 #include <stdint.h>
00005 #include "mbed.h"
00006 
00007 /**
00008  * An interface for the RM3100 3-axis magnetometer from PNI Sensor Corp.
00009  *
00010  * @code
00011  * #include "mbed.h"
00012  * #include "Rm3100.hpp"
00013  * 
00014  * int main(void)
00015  * {
00016  *     Serial pc(USBTX, USBRX);
00017  *     pc.baud(115200);
00018  * 
00019  *     printf("### Hello RM3100 ###\r\n");
00020  * 
00021  *     int addr = ((Rm3100::RM3100_ADDR | Rm3100::RM3100_ADDR_SSN) << 1);
00022  *     struct Rm3100::Status status = { 0 };
00023  *     struct Rm3100::Sample sample = { 0 };
00024  * 
00025  *     Rm3100 sensor(I2C_SDA, I2C_SCL, addr);
00026  * 
00027  *     sensor.Begin();
00028  *     osDelay(1);
00029  * 
00030  *     sensor.SetCycleCounts(200);
00031  *     osDelay(1);
00032  * 
00033  *     sensor.SetRate(100.0f);
00034  *     osDelay(1);
00035  * 
00036  *     sensor.SetContinuousMeasurementMode(true);
00037  *     osDelay(1);
00038  * 
00039  *     while (true) {
00040  *         sensor.GetStatus(&status);
00041  *         if (status.drdy) {
00042  *             sensor.GetSample(&sample);
00043  *             printf("x: %f, y: %f, z: %f\r\n", sample.x, sample.y, sample.z);
00044  *         }
00045  *         osDelay(10);
00046  *     }
00047  * }
00048  * @endcode
00049  */
00050 class Rm3100
00051 {
00052 public:
00053 
00054     enum ReturnCode {
00055         RM3100_RET_EIO = -22,
00056         RM3100_RET_ENODEV = -19,
00057         RM3100_RET_EINVAL = -5,
00058         RM3100_RET_OK = 0,
00059     };
00060 
00061     enum I2CAddress {
00062         RM3100_ADDR_SA0 =  0x01, // address bit 0
00063         RM3100_ADDR_SA1 =  0x02, // address bit 1
00064         RM3100_ADDR_MASK = 0x03,
00065         RM3100_ADDR =      0x20, // 7-bit base address
00066         RM3100_ADDR_SSN = RM3100_ADDR_SA0, // SSN high = address bit 0
00067         RM3100_ADDR_SO = RM3100_ADDR_SA1, // SO high = address bit 1
00068     };
00069 
00070     enum Register {
00071         RM3100_REG_POLL =   0x00, // polls for a single measurement
00072         RM3100_REG_CMM =    0x01, // initiates continuous measurement mode
00073         RM3100_REG_CCX =    0x04, // cycle counts -- X axis
00074         RM3100_REG_CCY =    0x06, // cycle counts -- Y axis
00075         RM3100_REG_CCZ =    0x08, // cycle counts -- Z axis
00076         RM3100_REG_TMRC =   0x0B, // sets continuous mode data rate
00077         RM3100_REG_MX =     0x24, // measurement results -- X axis
00078         RM3100_REG_MY =     0x27, // measurement results -- Y axis
00079         RM3100_REG_MZ =     0x2A, // measurement results -- Z axis
00080         RM3100_REG_BIST =   0x33, // built-in self test
00081         RM3100_REG_STATUS = 0x34, // status of DRDY
00082         RM3100_REG_HSHAKE = 0x35, // handshake register
00083         RM3100_REG_REVID =  0x36, // MagI2C revision identification
00084     };
00085 
00086     struct SingleMeasurementMode {
00087         uint8_t res0:4;
00088         uint8_t pmx:1;
00089         uint8_t pmy:1;
00090         uint8_t pmz:1;
00091         uint8_t res7:1;
00092     };
00093 
00094     enum DataReadyMode {
00095         RM3100_DRDM_RES0 =     0x00, // reserved
00096         RM3100_DRDM_ANY_AXES = 0x01, // drdy on measurement complete on any axis
00097         RM3100_DRDM_ALL_AXES = 0x02, // drdy on measurement complete on all axes
00098         RM3100_DRDM_MASK =     0x03,
00099     };
00100 
00101     struct ContinuousMeasurementMode {
00102         uint8_t start:1;   // continuous measurement mode enabled
00103         uint8_t res1:1;
00104         uint8_t drdm:2;    // data ready mode
00105         uint8_t cmx:1;     // X axis measurement enabled in CMM
00106         uint8_t cmy:1;     // Y axis measurement enabled in CMM
00107         uint8_t cmz:1;     // Z axis measurement enabled in CMM
00108         uint8_t res7:1;
00109     };
00110 
00111     struct CycleCounts {
00112         uint16_t x;
00113         uint16_t y;
00114         uint16_t z;
00115     };
00116 
00117     enum ContinuousMeasurementModeUpdateRate {
00118         RM3100_CMM_RATE_600_0_HZ = 0x02, //   ~600 Hz
00119         RM3100_CMM_RATE_300_0_HZ = 0x03, //   ~300 Hz
00120         RM3100_CMM_RATE_150_0_HZ = 0x04, //   ~150 Hz
00121         RM3100_CMM_RATE_75_0_HZ =  0x05, //    ~75 Hz
00122         RM3100_CMM_RATE_37_0_HZ =  0x06, //    ~37 Hz
00123         RM3100_CMM_RATE_18_0_HZ =  0x07, //    ~18 Hz
00124         RM3100_CMM_RATE_9_0_HZ =   0x08, //     ~9 Hz
00125         RM3100_CMM_RATE_4_5_HZ =   0x09, //   ~4.5 Hz
00126         RM3100_CMM_RATE_2_3_HZ =   0x0A, //   ~2.3 Hz
00127         RM3100_CMM_RATE_1_2_HZ =   0x0B, //   ~1.2 Hz
00128         RM3100_CMM_RATE_0_6_HZ =   0x0C, //   ~0.6 Hz
00129         RM3100_CMM_RATE_0_3_HZ =   0x0D, //   ~0.3 Hz
00130         RM3100_CMM_RATE_0_015_HZ = 0x0E, // ~0.015 Hz
00131         RM3100_CMM_RATE_0_075_HZ = 0x0F, // ~0.075 Hz
00132         RM3100_CMM_RATE_MASK = RM3100_CMM_RATE_0_075_HZ,
00133         RM3100_CMM_RATE_MSB =      0x90,
00134     };
00135 
00136     enum StatusFlag {
00137         RM3100_STATUS_FLAG_DRDY = (1 << 7),
00138     };
00139 
00140     struct Status {
00141         uint8_t res0:7;
00142         uint8_t drdy:1;
00143     };
00144 
00145     struct Measurement {
00146         int32_t x;
00147         int32_t y;
00148         int32_t z;
00149     };
00150 
00151     struct Sample {
00152         float x;
00153         float y;
00154         float z;
00155     };
00156 
00157     struct MeasurementScale {
00158         float x;
00159         float y;
00160         float z;
00161         MeasurementScale(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
00162     };
00163 
00164     enum SelfTestCount {
00165         RM3100_SELF_TEST_COUNT_1 = 0x01, // 1 LR periods
00166         RM3100_SELF_TEST_COUNT_2 = 0x02, // 2 LR periods
00167         RM3100_SELF_TEST_COUNT_4 = 0x03, // 4 LR periods
00168         RM3100_SELF_TEST_COUNT_MASK = RM3100_SELF_TEST_COUNT_4,
00169     };
00170 
00171     enum SelfTestTimeout {
00172         RM3100_SELF_TEST_TIMEOUT_30_US = 0x01,  // 1 cycle  --  30 µs
00173         RM3100_SELF_TEST_TIMEOUT_60_US = 0x02,  // 2 cycles --  60 µs
00174         RM3100_SELF_TEST_TIMEOUT_120_US = 0x03, // 4 cycles -- 120 µs
00175         RM3100_SELF_TEST_TIMEOUT_MASK = RM3100_SELF_TEST_TIMEOUT_120_US,
00176     };
00177 
00178     struct SelfTestConfig {
00179         uint8_t bp:2;  // test count (LR periods)
00180         uint8_t bw:2;  // timeout (sleep oscillation cycles)
00181         uint8_t xok:1; // X result -- 0 = error, 1 = ok
00182         uint8_t yok:1; // Y result -- 0 = error, 1 = ok
00183         uint8_t zok:1; // Z result -- 0 = error, 1 = ok
00184         uint8_t ste:1; // self test enable -- 0 = disable, 1 = enable
00185     };
00186 
00187     struct HandShakeConfig {
00188         uint8_t drc0:1;  // clear drdy on any register write
00189         uint8_t drc1:1;  // clear drdy on measurement read
00190         uint8_t res2:1;  // 0
00191         uint8_t res3:1;  // 1
00192         uint8_t nack0:1; // 1 when undef register write
00193         uint8_t nack1:1; // 1 when write SMM when CMM or visa versa
00194         uint8_t nack2:1; // 1 when measurement read before data ready
00195     };
00196 
00197     static const uint8_t RM3100_REVID = 0x22;
00198 
00199     /**
00200      * Creates a new instance attached to the specified I2C pins and address
00201      *
00202      * @param sda I2C data pin
00203      * @param scl I2C clock pin
00204      * @param addr 8-bit I2C address
00205      */
00206     Rm3100(PinName sda, PinName scl, uint8_t addr);
00207 
00208     virtual ~Rm3100();
00209 
00210     /**
00211      * Checks hardware id and sets the data scale
00212      *
00213      * @return 0 on success
00214      */
00215     int Begin(void);
00216 
00217     /**
00218      * Gets the current single measurement mode config
00219      *
00220      * @param smm pointer to read config into
00221      * @return 0 on success
00222      */
00223     int GetSingleMeasurementMode(struct SingleMeasurementMode *smm);
00224 
00225     /**
00226      * Sets the current single measurement mode config
00227      *
00228      * @param smm pointer to write config from
00229      * @return 0 on success
00230      */
00231     int SetSingleMeasurementMode(struct SingleMeasurementMode *smm);
00232 
00233     /**
00234      * Sets the current single measurement mode config
00235      *
00236      * @param x enable measurement on X axis
00237      * @param y enable measurement on Y axis
00238      * @param z enable measurement on Z axis
00239      * @return 0 on success
00240      */
00241     int SetSingleMeasurementMode(bool x, bool y, bool z);
00242 
00243     /**
00244      * Gets the current continuous measurement mode config
00245      *
00246      * @param cmm pointer to read config into
00247      * @return 0 on success
00248      */
00249     int GetContinuousMeasurementMode(struct ContinuousMeasurementMode *cmm);
00250 
00251     /**
00252      * Sets the current continuous measurement mode config
00253      *
00254      * @param cmm pointer to write config from
00255      * @return 0 on success
00256      */
00257     int SetContinuousMeasurementMode(struct ContinuousMeasurementMode *cmm);
00258 
00259     /**
00260      * Sets the current continuous measurement mode config
00261      *
00262      * @param enabled enable CMM -- true = enabled, false = disabled
00263      * @param drdm data ready mode
00264      * @param x enable measurement on X axis
00265      * @param y enable measurement on Y axis
00266      * @param z enable measurement on Z axis
00267      * @return 0 on success
00268      */
00269     int SetContinuousMeasurementMode(bool enabled, uint8_t drdm, bool x,
00270                                      bool y, bool z);
00271 
00272     /**
00273      * Sets the current continuous measurement mode config
00274      *
00275      * @param enabled enable CMM -- true = enabled on all axes, false = disabled
00276      * @return 0 on success
00277      */
00278     int SetContinuousMeasurementMode(bool enabled);
00279 
00280     /**
00281      * Gets the current cycle counts
00282      *
00283      * @param cc pointer to read into
00284      * @return 0 on success
00285      */
00286     int GetCycleCounts(struct CycleCounts *cc);
00287 
00288     /**
00289      * Sets the current cycle counts
00290      *
00291      * @param cc pointer to write from
00292      * @return 0 on success
00293      */
00294     int SetCycleCounts(struct CycleCounts *cc);
00295 
00296     /*
00297      * Sets the current cycle counts (x, y, z)
00298      *
00299      * @param x cycle counts for X axis
00300      * @param y cycle counts for Y axis
00301      * @param z cycle counts for Z axis
00302      * @return 0 on success
00303      */
00304     int SetCycleCounts(uint16_t x, uint16_t y, uint16_t z);
00305 
00306     /*
00307      * Sets the current cycle counts (x = y, z)
00308      *
00309      * @param xy cycle counts for X and Y axes
00310      * @param z cycle counts for Z axis
00311      * @return 0 on success
00312      */
00313     int SetCycleCounts(uint16_t xy, uint16_t z);
00314 
00315     /*
00316      * Sets the current cycle counts (x = y = z)
00317      *
00318      * @param xyz cycle counts for all axes
00319      * @return 0 on success
00320      */
00321     int SetCycleCounts(uint16_t xyz);
00322 
00323     /**
00324      * Updates the measurement scale based on the given cycle counts
00325      *
00326      * @param cc pointer to cycle counts
00327      * @return 0 on success
00328      */
00329     void UpdateMeasurementScale(struct CycleCounts *cc);
00330 
00331     /**
00332      * Gets the continuous mode update rate
00333      *
00334      * @param tmrc pointer to read into
00335      * @return 0 on success
00336      */
00337     int GetContinuousMeasurementModeUpdateRate(uint8_t *tmrc);
00338 
00339     /**
00340      * Sets the continuous mode update rate (TMRC)
00341      *
00342      * @param tmrc rate to set according to TMRC table
00343      * @return 0 on success
00344      */
00345     int SetContinuousMeasurementModeUpdateRate(uint8_t tmrc);
00346 
00347     /**
00348      * Sets the contiunous mode update rate (Hz)
00349      *
00350      * @param rate rate to set in Hz
00351      * @return 0 on success
00352      */
00353     int SetRate(float rate);
00354 
00355     /**
00356      * Gets the current status
00357      *
00358      * @param status pointer to read into
00359      * @return 0 on success
00360      */
00361     int GetStatus(struct Status *status);
00362 
00363     /**
00364      * Gets the current measurement data (24-bit signed)
00365      *
00366      * @param m pointer to read into
00367      * @return 0 on success
00368      */
00369     int GetMeasurement(struct Measurement *m);
00370 
00371     /**
00372      * Gets the current measurement sample (scale to µT)
00373      *
00374      * @param s pointer to read into
00375      * @return 0 on success
00376      */
00377     int GetSample(struct Sample *s);
00378 
00379     /**
00380      * Gets the current self-test config/result
00381      *
00382      * @param cfg pointer to read into
00383      * @return 0 on success
00384      */
00385     int GetSelfTestConfig(struct SelfTestConfig *cfg);
00386 
00387     /**
00388      * Sets the current self-test config
00389      *
00390      * @param cfg pointer to write from
00391      * @return 0 on success
00392      */
00393     int SetSelfTestConfig(struct SelfTestConfig *cfg);
00394 
00395     /**
00396      * Sets the current self-test config
00397      *
00398      * @param count LR periods
00399      * @param timeout sleep oscillation cycles
00400      * @return 0 on success
00401      */
00402     int SetSelfTestConfig(uint8_t count, uint8_t timeout, bool enabled);
00403 
00404     /**
00405      * Performs a self-test, returning result
00406      *
00407      * @param count LR periods
00408      * @param timeout sleep oscillation cycles
00409      * @param result pointer to read result into
00410      * @return 0 on success
00411      */
00412     int PerformSelfTest(uint8_t count, uint8_t timeout,
00413                         struct SelfTestConfig *result);
00414 
00415     /**
00416      * Clears the self-test config
00417      *
00418      * @return 0 on success
00419      */
00420     int ClearSelfTest();
00421 
00422     /**
00423      * Gets the current handshake config
00424      *
00425      * @param cfg pointer to read into
00426      * @return 0 on success
00427      */
00428     int GetHandShakeConfig(struct HandShakeConfig *cfg);
00429 
00430     /**
00431      * Sets the current handshake config
00432      *
00433      * @param cfg pointer to write from
00434      * @return 0 on success
00435      */
00436     int SetHandShakeConfig(struct HandShakeConfig *cfg);
00437 
00438     /**
00439      * Sets the current data ready config
00440      *
00441      * @param on_write 1 = drdy cleared on any register write
00442      * @param on_read_measurement 1 = drdy cleared on measurement register read
00443      * @return 0 on success
00444      */
00445     int SetDrdyClearConfig(bool on_write, bool on_read_measurement);
00446 
00447     /**
00448      * Gets the current hardware revision
00449      *
00450      * @param rev pointer to read into
00451      * @return 0 on success
00452      */
00453     int GetHardwareRevision(uint8_t *rev);
00454 
00455 private:
00456     I2C _i2c;
00457     uint8_t _addr;
00458     struct MeasurementScale _scale;
00459     int _sample_delay_ms;
00460     int Read(uint8_t reg, uint8_t *buffer, uint8_t count);
00461     int Write(uint8_t reg, uint8_t *buffer, uint8_t count);
00462 };
00463 
00464 #endif /* RM3100_HPP */