Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ardupilot
GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_Baro/examples/ICM20789/ICM20789.cpp
9692 views
1
/*
2
minimal test program for ICM20789 baro with IMU on SPI and baro on I2C
3
*/
4
5
#include <AP_HAL/AP_HAL.h>
6
#include <AP_HAL/I2CDevice.h>
7
#include <AP_Baro/AP_Baro.h>
8
#include <AP_BoardConfig/AP_BoardConfig.h>
9
#include <stdio.h>
10
11
const AP_HAL::HAL& hal = AP_HAL::get_HAL();
12
13
#ifdef HAL_INS_MPU60x0_NAME
14
static AP_HAL::Device *i2c_dev;
15
static AP_HAL::Device *spi_dev;
16
static AP_HAL::Device *dev;
17
#endif // defined(HAL_INS_MPU60x0_NAME)
18
19
// SPI registers
20
#define MPUREG_WHOAMI 0x75
21
#define MPUREG_USER_CTRL 0x6A
22
#define MPUREG_PWR_MGMT_1 0x6B
23
24
#define MPUREG_INT_PIN_CFG 0x37
25
# define BIT_BYPASS_EN 0x02
26
# define BIT_INT_RD_CLEAR 0x10 // clear the interrupt when any read occurs
27
# define BIT_LATCH_INT_EN 0x20 // latch data ready pin
28
29
#define BIT_USER_CTRL_I2C_MST_EN 0x20 // Enable MPU to act as the I2C Master to external slave sensors
30
#define BIT_PWR_MGMT_1_DEVICE_RESET 0x80 // reset entire device
31
#define BIT_USER_CTRL_I2C_IF_DIS 0x10 // Disable primary I2C interface and enable hal.spi->interface
32
#define BIT_PWR_MGMT_1_CLK_XGYRO 0x01 // PLL with X axis gyroscope reference
33
#define BIT_PWR_MGMT_1_CLK_ZGYRO 0x03 // PLL with Z axis gyroscope reference
34
35
// baro commands
36
#define CMD_SOFT_RESET 0x805D
37
#define CMD_READ_ID 0xEFC8
38
39
void setup(void);
40
void loop(void);
41
42
43
#ifdef HAL_INS_MPU60x0_NAME
44
static void spi_init()
45
{
46
// SPI reads have flag 0x80 set
47
spi_dev->set_read_flag(0x80);
48
49
// run the SPI bus at low speed
50
spi_dev->set_speed(AP_HAL::Device::SPEED_LOW);
51
52
uint8_t whoami = 0;
53
uint8_t v;
54
55
spi_dev->write_register(0x6B, 0x01);
56
spi_dev->write_register(0x6B, 0x01);
57
58
hal.scheduler->delay(1);
59
spi_dev->write_register(0x6A, 0x10);
60
spi_dev->write_register(0x6B, 0x41);
61
62
hal.scheduler->delay(1);
63
spi_dev->write_register(0x6C, 0x3f);
64
spi_dev->write_register(0xF5, 0x00);
65
spi_dev->write_register(0x19, 0x09);
66
spi_dev->write_register(0xEA, 0x00);
67
spi_dev->write_register(0x6B, 0x01);
68
69
hal.scheduler->delay(1);
70
spi_dev->write_register(0x6A, 0x10);
71
spi_dev->write_register(0x6B, 0x41);
72
73
hal.scheduler->delay(1);
74
spi_dev->write_register(0x6B, 0x01);
75
76
hal.scheduler->delay(1);
77
spi_dev->write_register(0x23, 0x00);
78
spi_dev->write_register(0x6B, 0x41);
79
80
hal.scheduler->delay(1);
81
spi_dev->write_register(0x1D, 0xC0);
82
spi_dev->write_register(0x6B, 0x01);
83
84
hal.scheduler->delay(1);
85
spi_dev->write_register(0x1A, 0xC0);
86
spi_dev->write_register(0x6B, 0x41);
87
88
hal.scheduler->delay(1);
89
spi_dev->write_register(0x38, 0x01);
90
91
spi_dev->read_registers(0x6A, &v, 1);
92
printf("reg 0x6A=0x%02x\n", v);
93
spi_dev->read_registers(0x6B, &v, 1);
94
printf("reg 0x6B=0x%02x\n", v);
95
96
hal.scheduler->delay(1);
97
spi_dev->write_register(0x6A, 0x10);
98
spi_dev->write_register(0x6B, 0x41);
99
100
hal.scheduler->delay(1);
101
spi_dev->write_register(0x6B, 0x01);
102
103
hal.scheduler->delay(1);
104
spi_dev->write_register(0x23, 0x00);
105
spi_dev->write_register(0x6B, 0x41);
106
107
hal.scheduler->delay(1);
108
spi_dev->write_register(0x6B, 0x41);
109
spi_dev->write_register(0x6C, 0x3f);
110
spi_dev->write_register(0x6B, 0x41);
111
112
spi_dev->read_registers(0x6A, &v, 1);
113
printf("reg 0x6A=0x%02x\n", v);
114
spi_dev->write_register(0x6B, 0x01);
115
116
hal.scheduler->delay(1);
117
spi_dev->write_register(0x6A, 0x10);
118
spi_dev->write_register(0x6B, 0x41);
119
120
hal.scheduler->delay(1);
121
spi_dev->write_register(0x6B, 0x01);
122
123
hal.scheduler->delay(1);
124
spi_dev->write_register(0x23, 0x00);
125
spi_dev->write_register(0x6B, 0x41);
126
127
hal.scheduler->delay(1);
128
spi_dev->read_registers(0x6A, &v, 1);
129
printf("reg 0x6A=0x%02x\n", v);
130
spi_dev->write_register(0x6B, 0x01);
131
132
hal.scheduler->delay(1);
133
spi_dev->write_register(0x6A, 0x10);
134
spi_dev->write_register(0x6B, 0x41);
135
136
hal.scheduler->delay(1);
137
spi_dev->write_register(0x6B, 0x01);
138
139
hal.scheduler->delay(1);
140
spi_dev->write_register(0x23, 0x00);
141
spi_dev->write_register(0x6B, 0x41);
142
143
hal.scheduler->delay(1);
144
spi_dev->write_register(0x6B, 0x41);
145
spi_dev->write_register(0x6C, 0x3f);
146
spi_dev->write_register(0x6B, 0x41);
147
148
spi_dev->read_registers(0x6A, &v, 1);
149
printf("reg 0x6A=0x%02x\n", v);
150
spi_dev->write_register(0x6B, 0x01);
151
152
hal.scheduler->delay(1);
153
spi_dev->write_register(0x6A, 0x10);
154
spi_dev->write_register(0x6B, 0x41);
155
156
hal.scheduler->delay(1);
157
spi_dev->write_register(0x6B, 0x01);
158
159
hal.scheduler->delay(1);
160
spi_dev->write_register(0x23, 0x00);
161
spi_dev->write_register(0x6B, 0x41);
162
163
// print the WHOAMI
164
spi_dev->read_registers(MPUREG_WHOAMI, &whoami, 1);
165
printf("20789 SPI whoami: 0x%02x\n", whoami);
166
167
// wait for sensor to settle
168
hal.scheduler->delay(100);
169
170
// dump registers
171
printf("ICM20789 registers\n");
172
#if 0
173
for (uint8_t reg = 0; reg<0x80; reg++) {
174
v=0;
175
spi_dev->read_registers(reg, &v, 1);
176
printf("%02x:%02x ", (unsigned)reg, (unsigned)v);
177
if ((reg+1) % 16 == 0) {
178
printf("\n");
179
}
180
}
181
printf("\n");
182
#endif
183
184
spi_dev->get_semaphore()->give();
185
}
186
#endif
187
188
#ifdef HAL_INS_MPU60x0_NAME
189
/*
190
send a 16 bit command to the baro
191
*/
192
static bool send_cmd16(uint16_t cmd)
193
{
194
uint8_t cmd_b[2] = { uint8_t(cmd >> 8), uint8_t(cmd & 0xFF) };
195
return i2c_dev->transfer(cmd_b, 2, nullptr, 0);
196
}
197
198
/*
199
read baro calibration data
200
*/
201
static bool read_calibration_data(void)
202
{
203
// setup for OTP read
204
const uint8_t cmd[5] = { 0xC5, 0x95, 0x00, 0x66, 0x9C };
205
if (!i2c_dev->transfer(cmd, sizeof(cmd), nullptr, 0)) {
206
return false;
207
}
208
for (uint8_t i=0; i<4; i++) {
209
if (!send_cmd16(0xC7F7)) {
210
return false;
211
}
212
uint8_t d[3];
213
if (!i2c_dev->transfer(nullptr, 0, d, sizeof(d))) {
214
return false;
215
}
216
uint16_t c = int16_t((d[0]<<8) | d[1]);
217
printf("sensor_constants[%u]=%d\n", i, c);
218
}
219
return true;
220
}
221
222
// initialise baro on i2c
223
static void i2c_init(void)
224
{
225
i2c_dev->get_semaphore()->take_blocking();
226
227
if (send_cmd16(CMD_READ_ID)) {
228
printf("ICM20789: read ID ******\n");
229
uint8_t id[3] {};
230
if (!i2c_dev->transfer(nullptr, 0, id, 3)) {
231
printf("ICM20789: failed to read ID\n");
232
}
233
printf("ICM20789: ID %02x %02x %02x\n", id[0], id[1], id[2]);
234
} else {
235
printf("ICM20789 read ID failed\n");
236
}
237
238
if (send_cmd16(CMD_SOFT_RESET)) {
239
printf("ICM20789: reset OK ************###########*********!!!!!!!!\n");
240
} else {
241
printf("ICM20789 baro reset failed\n");
242
}
243
hal.scheduler->delay(1);
244
245
246
read_calibration_data();
247
248
i2c_dev->get_semaphore()->give();
249
250
printf("checking baro\n");
251
dev->get_semaphore()->take_blocking();
252
253
uint8_t regs[3] = { 0xC0, 0xC1, 0xC2 };
254
for (uint8_t i=0; i<ARRAY_SIZE(regs); i++) {
255
uint8_t v = 0;
256
dev->read_registers(regs[i], &v, 1);
257
printf("0x%02x : 0x%02x\n", regs[i], v);
258
}
259
dev->get_semaphore()->give();
260
}
261
#endif
262
263
void setup()
264
{
265
printf("ICM20789 test\n");
266
267
AP_BoardConfig{}.init();
268
269
hal.scheduler->delay(1000);
270
271
#ifdef HAL_INS_MPU60x0_NAME
272
spi_dev = hal.spi->get_device_ptr(HAL_INS_MPU60x0_NAME);
273
274
spi_dev->get_semaphore()->take_blocking();
275
276
i2c_dev = hal.i2c_mgr->get_device_ptr(1, 0x63);
277
dev = hal.i2c_mgr->get_device_ptr(1, 0x29);
278
279
while (true) {
280
spi_init();
281
i2c_init();
282
hal.scheduler->delay(1000);
283
}
284
#else
285
while (true) {
286
printf("HAL_INS_MPU60x0_NAME not defined for this board\n");
287
hal.scheduler->delay(1000);
288
}
289
#endif
290
}
291
292
293
void loop()
294
{
295
}
296
297
AP_HAL_MAIN();
298
299