library for using LSM303DM chip

Committer:
fin4478
Date:
Tue Aug 12 11:43:45 2014 +0000
Revision:
5:9786e0a13a3a
Parent:
4:52892e52889a
Child:
6:22556393747b
accelometer calibration added

Who changed what in which revision?

UserRevisionLine numberNew contents of line
fin4478 0:4d358fbeab6e 1 #include "mbed.h"
fin4478 0:4d358fbeab6e 2 #include <math.h>
fin4478 0:4d358fbeab6e 3 #include "LSM303.h"
fin4478 0:4d358fbeab6e 4
fin4478 2:1052b1b97cc2 5
fin4478 0:4d358fbeab6e 6 I2C i2c(P0_5, P0_4);
fin4478 0:4d358fbeab6e 7
fin4478 0:4d358fbeab6e 8 int LSM303::setup()
fin4478 0:4d358fbeab6e 9 {
fin4478 5:9786e0a13a3a 10 #ifdef CALIBRATING //set in LSM303.h
fin4478 0:4d358fbeab6e 11 m_max.x = 1;
fin4478 0:4d358fbeab6e 12 m_max.y = 1;
fin4478 0:4d358fbeab6e 13 m_max.z = 1;
fin4478 0:4d358fbeab6e 14 m_min.x = 0;
fin4478 0:4d358fbeab6e 15 m_min.y = 0;
fin4478 0:4d358fbeab6e 16 m_min.z = 0;
fin4478 5:9786e0a13a3a 17
fin4478 5:9786e0a13a3a 18 a_max.x = 1;
fin4478 5:9786e0a13a3a 19 a_max.y = 1;
fin4478 5:9786e0a13a3a 20 a_max.z = 1;
fin4478 5:9786e0a13a3a 21 a_min.x = 0;
fin4478 5:9786e0a13a3a 22 a_min.y = 0;
fin4478 5:9786e0a13a3a 23 a_min.z = 0;
fin4478 5:9786e0a13a3a 24
fin4478 5:9786e0a13a3a 25 #else
fin4478 5:9786e0a13a3a 26 m_min.x = -671;
fin4478 5:9786e0a13a3a 27 m_min.y = -704;
fin4478 5:9786e0a13a3a 28 m_min.z = -450;
fin4478 5:9786e0a13a3a 29 m_max.x = 462;
fin4478 5:9786e0a13a3a 30 m_max.y = 419;
fin4478 5:9786e0a13a3a 31 m_max.z = 578;
fin4478 5:9786e0a13a3a 32
fin4478 5:9786e0a13a3a 33 a_min.x = -584;
fin4478 5:9786e0a13a3a 34 a_min.y = -776;
fin4478 5:9786e0a13a3a 35 a_min.z = -664;
fin4478 5:9786e0a13a3a 36 a_max.x = 48;
fin4478 5:9786e0a13a3a 37 a_max.y = 32;
fin4478 5:9786e0a13a3a 38 a_max.z = 992;
fin4478 0:4d358fbeab6e 39 #endif
fin4478 3:b2cc1d06e2f5 40 LSM303_write(0x27, CTRL_REG1_A);
fin4478 2:1052b1b97cc2 41 LSM303_write(0x00, CTRL_REG4_A);
fin4478 2:1052b1b97cc2 42 LSM303_write(MAG_SCALE_1_3, CRB_REG_M); //magnetic scale = +/-1.3Gauss
fin4478 2:1052b1b97cc2 43 LSM303_write(0x00, MR_REG_M); // 0x00 = continouous conversion mode
fin4478 2:1052b1b97cc2 44
fin4478 2:1052b1b97cc2 45 return 1; //success
fin4478 0:4d358fbeab6e 46 }
fin4478 0:4d358fbeab6e 47 int LSM303::testAcc()
fin4478 0:4d358fbeab6e 48 {
fin4478 0:4d358fbeab6e 49 if (i2c.write(LSM303_ACC, NULL, 0) ==0) return LSM303_ACC;
fin4478 0:4d358fbeab6e 50 return 255;
fin4478 0:4d358fbeab6e 51 }
fin4478 0:4d358fbeab6e 52
fin4478 0:4d358fbeab6e 53 int LSM303::testMag()
fin4478 0:4d358fbeab6e 54 {
fin4478 1:322c80f884d3 55 if (i2c.write(LSM303_MAG, NULL, 0) ==0)
fin4478 0:4d358fbeab6e 56 if (LSM303_read(LSM303_WHO_AM_I_M)==0x3C) {
fin4478 0:4d358fbeab6e 57 return LSM303_WHO_AM_I_M;
fin4478 1:322c80f884d3 58 } else {
fin4478 0:4d358fbeab6e 59 return LSM303_MAG;
fin4478 0:4d358fbeab6e 60 }
fin4478 1:322c80f884d3 61
fin4478 0:4d358fbeab6e 62 return 255;
fin4478 0:4d358fbeab6e 63 }
fin4478 0:4d358fbeab6e 64
fin4478 0:4d358fbeab6e 65 float LSM303::getTiltHeading()
fin4478 0:4d358fbeab6e 66 {
fin4478 5:9786e0a13a3a 67 a.x -= ((int32_t)a_min.x + a_max.x) / 2;
fin4478 5:9786e0a13a3a 68 a.y -= ((int32_t)a_min.y + a_max.y) / 2;
fin4478 5:9786e0a13a3a 69 a.z -= ((int32_t)a_min.z + a_max.z) / 2;
fin4478 5:9786e0a13a3a 70 // subtract offset (average of min and max) from magnetometer readings
fin4478 5:9786e0a13a3a 71 m.x -= ((int32_t)m_min.x + m_max.x) / 2;
fin4478 5:9786e0a13a3a 72 m.y -= ((int32_t)m_min.y + m_max.y) / 2;
fin4478 5:9786e0a13a3a 73 m.z -= ((int32_t)m_min.z + m_max.z) / 2;
fin4478 5:9786e0a13a3a 74
fin4478 0:4d358fbeab6e 75 vector_normalize(&a);
fin4478 0:4d358fbeab6e 76 vector_normalize(&m);
fin4478 0:4d358fbeab6e 77 //see appendix A in app note AN3192
fin4478 0:4d358fbeab6e 78 pitch = asin(-a.x);
fin4478 0:4d358fbeab6e 79 roll = asin(a.y/cos(pitch));
fin4478 0:4d358fbeab6e 80 float heading = 0;
fin4478 0:4d358fbeab6e 81 float xh = m.x * cos(pitch) + m.z * sin(pitch);
fin4478 0:4d358fbeab6e 82 float yh = m.x * sin(roll) * sin(pitch) + m.y * cos(roll) - m.z * sin(roll) * cos(pitch);
fin4478 5:9786e0a13a3a 83
fin4478 0:4d358fbeab6e 84 heading = 180 * atan2(yh, xh)/PI;
fin4478 0:4d358fbeab6e 85 if (heading < 0) heading += 360;
fin4478 5:9786e0a13a3a 86
fin4478 1:322c80f884d3 87 return heading;
fin4478 0:4d358fbeab6e 88 }
fin4478 0:4d358fbeab6e 89
fin4478 0:4d358fbeab6e 90 void LSM303::vector_cross( const Plane *a,const Plane *b, Plane *out )
fin4478 0:4d358fbeab6e 91 {
fin4478 0:4d358fbeab6e 92 out->x = a->y*b->z - a->z*b->y;
fin4478 0:4d358fbeab6e 93 out->y = a->z*b->x - a->x*b->z;
fin4478 0:4d358fbeab6e 94 out->z = a->x*b->y - a->y*b->x;
fin4478 0:4d358fbeab6e 95 }
fin4478 0:4d358fbeab6e 96
fin4478 0:4d358fbeab6e 97 float LSM303::vector_dot( const Plane *a,const Plane *b )
fin4478 0:4d358fbeab6e 98 {
fin4478 0:4d358fbeab6e 99 return a->x*b->x+a->y*b->y+a->z*b->z;
fin4478 0:4d358fbeab6e 100 }
fin4478 0:4d358fbeab6e 101
fin4478 0:4d358fbeab6e 102 void LSM303::vector_normalize( Plane *a )
fin4478 0:4d358fbeab6e 103 {
fin4478 0:4d358fbeab6e 104 float mag = sqrt(vector_dot(a,a));
fin4478 0:4d358fbeab6e 105 a->x /= mag;
fin4478 0:4d358fbeab6e 106 a->y /= mag;
fin4478 0:4d358fbeab6e 107 a->z /= mag;
fin4478 0:4d358fbeab6e 108 }
fin4478 0:4d358fbeab6e 109
fin4478 3:b2cc1d06e2f5 110 void LSM303::getLSM303_accel()
fin4478 3:b2cc1d06e2f5 111 {
fin4478 0:4d358fbeab6e 112 char data[1] = { OUT_X_L_A | (1<<7)};
fin4478 0:4d358fbeab6e 113 char out[6] = {0,0,0,0,0,0};
fin4478 0:4d358fbeab6e 114 i2c.write( LSM303_ACC, data,1);
fin4478 0:4d358fbeab6e 115 i2c.read( LSM303_ACC, out, 6);
fin4478 0:4d358fbeab6e 116
fin4478 0:4d358fbeab6e 117 a.x = short( (((short)out[1]) << 8) | out[0] );
fin4478 0:4d358fbeab6e 118 a.y = short( (((short)out[3]) << 8) | out[2] );
fin4478 3:b2cc1d06e2f5 119 a.z = short( (((short)out[5]) << 8) | out[4] );
fin4478 0:4d358fbeab6e 120 }
fin4478 0:4d358fbeab6e 121
fin4478 0:4d358fbeab6e 122 void LSM303::getLSM303_mag()
fin4478 0:4d358fbeab6e 123 {
fin4478 0:4d358fbeab6e 124 char data[1] = { OUT_X_H_M };
fin4478 0:4d358fbeab6e 125 char out[6];
fin4478 0:4d358fbeab6e 126
fin4478 0:4d358fbeab6e 127 i2c.write( LSM303_MAG, data, 1 );
fin4478 0:4d358fbeab6e 128 i2c.read( LSM303_MAG, out, 6 );
fin4478 0:4d358fbeab6e 129 // DLM, DLHC: register address for Z comes before Y
fin4478 0:4d358fbeab6e 130 m.x = short( out[0] << 8 | out[1] );
fin4478 0:4d358fbeab6e 131 m.y = short( out[4] << 8 | out[5] );
fin4478 0:4d358fbeab6e 132 m.z= short( out[2] << 8 | out[3] );
fin4478 0:4d358fbeab6e 133 }
fin4478 0:4d358fbeab6e 134
fin4478 0:4d358fbeab6e 135 int LSM303::LSM303_read(int address)
fin4478 0:4d358fbeab6e 136 {
fin4478 0:4d358fbeab6e 137 if (address >= 0x20) {
fin4478 0:4d358fbeab6e 138 _i2c_address = LSM303_ACC;
fin4478 0:4d358fbeab6e 139 } else {
fin4478 0:4d358fbeab6e 140 _i2c_address = LSM303_MAG;
fin4478 0:4d358fbeab6e 141 }
fin4478 0:4d358fbeab6e 142
fin4478 0:4d358fbeab6e 143 char value[1];
fin4478 0:4d358fbeab6e 144
fin4478 0:4d358fbeab6e 145 char data[1] = { address };
fin4478 0:4d358fbeab6e 146 i2c.write( _i2c_address, data, 1 );
fin4478 0:4d358fbeab6e 147 i2c.read( _i2c_address, value, 1 );
fin4478 0:4d358fbeab6e 148 return value[0];
fin4478 0:4d358fbeab6e 149 }
fin4478 0:4d358fbeab6e 150
fin4478 0:4d358fbeab6e 151 int LSM303::LSM303_write(int data, int address)
fin4478 0:4d358fbeab6e 152 {
fin4478 0:4d358fbeab6e 153 if (address >= 0x20) {
fin4478 0:4d358fbeab6e 154 _i2c_address = LSM303_ACC;
fin4478 0:4d358fbeab6e 155 } else {
fin4478 0:4d358fbeab6e 156 _i2c_address = LSM303_MAG;
fin4478 0:4d358fbeab6e 157 }
fin4478 0:4d358fbeab6e 158
fin4478 0:4d358fbeab6e 159 char out[2] = { address, data };
fin4478 0:4d358fbeab6e 160 i2c.write( _i2c_address, out, 2 );
fin4478 0:4d358fbeab6e 161 return 0;
fin4478 0:4d358fbeab6e 162 }