|
| 1 | +/*************************************************************************** |
| 2 | + This is a library for the LSM9DS0 Accelerometer and magnentometer/compass |
| 3 | +
|
| 4 | + Designed specifically to work with the Adafruit LSM9DS0 Breakouts |
| 5 | +
|
| 6 | + These sensors use I2C to communicate, 2 pins are required to interface. |
| 7 | +
|
| 8 | + Adafruit invests time and resources providing this open source code, |
| 9 | + please support Adafruit andopen-source hardware by purchasing products |
| 10 | + from Adafruit! |
| 11 | +
|
| 12 | + Written by Kevin Townsend for Adafruit Industries. |
| 13 | + BSD license, all text above must be included in any redistribution |
| 14 | + ***************************************************************************/ |
| 15 | +#include <Adafruit_LSM9DS0.h> |
| 16 | + |
| 17 | +/*************************************************************************** |
| 18 | + CONSTRUCTOR |
| 19 | + ***************************************************************************/ |
| 20 | +// default |
| 21 | +Adafruit_LSM9DS0::Adafruit_LSM9DS0() { |
| 22 | + _i2c = true; |
| 23 | + |
| 24 | +} |
| 25 | + |
| 26 | +Adafruit_LSM9DS0::Adafruit_LSM9DS0(int8_t xmcs, int8_t gcs) { |
| 27 | + _i2c = false; |
| 28 | + // hardware SPI! |
| 29 | + _csg = gcs; |
| 30 | + _csxm = xmcs; |
| 31 | + _mosi = _miso = _clk = -1; |
| 32 | +} |
| 33 | + |
| 34 | +Adafruit_LSM9DS0::Adafruit_LSM9DS0(int8_t clk, int8_t miso, int8_t mosi, int8_t xmcs, int8_t gcs) { |
| 35 | + _i2c = false; |
| 36 | + // software SPI! |
| 37 | + _csg = gcs; |
| 38 | + _csxm = xmcs; |
| 39 | + _mosi = mosi; |
| 40 | + _miso = miso; |
| 41 | + _clk = clk; |
| 42 | +} |
| 43 | + |
| 44 | +bool Adafruit_LSM9DS0::begin() |
| 45 | +{ |
| 46 | + if (_i2c) { |
| 47 | + Wire.begin(); |
| 48 | + |
| 49 | + } else if (_clk == -1) { |
| 50 | + // Hardware SPI |
| 51 | + pinMode(_csxm, OUTPUT); |
| 52 | + pinMode(_csg, OUTPUT); |
| 53 | + digitalWrite(_csxm, HIGH); |
| 54 | + digitalWrite(_csg, HIGH); |
| 55 | + SPCRback = SPCR; |
| 56 | + SPI.begin(); |
| 57 | + SPI.setClockDivider(SPI_CLOCK_DIV8); |
| 58 | + SPI.setDataMode(SPI_MODE0); |
| 59 | + mySPCR = SPCR; |
| 60 | + SPCR = SPCRback; |
| 61 | + } else { |
| 62 | + // Sofware SPI |
| 63 | + pinMode(_clk, OUTPUT); |
| 64 | + pinMode(_mosi, OUTPUT); |
| 65 | + pinMode(_csxm, OUTPUT); |
| 66 | + pinMode(_csg, OUTPUT); |
| 67 | + digitalWrite(_csxm, HIGH); |
| 68 | + digitalWrite(_csg, HIGH); |
| 69 | + digitalWrite(_clk, HIGH); |
| 70 | + } |
| 71 | + |
| 72 | + uint8_t id = read8(XMTYPE, LSM9DS0_REGISTER_WHO_AM_I_XM); |
| 73 | + Serial.print ("XM whoami: 0x"); |
| 74 | + Serial.println(id, HEX); |
| 75 | + if (id != LSM9DS0_XM_ID) |
| 76 | + return false; |
| 77 | + |
| 78 | + id = read8(GYROTYPE, LSM9DS0_REGISTER_WHO_AM_I_G); |
| 79 | + Serial.print ("G whoami: 0x"); |
| 80 | + Serial.println(id, HEX); |
| 81 | + if (id != LSM9DS0_G_ID) |
| 82 | + return false; |
| 83 | + |
| 84 | + |
| 85 | + // Enable the accelerometer continous |
| 86 | + write8(XMTYPE, LSM9DS0_REGISTER_CTRL_REG1_XM, 0x67); // 100hz XYZ |
| 87 | + write8(XMTYPE, LSM9DS0_REGISTER_CTRL_REG5_XM, 0b11110000); |
| 88 | + // enable mag continuous |
| 89 | + write8(XMTYPE, LSM9DS0_REGISTER_CTRL_REG7_XM, 0b00000000); |
| 90 | + // enable gyro continuous |
| 91 | + write8(GYROTYPE, LSM9DS0_REGISTER_CTRL_REG1_G, 0x0F); // on XYZ |
| 92 | + |
| 93 | + /* |
| 94 | + for (uint8_t i=0; i<0x30; i++) { |
| 95 | + Serial.print("$"); Serial.print(i, HEX); |
| 96 | + Serial.print(" = 0x"); |
| 97 | + Serial.println(read8(XMTYPE, i), HEX); |
| 98 | + } |
| 99 | + */ |
| 100 | + |
| 101 | + return true; |
| 102 | +} |
| 103 | + |
| 104 | +/*************************************************************************** |
| 105 | + PUBLIC FUNCTIONS |
| 106 | + ***************************************************************************/ |
| 107 | +void Adafruit_LSM9DS0::read() |
| 108 | +{ |
| 109 | + if (_i2c) { |
| 110 | + // Read the accelerometer |
| 111 | + Wire.beginTransmission((byte)LSM9DS0_ADDRESS_ACCELMAG); |
| 112 | + Wire.write(0x80 | LSM9DS0_REGISTER_OUT_X_L_A); |
| 113 | + Wire.endTransmission(); |
| 114 | + Wire.requestFrom((byte)LSM9DS0_ADDRESS_ACCELMAG, (byte)6); |
| 115 | + |
| 116 | + // Wait around until enough data is available |
| 117 | + while (Wire.available() < 6); |
| 118 | + |
| 119 | + uint8_t xlo = Wire.read(); |
| 120 | + uint8_t xhi = Wire.read(); |
| 121 | + uint8_t ylo = Wire.read(); |
| 122 | + uint8_t yhi = Wire.read(); |
| 123 | + uint8_t zlo = Wire.read(); |
| 124 | + uint8_t zhi = Wire.read(); |
| 125 | + |
| 126 | + // Shift values to create properly formed integer (low byte first) |
| 127 | + accelData.x = (xlo | (xhi << 8)) >> 4; |
| 128 | + accelData.y = (ylo | (yhi << 8)) >> 4; |
| 129 | + accelData.z = (zlo | (zhi << 8)) >> 4; |
| 130 | + |
| 131 | + // Read the magnetometer |
| 132 | + Wire.beginTransmission((byte)LSM9DS0_ADDRESS_ACCELMAG); |
| 133 | + Wire.write(0x80 | LSM9DS0_REGISTER_OUT_X_L_M); |
| 134 | + Wire.endTransmission(); |
| 135 | + Wire.requestFrom((byte)LSM9DS0_ADDRESS_ACCELMAG, (byte)6); |
| 136 | + |
| 137 | + // Wait around until enough data is available |
| 138 | + while (Wire.available() < 6); |
| 139 | + |
| 140 | + // Note high before low (different than accel) |
| 141 | + xlo = Wire.read(); |
| 142 | + xhi = Wire.read(); |
| 143 | + ylo = Wire.read(); |
| 144 | + yhi = Wire.read(); |
| 145 | + zlo = Wire.read(); |
| 146 | + zhi = Wire.read(); |
| 147 | + |
| 148 | + // Shift values to create properly formed integer (low byte first) |
| 149 | + magData.x = (xlo | (xhi << 8)); |
| 150 | + magData.y = (ylo | (yhi << 8)); |
| 151 | + magData.z = (zlo | (zhi << 8)); |
| 152 | + |
| 153 | + |
| 154 | + // Read gyro |
| 155 | + |
| 156 | + Wire.beginTransmission((byte)LSM9DS0_ADDRESS_GYRO); |
| 157 | + Wire.write(0x80 | LSM9DS0_REGISTER_OUT_X_L_G); |
| 158 | + Wire.endTransmission(); |
| 159 | + Wire.requestFrom((byte)LSM9DS0_ADDRESS_GYRO, (byte)6); |
| 160 | + |
| 161 | + // Wait around until enough data is available |
| 162 | + while (Wire.available() < 6); |
| 163 | + |
| 164 | + xlo = Wire.read(); |
| 165 | + xhi = Wire.read(); |
| 166 | + ylo = Wire.read(); |
| 167 | + yhi = Wire.read(); |
| 168 | + zlo = Wire.read(); |
| 169 | + zhi = Wire.read(); |
| 170 | + gyroData.x = (xlo | (xhi << 8)); |
| 171 | + gyroData.y = (ylo | (yhi << 8)); |
| 172 | + gyroData.z = (zlo | (zhi << 8)); |
| 173 | + |
| 174 | + } |
| 175 | + |
| 176 | + // ToDo: Calculate orientation |
| 177 | + magData.orientation = 0.0; |
| 178 | +} |
| 179 | + |
| 180 | +void Adafruit_LSM9DS0::setMagGain(lsm9ds0MagGain gain) |
| 181 | +{ |
| 182 | + |
| 183 | +} |
| 184 | + |
| 185 | +/*************************************************************************** |
| 186 | + PRIVATE FUNCTIONS |
| 187 | + ***************************************************************************/ |
| 188 | +void Adafruit_LSM9DS0::write8(boolean type, byte reg, byte value) |
| 189 | +{ |
| 190 | + byte address, _cs; |
| 191 | + |
| 192 | + if (type == GYROTYPE) { |
| 193 | + address = LSM9DS0_ADDRESS_GYRO; |
| 194 | + _cs = _csg; |
| 195 | + } else { |
| 196 | + address = LSM9DS0_ADDRESS_ACCELMAG; |
| 197 | + _cs = _csxm; |
| 198 | + } |
| 199 | + if (_i2c) { |
| 200 | + Wire.beginTransmission(address); |
| 201 | + Wire.write(reg); |
| 202 | + Wire.write(value); |
| 203 | + Wire.endTransmission(); |
| 204 | + } else { |
| 205 | + if (_clk == -1) { |
| 206 | + SPCRback = SPCR; |
| 207 | + SPCR = mySPCR; |
| 208 | + } |
| 209 | + digitalWrite(_cs, LOW); |
| 210 | + // set address |
| 211 | + spixfer(reg | 0x40); // write multiple |
| 212 | + spixfer(value); |
| 213 | + digitalWrite(_cs, HIGH); |
| 214 | + if (_clk == -1) { |
| 215 | + SPCR = SPCRback; |
| 216 | + } |
| 217 | + } |
| 218 | +} |
| 219 | + |
| 220 | +byte Adafruit_LSM9DS0::read8(boolean type, byte reg) |
| 221 | +{ |
| 222 | + byte address, _cs; |
| 223 | + byte value; |
| 224 | + |
| 225 | + if (type == GYROTYPE) { |
| 226 | + address = LSM9DS0_ADDRESS_GYRO; |
| 227 | + _cs = _csg; |
| 228 | + } else { |
| 229 | + address = LSM9DS0_ADDRESS_ACCELMAG; |
| 230 | + _cs = _csxm; |
| 231 | + } |
| 232 | + if (_i2c) { |
| 233 | + Wire.beginTransmission(address); |
| 234 | + Wire.write(reg); |
| 235 | + Wire.endTransmission(); |
| 236 | + Wire.requestFrom(address, (byte)1); |
| 237 | + value = Wire.read(); |
| 238 | + Wire.endTransmission(); |
| 239 | + } else { |
| 240 | + if (_clk == -1) { |
| 241 | + SPCRback = SPCR; |
| 242 | + SPCR = mySPCR; |
| 243 | + } |
| 244 | + digitalWrite(_cs, LOW); |
| 245 | + // set address |
| 246 | + spixfer(reg | 0x80 | 0x40); // read multiple |
| 247 | + value = spixfer(0); |
| 248 | + digitalWrite(_cs, HIGH); |
| 249 | + if (_clk == -1) { |
| 250 | + SPCR = SPCRback; |
| 251 | + } |
| 252 | + } |
| 253 | + |
| 254 | + return value; |
| 255 | +} |
| 256 | + |
| 257 | +uint8_t Adafruit_LSM9DS0::spixfer(uint8_t data) { |
| 258 | + if (_clk == -1) { |
| 259 | + //Serial.println("Hardware SPI"); |
| 260 | + return SPI.transfer(data); |
| 261 | + } else { |
| 262 | + //Serial.println("Software SPI"); |
| 263 | + uint8_t reply = 0; |
| 264 | + for (int i=7; i>=0; i--) { |
| 265 | + reply <<= 1; |
| 266 | + digitalWrite(_clk, LOW); |
| 267 | + digitalWrite(_mosi, data & (1<<i)); |
| 268 | + digitalWrite(_clk, HIGH); |
| 269 | + if (digitalRead(_miso)) |
| 270 | + reply |= 1; |
| 271 | + } |
| 272 | + return reply; |
| 273 | + } |
| 274 | +} |
0 commit comments