mirror of
https://gitee.com/xiaohuolufeihua/bizhang_-obav.git
synced 2026-05-22 01:12:31 +00:00
MPU9250 I2C mode
Fixes for other boards Functioning sensors
This commit is contained in:
committed by
Lorenz Meier
parent
9c8e56401b
commit
5100785f51
@@ -10,5 +10,12 @@
|
|||||||
sh /etc/init.d/4001_quad_x
|
sh /etc/init.d/4001_quad_x
|
||||||
|
|
||||||
|
|
||||||
|
if [ $AUTOCNF == yes ]
|
||||||
|
then
|
||||||
|
param set COM_RC_IN_MODE 2
|
||||||
|
param set BAT_N_CELLS 1
|
||||||
|
param set BAT_CAPACITY 240
|
||||||
|
param set BAT_SOURCE 1
|
||||||
|
fi
|
||||||
|
|
||||||
set OUTPUT_MODE crazyflie
|
set OUTPUT_MODE crazyflie
|
||||||
set USE_IO no
|
|
||||||
|
|||||||
@@ -109,6 +109,11 @@ then
|
|||||||
set MIXER_AUX none
|
set MIXER_AUX none
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ver hwcmp CRAZYFLIE
|
||||||
|
then
|
||||||
|
set MIXER_AUX none
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $MIXER_AUX != none -a $AUX_MODE != none ]
|
if [ $MIXER_AUX != none -a $AUX_MODE != none ]
|
||||||
then
|
then
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -8,12 +8,20 @@ then
|
|||||||
if ms5611 start
|
if ms5611 start
|
||||||
then
|
then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
|
if ver hwcmp CRAZYFLIE
|
||||||
|
then
|
||||||
|
# Crazyflie uses separate driver
|
||||||
|
else
|
||||||
|
|
||||||
# Configure all I2C buses to 100 KHz as they
|
# Configure all I2C buses to 100 KHz as they
|
||||||
# are all external or slow
|
# are all external or slow
|
||||||
fmu i2c 1 100000
|
fmu i2c 1 100000
|
||||||
fmu i2c 2 100000
|
fmu i2c 2 100000
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
if ver hwcmp PX4FMU_V4
|
if ver hwcmp PX4FMU_V4
|
||||||
then
|
then
|
||||||
# We know there are sketchy boards out there
|
# We know there are sketchy boards out there
|
||||||
@@ -198,6 +206,19 @@ then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ver hwcmp CRAZYFLIE
|
||||||
|
then
|
||||||
|
# Onboard I2C
|
||||||
|
if mpu9250 -R 12 start
|
||||||
|
then
|
||||||
|
fi
|
||||||
|
|
||||||
|
# I2C bypass of mpu
|
||||||
|
if lps25h start
|
||||||
|
then
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if meas_airspeed start
|
if meas_airspeed start
|
||||||
then
|
then
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -164,10 +164,16 @@ then
|
|||||||
then
|
then
|
||||||
set USE_IO no
|
set USE_IO no
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ver hwcmp CRAZYFLIE
|
||||||
|
then
|
||||||
|
set USE_IO no
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
set USE_IO no
|
set USE_IO no
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# should set to 0.8 for mindpx-v2 borad.
|
# should set to 0.8 for mindpx-v2 borad.
|
||||||
if param compare INAV_LIDAR_ERR 0.5
|
if param compare INAV_LIDAR_ERR 0.5
|
||||||
then
|
then
|
||||||
@@ -675,6 +681,15 @@ then
|
|||||||
ardrone_interface start -d /dev/ttyS1
|
ardrone_interface start -d /dev/ttyS1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Start Crazyflie driver
|
||||||
|
#
|
||||||
|
if ver hwcmp CRAZYFLIE
|
||||||
|
then
|
||||||
|
crazyflie start
|
||||||
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# Fixed wing setup
|
# Fixed wing setup
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ set(config_module_list
|
|||||||
drivers/led
|
drivers/led
|
||||||
drivers/boards/crazyflie
|
drivers/boards/crazyflie
|
||||||
drivers/crazyflie
|
drivers/crazyflie
|
||||||
#drivers/mpu9250
|
drivers/mpu9250
|
||||||
#drivers/ak8963
|
#drivers/ak8963
|
||||||
drivers/lps25h
|
drivers/lps25h
|
||||||
drivers/gps
|
drivers/gps
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ px4_add_module(
|
|||||||
main.cpp
|
main.cpp
|
||||||
gyro.cpp
|
gyro.cpp
|
||||||
mag.cpp
|
mag.cpp
|
||||||
|
mag_i2c.cpp
|
||||||
DEPENDS
|
DEPENDS
|
||||||
platforms__common
|
platforms__common
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
class MPU9250;
|
class MPU9250;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -149,8 +149,11 @@
|
|||||||
#define AK8963_RESET 0x01
|
#define AK8963_RESET 0x01
|
||||||
|
|
||||||
|
|
||||||
MPU9250_mag::MPU9250_mag(MPU9250 *parent, const char *path) :
|
// If interface is non-null, then it will used for interacting with the device.
|
||||||
|
// Otherwise, it will passthrough the parent MPU9250
|
||||||
|
MPU9250_mag::MPU9250_mag(MPU9250 *parent, device::Device *interface, const char *path) :
|
||||||
CDev("MPU9250_mag", path),
|
CDev("MPU9250_mag", path),
|
||||||
|
_interface(interface),
|
||||||
_parent(parent),
|
_parent(parent),
|
||||||
_mag_topic(nullptr),
|
_mag_topic(nullptr),
|
||||||
_mag_orb_class_instance(-1),
|
_mag_orb_class_instance(-1),
|
||||||
@@ -249,7 +252,16 @@ bool MPU9250_mag::check_duplicate(uint8_t *mag_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MPU9250_mag::measure(struct ak8963_regs data)
|
MPU9250_mag::measure()
|
||||||
|
{
|
||||||
|
struct ak8963_regs data;
|
||||||
|
if(OK == _interface->read(AK8963REG_ST1, &data, sizeof(struct ak8963_regs))){
|
||||||
|
_measure(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MPU9250_mag::_measure(struct ak8963_regs data)
|
||||||
{
|
{
|
||||||
bool mag_notify = true;
|
bool mag_notify = true;
|
||||||
|
|
||||||
@@ -508,12 +520,7 @@ MPU9250_mag::set_passthrough(uint8_t reg, uint8_t size, uint8_t *out)
|
|||||||
void
|
void
|
||||||
MPU9250_mag::read_block(uint8_t reg, uint8_t *val, uint8_t count)
|
MPU9250_mag::read_block(uint8_t reg, uint8_t *val, uint8_t count)
|
||||||
{
|
{
|
||||||
uint8_t addr = reg | 0x80;
|
_parent->_interface->read(reg, val, count);
|
||||||
uint8_t tx[32] = { addr, };
|
|
||||||
uint8_t rx[32];
|
|
||||||
|
|
||||||
_parent->transfer(tx, rx, count + 1);
|
|
||||||
memcpy(val, rx + 1, count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -525,12 +532,26 @@ MPU9250_mag::passthrough_read(uint8_t reg, uint8_t *buf, uint8_t size)
|
|||||||
_parent->write_reg(MPUREG_I2C_SLV0_CTRL, 0); // disable new reads
|
_parent->write_reg(MPUREG_I2C_SLV0_CTRL, 0); // disable new reads
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
MPU9250_mag::read_reg(unsigned int reg)
|
||||||
|
{
|
||||||
|
uint8_t buf;
|
||||||
|
if (_interface == nullptr) {
|
||||||
|
passthrough_read(reg, &buf, 0x01);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_interface->read(reg, &buf, 1);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MPU9250_mag::ak8963_check_id(void)
|
MPU9250_mag::ak8963_check_id(void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
uint8_t deviceid = 0;
|
|
||||||
passthrough_read(AK8963REG_WIA, &deviceid, 0x01);
|
uint8_t deviceid = read_reg(AK8963REG_WIA);
|
||||||
|
|
||||||
if (AK8963_DEVICE_ID == deviceid) {
|
if (AK8963_DEVICE_ID == deviceid) {
|
||||||
return true;
|
return true;
|
||||||
@@ -551,10 +572,27 @@ MPU9250_mag::passthrough_write(uint8_t reg, uint8_t val)
|
|||||||
_parent->write_reg(MPUREG_I2C_SLV0_CTRL, 0); // disable new writes
|
_parent->write_reg(MPUREG_I2C_SLV0_CTRL, 0); // disable new writes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MPU9250_mag::write_reg(unsigned reg, uint8_t value)
|
||||||
|
{
|
||||||
|
// general register transfer at low clock speed
|
||||||
|
if (_interface == nullptr) {
|
||||||
|
passthrough_write(reg, value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_interface->write(MPU9250_LOW_SPEED_OP(reg), &value, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MPU9250_mag::ak8963_reset(void)
|
MPU9250_mag::ak8963_reset(void)
|
||||||
{
|
{
|
||||||
passthrough_write(AK8963REG_CNTL2, AK8963_RESET);
|
write_reg(AK8963REG_CNTL2, AK8963_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -563,10 +601,15 @@ MPU9250_mag::ak8963_read_adjustments(void)
|
|||||||
uint8_t response[3];
|
uint8_t response[3];
|
||||||
float ak8963_ASA[3];
|
float ak8963_ASA[3];
|
||||||
|
|
||||||
passthrough_write(AK8963REG_CNTL1, AK8963_FUZE_MODE | AK8963_16BIT_ADC);
|
write_reg(AK8963REG_CNTL1, AK8963_FUZE_MODE | AK8963_16BIT_ADC);
|
||||||
usleep(50);
|
usleep(50);
|
||||||
|
if (_interface != nullptr) {
|
||||||
|
_interface->read(AK8963REG_ASAX, response, 3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
passthrough_read(AK8963REG_ASAX, response, 3);
|
passthrough_read(AK8963REG_ASAX, response, 3);
|
||||||
passthrough_write(AK8963REG_CNTL1, AK8963_POWERDOWN_MODE);
|
}
|
||||||
|
write_reg(AK8963REG_CNTL1, AK8963_POWERDOWN_MODE);
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (0 != response[i] && 0xff != response[i]) {
|
if (0 != response[i] && 0xff != response[i]) {
|
||||||
@@ -589,10 +632,18 @@ MPU9250_mag::ak8963_setup(void)
|
|||||||
{
|
{
|
||||||
int retries = 10;
|
int retries = 10;
|
||||||
|
|
||||||
// enable the I2C master to slaves on the aux bus
|
/* Configures the parent to act in master mode */
|
||||||
|
if(_interface == nullptr) {
|
||||||
uint8_t user_ctrl = _parent->read_reg(MPUREG_USER_CTRL);
|
uint8_t user_ctrl = _parent->read_reg(MPUREG_USER_CTRL);
|
||||||
_parent->write_checked_reg(MPUREG_USER_CTRL, user_ctrl | BIT_I2C_MST_EN);
|
_parent->write_checked_reg(MPUREG_USER_CTRL, user_ctrl | BIT_I2C_MST_EN);
|
||||||
_parent->write_reg(MPUREG_I2C_MST_CTRL, BIT_I2C_MST_P_NSR | BIT_I2C_MST_WAIT_FOR_ES | BITS_I2C_MST_CLOCK_400HZ);
|
_parent->write_reg(MPUREG_I2C_MST_CTRL, BIT_I2C_MST_P_NSR | BIT_I2C_MST_WAIT_FOR_ES | BITS_I2C_MST_CLOCK_400HZ);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// uint8_t user_ctrl = _parent->read_reg(MPUREG_USER_CTRL);
|
||||||
|
|
||||||
|
// // Passthrough mode
|
||||||
|
// _parent->write_checked_reg(MPUREG_USER_CTRL, user_ctrl & (~BIT_I2C_MST_EN));
|
||||||
|
}
|
||||||
|
|
||||||
if (!ak8963_check_id()) {
|
if (!ak8963_check_id()) {
|
||||||
::printf("AK8963: bad id\n");
|
::printf("AK8963: bad id\n");
|
||||||
@@ -605,9 +656,13 @@ MPU9250_mag::ak8963_setup(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
passthrough_write(AK8963REG_CNTL1, AK8963_CONTINUOUS_MODE2 | AK8963_16BIT_ADC);
|
write_reg(AK8963REG_CNTL1, AK8963_CONTINUOUS_MODE2 | AK8963_16BIT_ADC);
|
||||||
|
|
||||||
|
|
||||||
|
if(_interface == NULL) {
|
||||||
|
/* Configure mpu to internally read ak8963 data */
|
||||||
set_passthrough(AK8963REG_ST1, sizeof(struct ak8963_regs));
|
set_passthrough(AK8963REG_ST1, sizeof(struct ak8963_regs));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
class MPU9250;
|
class MPU9250;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
@@ -43,13 +45,18 @@ struct ak8963_regs {
|
|||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
extern device::Device *AK8963_I2C_interface(int bus, bool external_bus);
|
||||||
|
|
||||||
|
typedef device::Device *(*MPU9250_mag_constructor)(int, bool);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class implementing the magnetometer driver node.
|
* Helper class implementing the magnetometer driver node.
|
||||||
*/
|
*/
|
||||||
class MPU9250_mag : public device::CDev
|
class MPU9250_mag : public device::CDev
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MPU9250_mag(MPU9250 *parent, const char *path);
|
MPU9250_mag(MPU9250 *parent, device::Device *interface, const char *path);
|
||||||
~MPU9250_mag();
|
~MPU9250_mag();
|
||||||
|
|
||||||
virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
|
virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
|
||||||
@@ -67,9 +74,24 @@ public:
|
|||||||
bool ak8963_read_adjustments(void);
|
bool ak8963_read_adjustments(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Device *_interface;
|
||||||
|
|
||||||
friend class MPU9250;
|
friend class MPU9250;
|
||||||
|
|
||||||
void measure(struct ak8963_regs data);
|
/* Directly measure from the _interface if possible */
|
||||||
|
void measure();
|
||||||
|
|
||||||
|
/* Update the state with prefetched data (internally called by the regular measure() )*/
|
||||||
|
void _measure(struct ak8963_regs data);
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t read_reg(unsigned reg);
|
||||||
|
void write_reg(unsigned reg, uint8_t value);
|
||||||
|
|
||||||
|
|
||||||
|
bool is_passthrough() { return _interface == nullptr; }
|
||||||
|
|
||||||
|
|
||||||
int self_test(void);
|
int self_test(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
179
src/drivers/mpu9250/mag_i2c.cpp
Normal file
179
src/drivers/mpu9250/mag_i2c.cpp
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 PX4 Development Team. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file mag_i2c.cpp
|
||||||
|
*
|
||||||
|
* I2C interface for AK8963
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* XXX trim includes */
|
||||||
|
#include <px4_config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <arch/board/board.h>
|
||||||
|
|
||||||
|
#include <drivers/device/i2c.h>
|
||||||
|
#include <drivers/drv_accel.h>
|
||||||
|
#include <drivers/drv_device.h>
|
||||||
|
|
||||||
|
#include "MPU9250.h"
|
||||||
|
#include "mag.h"
|
||||||
|
|
||||||
|
#include "board_config.h"
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: This is redundant with mag.cpp
|
||||||
|
#define AK8963_I2C_ADDR 0x0C
|
||||||
|
#define ADDR_ID 0x00
|
||||||
|
|
||||||
|
#define ID_WHO_AM_I 0x48
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_I2C
|
||||||
|
|
||||||
|
device::Device *AK8963_I2C_interface(int bus, bool external_bus);
|
||||||
|
|
||||||
|
class AK8963_I2C : public device::I2C
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AK8963_I2C(int bus);
|
||||||
|
virtual ~AK8963_I2C();
|
||||||
|
|
||||||
|
virtual int init();
|
||||||
|
virtual int read(unsigned address, void *data, unsigned count);
|
||||||
|
virtual int write(unsigned address, void *data, unsigned count);
|
||||||
|
|
||||||
|
virtual int ioctl(unsigned operation, unsigned &arg);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int probe();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
device::Device *
|
||||||
|
AK8963_I2C_interface(int bus, bool external_bus)
|
||||||
|
{
|
||||||
|
return new AK8963_I2C(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
AK8963_I2C::AK8963_I2C(int bus) :
|
||||||
|
I2C("AK8963_I2C", nullptr, bus, AK8963_I2C_ADDR, 400000)
|
||||||
|
{
|
||||||
|
_device_id.devid_s.devtype = DRV_MAG_DEVTYPE_MPU9250;
|
||||||
|
}
|
||||||
|
|
||||||
|
AK8963_I2C::~AK8963_I2C()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
AK8963_I2C::init()
|
||||||
|
{
|
||||||
|
/* this will call probe() */
|
||||||
|
return I2C::init();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
AK8963_I2C::ioctl(unsigned operation, unsigned &arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
switch (operation) {
|
||||||
|
|
||||||
|
case ACCELIOCGEXTERNAL:
|
||||||
|
return _bus == PX4_I2C_BUS_EXPANSION ? 1 : 0;
|
||||||
|
|
||||||
|
case DEVIOCGDEVICEID:
|
||||||
|
return CDev::ioctl(nullptr, operation, arg);
|
||||||
|
|
||||||
|
case MPUIOCGIS_I2C:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
AK8963_I2C::write(unsigned reg_speed, void *data, unsigned count)
|
||||||
|
{
|
||||||
|
uint8_t cmd[MPU_MAX_WRITE_BUFFER_SIZE];
|
||||||
|
|
||||||
|
if (sizeof(cmd) < (count + 1)) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd[0] = MPU9250_REG(reg_speed);
|
||||||
|
cmd[1] = *(uint8_t *)data;
|
||||||
|
return transfer(&cmd[0], count + 1, nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
AK8963_I2C::read(unsigned reg_speed, void *data, unsigned count)
|
||||||
|
{
|
||||||
|
uint8_t cmd = MPU9250_REG(reg_speed);
|
||||||
|
return transfer(&cmd, 1, (uint8_t *)data, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
AK8963_I2C::probe()
|
||||||
|
{
|
||||||
|
uint8_t whoami = 0;
|
||||||
|
uint8_t expected = ID_WHO_AM_I;
|
||||||
|
|
||||||
|
if (read(ADDR_ID, &whoami, 1)) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (whoami != expected) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
/**
|
/**
|
||||||
* @file main.cpp
|
* @file main.cpp
|
||||||
*
|
*
|
||||||
* Driver for the Invensense mpu9250 connected via SPI.
|
* Driver for the Invensense mpu9250 connected via I2C or SPI.
|
||||||
*
|
*
|
||||||
* @authors Andrew Tridgell
|
* @authors Andrew Tridgell
|
||||||
* Robert Dickenson
|
* Robert Dickenson
|
||||||
@@ -83,11 +83,6 @@
|
|||||||
/** driver 'main' command */
|
/** driver 'main' command */
|
||||||
extern "C" { __EXPORT int mpu9250_main(int argc, char *argv[]); }
|
extern "C" { __EXPORT int mpu9250_main(int argc, char *argv[]); }
|
||||||
|
|
||||||
/**
|
|
||||||
* Local functions in support of the shell command.
|
|
||||||
*/
|
|
||||||
namespace mpu9250
|
|
||||||
{
|
|
||||||
|
|
||||||
enum MPU9250_BUS {
|
enum MPU9250_BUS {
|
||||||
MPU9250_BUS_ALL = 0,
|
MPU9250_BUS_ALL = 0,
|
||||||
@@ -97,6 +92,13 @@ enum MPU9250_BUS {
|
|||||||
MPU9250_BUS_SPI_EXTERNAL
|
MPU9250_BUS_SPI_EXTERNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local functions in support of the shell command.
|
||||||
|
*/
|
||||||
|
namespace mpu9250
|
||||||
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
list of supported bus configurations
|
list of supported bus configurations
|
||||||
*/
|
*/
|
||||||
@@ -107,30 +109,31 @@ struct mpu9250_bus_option {
|
|||||||
const char *gyropath;
|
const char *gyropath;
|
||||||
const char *magpath;
|
const char *magpath;
|
||||||
MPU9250_constructor interface_constructor;
|
MPU9250_constructor interface_constructor;
|
||||||
|
bool magpassthrough;
|
||||||
uint8_t busnum;
|
uint8_t busnum;
|
||||||
MPU6000 *dev;
|
MPU9250 *dev;
|
||||||
} bus_options[] = {
|
} bus_options[] = {
|
||||||
#if defined (USE_I2C)
|
#if defined (USE_I2C)
|
||||||
# if defined(PX4_I2C_BUS_ONBOARD)
|
# if defined(PX4_I2C_BUS_ONBOARD)
|
||||||
{ MPU9250_BUS_I2C_INTERNAL, MPU_DEVICE_PATH_ACCEL, MPU_DEVICE_PATH_GYRO, MPU_DEVICE_PATH_MAG, &MPU9250_I2C_interface, PX4_I2C_BUS_ONBOARD, NULL },
|
{ MPU9250_BUS_I2C_INTERNAL, MPU_DEVICE_PATH_ACCEL, MPU_DEVICE_PATH_GYRO, MPU_DEVICE_PATH_MAG, &MPU9250_I2C_interface, false, PX4_I2C_BUS_ONBOARD, NULL },
|
||||||
# endif
|
# endif
|
||||||
# if defined(PX4_I2C_BUS_EXPANSION)
|
# if defined(PX4_I2C_BUS_EXPANSION)
|
||||||
{ MPU9250_BUS_I2C_EXTERNAL, MPU_DEVICE_PATH_ACCEL_EXT, MPU_DEVICE_PATH_GYRO_EXT, MPU_DEVICE_PATH_MAG_EXT, &MPU9250_I2C_interface, PX4_I2C_BUS_EXPANSION, NULL },
|
{ MPU9250_BUS_I2C_EXTERNAL, MPU_DEVICE_PATH_ACCEL_EXT, MPU_DEVICE_PATH_GYRO_EXT, MPU_DEVICE_PATH_MAG_EXT, &MPU9250_I2C_interface, false, PX4_I2C_BUS_EXPANSION, NULL },
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef PX4_SPIDEV_MPU
|
#ifdef PX4_SPIDEV_MPU
|
||||||
{ MPU9250_BUS_SPI_INTERNAL, MPU_DEVICE_PATH_ACCEL, MPU_DEVICE_PATH_GYRO, MPU_DEVICE_PATH_MAG, &MPU9250_SPI_interface, PX4_SPI_BUS_SENSORS, NULL },
|
{ MPU9250_BUS_SPI_INTERNAL, MPU_DEVICE_PATH_ACCEL, MPU_DEVICE_PATH_GYRO, MPU_DEVICE_PATH_MAG, &MPU9250_SPI_interface, true, PX4_SPI_BUS_SENSORS, NULL },
|
||||||
#endif
|
#endif
|
||||||
#if defined(PX4_SPI_BUS_EXT)
|
#if defined(PX4_SPI_BUS_EXT)
|
||||||
{ MPU9250_BUS_SPI_EXTERNAL, MPU_DEVICE_PATH_ACCEL_EXT, MPU_DEVICE_PATH_GYRO_EXT, MPU_DEVICE_PATH_MAG_EXT &MPU9250_SPI_interface, PX4_SPI_BUS_EXT, NULL },
|
{ MPU9250_BUS_SPI_EXTERNAL, MPU_DEVICE_PATH_ACCEL_EXT, MPU_DEVICE_PATH_GYRO_EXT, MPU_DEVICE_PATH_MAG_EXT &MPU9250_SPI_interface, true, PX4_SPI_BUS_EXT, NULL },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_BUS_OPTIONS (sizeof(bus_options)/sizeof(bus_options[0]))
|
#define NUM_BUS_OPTIONS (sizeof(bus_options)/sizeof(bus_options[0]))
|
||||||
|
|
||||||
|
|
||||||
void start(enum MPU9250_BUS busid, enum Rotation rotation);
|
void start(enum MPU9250_BUS busid, enum Rotation rotation, bool external_bus);
|
||||||
bool start_bus(struct mpu9250_bus_option &bus, enum Rotation rotation);
|
bool start_bus(struct mpu9250_bus_option &bus, enum Rotation rotation, bool external_bus);
|
||||||
struct mpu9250_bus_option &find_bus(enum MPU9250_BUS busid);
|
struct mpu9250_bus_option &find_bus(enum MPU9250_BUS busid);
|
||||||
void stop(enum MPU9250_BUS busid);
|
void stop(enum MPU9250_BUS busid);
|
||||||
void test(enum MPU9250_BUS busid);
|
void test(enum MPU9250_BUS busid);
|
||||||
@@ -159,7 +162,7 @@ struct mpu9250_bus_option &find_bus(enum MPU9250_BUS busid)
|
|||||||
* start driver for a specific bus option
|
* start driver for a specific bus option
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
start_bus(struct mpu9250_bus_option &bus, enum Rotation rotation, int range, int device_type, bool external)
|
start_bus(struct mpu9250_bus_option &bus, enum Rotation rotation, bool external)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
|
||||||
@@ -168,7 +171,7 @@ start_bus(struct mpu9250_bus_option &bus, enum Rotation rotation, int range, int
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
device::Device *interface = bus.interface_constructor(bus.busnum, device_type, external);
|
device::Device *interface = bus.interface_constructor(bus.busnum, external);
|
||||||
|
|
||||||
if (interface == nullptr) {
|
if (interface == nullptr) {
|
||||||
warnx("no device on bus %u", (unsigned)bus.busid);
|
warnx("no device on bus %u", (unsigned)bus.busid);
|
||||||
@@ -181,7 +184,17 @@ start_bus(struct mpu9250_bus_option &bus, enum Rotation rotation, int range, int
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus.dev = new MPU9250(interface, bus.accelpath, bus.gyropath, bus.magpath, rotation, device_type);
|
device::Device *mag_interface = nullptr;
|
||||||
|
|
||||||
|
#ifdef USE_I2C
|
||||||
|
/* For i2c interfaces, connect to the magnetomer directly */
|
||||||
|
bool is_i2c = bus.busid == MPU9250_BUS_I2C_INTERNAL || bus.busid == MPU9250_BUS_I2C_EXTERNAL;
|
||||||
|
if (is_i2c) {
|
||||||
|
mag_interface = AK8963_I2C_interface(bus.busnum, external);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bus.dev = new MPU9250(interface, mag_interface, bus.accelpath, bus.gyropath, bus.magpath, rotation);
|
||||||
|
|
||||||
if (bus.dev == nullptr) {
|
if (bus.dev == nullptr) {
|
||||||
delete interface;
|
delete interface;
|
||||||
@@ -203,9 +216,6 @@ start_bus(struct mpu9250_bus_option &bus, enum Rotation rotation, int range, int
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(fd, ACCELIOCSRANGE, range) < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
@@ -232,7 +242,7 @@ fail:
|
|||||||
* or failed to detect the sensor.
|
* or failed to detect the sensor.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
start(enum MPU9250_BUS busid, enum Rotation rotation, int range, int device_type, bool external)
|
start(enum MPU9250_BUS busid, enum Rotation rotation, bool external)
|
||||||
{
|
{
|
||||||
|
|
||||||
bool started = false;
|
bool started = false;
|
||||||
@@ -248,7 +258,7 @@ start(enum MPU9250_BUS busid, enum Rotation rotation, int range, int device_type
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
started |= start_bus(bus_options[i], rotation, range, device_type, external);
|
started |= start_bus(bus_options[i], rotation, external);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(started ? 0 : 1);
|
exit(started ? 0 : 1);
|
||||||
@@ -473,7 +483,6 @@ usage()
|
|||||||
warnx("options:");
|
warnx("options:");
|
||||||
warnx(" -X (external bus)");
|
warnx(" -X (external bus)");
|
||||||
warnx(" -R rotation");
|
warnx(" -R rotation");
|
||||||
warnx(" -a accel range (in g)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -485,13 +494,13 @@ mpu9250_main(int argc, char *argv[])
|
|||||||
int ch;
|
int ch;
|
||||||
bool external = false;
|
bool external = false;
|
||||||
enum Rotation rotation = ROTATION_NONE;
|
enum Rotation rotation = ROTATION_NONE;
|
||||||
int accel_range = 8;
|
//int accel_range = 8;
|
||||||
|
|
||||||
/* jump over start/off/etc and look at options first */
|
/* jump over start/off/etc and look at options first */
|
||||||
while ((ch = getopt(argc, argv, "XISsR:a:")) != EOF) {
|
while ((ch = getopt(argc, argv, "XISsR:")) != EOF) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'X':
|
case 'X':
|
||||||
busid = MPU9260_BUS_I2C_EXTERNAL;
|
busid = MPU9250_BUS_I2C_EXTERNAL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'I':
|
case 'I':
|
||||||
@@ -503,17 +512,13 @@ mpu9250_main(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
busid = MPU9260_BUS_SPI_INTERNAL;
|
busid = MPU9250_BUS_SPI_INTERNAL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
rotation = (enum Rotation)atoi(optarg);
|
rotation = (enum Rotation)atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a':
|
|
||||||
accel_range = atoi(optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
mpu9250::usage();
|
mpu9250::usage();
|
||||||
exit(0);
|
exit(0);
|
||||||
@@ -529,7 +534,7 @@ mpu9250_main(int argc, char *argv[])
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
if (!strcmp(verb, "start")) {
|
if (!strcmp(verb, "start")) {
|
||||||
mpu9250::start(busid, rotation, accel_range, device_type, external);
|
mpu9250::start(busid, rotation, external);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(verb, "stop")) {
|
if (!strcmp(verb, "stop")) {
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
#include <systemlib/perf_counter.h>
|
#include <systemlib/perf_counter.h>
|
||||||
#include <systemlib/err.h>
|
#include <systemlib/err.h>
|
||||||
#include <systemlib/conversions.h>
|
#include <systemlib/conversions.h>
|
||||||
|
#include <systemlib/px4_macros.h>
|
||||||
|
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include <nuttx/clock.h>
|
#include <nuttx/clock.h>
|
||||||
@@ -81,113 +82,6 @@
|
|||||||
#include "gyro.h"
|
#include "gyro.h"
|
||||||
#include "mpu9250.h"
|
#include "mpu9250.h"
|
||||||
|
|
||||||
#define DIR_READ 0x80
|
|
||||||
#define DIR_WRITE 0x00
|
|
||||||
|
|
||||||
// MPU 9250 registers
|
|
||||||
#define MPUREG_WHOAMI 0x75
|
|
||||||
#define MPUREG_SMPLRT_DIV 0x19
|
|
||||||
#define MPUREG_CONFIG 0x1A
|
|
||||||
#define MPUREG_GYRO_CONFIG 0x1B
|
|
||||||
#define MPUREG_ACCEL_CONFIG 0x1C
|
|
||||||
#define MPUREG_ACCEL_CONFIG2 0x1D
|
|
||||||
#define MPUREG_LPACCEL_ODR 0x1E
|
|
||||||
#define MPUREG_WOM_THRESH 0x1F
|
|
||||||
#define MPUREG_FIFO_EN 0x23
|
|
||||||
#define MPUREG_I2C_MST_CTRL 0x24
|
|
||||||
#define MPUREG_I2C_SLV0_ADDR 0x25
|
|
||||||
#define MPUREG_I2C_SLV0_REG 0x26
|
|
||||||
#define MPUREG_I2C_SLV0_CTRL 0x27
|
|
||||||
#define MPUREG_I2C_SLV1_ADDR 0x28
|
|
||||||
#define MPUREG_I2C_SLV1_REG 0x29
|
|
||||||
#define MPUREG_I2C_SLV1_CTRL 0x2A
|
|
||||||
#define MPUREG_I2C_SLV2_ADDR 0x2B
|
|
||||||
#define MPUREG_I2C_SLV2_REG 0x2C
|
|
||||||
#define MPUREG_I2C_SLV2_CTRL 0x2D
|
|
||||||
#define MPUREG_I2C_SLV3_ADDR 0x2E
|
|
||||||
#define MPUREG_I2C_SLV3_REG 0x2F
|
|
||||||
#define MPUREG_I2C_SLV3_CTRL 0x30
|
|
||||||
#define MPUREG_I2C_SLV4_ADDR 0x31
|
|
||||||
#define MPUREG_I2C_SLV4_REG 0x32
|
|
||||||
#define MPUREG_I2C_SLV4_DO 0x33
|
|
||||||
#define MPUREG_I2C_SLV4_CTRL 0x34
|
|
||||||
#define MPUREG_I2C_SLV4_DI 0x35
|
|
||||||
#define MPUREG_I2C_MST_STATUS 0x36
|
|
||||||
#define MPUREG_INT_PIN_CFG 0x37
|
|
||||||
#define MPUREG_INT_ENABLE 0x38
|
|
||||||
#define MPUREG_INT_STATUS 0x3A
|
|
||||||
#define MPUREG_ACCEL_XOUT_H 0x3B
|
|
||||||
#define MPUREG_ACCEL_XOUT_L 0x3C
|
|
||||||
#define MPUREG_ACCEL_YOUT_H 0x3D
|
|
||||||
#define MPUREG_ACCEL_YOUT_L 0x3E
|
|
||||||
#define MPUREG_ACCEL_ZOUT_H 0x3F
|
|
||||||
#define MPUREG_ACCEL_ZOUT_L 0x40
|
|
||||||
#define MPUREG_TEMP_OUT_H 0x41
|
|
||||||
#define MPUREG_TEMP_OUT_L 0x42
|
|
||||||
#define MPUREG_GYRO_XOUT_H 0x43
|
|
||||||
#define MPUREG_GYRO_XOUT_L 0x44
|
|
||||||
#define MPUREG_GYRO_YOUT_H 0x45
|
|
||||||
#define MPUREG_GYRO_YOUT_L 0x46
|
|
||||||
#define MPUREG_GYRO_ZOUT_H 0x47
|
|
||||||
#define MPUREG_GYRO_ZOUT_L 0x48
|
|
||||||
#define MPUREG_EXT_SENS_DATA_00 0x49
|
|
||||||
#define MPUREG_I2C_SLV0_D0 0x63
|
|
||||||
#define MPUREG_I2C_SLV1_D0 0x64
|
|
||||||
#define MPUREG_I2C_SLV2_D0 0x65
|
|
||||||
#define MPUREG_I2C_SLV3_D0 0x66
|
|
||||||
#define MPUREG_I2C_MST_DELAY_CTRL 0x67
|
|
||||||
#define MPUREG_SIGNAL_PATH_RESET 0x68
|
|
||||||
#define MPUREG_MOT_DETECT_CTRL 0x69
|
|
||||||
#define MPUREG_USER_CTRL 0x6A
|
|
||||||
#define MPUREG_PWR_MGMT_1 0x6B
|
|
||||||
#define MPUREG_PWR_MGMT_2 0x6C
|
|
||||||
#define MPUREG_FIFO_COUNTH 0x72
|
|
||||||
#define MPUREG_FIFO_COUNTL 0x73
|
|
||||||
#define MPUREG_FIFO_R_W 0x74
|
|
||||||
|
|
||||||
// Configuration bits MPU 9250
|
|
||||||
#define BIT_SLEEP 0x40
|
|
||||||
#define BIT_H_RESET 0x80
|
|
||||||
#define MPU_CLK_SEL_AUTO 0x01
|
|
||||||
|
|
||||||
#define BITS_GYRO_ST_X 0x80
|
|
||||||
#define BITS_GYRO_ST_Y 0x40
|
|
||||||
#define BITS_GYRO_ST_Z 0x20
|
|
||||||
#define BITS_FS_250DPS 0x00
|
|
||||||
#define BITS_FS_500DPS 0x08
|
|
||||||
#define BITS_FS_1000DPS 0x10
|
|
||||||
#define BITS_FS_2000DPS 0x18
|
|
||||||
#define BITS_FS_MASK 0x18
|
|
||||||
|
|
||||||
#define BITS_DLPF_CFG_250HZ 0x00
|
|
||||||
#define BITS_DLPF_CFG_184HZ 0x01
|
|
||||||
#define BITS_DLPF_CFG_92HZ 0x02
|
|
||||||
#define BITS_DLPF_CFG_41HZ 0x03
|
|
||||||
#define BITS_DLPF_CFG_20HZ 0x04
|
|
||||||
#define BITS_DLPF_CFG_10HZ 0x05
|
|
||||||
#define BITS_DLPF_CFG_5HZ 0x06
|
|
||||||
#define BITS_DLPF_CFG_3600HZ 0x07
|
|
||||||
#define BITS_DLPF_CFG_MASK 0x07
|
|
||||||
|
|
||||||
#define BITS_ACCEL_CONFIG2_41HZ 0x03
|
|
||||||
|
|
||||||
#define BIT_RAW_RDY_EN 0x01
|
|
||||||
#define BIT_INT_ANYRD_2CLEAR 0x10
|
|
||||||
|
|
||||||
#define MPU_WHOAMI_9250 0x71
|
|
||||||
|
|
||||||
#define MPU9250_ACCEL_DEFAULT_RATE 1000
|
|
||||||
#define MPU9250_ACCEL_MAX_OUTPUT_RATE 280
|
|
||||||
#define MPU9250_ACCEL_DEFAULT_DRIVER_FILTER_FREQ 30
|
|
||||||
#define MPU9250_GYRO_DEFAULT_RATE 1000
|
|
||||||
/* rates need to be the same between accel and gyro */
|
|
||||||
#define MPU9250_GYRO_MAX_OUTPUT_RATE MPU9250_ACCEL_MAX_OUTPUT_RATE
|
|
||||||
#define MPU9250_GYRO_DEFAULT_DRIVER_FILTER_FREQ 30
|
|
||||||
|
|
||||||
#define MPU9250_DEFAULT_ONCHIP_FILTER_FREQ 41
|
|
||||||
|
|
||||||
#define MPU9250_ONE_G 9.80665f
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
we set the timer interrupt to run a bit faster than the desired
|
we set the timer interrupt to run a bit faster than the desired
|
||||||
sample rate and then throw away duplicates by comparing
|
sample rate and then throw away duplicates by comparing
|
||||||
@@ -215,15 +109,19 @@ const uint8_t MPU9250::_checked_registers[MPU9250_NUM_CHECKED_REGISTERS] = { MPU
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
MPU9250::MPU9250(device::Device *interface, const char *path_accel, const char *path_gyro, const char *path_mag,
|
MPU9250::MPU9250(device::Device *interface, device::Device *mag_interface, const char *path_accel, const char *path_gyro, const char *path_mag,
|
||||||
enum Rotation rotation) :
|
enum Rotation rotation) :
|
||||||
CDev("MPU9250", path_accel),
|
CDev("MPU9250", path_accel),
|
||||||
_interface(interface),
|
_interface(interface),
|
||||||
_interface_bus(interface_bus),
|
|
||||||
//SPI("MPU9250", path_accel, bus, device, SPIDEV_MODE3, MPU9250_LOW_BUS_SPEED),
|
|
||||||
_gyro(new MPU9250_gyro(this, path_gyro)),
|
_gyro(new MPU9250_gyro(this, path_gyro)),
|
||||||
_mag(new MPU9250_mag(this, path_mag)),
|
_mag(new MPU9250_mag(this, mag_interface, path_mag)),
|
||||||
_whoami(0),
|
_whoami(0),
|
||||||
|
#if defined(USE_I2C)
|
||||||
|
_work {},
|
||||||
|
_use_hrt(false),
|
||||||
|
#else
|
||||||
|
_use_hrt(true),
|
||||||
|
#endif
|
||||||
_call{},
|
_call{},
|
||||||
_call_interval(0),
|
_call_interval(0),
|
||||||
_accel_reports(nullptr),
|
_accel_reports(nullptr),
|
||||||
@@ -277,6 +175,9 @@ MPU9250::MPU9250(device::Device *interface, const char *path_accel, const char *
|
|||||||
_mag->_device_id.devid = _device_id.devid;
|
_mag->_device_id.devid = _device_id.devid;
|
||||||
_mag->_device_id.devid_s.devtype = DRV_MAG_DEVTYPE_MPU9250;
|
_mag->_device_id.devid_s.devtype = DRV_MAG_DEVTYPE_MPU9250;
|
||||||
|
|
||||||
|
/* For an independent mag, ensure that it is connected to the i2c bus */
|
||||||
|
|
||||||
|
|
||||||
// default accel scale factors
|
// default accel scale factors
|
||||||
_accel_scale.x_offset = 0;
|
_accel_scale.x_offset = 0;
|
||||||
_accel_scale.x_scale = 1.0f;
|
_accel_scale.x_scale = 1.0f;
|
||||||
@@ -294,6 +195,7 @@ MPU9250::MPU9250(device::Device *interface, const char *path_accel, const char *
|
|||||||
_gyro_scale.z_scale = 1.0f;
|
_gyro_scale.z_scale = 1.0f;
|
||||||
|
|
||||||
memset(&_call, 0, sizeof(_call));
|
memset(&_call, 0, sizeof(_call));
|
||||||
|
memset(&_work, 0, sizeof(_work));
|
||||||
}
|
}
|
||||||
|
|
||||||
MPU9250::~MPU9250()
|
MPU9250::~MPU9250()
|
||||||
@@ -334,8 +236,19 @@ MPU9250::~MPU9250()
|
|||||||
int
|
int
|
||||||
MPU9250::init()
|
MPU9250::init()
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
|
#if defined(USE_I2C)
|
||||||
|
unsigned dummy;
|
||||||
|
use_i2c(_interface->ioctl(MPUIOCGIS_I2C, dummy));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int ret = probe();
|
||||||
|
|
||||||
|
if (ret != OK) {
|
||||||
|
DEVICE_DEBUG("MPU9250 probe failed");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* do init */
|
/* do init */
|
||||||
@@ -349,21 +262,7 @@ MPU9250::init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// /* do SPI init (and probe) first */
|
|
||||||
// ret = SPI::init();
|
|
||||||
|
|
||||||
// /* if probe/setup failed, bail now */
|
|
||||||
// if (ret != OK) {
|
|
||||||
// DEVICE_DEBUG("SPI setup failed");
|
|
||||||
// return ret;
|
|
||||||
// }
|
|
||||||
|
|
||||||
ret = probe();
|
|
||||||
|
|
||||||
if (ret != OK) {
|
|
||||||
DEVICE_DEBUG("MPU9250 probe failed");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate basic report buffers */
|
/* allocate basic report buffers */
|
||||||
_accel_reports = new ringbuffer::RingBuffer(2, sizeof(accel_report));
|
_accel_reports = new ringbuffer::RingBuffer(2, sizeof(accel_report));
|
||||||
@@ -406,6 +305,11 @@ MPU9250::init()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!_mag->is_passthrough() && _mag->_interface->init() != OK) {
|
||||||
|
warnx("failed to setup ak8963 interface");
|
||||||
|
}
|
||||||
|
|
||||||
/* do CDev init for the mag device node, keep it optional */
|
/* do CDev init for the mag device node, keep it optional */
|
||||||
ret = _mag->init();
|
ret = _mag->init();
|
||||||
|
|
||||||
@@ -486,7 +390,7 @@ int MPU9250::reset()
|
|||||||
// INT CFG => Interrupt on Data Ready
|
// INT CFG => Interrupt on Data Ready
|
||||||
write_checked_reg(MPUREG_INT_ENABLE, BIT_RAW_RDY_EN); // INT: Raw data ready
|
write_checked_reg(MPUREG_INT_ENABLE, BIT_RAW_RDY_EN); // INT: Raw data ready
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
write_checked_reg(MPUREG_INT_PIN_CFG, BIT_INT_ANYRD_2CLEAR); // INT: Clear on any read
|
write_checked_reg(MPUREG_INT_PIN_CFG, BIT_INT_ANYRD_2CLEAR | (_mag->is_passthrough()? 0 : BIT_INT_BYPASS_EN)); // INT: Clear on any read, also use i2c bypass is master mode isn't needed
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
|
|
||||||
write_checked_reg(MPUREG_ACCEL_CONFIG2, BITS_ACCEL_CONFIG2_41HZ);
|
write_checked_reg(MPUREG_ACCEL_CONFIG2, BITS_ACCEL_CONFIG2_41HZ);
|
||||||
@@ -758,8 +662,7 @@ MPU9250::test_error()
|
|||||||
// development as a handy way to test the reset logic
|
// development as a handy way to test the reset logic
|
||||||
uint8_t data[16];
|
uint8_t data[16];
|
||||||
memset(data, 0, sizeof(data));
|
memset(data, 0, sizeof(data));
|
||||||
_interface->read(MPU6000_SET_SPEED(MPUREG_INT_STATUS, MPU6000_LOW_BUS_SPEED), data, sizeof(data));
|
_interface->read(MPU9250_SET_SPEED(MPUREG_INT_STATUS, MPU9250_LOW_BUS_SPEED), data, sizeof(data));
|
||||||
//transfer(data, data, sizeof(data));
|
|
||||||
::printf("error triggered\n");
|
::printf("error triggered\n");
|
||||||
print_registers();
|
print_registers();
|
||||||
}
|
}
|
||||||
@@ -973,7 +876,7 @@ MPU9250::ioctl(struct file *filp, int cmd, unsigned long arg)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
/* give it to the superclass */
|
/* give it to the superclass */
|
||||||
return SPI::ioctl(filp, cmd, arg);
|
return CDev::ioctl(filp, cmd, arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1071,23 +974,9 @@ MPU9250::gyro_ioctl(struct file *filp, int cmd, unsigned long arg)
|
|||||||
uint8_t
|
uint8_t
|
||||||
MPU9250::read_reg(unsigned reg, uint32_t speed)
|
MPU9250::read_reg(unsigned reg, uint32_t speed)
|
||||||
{
|
{
|
||||||
|
|
||||||
// From MPU6000 implementation
|
|
||||||
uint8_t buf;
|
uint8_t buf;
|
||||||
_interface->read(MPU6000_SET_SPEED(reg, speed), &buf, 1);
|
_interface->read(MPU9250_SET_SPEED(reg, speed), &buf, 1);
|
||||||
return buf;
|
return buf;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t cmd[2] = { (uint8_t)(reg | DIR_READ), 0};
|
|
||||||
|
|
||||||
// general register transfer at low clock speed
|
|
||||||
set_frequency(speed);
|
|
||||||
|
|
||||||
transfer(cmd, cmd, sizeof(cmd));
|
|
||||||
|
|
||||||
return cmd[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t
|
uint16_t
|
||||||
@@ -1099,18 +988,6 @@ MPU9250::read_reg16(unsigned reg)
|
|||||||
|
|
||||||
_interface->read(MPU9250_LOW_SPEED_OP(reg), &buf, arraySize(buf));
|
_interface->read(MPU9250_LOW_SPEED_OP(reg), &buf, arraySize(buf));
|
||||||
return (uint16_t)(buf[0] << 8) | buf[1];
|
return (uint16_t)(buf[0] << 8) | buf[1];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t cmd[3] = { (uint8_t)(reg | DIR_READ), 0, 0 };
|
|
||||||
|
|
||||||
// general register transfer at low clock speed
|
|
||||||
set_frequency(MPU9250_LOW_BUS_SPEED);
|
|
||||||
|
|
||||||
transfer(cmd, cmd, sizeof(cmd));
|
|
||||||
|
|
||||||
return (uint16_t)(cmd[1] << 8) | cmd[2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1118,19 +995,7 @@ MPU9250::write_reg(unsigned reg, uint8_t value)
|
|||||||
{
|
{
|
||||||
// general register transfer at low clock speed
|
// general register transfer at low clock speed
|
||||||
|
|
||||||
return _interface->write(MPU9250_LOW_SPEED_OP(reg), &value, 1);
|
_interface->write(MPU9250_LOW_SPEED_OP(reg), &value, 1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t cmd[2];
|
|
||||||
|
|
||||||
cmd[0] = reg | DIR_WRITE;
|
|
||||||
cmd[1] = value;
|
|
||||||
|
|
||||||
// general register transfer at low clock speed
|
|
||||||
set_frequency(MPU9250_LOW_BUS_SPEED);
|
|
||||||
|
|
||||||
transfer(cmd, nullptr, sizeof(cmd));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1153,6 +1018,7 @@ MPU9250::write_checked_reg(unsigned reg, uint8_t value)
|
|||||||
if (reg == _checked_registers[i]) {
|
if (reg == _checked_registers[i]) {
|
||||||
_checked_values[i] = value;
|
_checked_values[i] = value;
|
||||||
_checked_bad[i] = value;
|
_checked_bad[i] = value;
|
||||||
|
break; // TODO: Assumes no duplicates
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1203,18 +1069,69 @@ MPU9250::start()
|
|||||||
_gyro_reports->flush();
|
_gyro_reports->flush();
|
||||||
_mag->_mag_reports->flush();
|
_mag->_mag_reports->flush();
|
||||||
|
|
||||||
|
if (_use_hrt) {
|
||||||
/* start polling at the specified rate */
|
/* start polling at the specified rate */
|
||||||
hrt_call_every(&_call,
|
hrt_call_every(&_call,
|
||||||
1000,
|
1000,
|
||||||
_call_interval - MPU9250_TIMER_REDUCTION,
|
_call_interval - MPU9250_TIMER_REDUCTION,
|
||||||
(hrt_callout)&MPU9250::measure_trampoline, this);
|
(hrt_callout)&MPU9250::measure_trampoline, this);;
|
||||||
|
} else {
|
||||||
|
#ifdef USE_I2C
|
||||||
|
/* schedule a cycle to start things */
|
||||||
|
work_queue(HPWORK, &_work, (worker_t)&MPU9250::cycle_trampoline, this, 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MPU9250::stop()
|
MPU9250::stop()
|
||||||
{
|
{
|
||||||
|
if (_use_hrt) {
|
||||||
hrt_cancel(&_call);
|
hrt_cancel(&_call);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
#ifdef USE_I2C
|
||||||
|
work_cancel(HPWORK, &_work);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(USE_I2C)
|
||||||
|
void
|
||||||
|
MPU9250::cycle_trampoline(void *arg)
|
||||||
|
{
|
||||||
|
MPU9250 *dev = (MPU9250 *)arg;
|
||||||
|
|
||||||
|
dev->cycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MPU9250::cycle()
|
||||||
|
{
|
||||||
|
|
||||||
|
// int ret = measure();
|
||||||
|
|
||||||
|
measure();
|
||||||
|
|
||||||
|
// if (ret != OK) {
|
||||||
|
// /* issue a reset command to the sensor */
|
||||||
|
// reset();
|
||||||
|
// start();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (_call_interval != 0) {
|
||||||
|
work_queue(HPWORK,
|
||||||
|
&_work,
|
||||||
|
(worker_t)&MPU9250::cycle_trampoline,
|
||||||
|
this,
|
||||||
|
USEC2TICK(_call_interval - MPU9250_TIMER_REDUCTION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MPU9250::measure_trampoline(void *arg)
|
MPU9250::measure_trampoline(void *arg)
|
||||||
@@ -1350,12 +1267,13 @@ MPU9250::measure()
|
|||||||
/* start measuring */
|
/* start measuring */
|
||||||
perf_begin(_sample_perf);
|
perf_begin(_sample_perf);
|
||||||
|
|
||||||
|
// TODO: Don't fetch magnetometer data if it isn't being managed
|
||||||
|
// In that case, trigger a magnetometer read
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch the full set of measurements from the MPU9250 in one pass.
|
* Fetch the full set of measurements from the MPU9250 in one pass.
|
||||||
*/
|
*/
|
||||||
mpu_report.cmd = DIR_READ | MPUREG_INT_STATUS;
|
if (OK != _interface->read(MPU9250_SET_SPEED(MPUREG_INT_STATUS, MPU9250_HIGH_BUS_SPEED),
|
||||||
|
|
||||||
if (sizeof(mpu_report) != _interface->read(MPU9250_SET_SPEED(MPUREG_INT_STATUS, MPU9250_HIGH_BUS_SPEED),
|
|
||||||
(uint8_t *)&mpu_report,
|
(uint8_t *)&mpu_report,
|
||||||
sizeof(mpu_report))) {
|
sizeof(mpu_report))) {
|
||||||
return;
|
return;
|
||||||
@@ -1367,7 +1285,12 @@ MPU9250::measure()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_mag->measure(mpu_report.mag);
|
if (_mag->is_passthrough()) {
|
||||||
|
_mag->_measure(mpu_report.mag);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_mag->measure();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert from big to little endian
|
* Convert from big to little endian
|
||||||
|
|||||||
@@ -1,13 +1,250 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 PX4 Development Team. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: All these includes are from main.cpp
|
||||||
|
#include <px4_config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include <systemlib/perf_counter.h>
|
||||||
|
#include <systemlib/err.h>
|
||||||
|
#include <systemlib/conversions.h>
|
||||||
|
|
||||||
|
// TODO: These three are new
|
||||||
|
#include <nuttx/arch.h>
|
||||||
|
#include <nuttx/wqueue.h>
|
||||||
|
#include <nuttx/clock.h>
|
||||||
|
|
||||||
|
#include <board_config.h>
|
||||||
|
#include <drivers/drv_hrt.h>
|
||||||
|
|
||||||
|
#include <drivers/device/spi.h>
|
||||||
|
#include <drivers/device/i2c.h>
|
||||||
|
#include <drivers/device/ringbuffer.h>
|
||||||
|
#include <drivers/device/integrator.h>
|
||||||
|
#include <drivers/drv_accel.h>
|
||||||
|
#include <drivers/drv_gyro.h>
|
||||||
|
#include <drivers/drv_mag.h>
|
||||||
|
#include <mathlib/math/filter/LowPassFilter2p.hpp>
|
||||||
|
#include <lib/conversion/rotation.h>
|
||||||
|
|
||||||
|
#include "mag.h"
|
||||||
|
#include "gyro.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(PX4_I2C_OBDEV_MPU9250)
|
||||||
|
# define USE_I2C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DIR_READ 0x80
|
||||||
|
#define DIR_WRITE 0x00
|
||||||
|
|
||||||
|
// MPU 9250 registers
|
||||||
|
#define MPUREG_WHOAMI 0x75
|
||||||
|
#define MPUREG_SMPLRT_DIV 0x19
|
||||||
|
#define MPUREG_CONFIG 0x1A
|
||||||
|
#define MPUREG_GYRO_CONFIG 0x1B
|
||||||
|
#define MPUREG_ACCEL_CONFIG 0x1C
|
||||||
|
#define MPUREG_ACCEL_CONFIG2 0x1D
|
||||||
|
#define MPUREG_LPACCEL_ODR 0x1E
|
||||||
|
#define MPUREG_WOM_THRESH 0x1F
|
||||||
|
#define MPUREG_FIFO_EN 0x23
|
||||||
|
#define MPUREG_I2C_MST_CTRL 0x24
|
||||||
|
#define MPUREG_I2C_SLV0_ADDR 0x25
|
||||||
|
#define MPUREG_I2C_SLV0_REG 0x26
|
||||||
|
#define MPUREG_I2C_SLV0_CTRL 0x27
|
||||||
|
#define MPUREG_I2C_SLV1_ADDR 0x28
|
||||||
|
#define MPUREG_I2C_SLV1_REG 0x29
|
||||||
|
#define MPUREG_I2C_SLV1_CTRL 0x2A
|
||||||
|
#define MPUREG_I2C_SLV2_ADDR 0x2B
|
||||||
|
#define MPUREG_I2C_SLV2_REG 0x2C
|
||||||
|
#define MPUREG_I2C_SLV2_CTRL 0x2D
|
||||||
|
#define MPUREG_I2C_SLV3_ADDR 0x2E
|
||||||
|
#define MPUREG_I2C_SLV3_REG 0x2F
|
||||||
|
#define MPUREG_I2C_SLV3_CTRL 0x30
|
||||||
|
#define MPUREG_I2C_SLV4_ADDR 0x31
|
||||||
|
#define MPUREG_I2C_SLV4_REG 0x32
|
||||||
|
#define MPUREG_I2C_SLV4_DO 0x33
|
||||||
|
#define MPUREG_I2C_SLV4_CTRL 0x34
|
||||||
|
#define MPUREG_I2C_SLV4_DI 0x35
|
||||||
|
#define MPUREG_I2C_MST_STATUS 0x36
|
||||||
|
#define MPUREG_INT_PIN_CFG 0x37
|
||||||
|
#define MPUREG_INT_ENABLE 0x38
|
||||||
|
#define MPUREG_INT_STATUS 0x3A
|
||||||
|
#define MPUREG_ACCEL_XOUT_H 0x3B
|
||||||
|
#define MPUREG_ACCEL_XOUT_L 0x3C
|
||||||
|
#define MPUREG_ACCEL_YOUT_H 0x3D
|
||||||
|
#define MPUREG_ACCEL_YOUT_L 0x3E
|
||||||
|
#define MPUREG_ACCEL_ZOUT_H 0x3F
|
||||||
|
#define MPUREG_ACCEL_ZOUT_L 0x40
|
||||||
|
#define MPUREG_TEMP_OUT_H 0x41
|
||||||
|
#define MPUREG_TEMP_OUT_L 0x42
|
||||||
|
#define MPUREG_GYRO_XOUT_H 0x43
|
||||||
|
#define MPUREG_GYRO_XOUT_L 0x44
|
||||||
|
#define MPUREG_GYRO_YOUT_H 0x45
|
||||||
|
#define MPUREG_GYRO_YOUT_L 0x46
|
||||||
|
#define MPUREG_GYRO_ZOUT_H 0x47
|
||||||
|
#define MPUREG_GYRO_ZOUT_L 0x48
|
||||||
|
#define MPUREG_EXT_SENS_DATA_00 0x49
|
||||||
|
#define MPUREG_I2C_SLV0_D0 0x63
|
||||||
|
#define MPUREG_I2C_SLV1_D0 0x64
|
||||||
|
#define MPUREG_I2C_SLV2_D0 0x65
|
||||||
|
#define MPUREG_I2C_SLV3_D0 0x66
|
||||||
|
#define MPUREG_I2C_MST_DELAY_CTRL 0x67
|
||||||
|
#define MPUREG_SIGNAL_PATH_RESET 0x68
|
||||||
|
#define MPUREG_MOT_DETECT_CTRL 0x69
|
||||||
|
#define MPUREG_USER_CTRL 0x6A
|
||||||
|
#define MPUREG_PWR_MGMT_1 0x6B
|
||||||
|
#define MPUREG_PWR_MGMT_2 0x6C
|
||||||
|
#define MPUREG_FIFO_COUNTH 0x72
|
||||||
|
#define MPUREG_FIFO_COUNTL 0x73
|
||||||
|
#define MPUREG_FIFO_R_W 0x74
|
||||||
|
|
||||||
|
// Configuration bits MPU 9250
|
||||||
|
#define BIT_SLEEP 0x40
|
||||||
|
#define BIT_H_RESET 0x80
|
||||||
|
#define MPU_CLK_SEL_AUTO 0x01
|
||||||
|
|
||||||
|
#define BITS_GYRO_ST_X 0x80
|
||||||
|
#define BITS_GYRO_ST_Y 0x40
|
||||||
|
#define BITS_GYRO_ST_Z 0x20
|
||||||
|
#define BITS_FS_250DPS 0x00
|
||||||
|
#define BITS_FS_500DPS 0x08
|
||||||
|
#define BITS_FS_1000DPS 0x10
|
||||||
|
#define BITS_FS_2000DPS 0x18
|
||||||
|
#define BITS_FS_MASK 0x18
|
||||||
|
|
||||||
|
#define BITS_DLPF_CFG_250HZ 0x00
|
||||||
|
#define BITS_DLPF_CFG_184HZ 0x01
|
||||||
|
#define BITS_DLPF_CFG_92HZ 0x02
|
||||||
|
#define BITS_DLPF_CFG_41HZ 0x03
|
||||||
|
#define BITS_DLPF_CFG_20HZ 0x04
|
||||||
|
#define BITS_DLPF_CFG_10HZ 0x05
|
||||||
|
#define BITS_DLPF_CFG_5HZ 0x06
|
||||||
|
#define BITS_DLPF_CFG_3600HZ 0x07
|
||||||
|
#define BITS_DLPF_CFG_MASK 0x07
|
||||||
|
|
||||||
|
#define BITS_ACCEL_CONFIG2_41HZ 0x03
|
||||||
|
|
||||||
|
#define BIT_RAW_RDY_EN 0x01
|
||||||
|
#define BIT_INT_ANYRD_2CLEAR 0x10
|
||||||
|
#define BIT_INT_BYPASS_EN 0x02
|
||||||
|
|
||||||
|
#define MPU_WHOAMI_9250 0x71
|
||||||
|
|
||||||
|
#define MPU9250_ACCEL_DEFAULT_RATE 1000
|
||||||
|
#define MPU9250_ACCEL_MAX_OUTPUT_RATE 280
|
||||||
|
#define MPU9250_ACCEL_DEFAULT_DRIVER_FILTER_FREQ 30
|
||||||
|
#define MPU9250_GYRO_DEFAULT_RATE 1000
|
||||||
|
/* rates need to be the same between accel and gyro */
|
||||||
|
#define MPU9250_GYRO_MAX_OUTPUT_RATE MPU9250_ACCEL_MAX_OUTPUT_RATE
|
||||||
|
#define MPU9250_GYRO_DEFAULT_DRIVER_FILTER_FREQ 30
|
||||||
|
|
||||||
|
#define MPU9250_DEFAULT_ONCHIP_FILTER_FREQ 41
|
||||||
|
|
||||||
#define MPU9250_ONE_G 9.80665f
|
#define MPU9250_ONE_G 9.80665f
|
||||||
|
|
||||||
|
#define MPUIOCGIS_I2C (unsigned)(DEVIOCGDEVICEID+100)
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
/**
|
||||||
|
* Report conversation within the mpu, including command byte and
|
||||||
|
* interrupt status.
|
||||||
|
*/
|
||||||
|
struct MPUReport {
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t accel_x[2];
|
||||||
|
uint8_t accel_y[2];
|
||||||
|
uint8_t accel_z[2];
|
||||||
|
uint8_t temp[2];
|
||||||
|
uint8_t gyro_x[2];
|
||||||
|
uint8_t gyro_y[2];
|
||||||
|
uint8_t gyro_z[2];
|
||||||
|
struct ak8963_regs mag;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
// TODO: Big enough?
|
||||||
|
#define MPU_MAX_WRITE_BUFFER_SIZE (2)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
The MPU9250 can only handle high bus speeds on the sensor and
|
||||||
|
interrupt status registers. All other registers have a maximum 1MHz
|
||||||
|
Communication with all registers of the device is performed using either
|
||||||
|
I2C at 400kHz or SPI at 1MHz. For applications requiring faster communications,
|
||||||
|
the sensor and interrupt registers may be read using SPI at 20MHz
|
||||||
|
*/
|
||||||
|
#define MPU9250_LOW_BUS_SPEED 0
|
||||||
|
#define MPU9250_HIGH_BUS_SPEED 0x8000
|
||||||
|
# define MPU9250_IS_HIGH_SPEED(r) ((r) & MPU9250_HIGH_BUS_SPEED)
|
||||||
|
# define MPU9250_REG(r) ((r) &~MPU9250_HIGH_BUS_SPEED)
|
||||||
|
# define MPU9250_SET_SPEED(r, s) ((r)|(s))
|
||||||
|
# define MPU9250_HIGH_SPEED_OP(r) MPU9250_SET_SPEED((r), MPU9250_HIGH_BUS_SPEED)
|
||||||
|
# define MPU9250_LOW_SPEED_OP(r) MPU9250_REG((r))
|
||||||
|
|
||||||
|
/* interface factories */
|
||||||
|
extern device::Device *MPU9250_SPI_interface(int bus, bool external_bus);
|
||||||
|
extern device::Device *MPU9250_I2C_interface(int bus, bool external_bus);
|
||||||
|
extern int MPU9250_probe(device::Device *dev, int device_type);
|
||||||
|
|
||||||
|
typedef device::Device *(*MPU9250_constructor)(int, bool);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MPU9250_mag;
|
class MPU9250_mag;
|
||||||
class MPU9250_gyro;
|
class MPU9250_gyro;
|
||||||
|
|
||||||
class MPU9250 : public device::CDev
|
class MPU9250 : public device::CDev
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MPU9250(device::Device *interface, const char *path_accel, const char *path_gyro, const char *path_mag,
|
MPU9250(device::Device *interface, device::Device *mag_interface, const char *path_accel, const char *path_gyro, const char *path_mag,
|
||||||
enum Rotation rotation);
|
enum Rotation rotation);
|
||||||
virtual ~MPU9250();
|
virtual ~MPU9250();
|
||||||
|
|
||||||
@@ -42,6 +279,15 @@ private:
|
|||||||
MPU9250_mag *_mag;
|
MPU9250_mag *_mag;
|
||||||
uint8_t _whoami; /** whoami result */
|
uint8_t _whoami; /** whoami result */
|
||||||
|
|
||||||
|
#if defined(USE_I2C)
|
||||||
|
/*
|
||||||
|
* SPI bus based device use hrt
|
||||||
|
* I2C bus needs to use work queue
|
||||||
|
*/
|
||||||
|
work_s _work;
|
||||||
|
#endif
|
||||||
|
bool _use_hrt;
|
||||||
|
|
||||||
struct hrt_call _call;
|
struct hrt_call _call;
|
||||||
unsigned _call_interval;
|
unsigned _call_interval;
|
||||||
|
|
||||||
@@ -123,6 +369,42 @@ private:
|
|||||||
*/
|
*/
|
||||||
int reset();
|
int reset();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(USE_I2C)
|
||||||
|
/**
|
||||||
|
* When the I2C interfase is on
|
||||||
|
* Perform a poll cycle; collect from the previous measurement
|
||||||
|
* and start a new one.
|
||||||
|
*
|
||||||
|
* This is the heart of the measurement state machine. This function
|
||||||
|
* alternately starts a measurement, or collects the data from the
|
||||||
|
* previous measurement.
|
||||||
|
*
|
||||||
|
* When the interval between measurements is greater than the minimum
|
||||||
|
* measurement interval, a gap is inserted between collection
|
||||||
|
* and measurement to provide the most recent measurement possible
|
||||||
|
* at the next interval.
|
||||||
|
*/
|
||||||
|
void cycle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static trampoline from the workq context; because we don't have a
|
||||||
|
* generic workq wrapper yet.
|
||||||
|
*
|
||||||
|
* @param arg Instance pointer for the driver that is polling.
|
||||||
|
*/
|
||||||
|
static void cycle_trampoline(void *arg);
|
||||||
|
|
||||||
|
void use_i2c(bool on_true) { _use_hrt = !on_true; }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool is_i2c(void) { return !_use_hrt; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static trampoline from the hrt_call context; because we don't have a
|
* Static trampoline from the hrt_call context; because we don't have a
|
||||||
* generic hrt wrapper yet.
|
* generic hrt wrapper yet.
|
||||||
@@ -193,7 +475,11 @@ private:
|
|||||||
*
|
*
|
||||||
* @return true if the sensor is not on the main MCU board
|
* @return true if the sensor is not on the main MCU board
|
||||||
*/
|
*/
|
||||||
bool is_external() { return (_bus == EXTERNAL_BUS); }
|
bool is_external()
|
||||||
|
{
|
||||||
|
unsigned dummy;
|
||||||
|
return !_interface->ioctl(ACCELIOCGEXTERNAL, dummy);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Measurement self test
|
* Measurement self test
|
||||||
@@ -234,48 +520,4 @@ private:
|
|||||||
/* do not allow to copy this class due to pointer data members */
|
/* do not allow to copy this class due to pointer data members */
|
||||||
MPU9250(const MPU9250 &);
|
MPU9250(const MPU9250 &);
|
||||||
MPU9250 operator=(const MPU9250 &);
|
MPU9250 operator=(const MPU9250 &);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
/**
|
|
||||||
* Report conversation within the mpu, including command byte and
|
|
||||||
* interrupt status.
|
|
||||||
*/
|
|
||||||
struct MPUReport {
|
|
||||||
uint8_t cmd;
|
|
||||||
uint8_t status;
|
|
||||||
uint8_t accel_x[2];
|
|
||||||
uint8_t accel_y[2];
|
|
||||||
uint8_t accel_z[2];
|
|
||||||
uint8_t temp[2];
|
|
||||||
uint8_t gyro_x[2];
|
|
||||||
uint8_t gyro_y[2];
|
|
||||||
uint8_t gyro_z[2];
|
|
||||||
struct ak8963_regs mag;
|
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
The MPU9250 can only handle high bus speeds on the sensor and
|
|
||||||
interrupt status registers. All other registers have a maximum 1MHz
|
|
||||||
Communication with all registers of the device is performed using either
|
|
||||||
I2C at 400kHz or SPI at 1MHz. For applications requiring faster communications,
|
|
||||||
the sensor and interrupt registers may be read using SPI at 20MHz
|
|
||||||
*/
|
|
||||||
#define MPU9250_LOW_BUS_SPEED 0
|
|
||||||
#define MPU9250_HIGH_BUS_SPEED 0x8000
|
|
||||||
# define MPU9250_IS_HIGH_SPEED(r) ((r) & MPU9250_HIGH_BUS_SPEED)
|
|
||||||
# define MPU9250_REG(r) ((r) &~MPU9250_HIGH_BUS_SPEED)
|
|
||||||
# define MPU9250_SET_SPEED(r, s) ((r)|(s))
|
|
||||||
# define MPU9250_HIGH_SPEED_OP(r) MPU9250_SET_SPEED((r), MPU9250_HIGH_BUS_SPEED)
|
|
||||||
# define MPU9250_LOW_SPEED_OP(r) MPU9250_REG((r))
|
|
||||||
|
|
||||||
|
|
||||||
/* interface factories */
|
|
||||||
extern device::Device *MPU9250_SPI_interface(int bus, int device_type, bool external_bus);
|
|
||||||
extern device::Device *MPU9250_I2C_interface(int bus, int device_type, bool external_bus);
|
|
||||||
extern int MPU9250_probe(device::Device *dev, int device_type);
|
|
||||||
|
|
||||||
typedef device::Device *(*MPU9250_constructor)(int, int, bool);
|
|
||||||
|
|||||||
@@ -55,18 +55,18 @@
|
|||||||
#include <drivers/drv_accel.h>
|
#include <drivers/drv_accel.h>
|
||||||
#include <drivers/drv_device.h>
|
#include <drivers/drv_device.h>
|
||||||
|
|
||||||
#include "MPU9250.h"
|
#include "mpu9250.h"
|
||||||
|
|
||||||
#include "board_config.h"
|
#include "board_config.h"
|
||||||
|
|
||||||
#ifdef USE_I2C
|
#ifdef USE_I2C
|
||||||
|
|
||||||
device::Device *MPU9250_I2C_interface(int bus, int device_type, bool external_bus);
|
device::Device *MPU9250_I2C_interface(int bus, bool external_bus);
|
||||||
|
|
||||||
class MPU9250_I2C : public device::I2C
|
class MPU9250_I2C : public device::I2C
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MPU9250_I2C(int bus, int device_type);
|
MPU9250_I2C(int bus);
|
||||||
virtual ~MPU9250_I2C();
|
virtual ~MPU9250_I2C();
|
||||||
|
|
||||||
virtual int init();
|
virtual int init();
|
||||||
@@ -78,21 +78,17 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual int probe();
|
virtual int probe();
|
||||||
|
|
||||||
private:
|
|
||||||
int _device_type;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
device::Device *
|
device::Device *
|
||||||
MPU9250_I2C_interface(int bus, int device_type, bool external_bus)
|
MPU9250_I2C_interface(int bus, bool external_bus)
|
||||||
{
|
{
|
||||||
return new MPU9250_I2C(bus, device_type);
|
return new MPU9250_I2C(bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
MPU9250_I2C::MPU9250_I2C(int bus, int device_type) :
|
MPU9250_I2C::MPU9250_I2C(int bus) :
|
||||||
I2C("MPU9250_I2C", nullptr, bus, PX4_I2C_OBDEV_MPU9250, 400000),
|
I2C("MPU9250_I2C", nullptr, bus, PX4_I2C_OBDEV_MPU9250, 400000)
|
||||||
_device_type(device_type)
|
|
||||||
{
|
{
|
||||||
_device_id.devid_s.devtype = DRV_ACC_DEVTYPE_MPU9250;
|
_device_id.devid_s.devtype = DRV_ACC_DEVTYPE_MPU9250;
|
||||||
}
|
}
|
||||||
@@ -156,8 +152,7 @@ MPU9250_I2C::read(unsigned reg_speed, void *data, unsigned count)
|
|||||||
*/
|
*/
|
||||||
uint32_t offset = count < sizeof(MPUReport) ? 0 : offsetof(MPUReport, status);
|
uint32_t offset = count < sizeof(MPUReport) ? 0 : offsetof(MPUReport, status);
|
||||||
uint8_t cmd = MPU9250_REG(reg_speed);
|
uint8_t cmd = MPU9250_REG(reg_speed);
|
||||||
int ret = transfer(&cmd, 1, &((uint8_t *)data)[offset], count);
|
return transfer(&cmd, 1, &((uint8_t *)data)[offset], count);
|
||||||
return ret == OK ? count : ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -165,8 +160,8 @@ int
|
|||||||
MPU9250_I2C::probe()
|
MPU9250_I2C::probe()
|
||||||
{
|
{
|
||||||
uint8_t whoami = 0;
|
uint8_t whoami = 0;
|
||||||
uint8_t expected = _device_type == 6000 ? MPU_WHOAMI_6000 : ICM_WHOAMI_20608;
|
uint8_t expected = MPU_WHOAMI_9250;
|
||||||
return (read(MPUREG_WHOAMI, &whoami, 1) > 0 && (whoami == expected)) ? 0 : -EIO;
|
return (read(MPUREG_WHOAMI, &whoami, 1) == OK && (whoami == expected)) ? 0 : -EIO;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* PX4_I2C_OBDEV_HMC5883 */
|
|
||||||
|
#endif /* USE_I2C */
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
#define DIR_READ 0x80
|
#define DIR_READ 0x80
|
||||||
#define DIR_WRITE 0x00
|
#define DIR_WRITE 0x00
|
||||||
|
|
||||||
|
|
||||||
#if PX4_SPIDEV_MPU
|
#if PX4_SPIDEV_MPU
|
||||||
#ifdef PX4_SPI_BUS_EXT
|
#ifdef PX4_SPI_BUS_EXT
|
||||||
#define EXTERNAL_BUS PX4_SPI_BUS_EXT
|
#define EXTERNAL_BUS PX4_SPI_BUS_EXT
|
||||||
@@ -78,16 +79,16 @@
|
|||||||
SPI speed
|
SPI speed
|
||||||
*/
|
*/
|
||||||
#define MPU9250_LOW_SPI_BUS_SPEED 1000*1000
|
#define MPU9250_LOW_SPI_BUS_SPEED 1000*1000
|
||||||
#define MPU9250_HIGH_SPI_BUS_SPEED 11*1000*1000 /* will be rounded to 10.4 MHz, within margins for MPU6K */
|
#define MPU9250_HIGH_SPI_BUS_SPEED 11*1000*1000 /* will be rounded to 10.4 MHz, within margins for MPU9250 */
|
||||||
|
|
||||||
|
|
||||||
device::Device *MPU9250_SPI_interface(int bus, int device_type, bool external_bus);
|
device::Device *MPU9250_SPI_interface(int bus, bool external_bus);
|
||||||
|
|
||||||
|
|
||||||
class MPU9250_SPI : public device::SPI
|
class MPU9250_SPI : public device::SPI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MPU9250_SPI(int bus, spi_dev_e device, int device_type);
|
MPU9250_SPI(int bus, spi_dev_e device);
|
||||||
virtual ~MPU9250_SPI();
|
virtual ~MPU9250_SPI();
|
||||||
|
|
||||||
virtual int init();
|
virtual int init();
|
||||||
@@ -100,47 +101,37 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int _device_type;
|
|
||||||
/* Helper to set the desired speed and isolate the register on return */
|
/* Helper to set the desired speed and isolate the register on return */
|
||||||
|
|
||||||
void set_bus_frequency(unsigned ®_speed_reg_out);
|
void set_bus_frequency(unsigned ®_speed_reg_out);
|
||||||
};
|
};
|
||||||
|
|
||||||
device::Device *
|
device::Device *
|
||||||
MPU9250_SPI_interface(int bus, int device_type, bool external_bus)
|
MPU9250_SPI_interface(int bus, bool external_bus)
|
||||||
{
|
{
|
||||||
spi_dev_e cs = SPIDEV_NONE;
|
spi_dev_e cs = SPIDEV_NONE;
|
||||||
device::Device *interface = nullptr;
|
device::Device *interface = nullptr;
|
||||||
|
|
||||||
if (external_bus) {
|
if (external_bus) {
|
||||||
#ifdef PX4_SPI_BUS_EXT
|
#ifdef PX4_SPI_BUS_EXT
|
||||||
# if defined(PX4_SPIDEV_EXT_ICM)
|
|
||||||
cs = (spi_dev_e)(device_type == 6000 ? PX4_SPIDEV_EXT_MPU : PX4_SPIDEV_EXT_ICM);
|
|
||||||
# else
|
|
||||||
cs = (spi_dev_e) PX4_SPIDEV_EXT_MPU;
|
cs = (spi_dev_e) PX4_SPIDEV_EXT_MPU;
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
#if defined(PX4_SPIDEV_ICM)
|
|
||||||
cs = (spi_dev_e)(device_type == 6000 ? PX4_SPIDEV_MPU : PX4_SPIDEV_ICM);
|
|
||||||
#else
|
#else
|
||||||
cs = (spi_dev_e) PX4_SPIDEV_MPU;
|
errx(0, "External SPI not available");
|
||||||
#endif
|
#endif
|
||||||
|
} else {
|
||||||
|
cs = (spi_dev_e) PX4_SPIDEV_MPU;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cs != SPIDEV_NONE) {
|
if (cs != SPIDEV_NONE) {
|
||||||
|
|
||||||
interface = new MPU9250_SPI(bus, cs, device_type);
|
interface = new MPU9250_SPI(bus, cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return interface;
|
return interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
MPU9250_SPI::MPU9250_SPI(int bus, spi_dev_e device, int device_type) :
|
MPU9250_SPI::MPU9250_SPI(int bus, spi_dev_e device) :
|
||||||
SPI("MPU9250", nullptr, bus, device, SPIDEV_MODE3, MPU9250_LOW_SPI_BUS_SPEED),
|
SPI("MPU9250", nullptr, bus, device, SPIDEV_MODE3, MPU9250_LOW_SPI_BUS_SPEED)
|
||||||
_device_type(device_type)
|
|
||||||
{
|
{
|
||||||
_device_id.devid_s.devtype = DRV_ACC_DEVTYPE_MPU9250;
|
_device_id.devid_s.devtype = DRV_ACC_DEVTYPE_MPU9250;
|
||||||
}
|
}
|
||||||
@@ -266,16 +257,15 @@ MPU9250_SPI::read(unsigned reg_speed, void *data, unsigned count)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret == OK ? count : ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
MPU9250_SPI::probe()
|
MPU9250_SPI::probe()
|
||||||
{
|
{
|
||||||
uint8_t whoami = 0;
|
uint8_t whoami = 0;
|
||||||
uint8_t expected = _device_type == 6000 ? MPU_WHOAMI_6000 : ICM_WHOAMI_20608;
|
uint8_t expected = MPU_WHOAMI_9250;
|
||||||
return (read(MPUREG_WHOAMI, &whoami, 1) > 0 && (whoami == expected)) ? 0 : -EIO;
|
return (read(MPUREG_WHOAMI, &whoami, 1) == OK && (whoami == expected)) ? 0 : -EIO;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // PX4_SPIDEV_MPU
|
#endif // PX4_SPIDEV_MPU
|
||||||
|
|||||||
Reference in New Issue
Block a user