DevLab_ICM20948 1.0.2
ICM-20948 9-Axis Motion Sensor Driver
Loading...
Searching...
No Matches
test.ino
Go to the documentation of this file.
1/**
2 * @file test.ino
3 * @author Jonathan Mejorado Lopez
4 * @brief Accelerometer DLPF validation sketch for the 7Semi ICM-20948.
5 * @details Runs an I2C accelerometer sweep across DLPF settings, prints sample
6 * data to Serial, and is intended for bench validation with the sensor flat and
7 * stationary.
8 */
9
10#include <Wire.h>
11#include <DevLab_ICM20948.h>
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 // Fast Mode 400 kHz
21
22// -----------------------------------------------------------
23// DIRECCIONES I2C
24// -----------------------------------------------------------
25/** @brief ICM-20948 I2C address selected by the AD0 pin. */
26#define ICM_ADDR 0x69 // AD0 = LOW (GND)
27
28/** @brief Accelerometer DLPF divider and timing configuration. */
29struct configDLPF {
30 /** @brief Index into the accelDLPF lookup table. */
31 uint8_t dlpf_idx;
32 /** @brief Sample-rate divider written to the IMU register. */
33 uint16_t div; // el valor REAL del registro, 0-4095, sin ambigüedad
34 /** @brief Noise bandwidth in hertz for reporting. */
35 float nbw_hz;
36 /** @brief Output data rate in hertz for timing calculations. */
37 float odr_hz; // = 1125.0f / (1 + div), para calcular tiempos
38 /** @brief Text label printed with each captured sample. */
39 const char* nombre;
40};
41
42/** @brief Accelerometer DLPF configurations exercised by this validation. */
44 // idx div NBW(Hz) ODR(Hz) nombre
45 { 0, 0, 265.0f, 1125.0f, "DLPF0_246 | NBW=265Hz | ODR=1125Hz (4.2x)" },
46 { 1, 0, 265.0f, 1125.0f, "DLPF_246 | NBW=265Hz | ODR=1125Hz (4.2x)" },
47 { 2, 1, 136.0f, 562.5f, "DLPF_111 | NBW=136Hz | ODR= 562Hz (4.1x)" },
48 { 3, 3, 68.8f, 281.3f, "DLPF_50 | NBW= 69Hz | ODR= 281Hz (4.1x)" },
49 { 4, 7, 34.4f, 140.6f, "DLPF_24 | NBW= 34Hz | ODR= 141Hz (4.1x)" },
50 { 5, 15, 17.0f, 70.3f, "DLPF_12 | NBW= 17Hz | ODR= 70Hz (4.1x)" },
51 { 6, 31, 8.3f, 35.2f, "DLPF_6 | NBW= 8Hz | ODR= 35Hz (4.2x)" },
52 { 7, 0, 499.0f, 1125.0f, "DLPF_473 | NBW=499Hz | ODR=1125Hz (2.3x)" },
53};
54//------------------------------------------------------
55// ARRAYS DE CONFIGURACIÓN
56// -----------------------------------------------------------
57/** @brief Number of accelerometer DLPF configurations. */
58const uint8_t N_DLPF = sizeof(configsDLPF) / sizeof(configsDLPF[0]);
59
60/** @brief Accelerometer full-scale ranges available for validation. */
62/** @brief Text labels matching accelCfg. */
63const char* etiquetasAccelCfg[] = {"+-2G","+-4G", "+-8G", "+-16G"};
64/** @brief Number of accelerometer full-scale ranges. */
65const uint8_t N_FS = 4;
66
67/** @brief Accelerometer DLPF enum values matching configsDLPF. */
69/** @brief Text labels describing accelDLPF bandwidth pairs. */
70const char* etiquetasAccelDLPFCFG[] = { "246/265", "246/265", "111/136", "50.4/68.8","23.9/34.4", "11.5/17.0", "5.7/8.3","473/499"};
71
72/** @brief Accelerometer averaging settings available for validation. */
74/** @brief Text labels matching accelAVG. */
75const char* etiquetasAccelAVG[] = {"1 OR 4","8","16","32"};
76
77/** @brief Raw accelerometer sample-rate divider values for experiments. */
78const uint16_t accelSR[] = {0, 1, 3, 5, 7 , 10, 15, 22, 31, 63, 127, 255, 513, 1022, 2044, 4095};
79/** @brief Text labels matching accelSR output data rates. */
80const char* etiquetasSR[] = { "1125.0","562.5", "281.3", "187.5","140.6", "102.3", "70.3", "48.9", "35.2", "17.6", "8.8", "4.4", "2.2", "1.1", "0.55", "0.27"};
81// -----------------------------------------------------------
82// INSTANCIA DEL SENSOR
83// -----------------------------------------------------------
84/** @brief Global ICM-20948 driver instance. */
86
87/** @brief Count of validation passes reserved for future checks. */
88uint8_t total_pass = 0;
89/** @brief Count of validation failures reserved for future checks. */
90uint8_t total_fail = 0;
91/** @brief Count of validation warnings reserved for future checks. */
92uint8_t total_warn = 0;
93
94// ============================================================
95// UTILIDADES DE IMPRESIÓN
96// ============================================================
97
98/** @brief Print a separator line to Serial. */
99void printLinea() {
100 Serial.println(F("------------------------------------------------------------"));
101}
102
103/** @brief Print a double separator line to Serial. */
105 Serial.println(F("============================================================"));
106}
107
108/**
109 * @brief Apply one accelerometer full-scale and DLPF configuration.
110 *
111 * @param fs_idx Index into accelCfg.
112 * @param cfg DLPF timing and divider configuration.
113 * @return true if all configuration writes succeeded, otherwise false.
114 */
115bool applySettings(uint8_t fs_idx,const configDLPF &cfg){
116 uint8_t dlpf_val = (uint8_t)accelDLPF[cfg.dlpf_idx];
117 bool ok = true;
118
119 ok &= imu.setAccelScale(accelCfg[fs_idx]);
120
121 ok &= imu.setAccelDLPF(dlpf_val,false);
122
123 ok &= imu.setAccelDivRate(cfg.div);
124
125 return ok;
126}
127
128
129/**
130 * @brief Verify the IMU identity register.
131 */
133 uint8_t who;
134 if (!imu.readWhoAmI(who) || who != 0xEA) {
135 Serial.println(F("ERROR: WHO_AM_I mismatch"));
136 while (1) delay(200);
137 }
138 Serial.print(F("WHO_AM_I = 0x"));
139 Serial.println(who, HEX);
140}
141
142/**
143 * @brief Run the accelerometer DLPF validation sweep and print samples.
144 */
145void runSweep(){
147 Serial.println("Acelerometro ICM-200948 | UNIT Electronics");
148 Serial.printf("%d DLPFS x %d FS = %d combinaciones\n",N_DLPF,N_FS,N_DLPF * N_FS);
149 Serial.println(F("Coloque el sensor plano y quieto mirando hacia arriba"));
151 for(uint8_t d = 0; d < N_DLPF; d++){
152 Serial.printf(" BLOQUE %d/%d: %s\n", d+1, N_DLPF,configsDLPF[d].nombre);
153 Serial.printf(" ODR = %.1fHz | Delay = %lums | Periodo= %.1fms\n",configsDLPF[d].odr_hz,max((uint32_t)(10000.0f/configsDLPF[d].odr_hz),(uint32_t)50),
154 1000.0f/configsDLPF[d].odr_hz);
156 bool cfg_ok = applySettings(configsDLPF[d].dlpf_idx, configsDLPF[d]);
157 if (!cfg_ok) {
158 Serial.println(F(" ERROR: applySettings() fallo"));
159 continue;
160 }
161 // Esperar que el filtro estabilice (10 periodos del ODR, min 50ms)
162 uint32_t settle_ms = max((uint32_t)(10000.0f / configsDLPF[d].odr_hz),
163 (uint32_t)50);
164 delay(settle_ms);
165
166
167 // Tomar 3 lecturas espaciadas por el periodo del ODR
168 uint32_t periodo_ms = max((uint32_t)(1000.0f / configsDLPF[d].odr_hz),
169 (uint32_t)1);
170 float ax, ay, az;
171 for (uint8_t r = 0; r < 3; r++) {
172 delay(periodo_ms);
173 if (imu.readAccel(ax, ay, az)) {
174 Serial.printf(" [%d] Ax=%+.3f Ay=%+.3f Az=%+.3f g\n",
175 r+1, ax, ay, az);
176 } else {
177 Serial.println(F(" [?] readAccel() fallo"));
178 }
179 }
180 printLinea();
181 }
182}
183
184/**
185 * @brief Initialize I2C, reset/wake the IMU, enable sensors, and start sweep.
186 */
187void setup() {
188
189 Serial.begin(115200);
190 delay(200);
191 Serial.println(F("ICM-20948 — I2C Basic"));
193 Serial.println(F(" ICM-20948 VALIDACION ACELEROMETRO"));
195 // I2C init (UNO/ESP32 defaults). For ESP32 custom pins: Wire.begin(SDA,SCL);
196 Wire.begin(SDA_PIN,SCL_PIN);
197 // Attach IMU
198 if (!imu.beginI2C(ICM_ADDR,Wire,I2C_FREQ)) {
199 Serial.println(F("ERROR: begin(I2C) failed"));
200 while (1) delay(200);
201 }
202
203 firstStage();
204
205 imu.softReset();
206
207 imu.sleep(false);
208 delay(50);
209 /* Enable all sensors. */
210 if (!imu.setSensors(true, true, true)) {
211 Serial.println(F("ERROR: setSensors failed"));
212 }
213 Serial.println(F(" Sensor listo.\n"));
214 Serial.println(F(" Sensor PLANO y QUIETO sobre la mesa."));
215 Serial.println(F(" Iniciando en 5 segundos..."));
216 for (int i = 5; i > 0; i--) {
217 Serial.printf(" %d...\n", i);
218 delay(1000);
219 }
220 runSweep();
221}
222
223/**
224 * @brief Optional post-sweep loop for manual accelerometer reads.
225 */
226void loop() {
227 /*float ax, ay, az;
228 if (imu.readAccel(ax, ay, az)) {
229 Serial.printf("X:%.3f Y:%.3f Z:%.3f\n", ax, ay, az);
230 }
231 delay(200);*/
232}
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 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 test.ino:18
const char * etiquetasAccelCfg[]
Text labels matching accelCfg.
Definition test.ino:63
const ICM20948_Accel_DLPFCFG accelDLPF[]
Accelerometer DLPF enum values matching configsDLPF.
Definition test.ino:68
uint8_t total_fail
Count of validation failures reserved for future checks.
Definition test.ino:90
void firstStage()
Verify the IMU identity register.
Definition test.ino:132
const char * etiquetasAccelAVG[]
Text labels matching accelAVG.
Definition test.ino:75
void printDobleLinea()
Print a double separator line to Serial.
Definition test.ino:104
const ICM20948_Accel_Average accelAVG[]
Accelerometer averaging settings available for validation.
Definition test.ino:73
void setup()
Initialize I2C, reset/wake the IMU, enable sensors, and start sweep.
Definition test.ino:187
#define SDA_PIN
I2C SDA pin used by the example board.
Definition test.ino:16
void runSweep()
Run the accelerometer DLPF validation sweep and print samples.
Definition test.ino:145
const uint8_t N_FS
Number of accelerometer full-scale ranges.
Definition test.ino:65
const uint8_t N_DLPF
Number of accelerometer DLPF configurations.
Definition test.ino:58
const char * etiquetasAccelDLPFCFG[]
Text labels describing accelDLPF bandwidth pairs.
Definition test.ino:70
void printLinea()
Print a separator line to Serial.
Definition test.ino:99
#define I2C_FREQ
I2C bus speed in hertz.
Definition test.ino:20
#define ICM_ADDR
ICM-20948 I2C address selected by the AD0 pin.
Definition test.ino:26
const configDLPF configsDLPF[]
Accelerometer DLPF configurations exercised by this validation.
Definition test.ino:43
DevLab_ICM20948 imu
Global ICM-20948 driver instance.
Definition test.ino:85
const char * etiquetasSR[]
Text labels matching accelSR output data rates.
Definition test.ino:80
uint8_t total_pass
Count of validation passes reserved for future checks.
Definition test.ino:88
uint8_t total_warn
Count of validation warnings reserved for future checks.
Definition test.ino:92
const uint16_t accelSR[]
Raw accelerometer sample-rate divider values for experiments.
Definition test.ino:78
const ICM20948_Accel_FullScale accelCfg[]
Accelerometer full-scale ranges available for validation.
Definition test.ino:61
void loop()
Optional post-sweep loop for manual accelerometer reads.
Definition test.ino:226