Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of ITG3200 by
ITG3200.cpp
- Committer:
- gltest26
- Date:
- 2012-09-12
- Revision:
- 3:eea9733ca427
- Parent:
- 2:f44a902ba081
- Child:
- 4:155c44407af5
File content as of revision 3:eea9733ca427:
/** * @author Aaron Berk * * @section LICENSE * * Copyright (c) 2010 ARM Limited * * 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. * * @section DESCRIPTION * * ITG-3200 triple axis, digital interface, gyroscope. * * Datasheet: * * http://invensense.com/mems/gyro/documents/PS-ITG-3200-00-01.4.pdf */ #include "ITG3200.h" ITG3200::ITG3200(PinName sda, PinName scl) : i2c_(sda, scl) { offset[0] = offset[1] = offset[2] = 0; //400kHz, fast mode. i2c_.frequency(400000); //Set FS_SEL to 0x03 for proper operation. //See datasheet for details. char tx[2]; tx[0] = DLPF_FS_REG; //FS_SEL bits sit in bits 4 and 3 of DLPF_FS register. tx[1] = 0x03 << 3; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, tx, 2); } char ITG3200::getWhoAmI(void){ //WhoAmI Register address. char tx = WHO_AM_I_REG; char rx; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, &tx, 1); i2c_.read((ITG3200_I2C_ADDRESS << 1) | 0x01, &rx, 1); return rx; } void ITG3200::setWhoAmI(char address){ char tx[2]; tx[0] = WHO_AM_I_REG; tx[1] = address; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, tx, 2); } char ITG3200::getSampleRateDivider(void){ char tx = SMPLRT_DIV_REG; char rx; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, &tx, 1); i2c_.read((ITG3200_I2C_ADDRESS << 1) | 0x01, &rx, 1); return rx; } void ITG3200::setSampleRateDivider(char divider){ char tx[2]; tx[0] = SMPLRT_DIV_REG; tx[1] = divider; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, tx, 2); } int ITG3200::getInternalSampleRate(void){ char tx = DLPF_FS_REG; char rx; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, &tx, 1); i2c_.read((ITG3200_I2C_ADDRESS << 1) | 0x01, &rx, 1); //DLPF_CFG == 0 -> sample rate = 8kHz. if(rx == 0){ return 8; } //DLPF_CFG = 1..7 -> sample rate = 1kHz. else if(rx >= 1 && rx <= 7){ return 1; } //DLPF_CFG = anything else -> something's wrong! else{ return -1; } } void ITG3200::setLpBandwidth(char bandwidth){ char tx[2]; tx[0] = DLPF_FS_REG; //Bits 4,3 are required to be 0x03 for proper operation. tx[1] = bandwidth | (0x03 << 3); i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, tx, 2); } char ITG3200::getInterruptConfiguration(void){ char tx = INT_CFG_REG; char rx; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, &tx, 1); i2c_.read((ITG3200_I2C_ADDRESS << 1) | 0x01, &rx, 1); return rx; } void ITG3200::setInterruptConfiguration(char config){ char tx[2]; tx[0] = INT_CFG_REG; tx[1] = config; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, tx, 2); } bool ITG3200::isPllReady(void){ char tx = INT_STATUS; char rx; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, &tx, 1); i2c_.read((ITG3200_I2C_ADDRESS << 1) | 0x01, &rx, 1); //ITG_RDY bit is bit 4 of INT_STATUS register. if(rx & 0x04){ return true; } else{ return false; } } bool ITG3200::isRawDataReady(void){ char tx = INT_STATUS; char rx; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, &tx, 1); i2c_.read((ITG3200_I2C_ADDRESS << 1) | 0x01, &rx, 1); //RAW_DATA_RDY bit is bit 1 of INT_STATUS register. if(rx & 0x01){ return true; } else{ return false; } } int ITG3200::getRawTemperature(void){ char tx = TEMP_OUT_H_REG; char rx[2]; i2c_.write(I2C_ADDRESS, &tx, 1); i2c_.read(I2C_ADDRESS, rx, 2); // Readings are expressed in 16bit 2's complement, so we must first // concatenate two bytes to make a word and sign extend it to obtain // correct negative values. // ARMCC compiles char as unsigned, which means no sign extension is // performed during bitwise operations to chars. But we should make sure // that lower byte won't extend its sign past upper byte for other // compilers if we want to keep it portable. return int16_t(((unsigned)rx[0] << 8) | (unsigned)rx[1]); } float ITG3200::getTemperature(){ //Offset = -35 degrees, 13200 counts. 280 counts/degrees C. return 35.0 + ((getRawTemperature() + 13200)/280.0); } int ITG3200::getGyroX(void){ char tx = GYRO_XOUT_H_REG; char rx[2]; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, &tx, 1); i2c_.read((ITG3200_I2C_ADDRESS << 1) | 0x01, rx, 2); int16_t output = ((int) rx[0] << 8) | ((int) rx[1]); return output; } int ITG3200::getGyroY(void){ char tx = GYRO_YOUT_H_REG; char rx[2]; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, &tx, 1); i2c_.read((ITG3200_I2C_ADDRESS << 1) | 0x01, rx, 2); int16_t output = ((int) rx[0] << 8) | ((int) rx[1]); return output; } int ITG3200::getGyroZ(void){ char tx = GYRO_ZOUT_H_REG; char rx[2]; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, &tx, 1); i2c_.read((ITG3200_I2C_ADDRESS << 1) | 0x01, rx, 2); int16_t output = ((int) rx[0] << 8) | ((int) rx[1]); return output; } void ITG3200::getRawGyroXYZ(int readings[3]){ char tx = GYRO_XOUT_H_REG; char rx[2]; i2c_.write(I2C_ADDRESS, &tx, 1); i2c_.read(I2C_ADDRESS, rx, 6); for(int i = 0; i < 3; i++) readings[i] = int16_t((unsigned) rx[i * 2 + 0] << 8) | ((unsigned) rx[i * 2 + 1]); } char ITG3200::getPowerManagement(void){ char tx = PWR_MGM_REG; char rx; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, &tx, 1); i2c_.read((ITG3200_I2C_ADDRESS << 1) | 0x01, &rx, 1); return rx; } void ITG3200::setPowerManagement(char config){ char tx[2]; tx[0] = PWR_MGM_REG; tx[1] = config; i2c_.write((ITG3200_I2C_ADDRESS << 1) & 0xFE, tx, 2); } void ITG3200::calibrate(double time){ static const double deltaTime = 0.002; long sum[3] = {0}; int sumCount = 0; for(; 0 < time; time -= deltaTime){ int gyro[3]; getGyroXYZ(gyro); for(int i = 0; i < 3; i++) sum[i] += gyro[i]; sumCount++; } // Avoid zero division if(0 < sumCount){ for(int i = 0; i < 3; i++) offset[i] = sum[i] / sumCount; } }