123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- /*
- minimal test program for ICM20789 baro with IMU on SPI and baro on I2C
- */
- #include <AP_HAL/AP_HAL.h>
- #include <AP_HAL/I2CDevice.h>
- #include <AP_Baro/AP_Baro.h>
- #include <AP_BoardConfig/AP_BoardConfig.h>
- #include <utility>
- #include <stdio.h>
- const AP_HAL::HAL& hal = AP_HAL::get_HAL();
- static AP_HAL::OwnPtr<AP_HAL::Device> i2c_dev;
- static AP_HAL::OwnPtr<AP_HAL::Device> spi_dev;
- static AP_HAL::OwnPtr<AP_HAL::Device> dev;
- // SPI registers
- #define MPUREG_WHOAMI 0x75
- #define MPUREG_USER_CTRL 0x6A
- #define MPUREG_PWR_MGMT_1 0x6B
- #define MPUREG_INT_PIN_CFG 0x37
- # define BIT_BYPASS_EN 0x02
- # define BIT_INT_RD_CLEAR 0x10 // clear the interrupt when any read occurs
- # define BIT_LATCH_INT_EN 0x20 // latch data ready pin
- #define BIT_USER_CTRL_I2C_MST_EN 0x20 // Enable MPU to act as the I2C Master to external slave sensors
- #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
- // baro commands
- #define CMD_SOFT_RESET 0x805D
- #define CMD_READ_ID 0xEFC8
- void setup(void);
- void loop(void);
- #ifdef HAL_INS_MPU60x0_NAME
- static void spi_init()
- {
- // SPI reads have flag 0x80 set
- spi_dev->set_read_flag(0x80);
- // run the SPI bus at low speed
- spi_dev->set_speed(AP_HAL::Device::SPEED_LOW);
- uint8_t whoami = 0;
- uint8_t v;
- spi_dev->write_register(0x6B, 0x01);
- spi_dev->write_register(0x6B, 0x01);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6A, 0x10);
- spi_dev->write_register(0x6B, 0x41);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6C, 0x3f);
- spi_dev->write_register(0xF5, 0x00);
- spi_dev->write_register(0x19, 0x09);
- spi_dev->write_register(0xEA, 0x00);
- spi_dev->write_register(0x6B, 0x01);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6A, 0x10);
- spi_dev->write_register(0x6B, 0x41);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6B, 0x01);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x23, 0x00);
- spi_dev->write_register(0x6B, 0x41);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x1D, 0xC0);
- spi_dev->write_register(0x6B, 0x01);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x1A, 0xC0);
- spi_dev->write_register(0x6B, 0x41);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x38, 0x01);
- spi_dev->read_registers(0x6A, &v, 1);
- printf("reg 0x6A=0x%02x\n", v);
- spi_dev->read_registers(0x6B, &v, 1);
- printf("reg 0x6B=0x%02x\n", v);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6A, 0x10);
- spi_dev->write_register(0x6B, 0x41);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6B, 0x01);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x23, 0x00);
- spi_dev->write_register(0x6B, 0x41);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6B, 0x41);
- spi_dev->write_register(0x6C, 0x3f);
- spi_dev->write_register(0x6B, 0x41);
- spi_dev->read_registers(0x6A, &v, 1);
- printf("reg 0x6A=0x%02x\n", v);
- spi_dev->write_register(0x6B, 0x01);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6A, 0x10);
- spi_dev->write_register(0x6B, 0x41);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6B, 0x01);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x23, 0x00);
- spi_dev->write_register(0x6B, 0x41);
- hal.scheduler->delay(1);
- spi_dev->read_registers(0x6A, &v, 1);
- printf("reg 0x6A=0x%02x\n", v);
- spi_dev->write_register(0x6B, 0x01);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6A, 0x10);
- spi_dev->write_register(0x6B, 0x41);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6B, 0x01);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x23, 0x00);
- spi_dev->write_register(0x6B, 0x41);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6B, 0x41);
- spi_dev->write_register(0x6C, 0x3f);
- spi_dev->write_register(0x6B, 0x41);
- spi_dev->read_registers(0x6A, &v, 1);
- printf("reg 0x6A=0x%02x\n", v);
- spi_dev->write_register(0x6B, 0x01);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6A, 0x10);
- spi_dev->write_register(0x6B, 0x41);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x6B, 0x01);
- hal.scheduler->delay(1);
- spi_dev->write_register(0x23, 0x00);
- spi_dev->write_register(0x6B, 0x41);
- // print the WHOAMI
- spi_dev->read_registers(MPUREG_WHOAMI, &whoami, 1);
- printf("20789 SPI whoami: 0x%02x\n", whoami);
- // wait for sensor to settle
- hal.scheduler->delay(100);
- // dump registers
- printf("ICM20789 registers\n");
- #if 0
- for (uint8_t reg = 0; reg<0x80; reg++) {
- v=0;
- spi_dev->read_registers(reg, &v, 1);
- printf("%02x:%02x ", (unsigned)reg, (unsigned)v);
- if ((reg+1) % 16 == 0) {
- printf("\n");
- }
- }
- printf("\n");
- #endif
- spi_dev->get_semaphore()->give();
- }
- #endif
- /*
- send a 16 bit command to the baro
- */
- static bool send_cmd16(uint16_t cmd)
- {
- uint8_t cmd_b[2] = { uint8_t(cmd >> 8), uint8_t(cmd & 0xFF) };
- return i2c_dev->transfer(cmd_b, 2, nullptr, 0);
- }
- /*
- read baro calibration data
- */
- static bool read_calibration_data(void)
- {
- // setup for OTP read
- const uint8_t cmd[5] = { 0xC5, 0x95, 0x00, 0x66, 0x9C };
- if (!i2c_dev->transfer(cmd, sizeof(cmd), nullptr, 0)) {
- return false;
- }
- for (uint8_t i=0; i<4; i++) {
- if (!send_cmd16(0xC7F7)) {
- return false;
- }
- uint8_t d[3];
- if (!i2c_dev->transfer(nullptr, 0, d, sizeof(d))) {
- return false;
- }
- uint16_t c = int16_t((d[0]<<8) | d[1]);
- printf("sensor_constants[%u]=%d\n", i, c);
- }
- return true;
- }
- #ifdef HAL_INS_MPU60x0_NAME
- // initialise baro on i2c
- static void i2c_init(void)
- {
- if (!i2c_dev->get_semaphore()->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
- AP_HAL::panic("Failed to get baro semaphore");
- }
- if (send_cmd16(CMD_READ_ID)) {
- printf("ICM20789: read ID ******\n");
- uint8_t id[3] {};
- if (!i2c_dev->transfer(nullptr, 0, id, 3)) {
- printf("ICM20789: failed to read ID\n");
- }
- printf("ICM20789: ID %02x %02x %02x\n", id[0], id[1], id[2]);
- } else {
- printf("ICM20789 read ID failed\n");
- }
- if (send_cmd16(CMD_SOFT_RESET)) {
- printf("ICM20789: reset OK ************###########*********!!!!!!!!\n");
- } else {
- printf("ICM20789 baro reset failed\n");
- }
- hal.scheduler->delay(1);
- read_calibration_data();
- i2c_dev->get_semaphore()->give();
- printf("checking baro\n");
- if (!dev->get_semaphore()->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
- AP_HAL::panic("Failed to get device semaphore");
- }
- uint8_t regs[3] = { 0xC0, 0xC1, 0xC2 };
- for (uint8_t i=0; i<ARRAY_SIZE(regs); i++) {
- uint8_t v = 0;
- dev->read_registers(regs[i], &v, 1);
- printf("0x%02x : 0x%02x\n", regs[i], v);
- }
- dev->get_semaphore()->give();
- }
- #endif
- void setup()
- {
- printf("ICM20789 test\n");
- AP_BoardConfig{}.init();
- hal.scheduler->delay(1000);
- #ifdef HAL_INS_MPU60x0_NAME
- spi_dev = std::move(hal.spi->get_device(HAL_INS_MPU60x0_NAME));
- if (!spi_dev->get_semaphore()->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
- AP_HAL::panic("Failed to get spi semaphore");
- }
- i2c_dev = std::move(hal.i2c_mgr->get_device(1, 0x63));
- dev = std::move(hal.i2c_mgr->get_device(1, 0x29));
- while (true) {
- spi_init();
- i2c_init();
- hal.scheduler->delay(1000);
- }
- #else
- while (true) {
- printf("HAL_INS_MPU60x0_NAME not defined for this board\n");
- hal.scheduler->delay(1000);
- }
- #endif
- }
- void loop()
- {
- }
- AP_HAL_MAIN();
|