ben-pololu-imu

Annotated imu.h

1:e037b6ad9b71
2013-10-14 Paul Boddie Added some documentation.
paul@0 1
/*
paul@0 2
 * Ben NanoNote communication with the Pololu MinIMU-9 with the L3G4200D 3-axis
paul@0 3
 * gyroscope and LSM303DLM accelerometer/magnetometer.
paul@0 4
 *
paul@0 5
 * http://www.pololu.com/catalog/product/1265
paul@0 6
 *
paul@0 7
 * Copyright (C) 2013 Paul Boddie
paul@0 8
 *
paul@0 9
 * This program is free software; you can redistribute it and/or modify
paul@0 10
 * it under the terms of the GNU General Public License as published by
paul@0 11
 * the Free Software Foundation; either version 2 of the License, or
paul@0 12
 * (at your option) any later version.
paul@0 13
 */
paul@0 14
paul@0 15
#ifndef __IMU_H__
paul@0 16
#define __IMU_H__
paul@0 17
paul@0 18
#include <ubb/ubb.h>
paul@0 19
#include "i2c.h"
paul@0 20
#include "geo.h"
paul@0 21
paul@0 22
/* Pin assignments:
paul@0 23
 *
paul@0 24
 * Sniffer  UBB   MinIMU-9
paul@0 25
 * -------  ----  --------
paul@0 26
 * DAT2     DAT2
paul@0 27
 * CD       DAT3  SCL
paul@0 28
 * CMD      CMD   SDA
paul@0 29
 * VCC      VDD   VIN
paul@0 30
 * CLK      CLK   (3V)
paul@0 31
 * GND      GND   GND
paul@0 32
 * DAT0     DAT0  (1V8)
paul@0 33
 * DAT1     DAT1
paul@0 34
 *
paul@0 35
 * The 3V and 1V8 pins play no role in the communication, but a six pin header
paul@0 36
 * exposing these pins on the IMU can be used to connect the IMU with the
paul@0 37
 * Sniffer/UBB without any complications.
paul@0 38
 */
