DevLab_ICM20948 1.0.2
ICM-20948 9-Axis Motion Sensor Driver
Loading...
Searching...
No Matches
gyr_test.ino
Go to the documentation of this file.
1/**
2 * @file gyr_test.ino
3 * @brief Gyroscope DLPF and full-scale sweep for the DevLab ICM-20948.
4 * @author Jonathan Mejorado Lopez
5 * @details Applies each gyroscope filter/full-scale configuration over I2C and
6 * prints repeated samples for validation and noise comparison.
7 */
8
9#include <Wire.h>
10#include <DevLab_ICM20948.h>
11// -----------------------------------------------------------
12// PINES I2C — ESP32C6 NANO Unit Electronics
13// -----------------------------------------------------------
14/** @brief I2C SDA pin used by the example board. */
15#define SDA_PIN 6
16/** @brief I2C SCL pin used by the example board. */
17#define SCL_PIN 7
18/** @brief I2C bus speed in hertz. */
19#define I2C_FREQ 400000UL
20/** @brief ICM-20948 I2C address selected by the AD0 pin. */
21#define ICM_ADDR 0x69
22
23// -----------------------------------------------------------
24// STRUCT
25// -----------------------------------------------------------
26/** @brief Gyroscope DLPF divider and timing configuration. */
27struct configDLPF {
28 /** @brief Index into the gyroDLPF lookup table. */
29 uint8_t dlpf_idx;
30 /** @brief Sample-rate divider written to the IMU register. */
31 uint16_t div;
32 /** @brief Noise bandwidth in hertz for reporting. */
33 float nbw_hz;
34 /** @brief Output data rate in hertz for timing calculations. */
35 float odr_hz;
36 /** @brief Text label printed with each captured sample. */
37 const char* nombre;
38};
39//id,div,nbw_hz,odr_hz,nombre : {DLPF, NBW , ODR}
40/*
41/** @brief Gyroscope DLPF configurations exercised by the sweep. */
43 { 0, 0, 229.8f, 1125.0f, "196,6 ; 229,8 ; 1125.0 " },
44 { 1, 0, 187.6f, 1125.0f, "151,8 ; 187.6 ; 1125.0 " },
45 { 2, 0, 154.3f, 1125.0f, "119,5 ; 154,3 ; 1125.0 " },
46 { 3, 2, 73.3f, 375.0f, "51,2 ; 73,3 ; 375 " },
47 { 4, 5, 35.9f, 187.5f, "23,9 ; 35,9 ; 187.5 " },
48 { 5, 14, 17.8f, 75.0f, "11,6 ; 17,8 ; 75.0 " },
49 { 6, 29, 8.9f, 37.5f, "5,7 ; 8,9 ; 37.5 " },
50 { 7, 0, 376.5f, 1125.0f, "361,4 ; 376,5 ; 1125 " },
51};
52/** @brief Number of gyroscope DLPF configurations. */
53const uint8_t N_DLPF = sizeof(configsDLPF) / sizeof(configsDLPF[0]);
54
55/** @brief Gyroscope full-scale ranges exercised by the sweep. */
62
63/** @brief Text labels matching gyroFSCfg. */
64const char* etiquetasGyroFSCfg[] = {"250", "500", "1000", "2000"};
65/** @brief Number of gyroscope full-scale ranges. */
66const uint8_t N_FS = 4;
67
68/** @brief Gyroscope DLPF enum values matching configsDLPF. */
79
80/** @brief Gyroscope averaging settings available for experiments. */
91
92/** @brief Text labels matching gyroAVGCfg. */
93const char* etiquetasGyroAVGCfg[] = {"1","2","4","8","16","32","64","128"};
94/** @brief Number of gyroscope averaging settings. */
95const uint8_t N_AVG = 8;
96
97/** @brief Global ICM-20948 driver instance. */
99
100/** @brief Print a separator line to Serial. */
101void printLinea() { Serial.println(F("------------------------------------------------------------")); }
102/** @brief Print a double separator line to Serial. */
103void printDobleLinea() { Serial.println(F("============================================================")); }
104
105/**
106 * @brief Verify the IMU identity register.
107 */
109 uint8_t who;
110 if (!imu.readWhoAmI(who) || who != 0xEA) {
111 Serial.println(F("ERROR: WHO_AM_I mismatch"));
112 while (1) delay(200);
113 }
114 Serial.printf("WHO_AM_I = 0x%02X OK\n", who);
115}
116
117/**
118 * @brief Apply one gyroscope full-scale and DLPF configuration.
119 *
120 * @param fs_idx Index into gyroFSCfg.
121 * @param cfg DLPF timing and divider configuration.
122 * @return true if all configuration writes succeeded, otherwise false.
123 */
124bool applySettings(uint8_t fs_idx, const configDLPF &cfg) {
125 ICM20948_Gyro_DLPF dlpf_val = gyroDLPF[cfg.dlpf_idx];
126 bool ok = true;
127
128 ok &= imu.setGyroScale(gyroFSCfg[fs_idx]);
129
130
131 // Paso 1: escribe DLPFCFG en bits [5:3]
132 // SetDLPF false -> Activa DLPF
133 // SetDLPF true -> Desactiva DLPF
134 ok &= imu.setDLPF(dlpf_val, false);
135
136 //ok &= imu.setGyroAveraging(gyroAVGCfg[avg]);
137 // Paso 2: activa FCHOICE=1 (DLPF activo) sin tocar DLPFCFG
138 //ok &= imu.setAccelDLPF(0, true);
139
140 // DIV directo al registro, sin conversion interna
141 ok &= imu.setGyroDivRate(cfg.div);
142
143 return ok;
144}
145
146/**
147 * @brief Run the gyroscope validation sweep and print each captured sample.
148 */
149void runSweep(){
150 uint16_t n = 0;
152 Serial.println(F(" ICM-20948 | UNIT Electronics"));
153 Serial.println(F(" MODO VERIFICACION — FS=+-2g fijo, 3 lecturas por config"));
154 Serial.println(F(" Sensor PLANO y QUIETO | Az esperado: ~+1.000g"));
156 for (uint8_t i = 0; i < N_FS ; i++){
157 for(uint8_t d = 0; d < N_DLPF; d++){
158
159 bool cfg_ok = applySettings(i,configsDLPF[d]);
160 if(!cfg_ok){
161 Serial.println(F("ERROR: applySettings fallo"));
162 }
163
164 // Esperar que el filtro estabilice (10 periodos del ODR, min 50ms)
165 uint32_t settle_ms = max((uint32_t)(10000.0f / configsDLPF[d].odr_hz),
166 (uint32_t)50);
167 delay(settle_ms);
168 // Tomar 3 lecturas espaciadas por el periodo del ODR
169 uint32_t periodo_ms = max((uint32_t)(1000.0f / configsDLPF[d].odr_hz),
170 (uint32_t)1);
171 float gx, gy, gz;
172 for (uint8_t r = 0; r < 100; r++) {
173 n++;
174 delay(periodo_ms);
175 if (imu.readGyro(gx, gy, gz)) {
176 Serial.printf("%d ; %s ; %s ; %+.4f ; %+.4f ; %+.4f\n",
177 n,
178 configsDLPF[d].nombre, // "246 ; 265 ; 1125"
179 etiquetasGyroFSCfg[i], // "+-2G"
180 //etiquetasGyroAVGCfg[j], // "8"
181 gx, gy, gz);
182 } else {
183 Serial.println(F(" [?] readGyr() fallo"));
184 }
185 }
186 }
187
188 }
189}
190
191/**
192 * @brief Initialize I2C, reset/wake the IMU, enable gyro, and start the sweep.
193 */
194void setup() {
195 // put your setup code here, to run once:
196 Serial.begin(115200);
197 delay(200);
198
200 Serial.println(F(" ICM-20948 VALIDACION ACELEROMETRO"));
202
203 Wire.begin(SDA_PIN, SCL_PIN);
204
205 if (!imu.beginI2C(ICM_ADDR, Wire, I2C_FREQ)) {
206 Serial.println(F("ERROR: beginI2C() fallo"));
207 while (1) delay(200);
208 }
209
210 firstStage();
211
212 // softReset pone el chip a dormir
213 // Despues del reset hay que despertar el dispositivo
214 imu.softReset();
215 delay(100);
216 imu.sleep(false); // limpia SLEEP bit, CLKSEL=1
217 delay(50);
218
219 if (!imu.setSensors(false, true, false)) {
220 Serial.println(F("ERROR: setSensors() fallo"));
221 }
222
223 Serial.println(F(" Sensor listo.\n"));
224 Serial.println(F(" Sensor PLANO y QUIETO sobre la mesa."));
225 Serial.println(F(" Iniciando en 5 segundos..."));
226 for (int i = 5; i > 0; i--) {
227 Serial.printf(" %d...\n", i);
228 delay(1000);
229 }
230
231 //for (int runs = 0; runs < 20 ; runs++){
232 runSweep();
233 //}
234}
235
236/**
237 * @brief Empty loop; this sketch runs the gyroscope sweep once in setup().
238 */
239void loop() {
240 // put your main code here, to run repeatedly:
241
242}
ICM20948_Gyro_FullScale
ICM20948_Gyro_Average
ICM20948_Gyro_DLPF
bool readGyro(float &x, float &y, float &z)
bool setDLPF(ICM20948_Gyro_DLPF dlpf, bool bypass)
bool setGyroDivRate(uint8_t divisor)
bool sleep(bool en)
bool setGyroScale(ICM20948_Gyro_FullScale fullScale)
bool readWhoAmI(uint8_t &whoAmI)
bool beginI2C(uint8_t address=0x69, TwoWire &i2cPort=Wire, uint32_t i2cSpeed=400000)
bool setSensors(bool accel_on, bool gyro_on, bool temp_on)
#define SCL_PIN
I2C SCL pin used by the example board.
Definition gyr_test.ino:17
const uint8_t N_AVG
Number of gyroscope averaging settings.
Definition gyr_test.ino:95
void firstStage()
Verify the IMU identity register.
Definition gyr_test.ino:108
void printDobleLinea()
Print a double separator line to Serial.
Definition gyr_test.ino:103
const ICM20948_Gyro_Average gyroAVGCfg[]
Gyroscope averaging settings available for experiments.
Definition gyr_test.ino:81
void setup()
Initialize I2C, reset/wake the IMU, enable gyro, and start the sweep.
Definition gyr_test.ino:194
#define SDA_PIN
I2C SDA pin used by the example board.
Definition gyr_test.ino:15
void runSweep()
Run the gyroscope validation sweep and print each captured sample.
Definition gyr_test.ino:149
const uint8_t N_FS
Number of gyroscope full-scale ranges.
Definition gyr_test.ino:66
const ICM20948_Gyro_DLPF gyroDLPF[]
Gyroscope DLPF enum values matching configsDLPF.
Definition gyr_test.ino:69
const uint8_t N_DLPF
Number of gyroscope DLPF configurations.
Definition gyr_test.ino:53
void printLinea()
Print a separator line to Serial.
Definition gyr_test.ino:101
#define I2C_FREQ
I2C bus speed in hertz.
Definition gyr_test.ino:19
#define ICM_ADDR
ICM-20948 I2C address selected by the AD0 pin.
Definition gyr_test.ino:21
const ICM20948_Gyro_FullScale gyroFSCfg[]
Gyroscope full-scale ranges exercised by the sweep.
Definition gyr_test.ino:56
const configDLPF configsDLPF[]
Definition gyr_test.ino:42
DevLab_ICM20948 imu
Global ICM-20948 driver instance.
Definition gyr_test.ino:98
const char * etiquetasGyroFSCfg[]
Text labels matching gyroFSCfg.
Definition gyr_test.ino:64
const char * etiquetasGyroAVGCfg[]
Text labels matching gyroAVGCfg.
Definition gyr_test.ino:93
void loop()
Empty loop; this sketch runs the gyroscope sweep once in setup().
Definition gyr_test.ino:239
void applySettings()
Initialize the magnetometer and collect samples for each mode.
Definition mag_test.ino:53
Gyroscope DLPF divider and timing configuration.
Definition gyr_test.ino:27
float odr_hz
Output data rate in hertz for timing calculations.
Definition gyr_test.ino:35
uint8_t dlpf_idx
Index into the gyroDLPF lookup table.
Definition gyr_test.ino:29
const char * nombre
Text label printed with each captured sample.
Definition gyr_test.ino:37
uint16_t div
Sample-rate divider written to the IMU register.
Definition gyr_test.ino:31
float nbw_hz
Noise bandwidth in hertz for reporting.
Definition gyr_test.ino:33