Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ICM20789 IMU/Baro #6449

Closed
wants to merge 2 commits into from
Closed

Conversation

tridge
Copy link
Contributor

@tridge tridge commented Jun 17, 2017

The ICM20789 is an interesting variant of the invensense IMUs that has gyro, accel and barometer.

Copy link
Member

@OXINARF OXINARF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a couple of comments.

@@ -922,9 +946,12 @@ bool AP_InertialSensor_Invensense::_hardware_init(void)
/* bus-dependent initialization */
if ((_dev->bus_type() == AP_HAL::Device::BUS_TYPE_I2C) && (_mpu_type == Invensense_MPU9250)) {
/* Enable I2C bypass to access internal AK8963 */
_register_write(MPUREG_INT_PIN_CFG, BIT_BYPASS_EN);
if (_mpu_type != Invensense_ICM20789) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is always true (given the previous check). I'm a bit confused though because this bit is set on start just for this MPU type, why not do it here instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be trying to do it here.


if (_mpu_type == Invensense_ICM20789) {
// setup to allow for barometer
user_ctrl &= ~BIT_USER_CTRL_I2C_MST_EN;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to do this on every FIFO reset? Unless I'm missing something, user_ctrl should always have BIT_USER_CTRL_I2C_MST_EN unset - it is only set when _configure_slaves is called, where you added a check so that it returns immediately.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will remove this.

static struct {
uint32_t Praw, Traw;
float T, P;
} dd;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not dramatic in terms of space, but we should probably ifdef this inside a debug macro.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will create BARO_ICM20789_DEBUG and also use it to define the Debug(..) macro

return;
}

if (_sem->take(0)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use HAL_SEMAPHORE_BLOCK_FOREVER please? @peterbarker did a PR changing all places, I don't want to go back 🙂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Easy enough :-)

}

dev_icm->get_semaphore()->give();
#endif // HAL_INS_MPU60x0_NAME
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this isn't defined, shouldn't we return false here? Or are you relying on the methods below to fail?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to add an early exit in an #else


private:
AP_Baro_ICM20789(AP_Baro &baro, AP_HAL::OwnPtr<AP_HAL::Device> dev);
virtual ~AP_Baro_ICM20789(void) {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to define the destructor?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably because "that's how all the backends do it".

Will remove all the empty backend destructors.

return true;

failed:
dev_icm->get_semaphore()->give();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if HAL_INS_MPU60x0_NAME isn't defined? 🙂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to change things so we don't take the semaphore if the name isn't defined.


uint8_t instance;
AP_HAL::OwnPtr<AP_HAL::Device> dev;
AP_HAL::OwnPtr<AP_HAL::Device> dev_icm;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why keep dev_icm? Looks like it is only needed for initialization.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will make it a stack variable.

#define BIT_PWR_MGMT_1_DEVICE_RESET 0x80 // reset entire device
#define BIT_USER_CTRL_I2C_IF_DIS 0x10 // Disable primary I2C interface and enable hal.spi->interface
#define BIT_PWR_MGMT_1_CLK_XGYRO 0x01 // PLL with X axis gyroscope reference
#define BIT_PWR_MGMT_1_CLK_ZGYRO 0x03 // PLL with Z axis gyroscope reference
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So many beautiful macros you don't use anywhere 😛

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're cheap - and might be useful to someone in the future...



i2c_dev = std::move(hal.i2c_mgr->get_device(1, 0x63));
lidar_dev = std::move(hal.i2c_mgr->get_device(1, 0x29));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the VL53L0X doing in the middle of this example? 😜

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will generally fix the example.

Bypass Mode: Set register INT_PIN_CFG (Address: 55 (Decimal); 37 (Hex)) bit 1 to value 1
and I2C_MST_EN bit is 0 Address: 106 (Decimal); 6A (Hex)).
Pressure sensor data can then be accessed using the procedure described in Section 10.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should be on the function above. And it looks strange... Are you setting it to read in bypass mode so you have both the IMU on spi bus and baro on I2C bus (i.e. you have real access to both SPI pins and I2C pins and they are not the same)? This would be different from all the other Invensense sensors in which there's an I2C transaction over the SPI bus. By the name of this register (I2C_MST_EN) it looks like you are indeed enabling the I2C master engine on the sensor.

dev_icm->write_register(0x6B, 0x01);

hal.scheduler->delay(1);
dev_icm->write_register(0x6A, 0x10);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are setting an IMU register without reading whatever the INS set there... This will give us trouble if later we need to set something in this register there. It would be nice to keep this IMU part on the INS driver like it is when we have a mag rather than a baro.

And... now that we have access to the plain I2C/SPI dev, we can also simplify the AuxBus infra a little bit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lucasdemarchi Should I move the initialisation into the IMU, or is it OK where it is for the time being?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

baro is initialised before ins, which is why we need to init here, as ins doesn't yet exist

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

long ago I had this same problem when MS5611 was on the auxiliary bus of MPU6K... hence the infra for that. So if later on the INS drivers writes to this register, whatever we did here is lost. I think it's much safer to "keep INS registers on the INS driver and baro registers on the baro driver".

@OXINARF
Copy link
Member

OXINARF commented Jun 30, 2017

@lucasdemarchi Only @tridge can really answer, but my guess was that the current baro driver is that way because the INS driver isn't added to any board - so there is no init there and hence why everything is directly manipulated here. I should say though that the baro driver isn't added too and that, if that happens one day, it likely makes sense to add both the INS and baro drivers.

@lucasdemarchi
Copy link
Contributor

@OXINARF isn't the imu support it exactly the other commit in this pr?

@OXINARF
Copy link
Member

OXINARF commented Jun 30, 2017

Yes, what I meant is that maybe @tridge is using the baro driver on some board without using the INS driver.

@OXINARF
Copy link
Member

OXINARF commented Jan 8, 2018

Closing this in favor of #7477.

@lucasdemarchi Please comment there!

@OXINARF OXINARF closed this Jan 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants