DevLab_ICM20948 1.0.2
ICM-20948 9-Axis Motion Sensor Driver
Loading...
Searching...
No Matches
test2.ino
Go to the documentation of this file.
1/**
2 * @file test2.ino
3 * @brief Extended accelerometer DLPF, full-scale, and averaging sweep.
4 * @author Jonathan Mejorado Lopez
5 * @details Runs a larger I2C validation matrix for the DevLab ICM-20948
6 * accelerometer and prints CSV-like samples for later analysis.
7 */
8
9#include <Wire.h>
10#include <DevLab_ICM20948.h>
11
12// -----------------------------------------------------------
13// PINES I2C — ESP32C6 NANO Unit Electronics
14// -----------------------------------------------------------
15/** @brief I2C SDA pin used by the example board. */
16#define SDA_PIN 6
17/** @brief I2C SCL pin used by the example board. */
18#define SCL_PIN 7
19/** @brief I2C bus speed in hertz. */
20#define I2C_FREQ 400000UL
21/** @brief ICM-20948 I2C address selected by the AD0 pin. */
22#define ICM_ADDR 0x69
23
24// -----------------------------------------------------------
25// STRUCT
26// -----------------------------------------------------------
27/** @brief Accelerometer DLPF divider and timing configuration. */
28struct configDLPF {
29 /** @brief Index into the accelDLPF lookup table. */
30 uint8_t dlpf_idx;
31 /** @brief Sample-rate divider written to the IMU register. */
32 uint16_t div;
33 /** @brief Noise bandwidth in hertz for reporting. */
34 float nbw_hz;
35 /** @brief Output data rate in hertz for timing calculations. */
36 float odr_hz;
37 /** @brief Text label printed with each captured sample. */
38 const char* nombre;
39};
40//id,div,nbw_hz,odr_hz,nombre : {DLPF, NBW , ODR}
41/** @brief Accelerometer DLPF configurations exercised by this sweep. */
43 { 0, 0, 265.0f, 1125.0f, "246 ; 265 ; 1125 " },
44 { 1, 0, 265.0f, 1125.0f, "246 ; 265 ; 1125 " },
45 { 2, 1, 136.0f, 562.5f, "111 ; 136 ; 562 " },
46 { 3, 2, 68.8f, 375.0f, "50 ; 69 ; 375 " },
47 { 4, 7, 34.4f, 140.6f, "24 ; 34 ; 141 " },
48 { 5, 15, 17.0f, 70.3f, "12 ; 17 ; 70 " },
49 { 6, 29, 8.3f, 37.5f, "6 ; 8 ; 35 " },
50 { 7, 0, 499.0f, 1125.0f, "473 ; 499 ; 1125 " },
51};
52/** @brief Number of accelerometer DLPF configurations. */
53const uint8_t N_DLPF = sizeof(configsDLPF) / sizeof(configsDLPF[0]);
54
55// -----------------------------------------------------------
56// ARRAYS ORIGINALES
57// -----------------------------------------------------------
58/** @brief Accelerometer full-scale ranges exercised by the sweep. */
65/** @brief Text labels matching accelCfg. */
66const char* etiquetasAccelCfg[] = { "+-2G","+-4G","+-8G","+-16G" };
67/** @brief Number of accelerometer full-scale ranges. */
68const uint8_t N_FS = 4;
69
70/** @brief Accelerometer DLPF enum values matching configsDLPF. */
81
82/** @brief Accelerometer averaging settings exercised by the sweep. */
89/** @brief Text labels matching accelAVG. */
90const char* etiquetasAccelAVG[] = { "14","8","16","32" };
91/** @brief Number of accelerometer averaging settings. */
92const uint8_t N_AVG = 4;
93/** @brief Raw accelerometer sample-rate divider values for experiments. */
94const uint16_t accelSR[] = {
95 0, 1, 3, 5, 7, 10, 15, 22, 31, 63, 127, 255, 513, 1022, 2044, 4095
96};
97/** @brief Text labels matching accelSR output data rates. */
98const char* etiquetasSR[] = {
99 "1125.0","562.5","281.3","187.5","140.6","102.3","70.3",
100 "48.9","35.2","17.6","8.8","4.4","2.2","1.1","0.55","0.27"
101};
102
103// -----------------------------------------------------------
104/** @brief Global ICM-20948 driver instance. */
106/** @brief Count of validation passes reserved for future checks. */
107uint8_t total_pass = 0;
108/** @brief Count of validation failures reserved for future checks. */
109uint8_t total_fail = 0;
110/** @brief Count of validation warnings reserved for future checks. */
111uint8_t total_warn = 0;
112
113
114/** @brief Print a separator line to Serial. */
115void printLinea() { Serial.println(F("------------------------------------------------------------")); }
116/** @brief Print a double separator line to Serial. */
117void printDobleLinea() { Serial.println(F("============================================================")); }
118// -----------------------------------------------------------
119// WHO_AM_I
120// -----------------------------------------------------------
121/**
122 * @brief Verify the IMU identity register.
123 */
125 uint8_t who;
126 if (!imu.readWhoAmI(who) || who != 0xEA) {
127 Serial.println(F("ERROR: WHO_AM_I mismatch"));
128 while (1) delay(200);
129 }
130 Serial.printf("WHO_AM_I = 0x%02X OK\n", who);
131}
132
133// -----------------------------------------------------------
134// APLICAR CONFIGURACION
135//
136// FIX 1: Se agregan ambas llamadas a setAccelDLPF:
137// Llamada 1 (bypass=false): escribe bits DLPFCFG, deja FCHOICE=0
138// Llamada 2 (bypass=true): activa FCHOICE=1 sin tocar DLPFCFG
139//
140// FIX 2: setAccelDivRate escribe el DIV directo al registro
141// -----------------------------------------------------------
142/**
143 * @brief Apply one accelerometer full-scale, DLPF, and averaging configuration.
144 *
145 * @param fs_idx Index into accelCfg.
146 * @param cfg DLPF timing and divider configuration.
147 * @param avg Index into accelAVG.
148 * @return true if all configuration writes succeeded, otherwise false.
149 */
150bool applySettings(uint8_t fs_idx, const configDLPF &cfg,uint8_t avg) {
151 uint8_t dlpf_val = (uint8_t)accelDLPF[cfg.dlpf_idx];
152 bool ok = true;
153
154 ok &= imu.setAccelScale(accelCfg[fs_idx]);
155
156
157 // Paso 1: escribe DLPFCFG en bits [5:3]
158 ok &= imu.setAccelDLPF(dlpf_val, false);
159
160 ok &= imu.setAccelAveraging(accelAVG[avg]);
161 // Paso 2: activa FCHOICE=1 (DLPF activo) sin tocar DLPFCFG
162 //ok &= imu.setAccelDLPF(0, true);
163
164 // DIV directo al registro, sin conversion interna
165 ok &= imu.setAccelDivRate(cfg.div);
166
167 return ok;
168}
169
170// -----------------------------------------------------------
171// SWEEP — MODO VERIFICACION
172//
173// Por cada configuracion DLPF:
174// 1. Aplica la config (FS fijo en +-2g para verificacion)
175// 2. Espera settle del filtro
176// 3. Imprime 3 lecturas reales
177//
178// Cuando las lecturas muestren Az ~1g en reposo,
179// el sensor esta funcionando y se puede activar el sweep completo.
180// -----------------------------------------------------------
181/**
182 * @brief Run the full accelerometer validation matrix and print samples.
183 */
184void runSweep() {
185
186 uint16_t n = 0;
188 Serial.println(F(" ICM-20948 | UNIT Electronics"));
189 Serial.println(F(" MODO VERIFICACION — FS=+-2g fijo, 3 lecturas por config"));
190 Serial.println(F(" Sensor PLANO y QUIETO | Az esperado: ~+1.000g"));
192 for(uint8_t i = 0; i < N_AVG; i++){
193 for(uint8_t j = 0; j < N_FS;j++){
194 for (uint8_t d = 0; d < N_DLPF; d++) {
195
196 //Serial.println();
197 //printLinea();
198 /*Serial.printf(" Config %d/%d: %s\n", d+1, N_DLPF, configsDLPF[d].nombre);
199 Serial.printf(" ODR=%.1fHz | Periodo=%.1fms\n",
200 configsDLPF[d].odr_hz,
201 1000.0f / configsDLPF[d].odr_hz);*/
202
203 // --- FIX: aplicar la configuracion antes de leer ---
204 bool cfg_ok = applySettings(j, configsDLPF[d],i); // FS=0 → +-2g
205 if (!cfg_ok) {
206 Serial.println(F(" ERROR: applySettings() fallo"));
207 continue;
208 }
209
210 // Esperar que el filtro estabilice (10 periodos del ODR, min 50ms)
211 uint32_t settle_ms = max((uint32_t)(10000.0f / configsDLPF[d].odr_hz),
212 (uint32_t)50);
213 delay(settle_ms);
214
215 // Tomar 3 lecturas espaciadas por el periodo del ODR
216 uint32_t periodo_ms = max((uint32_t)(1000.0f / configsDLPF[d].odr_hz),
217 (uint32_t)1);
218 float ax, ay, az;
219 for (uint8_t r = 0; r < 100; r++) {
220 n++;
221 delay(periodo_ms);
222 if (imu.readAccel(ax, ay, az)) {
223 Serial.printf("%d ; %s ; %s ; %s ; %+.4f ; %+.4f ; %+.4f\n",
224 n,
225 configsDLPF[d].nombre, // "246 ; 265 ; 1125"
226 etiquetasAccelCfg[i], // "+-2G"
227 etiquetasAccelAVG[j], // "8"
228 ax, ay, az);
229 } else {
230 Serial.println(F(" [?] readAccel() fallo"));
231 }
232 }
233 }
234 }
235 }
236 Serial.println();
238 Serial.println(F(" VERIFICACION COMPLETA"));
239 Serial.println(F(" Si Az ~ +1.0g en todos los bloques:"));
240 Serial.println(F(" el sensor funciona correctamente."));
241 Serial.println(F(" Activar sweep completo cuando este listo."));
243}
244
245// -----------------------------------------------------------
246// SETUP
247// -----------------------------------------------------------
248/**
249 * @brief Initialize I2C, reset/wake the IMU, enable sensors, and start sweep.
250 */
251void setup() {
252 Serial.begin(115200);
253 delay(200);
254 Serial.println(F("ICM-20948 — Verificacion"));
255
257 Serial.println(F(" ICM-20948 VALIDACION ACELEROMETRO"));
259
260 Wire.begin(SDA_PIN, SCL_PIN);
261
262 if (!imu.beginI2C(ICM_ADDR, Wire, I2C_FREQ)) {
263 Serial.println(F("ERROR: beginI2C() fallo"));
264 while (1) delay(200);
265 }
266
267 firstStage();
268
269 // softReset pone el chip a dormir
270 // Despues del reset hay que despertar el dispositivo
271 imu.softReset();
272 delay(100);
273 imu.sleep(false); // limpia SLEEP bit, CLKSEL=1
274 delay(50);
275
276 if (!imu.setSensors(true, true, true)) {
277 Serial.println(F("ERROR: setSensors() fallo"));
278 }
279
280 Serial.println(F(" Sensor listo.\n"));
281 Serial.println(F(" Sensor PLANO y QUIETO sobre la mesa."));
282 Serial.println(F(" Iniciando en 5 segundos..."));
283 for (int i = 5; i > 0; i--) {
284 Serial.printf(" %d...\n", i);
285 delay(1000);
286 }
287
288 //for (int runs = 0; runs < 20 ; runs++){
289 runSweep();
290 //}
291}
292
293// -----------------------------------------------------------
294// LOOP — lectura simple post-sweep
295// -----------------------------------------------------------
296/**
297 * @brief Optional post-sweep loop for manual accelerometer reads.
298 */
299void loop() {
300 /*float ax, ay, az;
301 if (imu.readAccel(ax, ay, az)) {
302 Serial.printf("X:%+.3f Y:%+.3f Z:%+.3f\n", ax, ay, az);
303 }
304 delay(500);*/
305}
ICM20948_Accel_DLPFCFG
ICM20948_Accel_Average
ICM20948_Accel_FullScale
bool setAccelScale(ICM20948_Accel_FullScale fullScale)
bool readAccel(float &x, float &y, float &z)
bool sleep(bool en)
bool setAccelAveraging(ICM20948_Accel_Average avg)
bool readWhoAmI(uint8_t &whoAmI)
bool beginI2C(uint8_t address=0x69, TwoWire &i2cPort=Wire, uint32_t i2cSpeed=400000)
bool setAccelDLPF(uint8_t dlpf, bool bypass)
bool setAccelDivRate(uint16_t divisor)
bool setSensors(bool accel_on, bool gyro_on, bool temp_on)
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
#define SCL_PIN
I2C SCL pin used by the example board.
Definition test2.ino:18
const uint8_t N_AVG
Number of accelerometer averaging settings.
Definition test2.ino:92
const char * etiquetasAccelCfg[]
Text labels matching accelCfg.
Definition test2.ino:66
const ICM20948_Accel_DLPFCFG accelDLPF[]
Accelerometer DLPF enum values matching configsDLPF.
Definition test2.ino:71
uint8_t total_fail
Count of validation failures reserved for future checks.
Definition test2.ino:109
void firstStage()
Verify the IMU identity register.
Definition test2.ino:124
const char * etiquetasAccelAVG[]
Text labels matching accelAVG.
Definition test2.ino:90
void printDobleLinea()
Print a double separator line to Serial.
Definition test2.ino:117
const ICM20948_Accel_Average accelAVG[]
Accelerometer averaging settings exercised by the sweep.
Definition test2.ino:83
void setup()
Initialize I2C, reset/wake the IMU, enable sensors, and start sweep.
Definition test2.ino:251
#define SDA_PIN
I2C SDA pin used by the example board.
Definition test2.ino:16
void runSweep()
Run the full accelerometer validation matrix and print samples.
Definition test2.ino:184
const uint8_t N_FS
Number of accelerometer full-scale ranges.
Definition test2.ino:68
const uint8_t N_DLPF
Number of accelerometer DLPF configurations.
Definition test2.ino:53
void printLinea()
Print a separator line to Serial.
Definition test2.ino:115
#define I2C_FREQ
I2C bus speed in hertz.
Definition test2.ino:20
#define ICM_ADDR
ICM-20948 I2C address selected by the AD0 pin.
Definition test2.ino:22
const configDLPF configsDLPF[]
Accelerometer DLPF configurations exercised by this sweep.
Definition test2.ino:42
DevLab_ICM20948 imu
Global ICM-20948 driver instance.
Definition test2.ino:105
const char * etiquetasSR[]
Text labels matching accelSR output data rates.
Definition test2.ino:98
uint8_t total_pass
Count of validation passes reserved for future checks.
Definition test2.ino:107
uint8_t total_warn
Count of validation warnings reserved for future checks.
Definition test2.ino:111
const uint16_t accelSR[]
Raw accelerometer sample-rate divider values for experiments.
Definition test2.ino:94
const ICM20948_Accel_FullScale accelCfg[]
Accelerometer full-scale ranges exercised by the sweep.
Definition test2.ino:59
void loop()
Optional post-sweep loop for manual accelerometer reads.
Definition test2.ino:299