paul@0 39
paul@0 40
#define IMU_SCL UBB_DAT3
paul@0 41
#define IMU_SDA UBB_CMD
paul@0 42
#define IMU_3V  UBB_CLK
paul@0 43
#define IMU_1V8 UBB_DAT0
paul@0 44
paul@0 45
/* I2C addresses and operations. */
paul@0 46
paul@0 47
#define IMU_GYRO_ADDRESS            0xd2 /* 1101001x */
paul@0 48
#define IMU_ACCEL_ADDRESS           0x30 /* 0011000x */
paul@0 49
#define IMU_MAGNET_ADDRESS          0x3c /* 0011110x */
paul@0 50
paul@0 51
/* Gyroscope registers. */
paul@0 52
paul@0 53
#define IMU_GYRO_WHO_AM_I           0x0f
paul@0 54
#define IMU_GYRO_CTRL_REG1          0x20
paul@0 55
#define IMU_GYRO_CTRL_REG4          0x23
paul@0 56
#define IMU_GYRO_CTRL_REG5          0x24
paul@0 57
#define IMU_GYRO_OUT_TEMP           0x26
paul@0 58
#define IMU_GYRO_STATUS_REG         0x27
paul@0 59
paul@0 60
/* Gyroscope register values. */
paul@0 61
paul@0 62
#define IMU_GYRO_CTRL_REG1_PD       0x08
paul@0 63
#define IMU_GYRO_CTRL_REG1_ZEN      0x04
paul@0 64
#define IMU_GYRO_CTRL_REG1_YEN      0x02
paul@0 65
#define IMU_GYRO_CTRL_REG1_XEN      0x01
paul@0 66
#define IMU_GYRO_CTRL_REG1_ALL      0x0f /* composite of power and all axes */
paul@0 67
#define IMU_GYRO_CTRL_REG4_BDU      0x80
paul@0 68
#define IMU_GYRO_CTRL_REG4_250DPS   0x00 /* FS1 = 0; FS0 = 0 */
paul@0 69
#define IMU_GYRO_CTRL_REG4_500DPS   0x10 /* FS1 = 0; FS0 = 1 */
paul@0 70
#define IMU_GYRO_CTRL_REG4_2000DPS  0x20 /* FS1 = 1; FS0 = 0 */
paul@0 71
#define IMU_GYRO_CTRL_REG5_BOOT     0x80
paul@0 72
#define IMU_GYRO_CTRL_REG5_HPEN     0x10
paul@0 73
#define IMU_GYRO_CTRL_REG5_OUTSEL1  0x02
paul@0 74
#define IMU_GYRO_CTRL_REG5_OUTSEL0  0x01
paul@0 75
#define IMU_GYRO_OUT_X_L            0x28
paul@0 76
#define IMU_GYRO_OUT_X_H            0x29
paul@0 77
#define IMU_GYRO_OUT_Y_L            0x2a
paul@0 78
#define IMU_GYRO_OUT_Y_H            0x2b
paul@0 79
#define IMU_GYRO_OUT_Z_L            0x2c
paul@0 80
#define IMU_GYRO_OUT_Z_H            0x2d
paul@0 81
#define IMU_GYRO_READ_MANY          0x80 /* gyroscope register increment */
paul@0 82
paul@0 83
/* Accelerometer registers. */
paul@0 84
paul@0 85
#define IMU_ACCEL_CTRL_REG1_A       0x20
paul@0 86
#define IMU_ACCEL_CTRL_REG2_A       0x21
paul@0 87
#define IMU_ACCEL_CTRL_REG4_A       0x23
paul@0 88
#define IMU_ACCEL_HP_FILTER_RESET_A 0x25
paul@0 89
#define IMU_ACCEL_OUT_X_L_A         0x28
paul@0 90
#define IMU_ACCEL_OUT_X_H_A         0x29
paul@0 91
#define IMU_ACCEL_OUT_Y_L_A         0x2a
paul@0 92
#define IMU_ACCEL_OUT_Y_H_A         0x2b
paul@0 93
#define IMU_ACCEL_OUT_Z_L_A         0x2c
paul@0 94
#define IMU_ACCEL_OUT_Z_H_A         0x2d
paul@0 95
#define IMU_ACCEL_READ_MANY         0x80 /* accelerometer register increment */
paul@0 96
paul@0 97
/* Accelerometer register values. */
paul@0 98
paul@0 99
#define IMU_ACCEL_CTRL_REG1_50HZ    0x20 /* normal power */
paul@0 100
#define IMU_ACCEL_CTRL_REG1_100HZ   0x28 /* normal power */
paul@0 101
#define IMU_ACCEL_CTRL_REG1_400HZ   0x30 /* normal power */
paul@0 102
#define IMU_ACCEL_CTRL_REG1_1000HZ  0x38 /* normal power */
paul@0 103
#define IMU_ACCEL_CTRL_REG1_05HZ    0x40 /* low power, 0.5Hz */
paul@0 104
#define IMU_ACCEL_CTRL_REG1_1HZ     0x60 /* low power, 1Hz */
paul@0 105
#define IMU_ACCEL_CTRL_REG1_2HZ     0x80 /* low power, 2Hz */
paul@0 106
#define IMU_ACCEL_CTRL_REG1_5HZ     0x90 /* low power, 5Hz */
paul@0 107
#define IMU_ACCEL_CTRL_REG1_10HZ    0xa0 /* low power, 10Hz */
paul@0 108
#define IMU_ACCEL_CTRL_REG1_ZEN     0x04
paul@0 109
#define IMU_ACCEL_CTRL_REG1_YEN     0x02
paul@0 110
#define IMU_ACCEL_CTRL_REG1_XEN     0x01
paul@0 111
#define IMU_ACCEL_CTRL_REG1_ALL     0x07 /* composite of all axes */
paul@0 112
#define IMU_ACCEL_CTRL_REG2_FDS     0x10
paul@0 113
#define IMU_ACCEL_CTRL_REG2_50      0x00 /* filter cut off is rate/50 */
paul@0 114
#define IMU_ACCEL_CTRL_REG2_100     0x01 /* filter cut off is rate/100 */
paul@0 115
#define IMU_ACCEL_CTRL_REG2_200     0x02 /* filter cut off is rate/200 */
paul@0 116
#define IMU_ACCEL_CTRL_REG2_400     0x03 /* filter cut off is rate/400 */
paul@0 117
#define IMU_ACCEL_CTRL_REG2_HPCF1   0x02
paul@0 118
#define IMU_ACCEL_CTRL_REG4_BDU     0x80
paul@0 119
#define IMU_ACCEL_CTRL_REG4_2G      0x00 /* FS1 = 0; FS0 = 0 */
paul@0 120
#define IMU_ACCEL_CTRL_REG4_4G      0x10 /* FS1 = 0; FS0 = 1 */
paul@0 121
#define IMU_ACCEL_CTRL_REG4_8G      0x30 /* FS1 = 1; FS0 = 1 */
paul@0 122
paul@0 123
/* Magnetometer registers. */
paul@0 124
paul@0 125
#define IMU_MAGNET_CRA_REG_M        0x00
paul@0 126
#define IMU_MAGNET_CRB_REG_M        0x01
paul@0 127
#define IMU_MAGNET_MR_REG_M         0x02
paul@0 128
#define IMU_MAGNET_OUT_X_H_M        0x03
paul@0 129
#define IMU_MAGNET_OUT_X_L_M        0x04
paul@0 130
#define IMU_MAGNET_OUT_Z_H_M        0x05
paul@0 131
#define IMU_MAGNET_OUT_Z_L_M        0x06
paul@0 132
#define IMU_MAGNET_OUT_Y_H_M        0x07
paul@0 133
#define IMU_MAGNET_OUT_Y_L_M        0x08
paul@0 134
#define IMU_MAGNET_SR_REG_M         0x09
paul@0 135
#define IMU_MAGNET_IRA_REG_M        0x0a
paul@0 136
#define IMU_MAGNET_IRB_REG_M        0x0b
paul@0 137
#define IMU_MAGNET_IRC_REG_M        0x0c
paul@0 138
#define IMU_MAGNET_WHO_AM_I_M       0x0f
paul@0 139
paul@0 140
/* Magnetometer register values. */
paul@0 141
paul@0 142
#define IMU_MAGNET_CRA_REG_0_75HZ   0x00 /* 0.75Hz */
paul@0 143
#define IMU_MAGNET_CRA_REG_1_5HZ    0x04 /* 1.5Hz */
paul@0 144
#define IMU_MAGNET_CRA_REG_3HZ      0x08 /* 3Hz */
paul@0 145
#define IMU_MAGNET_CRA_REG_7_5HZ    0x0c /* 7.5Hz */
paul@0 146
#define IMU_MAGNET_CRA_REG_15HZ     0x10 /* 15Hz */
paul@0 147
#define IMU_MAGNET_CRA_REG_30HZ     0x14 /* 30Hz */
paul@0 148
#define IMU_MAGNET_CRA_REG_75HZ     0x18 /* 75Hz */
paul@0 149
#define IMU_MAGNET_CRA_REG_220HZ    0x1c /* 220Hz */
paul@0 150
#define IMU_MAGNET_CRB_REG_1_3G     0x20 /* 1.3G */
paul@0 151
#define IMU_MAGNET_CRB_REG_1_9G     0x40 /* 1.9G */
paul@0 152
#define IMU_MAGNET_CRB_REG_2_5G     0x60 /* 2.5G */
paul@0 153
#define IMU_MAGNET_CRB_REG_4_0G     0x80 /* 4.0G */
paul@0 154
#define IMU_MAGNET_CRB_REG_4_7G     0xa0 /* 4.7G */
paul@0 155
#define IMU_MAGNET_CRB_REG_5_6G     0xc0 /* 5.6G */
paul@0 156
#define IMU_MAGNET_CRB_REG_8_1G     0xe0 /* 8.1G */
paul@0 157
#define IMU_MAGNET_MR_REG_CONT      0x00
paul@0 158
#define IMU_MAGNET_MR_REG_SINGLE    0x01
paul@0 159
#define IMU_MAGNET_MR_REG_SLEEP     0x02
paul@0 160
paul@0 161
/* Common values. */
paul@0 162
paul@0 163
#define IMU_250DPS_UNIT             8750  /* ?dps -> 8.75mdps */
paul@0 164
#define IMU_500DPS_UNIT             17500 /* ?dps -> 17.5mdps */
paul@0 165
#define IMU_2000DPS_UNIT            70000 /* ?dps -> 70mdps */
paul@0 166
paul@0 167
#define IMU_2G_UNIT                 1000 /* ?g -> 1mg */
paul@0 168
#define IMU_4G_UNIT                 2000 /* ?g -> 2mg */
paul@0 169
#define IMU_8G_UNIT                 3900 /* ?g -> 3.9mg */
paul@0 170
paul@0 171
#define IMU_1_3G_UNIT               909 /* ?G (1G / 1100) */
paul@0 172
#define IMU_1_9G_UNIT               1169 /* ?G (1G / 855) */
paul@0 173
#define IMU_2_5G_UNIT               1492 /* ?G (1G / 670) */
paul@0 174
#define IMU_4_0G_UNIT               2222 /* ?G (1G / 450) */
paul@0 175
#define IMU_4_7G_UNIT               2500 /* ?G (1G / 400) */
paul@0 176
#define IMU_5_6G_UNIT               3030 /* ?G (1G / 330) */
paul@0 177
#define IMU_8_1G_UNIT               4347 /* ?G (1G / 230) */
paul@0 178
paul@0 179
#define IMU_MAGNET_Z_XY_RATIO       (9.0 / 8.0) /* adjustments to the above for the smaller Z scale */
paul@0 180
paul@0 181
/* Measurement parameters. */
paul@0 182
paul@0 183
#define IMU_UPDATE_PERIOD           10000 /* ?s -> 10ms == 0.01s (100Hz) */
paul@0 184
#define IMU_MAGNET_UPDATE_PERIOD    30000 /* ?s -> 30ms == 0.03s (33Hz) */
paul@0 185
#define TEXT_UPDATE_PERIOD          500000 /* ?s */
paul@0 186
#define GUI_UPDATE_PERIOD           100000 /* ?s */
paul@0 187
paul@0 188
#define IMU_CALIBRATION_WARMUP      100
paul@0 189
#define IMU_CALIBRATION_READINGS    100
paul@0 190
paul@0 191
#define IMU_ACCEL_BUFFER_SIZE       10
paul@0 192
paul@0 193
#define IMU_UDPS_FACTOR             IMU_2000DPS_UNIT
paul@0 194
#define IMU_GYRO_DPS_SCALE          IMU_GYRO_CTRL_REG4_2000DPS
paul@0 195
paul@0 196
#define IMU_UG_FACTOR               IMU_2G_UNIT
paul@0 197
#define IMU_ACCEL_SCALE             IMU_ACCEL_CTRL_REG4_2G
paul@0 198
#define IMU_ACCEL_FREQ              IMU_ACCEL_CTRL_REG1_50HZ
paul@0 199
#define IMU_ACCEL_FILTER_FREQ       IMU_ACCEL_CTRL_REG2_50
paul@0 200
paul@0 201
#define IMU_UGAUSS_FACTOR           IMU_4_0G_UNIT
paul@0 202
#define IMU_MAGNET_SCALE            IMU_MAGNET_CRB_REG_4_0G
paul@0 203
#define IMU_MAGNET_FREQ             IMU_MAGNET_CRA_REG_30HZ
paul@0 204
paul@0 205
#define ACCEL_G                     9.81 /* ms**-2 */
paul@0 206
paul@0 207
#define ACCEL_THRESHOLD             0.1 /* g */
paul@0 208
#define ACCEL_SUM_THRESHOLD         0.01 /* gs */
paul@0 209
#define VELOCITY_DECAY_SEVERE       0.5
paul@0 210
#define VELOCITY_DECAY_GRADUAL      0.9
paul@0 211
paul@0 212
#define ACCEL_REST_MAG_LOWER        0.995
paul@0 213
#define ACCEL_REST_MAG_UPPER        1.005
paul@0 214
#define ROTATION_ADJUSTMENT_FACTOR  0.1
paul@0 215
paul@0 216
/* Convert microdegrees * microseconds to degrees. */
paul@0 217
paul@0 218
#define to_angle(x)                 ((double) (x) / ((uint64_t) 1000000000000))
paul@0 219
paul@0 220
/* Convert microg to g. */
paul@0 221
paul@0 222
#define to_accel(x)                 ((double) (x) / 1000000)
paul@0 223
paul@0 224
/* Convert microgauss to gauss. */
paul@0 225
paul@0 226
#define to_field(x)                 to_accel(x)
paul@0 227
paul@0 228
/* Get a period in microseconds. */
paul@0 229
paul@0 230
#define get_period(now, then)       ((now.tv_sec - then.tv_sec) * 1000000 + (now.tv_usec - then.tv_usec))
paul@0 231
paul@0 232
/* Function definitions. */
paul@0 233
paul@0 234
bool imu_recv(uint8_t device, uint8_t reg, uint8_t *result, uint8_t len);
paul@0 235
bool imu_sendone(uint8_t device, uint8_t reg, uint8_t value);
paul@0 236
int16_t convert(uint8_t raw[]);
paul@0 237
int16_t convert12(uint8_t raw[]);
paul@0 238
int16_t convertBE12L(uint8_t raw[]);
paul@0 239
bool imu_read_vector(uint8_t device, uint8_t reg, vectorf *out, int16_t (*converter)(uint8_t *));
paul@0 240
bool imu_read_vector_xzy(uint8_t device, uint8_t reg, vectorf *out, int16_t (*converter)(uint8_t *));
paul@0 241
double scale(double value, double lower, double middle, double upper);
paul@0 242
void normalise(vectorf *in, vectorf *vmin, vectorf *vmax, vectorf *out);
paul@0 243
void queue(vectorf values[], int *oldest, int length, vectorf *value);
paul@0 244
void filter(vectorf values[], int oldest, int length, vectorf *result);
paul@0 245
void calibrate(vectorf *zerolevel, vectorf zerolevels[], int length, uint8_t address, uint8_t reg, uint16_t delay, int16_t (*converter)(uint8_t *));
paul@0 246
paul@0 247
/* Accelerometer-specific functions. */
paul@0 248
paul@0 249
void average_filter(vectorf *value, vectorf buffer[], int *index, int length);
paul@0 250
void noise_filter(vectorf *value, double threshold);
paul@0 251
void apply_acceleration(double acc, double acc_old, double *pos, double *neg, double seconds);
paul@0 252
void apply_decay(double acc, double* pos, double* neg);
paul@0 253
void update_velocity(vectorf *velocity, vectorf *acceleration, vectorf *acceleration_old, vectorf *apos, vectorf *aneg, double seconds);
paul@0 254
void update_displacement(vectorf *displacement, vectorf *velocity, vectorf *velocity_old, double seconds);
paul@0 255
paul@0 256
/* Function aliases. */
paul@0 257
paul@0 258
#define imu_init i2c_init
paul@0 259
paul@0 260
#endif /* __IMU_H__ */