openi2c
Version:
This library is a set of cross platform drivers for common I2C devices.
518 lines (517 loc) • 22.2 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.mpu9250 = exports.MPU9250 = void 0;
const i2c = __importStar(require("i2c-bus"));
const utils_1 = require("../../utils");
const AK8963_1 = require("../AK8963");
const BaseDevice_1 = require("../BaseDevice");
// MPU9250 Map
exports.MPU9250 = {
ID_MPU_9250: 0x71,
ID_MPU_9255: 0x73,
I2C_ADDRESS_AD0_LOW: 0x68,
I2C_ADDRESS_AD0_HIGH: 0x69,
WHO_AM_I: 0x75,
SMPLRT_DIV: 0x19,
RA_CONFIG: 0x1A,
RA_GYRO_CONFIG: 0x1B,
RA_ACCEL_CONFIG_1: 0x1C,
RA_ACCEL_CONFIG_2: 0x1D,
RA_INT_PIN_CFG: 0x37,
INTCFG_ACTL_BIT: 7,
INTCFG_OPEN_BIT: 6,
INTCFG_LATCH_INT_EN_BIT: 5,
INTCFG_INT_ANYRD_2CLEAR_BIT: 4,
INTCFG_ACTL_FSYNC_BIT: 3,
INTCFG_FSYNC_INT_MODE_EN_BIT: 2,
INTCFG_BYPASS_EN_BIT: 1,
INTCFG_NONE_BIT: 0,
// BY_PASS_MODE: 0x02,
ACCEL_XOUT_H: 0x3B,
ACCEL_XOUT_L: 0x3C,
ACCEL_YOUT_H: 0x3D,
ACCEL_YOUT_L: 0x3E,
ACCEL_ZOUT_H: 0x3F,
ACCEL_ZOUT_L: 0x40,
TEMP_OUT_H: 0x41,
TEMP_OUT_L: 0x42,
GYRO_XOUT_H: 0x43,
GYRO_XOUT_L: 0x44,
GYRO_YOUT_H: 0x45,
GYRO_YOUT_L: 0x46,
GYRO_ZOUT_H: 0x47,
GYRO_ZOUT_L: 0x48,
RA_USER_CTRL: 0x6A,
RA_PWR_MGMT_1: 0x6B,
RA_PWR_MGMT_2: 0x6C,
PWR1_DEVICE_RESET_BIT: 7,
PWR1_SLEEP_BIT: 6,
PWR1_CYCLE_BIT: 5,
PWR1_TEMP_DIS_BIT: 3, // (PD_PTAT)
PWR1_CLKSEL_BIT: 0,
PWR1_CLKSEL_LENGTH: 3,
GCONFIG_FS_SEL_BIT: 3,
GCONFIG_FS_SEL_LENGTH: 2,
GYRO_FS_250: 0x00,
GYRO_FS_500: 0x01,
GYRO_FS_1000: 0x02,
GYRO_FS_2000: 0x03,
GYRO_SCALE_FACTOR: [131, 65.5, 32.8, 16.4],
ACONFIG_FS_SEL_BIT: 3,
ACONFIG_FS_SEL_LENGTH: 2,
ACCEL_FS_2: 0x00,
ACCEL_FS_4: 0x01,
ACCEL_FS_8: 0x02,
ACCEL_FS_16: 0x03,
ACCEL_SCALE_FACTOR: [16384, 8192, 4096, 2048],
CLOCK_INTERNAL: 0x00,
CLOCK_PLL_XGYRO: 0x01,
CLOCK_PLL_YGYRO: 0x02,
CLOCK_PLL_ZGYRO: 0x03,
CLOCK_KEEP_RESET: 0x07,
CLOCK_PLL_EXT32K: 0x04,
CLOCK_PLL_EXT19M: 0x05,
I2C_SLV0_DO: 0x63,
I2C_SLV1_DO: 0x64,
I2C_SLV2_DO: 0x65,
USERCTRL_DMP_EN_BIT: 7,
USERCTRL_FIFO_EN_BIT: 6,
USERCTRL_I2C_MST_EN_BIT: 5,
USERCTRL_I2C_IF_DIS_BIT: 4,
USERCTRL_DMP_RESET_BIT: 3,
USERCTRL_FIFO_RESET_BIT: 2,
USERCTRL_I2C_MST_RESET_BIT: 1,
USERCTRL_SIG_COND_RESET_BIT: 0,
DEFAULT_GYRO_OFFSET: { x: 0, y: 0, z: 0 },
DEFAULT_ACCEL_CALIBRATION: {
offset: { x: 0, y: 0, z: 0 },
scale: {
x: [-1, 1],
y: [-1, 1],
z: [-1, 1]
}
},
/** For Gyro */
DLPF_CFG_250HZ: 0x00,
DLPF_CFG_184HZ: 0x01,
DLPF_CFG_92HZ: 0x02,
DLPF_CFG_41HZ: 0x03,
DLPF_CFG_20HZ: 0x04,
DLPF_CFG_10HZ: 0x05,
DLPF_CFG_5HZ: 0x06,
DLPF_CFG_3600HZ: 0x07,
/** Sample rate min/max value */
SAMPLERATE_MIN: 5,
SAMPLERATE_MAX: 32000,
/** For accel. */
A_DLPF_CFG_460HZ: 0x00,
A_DLPF_CFG_184HZ: 0x01,
A_DLPF_CFG_92HZ: 0x02,
A_DLPF_CFG_41HZ: 0x03,
A_DLPF_CFG_20HZ: 0x04,
A_DLPF_CFG_10HZ: 0x05,
A_DLPF_CFG_5HZ: 0x06,
A_DLPF_CFG_460HZ_2: 0x07,
A_DLPF_CFG_MASK: 0x07
};
class mpu9250 extends BaseDevice_1.BaseDevice {
// other properties as needed
constructor(config = {}) {
super();
this._config = Object.assign({
// device: '/dev/i2c-0',
bus: 0, address: exports.MPU9250.I2C_ADDRESS_AD0_LOW, UpMagneto: false, DEBUG: false, scaleValues: false, ak_address: AK8963_1.AK8963.ADDRESS, GYRO_FS: 0, ACCEL_FS: 2, gyroBiasOffset: exports.MPU9250.DEFAULT_GYRO_OFFSET, accelCalibration: exports.MPU9250.DEFAULT_ACCEL_CALIBRATION }, config);
this.address = this._config.address;
}
initialize() {
return __awaiter(this, void 0, void 0, function* () {
this.bus = i2c.openSync(this._config.bus).promisifiedBus(); //new MOD_I2C(this._config.address, { device: this._config.device });
// this.debug = new debugConsole(this._config.DEBUG);
this.debug.log('INFO', 'Initialization MPU9250 ....');
// Clear configuration
yield this.writeBit(exports.MPU9250.RA_PWR_MGMT_1, exports.MPU9250.PWR1_DEVICE_RESET_BIT, 1);
this.debug.log('INFO', 'Reset configuration MPU9250.');
yield (0, utils_1.sleep)(100);
// defined sample rate
if ('SAMPLE_RATE' in this._config
&& this._config.SAMPLE_RATE
&& (this._config.SAMPLE_RATE > exports.MPU9250.SAMPLERATE_MIN
&& this._config.SAMPLE_RATE < exports.MPU9250.SAMPLERATE_MAX)) {
yield this.setSampleRate(this._config.SAMPLE_RATE);
yield (0, utils_1.sleep)(100);
}
// Define DLPF_CFG
if ('DLPF_CFG' in this._config && this._config.DLPF_CFG) {
yield this.setDLPFConfig(this._config.DLPF_CFG);
yield (0, utils_1.sleep)(100);
}
// define A_DLPF_CFG
if ('A_DLPF_CFG' in this._config && this._config.A_DLPF_CFG) {
yield this.setAccelDLPFConfig(this._config.A_DLPF_CFG);
yield (0, utils_1.sleep)(100);
}
// define clock source
this.setClockSource(exports.MPU9250.CLOCK_PLL_XGYRO);
yield (0, utils_1.sleep)(100);
// define gyro range
var gyro_fs = [exports.MPU9250.GYRO_FS_250, exports.MPU9250.GYRO_FS_500, exports.MPU9250.GYRO_FS_1000, exports.MPU9250.GYRO_FS_2000];
var gyro_value = exports.MPU9250.GYRO_FS_250;
if (this._config.GYRO_FS > -1 && this._config.GYRO_FS < 4)
gyro_value = gyro_fs[this._config.GYRO_FS];
yield this.setFullScaleGyroRange(gyro_value);
yield (0, utils_1.sleep)(100);
// define accel range
var accel_fs = [exports.MPU9250.ACCEL_FS_2, exports.MPU9250.ACCEL_FS_4, exports.MPU9250.ACCEL_FS_8, exports.MPU9250.ACCEL_FS_16];
var accel_value = exports.MPU9250.ACCEL_FS_4;
if (this._config.ACCEL_FS > -1 && this._config.ACCEL_FS < 4)
accel_value = accel_fs[this._config.ACCEL_FS];
yield this.setFullScaleAccelRange(accel_value);
yield (0, utils_1.sleep)(100);
// disable sleepEnabled
yield this.setSleepEnabled(false);
yield (0, utils_1.sleep)(100);
if (this._config.UpMagneto) {
this.debug.log('INFO', 'Enabled magnetometer. Starting initialization ....');
yield this.enableMagnetometer();
this.debug.log('INFO', 'END of magnetometer initialization.');
}
this.debug.log('INFO', 'END of MPU9150 initialization.');
// Print out the configuration
if (this._config.DEBUG) {
yield this.printSettings();
yield this.printAccelSettings();
yield this.printGyroSettings();
if (this.ak8963) {
yield this.ak8963.printSettings();
}
}
return yield this.testDevice();
});
}
getMotion9() {
return __awaiter(this, void 0, void 0, function* () {
const mpudata = yield this.getMotion6();
let magdata;
if (this.ak8963) {
magdata = yield this.ak8963.getMagAttitude();
}
else {
magdata = [0, 0, 0];
}
return mpudata.concat(magdata);
});
}
getMotion6() {
return __awaiter(this, void 0, void 0, function* () {
var buffer = yield this.readBytes(exports.MPU9250.ACCEL_XOUT_H, 14);
var gCal = this._config.gyroBiasOffset;
var aCal = this._config.accelCalibration;
var xAccel = buffer.readInt16BE(0) * this.accelScalarInv;
var yAccel = buffer.readInt16BE(2) * this.accelScalarInv;
var zAccel = buffer.readInt16BE(4) * this.accelScalarInv;
return [
// Accelerometer
this.scaleAccel(xAccel, aCal.offset.x, aCal.scale.x),
this.scaleAccel(yAccel, aCal.offset.y, aCal.scale.y),
this.scaleAccel(zAccel, aCal.offset.z, aCal.scale.z),
// Skip Temperature - bytes 6:7
// Gyroscope
buffer.readInt16BE(8) * this.gyroScalarInv + gCal.x,
buffer.readInt16BE(10) * this.gyroScalarInv + gCal.y,
buffer.readInt16BE(12) * this.gyroScalarInv + gCal.z
];
});
}
scaleAccel(val, offset, scalerArr) {
if (val < 0) {
return -(val - offset) / (scalerArr[0] - offset);
}
else {
return (val - offset) / (scalerArr[1] - offset);
}
}
testDevice() {
return __awaiter(this, void 0, void 0, function* () {
var currentDeviceID = yield this.getIDDevice();
return (currentDeviceID === exports.MPU9250.ID_MPU_9250 || currentDeviceID === exports.MPU9250.ID_MPU_9255);
});
}
printGyroSettings() {
return __awaiter(this, void 0, void 0, function* () {
var FS_RANGE = ['+250dps (0)', '+500 dps (1)', '+1000 dps (2)', '+2000 dps (3)'];
this.debug.log('INFO', 'Gyroscope:');
this.debug.log('INFO', '--> Full Scale Range (0x1B): ' + FS_RANGE[yield this.getFullScaleGyroRange()]);
this.debug.log('INFO', '--> Scalar: 1/' + (1 / this.gyroScalarInv));
this.debug.log('INFO', '--> Bias Offset:');
this.debug.log('INFO', ' --> x: ' + this._config.gyroBiasOffset.x);
this.debug.log('INFO', ' --> y: ' + this._config.gyroBiasOffset.y);
this.debug.log('INFO', ' --> z: ' + this._config.gyroBiasOffset.z);
});
}
getFullScaleGyroRange() {
return __awaiter(this, void 0, void 0, function* () {
var byte = yield this.readByte(exports.MPU9250.RA_GYRO_CONFIG);
byte = byte & 0x18;
byte = byte >> 3;
return byte;
});
}
printAccelSettings() {
return __awaiter(this, void 0, void 0, function* () {
var FS_RANGE = ['±2g (0)', '±4g (1)', '±8g (2)', '±16g (3)'];
this.debug.log('INFO', 'Accelerometer:');
this.debug.log('INFO', '--> Full Scale Range (0x1C): ' + FS_RANGE[yield this.getFullScaleAccelRange()]);
this.debug.log('INFO', '--> Scalar: 1/' + (1 / this.accelScalarInv));
this.debug.log('INFO', '--> Calibration:');
this.debug.log('INFO', ' --> Offset: ');
this.debug.log('INFO', ' --> x: ' + this._config.accelCalibration.offset.x);
this.debug.log('INFO', ' --> y: ' + this._config.accelCalibration.offset.y);
this.debug.log('INFO', ' --> z: ' + this._config.accelCalibration.offset.z);
this.debug.log('INFO', ' --> Scale: ');
this.debug.log('INFO', ' --> x: ' + this._config.accelCalibration.scale.x);
this.debug.log('INFO', ' --> y: ' + this._config.accelCalibration.scale.y);
this.debug.log('INFO', ' --> z: ' + this._config.accelCalibration.scale.z);
});
}
getFullScaleAccelRange() {
return __awaiter(this, void 0, void 0, function* () {
var byte = yield this.readByte(exports.MPU9250.RA_ACCEL_CONFIG_1);
byte = byte & 0x18;
byte = byte >> 3;
return byte;
});
}
printSettings() {
return __awaiter(this, void 0, void 0, function* () {
var CLK_RNG = [
'0 (Internal 20MHz oscillator)',
'1 (Auto selects the best available clock source)',
'2 (Auto selects the best available clock source)',
'3 (Auto selects the best available clock source)',
'4 (Auto selects the best available clock source)',
'5 (Auto selects the best available clock source)',
'6 (Internal 20MHz oscillator)',
'7 (Stops the clock and keeps timing generator in reset)'
];
this.debug.log('INFO', 'MPU9250:');
this.debug.log('INFO', '--> Device address: 0x' + this._config.address.toString(16));
this.debug.log('INFO', '--> i2c bus: 0x' + (yield this.getIDDevice()).toString(16));
this.debug.log('INFO', '--> Device ID: 0x' + (yield this.getIDDevice()).toString(16));
this.debug.log('INFO', '--> BYPASS enabled: ' + ((yield this.getByPASSEnabled()) ? 'Yes' : 'No'));
this.debug.log('INFO', '--> SleepEnabled Mode: ' + ((yield this.getSleepEnabled()) === 1 ? 'On' : 'Off'));
this.debug.log('INFO', '--> i2c Master Mode: ' + ((yield this.getI2CMasterMode()) === 1 ? 'Enabled' : 'Disabled'));
this.debug.log('INFO', '--> Power Management (0x6B, 0x6C):');
this.debug.log('INFO', ' --> Clock Source: ' + CLK_RNG[yield this.getClockSource()]);
this.debug.log('INFO', ' --> Accel enabled (x, y, z): ' + this.vectorToYesNo(yield this.getAccelPowerSettings()));
this.debug.log('INFO', ' --> Gyro enabled (x, y, z): ' + this.vectorToYesNo(yield this.getGyroPowerSettings()));
});
}
getGyroPowerSettings() {
return __awaiter(this, void 0, void 0, function* () {
var byte = yield this.readByte(exports.MPU9250.RA_PWR_MGMT_2);
byte = byte & 0x07;
return [
(byte >> 2) & 1, // X
(byte >> 1) & 1, // Y
(byte >> 0) & 1 // Z
];
});
}
getPitch(value) {
return ((Math.atan2(value[0], value[2]) + Math.PI) * (180 / Math.PI)) - 180;
}
getRoll(value) {
return ((Math.atan2(value[1], value[2]) + Math.PI) * (180 / Math.PI)) - 180;
}
getYaw(value) {
return 0;
}
getGyro() {
return __awaiter(this, void 0, void 0, function* () {
var buffer = yield this.readBytes(exports.MPU9250.GYRO_XOUT_H, 6);
var gCal = this._config.gyroBiasOffset;
return [
buffer.readInt16BE(0) * this.gyroScalarInv + gCal.x,
buffer.readInt16BE(2) * this.gyroScalarInv + gCal.y,
buffer.readInt16BE(4) * this.gyroScalarInv + gCal.z
];
});
}
getAccel() {
return __awaiter(this, void 0, void 0, function* () {
var buffer = yield this.readBytes(exports.MPU9250.ACCEL_XOUT_H, 6);
var aCal = this._config.accelCalibration;
var xAccel = buffer.readInt16BE(0) * this.accelScalarInv;
var yAccel = buffer.readInt16BE(2) * this.accelScalarInv;
var zAccel = buffer.readInt16BE(4) * this.accelScalarInv;
return [
this.scaleAccel(xAccel, aCal.offset.x, aCal.scale.x),
this.scaleAccel(yAccel, aCal.offset.y, aCal.scale.y),
this.scaleAccel(zAccel, aCal.offset.z, aCal.scale.z)
];
});
}
getAccelPowerSettings() {
return __awaiter(this, void 0, void 0, function* () {
var byte = yield this.readByte(exports.MPU9250.RA_PWR_MGMT_2);
byte = byte & 0x38;
return [
(byte >> 5) & 1, // X
(byte >> 4) & 1, // Y
(byte >> 3) & 1 // Z
];
});
}
getClockSource() {
return __awaiter(this, void 0, void 0, function* () {
return (yield this.readByte(exports.MPU9250.RA_PWR_MGMT_1)) & 0x07;
});
}
getI2CMasterMode() {
return __awaiter(this, void 0, void 0, function* () {
return yield this.readBit(exports.MPU9250.RA_USER_CTRL, exports.MPU9250.USERCTRL_I2C_MST_EN_BIT);
});
}
getSleepEnabled() {
return __awaiter(this, void 0, void 0, function* () {
return yield this.readBit(exports.MPU9250.RA_PWR_MGMT_1, exports.MPU9250.PWR1_SLEEP_BIT);
});
}
getIDDevice() {
return __awaiter(this, void 0, void 0, function* () {
return yield this.readByte(exports.MPU9250.WHO_AM_I);
});
}
setSampleRate(sample_rate) {
return __awaiter(this, void 0, void 0, function* () {
if (sample_rate < exports.MPU9250.SAMPLERATE_MAX && sample_rate >= 8000) {
sample_rate = 8000;
}
if (sample_rate < 8000 && sample_rate > 1000) {
sample_rate = 1000;
}
if (sample_rate < 1000) {
sample_rate = 1000 / (1 + sample_rate);
}
yield this.writeBits(exports.MPU9250.SMPLRT_DIV, 0, 8, sample_rate).catch((r) => {
this.debug.log('ERROR', 'setSampleRate ' + r.message);
});
});
}
enableMagnetometer() {
return __awaiter(this, void 0, void 0, function* () {
yield this.setI2CMasterModeEnabled(false);
yield (0, utils_1.sleep)(100);
yield this.setByPASSEnabled(true);
yield (0, utils_1.sleep)(100);
if (yield this.getByPASSEnabled()) {
// this.ak8963 = new ak8963(this._config);
// await this.ak8963.initialize();
}
else {
this.debug.log('ERROR', 'Can\'t turn on RA_INT_PIN_CFG.');
}
});
}
getByPASSEnabled() {
return __awaiter(this, void 0, void 0, function* () {
return yield this.readBit(exports.MPU9250.RA_INT_PIN_CFG, exports.MPU9250.INTCFG_BYPASS_EN_BIT);
});
}
setByPASSEnabled(bool) {
return __awaiter(this, void 0, void 0, function* () {
var val = bool ? 1 : 0;
// await this.writeByte(MPU9250.RA_INT_PIN_CFG, 0x02)
yield this.writeBit(exports.MPU9250.RA_INT_PIN_CFG, exports.MPU9250.INTCFG_BYPASS_EN_BIT, val);
});
}
setI2CMasterModeEnabled(bool) {
return __awaiter(this, void 0, void 0, function* () {
var val = bool ? 1 : 0;
yield this.writeBit(exports.MPU9250.RA_USER_CTRL, exports.MPU9250.USERCTRL_I2C_MST_EN_BIT, val);
});
}
setSleepEnabled(bool) {
return __awaiter(this, void 0, void 0, function* () {
var val = bool ? 1 : 0;
yield this.writeBit(exports.MPU9250.RA_PWR_MGMT_1, exports.MPU9250.PWR1_SLEEP_BIT, val);
});
}
setFullScaleAccelRange(adrs) {
return __awaiter(this, void 0, void 0, function* () {
if (this._config.scaleValues) {
this.accelScalarInv = 1 / exports.MPU9250.ACCEL_SCALE_FACTOR[adrs];
}
else {
this.accelScalarInv = 1;
}
yield this.writeBits(exports.MPU9250.RA_ACCEL_CONFIG_1, exports.MPU9250.ACONFIG_FS_SEL_BIT, exports.MPU9250.ACONFIG_FS_SEL_LENGTH, adrs);
});
}
setFullScaleGyroRange(adrs) {
return __awaiter(this, void 0, void 0, function* () {
if (this._config.scaleValues) {
this.gyroScalarInv = 1 / exports.MPU9250.GYRO_SCALE_FACTOR[adrs];
}
else {
this.gyroScalarInv = 1;
}
yield this.writeBits(exports.MPU9250.RA_GYRO_CONFIG, exports.MPU9250.GCONFIG_FS_SEL_BIT, exports.MPU9250.GCONFIG_FS_SEL_LENGTH, adrs);
});
}
setClockSource(adrs) {
return __awaiter(this, void 0, void 0, function* () {
yield this.writeBits(exports.MPU9250.RA_PWR_MGMT_1, exports.MPU9250.PWR1_CLKSEL_BIT, exports.MPU9250.PWR1_CLKSEL_LENGTH, adrs);
});
}
setDLPFConfig(dlpf_cfg) {
return __awaiter(this, void 0, void 0, function* () {
yield this.writeBits(exports.MPU9250.RA_CONFIG, 0, 3, dlpf_cfg).catch((r) => {
this.debug.log('ERROR', 'setDLPFConfig ' + r.message);
});
});
}
setAccelDLPFConfig(a_dlpf_cfg) {
return __awaiter(this, void 0, void 0, function* () {
yield this.writeBits(exports.MPU9250.RA_ACCEL_CONFIG_2, 0, 4, a_dlpf_cfg).catch((r) => {
this.debug.log('ERROR', 'setAccelDLPFConfig ' + r.message);
});
});
}
}
exports.mpu9250 = mpu9250;
// Other classes (ak8963, debugConsole, etc.) and their methods with type annotations
// Export the module
exports.default = mpu9250;