Skip to Content

Primeros pasos con XIAO MG24 Sense

Primeros pasos con XIAO MG24 Sense

El XIAO MG24 Sense es una de las placas de la serie XIAO de Seeed Studio, que combina un potente microcontrolador Silicon Labs EFR32MG24 con sensores integrados como un micrófono y una IMU de 6 ejes. Gracias a su pequeño factor de forma, diseño de bajo consumo y capacidades inalámbricas integradas, es una excelente opción para proyectos de IoT, fusión de sensores y edge AI.

En esta guía, repasaremos los conceptos básicos para comenzar con el XIAO MG24 Sense. Empezaremos instalando el core necesario para la placa, luego ejecutaremos el clásico ejemplo Blink para confirmar que todo funciona. Después exploraremos sus características principales: el micrófono integrado y la IMU (Unidad de Medición Inercial).

Partes necesarias

Necesitarás una placa XIAO MG24 Sense de Seeed Studio y un cable USB-C para programar la placa y probar los ejemplos de código.

Seeed Studio XIAO MG24 Sense

Cable USB-C

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

El XIAO MG24 Sense

El XIAO MG24 Sense está potenciado por el sistema en chip Silicon Labs EFR32MG24, que utiliza un microcontrolador ARM Cortex-M33 funcionando hasta a 78 MHz. Esto le proporciona suficiente capacidad de procesamiento para proyectos embebidos generales, manteniendo una alta eficiencia energética. Una característica destacada de este chip es el Matrix-Vector Processor (MVP), un pequeño acelerador de hardware que acelera las operaciones matemáticas necesarias en machine learning. Esto hace que el MG24 Sense sea especialmente adecuado para aplicaciones TinyML, como detección de palabras clave o clasificación de movimientos, sin agotar la batería rápidamente.

Components of XIAO MG24 Sense
Componentes del XIAO MG24 Sense

En cuanto a memoria, la placa incluye 1,5 MB de flash y 256 kB de RAM integrados en el microcontrolador. Además, Seeed Studio ha añadido un chip flash SPI externo de 4 MB, útil para almacenar programas más grandes, datos de modelos o incluso registros. La combinación de memoria interna y externa te da espacio para experimentar con aplicaciones más complejas manteniendo un factor de forma pequeño.

La conectividad inalámbrica es otra fortaleza de este dispositivo. El MG24 soporta Matter sobre Thread así como Bluetooth Low Energy 5.3, asegurando compatibilidad con ecosistemas IoT modernos y conectividad con smartphones. La placa también incluye características de seguridad hardware Secure Vault, que protegen datos sensibles como claves de cifrado y permiten un arranque seguro.

Sensores

El “Sense” en el nombre de la placa proviene de sus sensores integrados. Primero, está la IMU LSM6DS3TR-C, un sensor de seis ejes que combina un acelerómetro de tres ejes con un giroscopio de tres ejes. Este sensor puede medir movimiento, orientación, pasos y gestos, e incluso incluye modos de bajo consumo para detección continua de actividad sin un alto gasto energético. Puedes encontrar más detalles en la hoja de datos enlazada abajo:

Además de la IMU, está el micrófono MEMS MSM381ACT001, que permite capturar sonido. Aunque es un micrófono analógico, el ADC del microcontrolador facilita muestrear y procesar audio, ya sea para detección de sonido o interacciones activadas por voz. Consulta la hoja de datos a continuación:

GPIO

Para la interfaz de hardware, el XIAO MG24 Sense expone 19 pines de entrada/salida general (GPIO), dispuestos en el formato familiar de XIAO. Estos pines pueden usarse para I²C, SPI, UART y otras interfaces estándar.

Pinout of XIAO MG24 Sense
Pinout del XIAO MG24 Sense

También hay un LED de usuario y un LED de alimentación/carga para ayudar con la depuración y proporcionar retroalimentación rápida. La carga de código se realiza vía el conector USB-C, que también funciona como interfaz de alimentación y carga.

Alimentación

La eficiencia energética es uno de los aspectos más fuertes del XIAO MG24 Sense. En modos de sueño profundo, el microcontrolador puede reducir su consumo a solo un par de microamperios, ideal para proyectos alimentados por batería. La placa incluye un circuito de carga para baterías Li-Po y puede medir el voltaje de la batería para que tus proyectos monitoreen sus niveles de energía. Con estas características, el MG24 Sense es una excelente opción para nodos IoT operados a batería a largo plazo.

Battery connector of XIAO MG24 Sense
Conector de batería del XIAO MG24 Sense

Tamaño

A pesar de incluir todas estas características, la placa mantiene el clásico factor de forma XIAO de solo 21 × 17,8 mm, facilitando su integración en proyectos compactos o wearables. Incluye una antena integrada para comunicación inalámbrica, por lo que no necesitas módulos adicionales para comenzar.

En resumen, el XIAO MG24 Sense combina un microcontrolador potente y eficiente, conectividad inalámbrica moderna, hardware seguro, sensores integrados de movimiento y audio, memoria generosa y un diseño amigable con baterías en un paquete muy pequeño.

Especificaciones técnicas

CaracterísticaEspecificación
ProcesadorSilicon Labs EFR32MG24, ARM Cortex-M33, hasta 78 MHz
Acelerador hardwareMatrix-Vector Processor (MVP) para cargas de ML
Memoria interna1536 kB flash, 256 kB RAM
Memoria externa4 MB flash SPI
InalámbricoMatter (Thread), Bluetooth Low Energy 5.3
SeguridadMotor de seguridad hardware Secure Vault
IMULSM6DS3TR-C, acelerómetro + giroscopio de 6 ejes
MicrófonoMicrófono MEMS analógico MSM381ACT001
GPIO19 pines (I²C, SPI, UART, GPIO, etc.)
USBUSB-C para programación, alimentación y carga
Características de bateríaCircuito de carga integrado, monitorización de voltaje de batería
Eficiencia energéticaUltra bajo consumo, corriente en modo sueño de ~1.95 µA
Factor de forma21 × 17,8 mm, antena integrada

XIAO MG24 Sense versus XIAO MG24

Seeed Studio ofrece dos versiones muy relacionadas de esta placa: la XIAO MG24 y la XIAO MG24 Sense. Ambas comparten la misma base, construida alrededor del microcontrolador EFR32MG24 con núcleo ARM Cortex-M33, Matrix-Vector Processor para machine learning y soporte para estándares inalámbricos modernos como Matter (Thread) y Bluetooth Low Energy 5.3. También comparten el mismo compacto factor de forma XIAO, la misma memoria flash externa de 4 MB y el mismo diseño de bajo consumo con circuito de carga integrado para baterías Li-Po.

La principal diferencia radica en las capacidades de detección. La XIAO MG24 Sense integra dos sensores adicionales a bordo: la IMU de 6 ejes LSM6DS3TR-C y el micrófono MEMS analógico MSM381ACT001. Estas adiciones permiten a la versión Sense detectar movimiento, orientación y sonido desde el primer momento, convirtiéndola en una opción mucho más potente para proyectos que involucren reconocimiento de gestos, entrada de audio o fusión de sensores. En cambio, la XIAO MG24 estándar no incluye estos sensores, lo que la hace un poco más económica y más adecuada si solo necesitas el microcontrolador, funciones inalámbricas y pines de E/S.

Otra pequeña distinción está en los casos de uso previstos. La XIAO MG24 está diseñada como una placa IoT de ultra bajo consumo para uso general, mientras que la XIAO MG24 Sense está orientada más a proyectos de edge AI y detección inteligente donde el movimiento y el audio juegan un papel. Si tu proyecto involucra cosas como detección de palabras clave TinyML, seguimiento de actividad física, control por gestos o eventos activados por sonido, la versión Sense te ahorrará el esfuerzo de conectar sensores externos. Si, por otro lado, quieres una placa base simple y económica para nodos IoT inalámbricos o redes de sensores, la MG24 sin Sense podría ser todo lo que necesitas.

XIAO MG24 versus ESP32

El ESP32 es bien conocido en la comunidad maker por combinar un procesador Xtensa LX6/LX7 de doble núcleo (o a veces núcleo único, según la variante) funcionando hasta a 240 MHz con conectividad Wi-Fi y Bluetooth. Esto lo hace especialmente atractivo para proyectos que requieren mayor potencia de procesamiento o conectividad a internet vía Wi-Fi. El ESP32 también tiene cantidades generosas de RAM (a menudo 520 kB SRAM, con PSRAM externa disponible en algunos módulos) y memoria flash, haciéndolo adecuado para aplicaciones como servidores web, streaming de audio en tiempo real o interfaces de usuario complejas. Su ecosistema es vasto, con excelente soporte comunitario, numerosos tutoriales y compatibilidad con plataformas como Arduino, ESP-IDF y MicroPython.

En contraste, el EFR32MG24 usado en el XIAO MG24 se enfoca en bajo consumo, estándares inalámbricos modernos y seguridad. Funciona a una velocidad de reloj menor (hasta 78 MHz) y tiene menos RAM, pero incluye el Matrix-Vector Processor (MVP) para acelerar tareas de machine learning. En lugar de Wi-Fi, soporta Matter (Thread) y Bluetooth Low Energy 5.3, ambos muy relevantes para aplicaciones de hogar inteligente e IoT donde el bajo consumo y las redes malladas son importantes. El MG24 también integra las características Secure Vault de Silicon Labs, ofreciendo cifrado a nivel hardware y arranques seguros.

En resumen, el ESP32 es más adecuado para aplicaciones que requieren conectividad Wi-Fi, mayor potencia de procesamiento o grandes cantidades de memoria, mientras que el MG24 está diseñado para nodos IoT alimentados por batería, dispositivos sensores y aplicaciones que requieren alta seguridad y estándares inalámbricos modernos. Ambos son compatibles con Arduino, pero el ESP32 se beneficia de una comunidad y ecosistema más grandes, mientras que el MG24 es una opción sólida para desarrolladores interesados en Matter, BLE 5.3 y operación ultra baja en consumo.

Tabla comparativa

CaracterísticaXIAO MG24 (EFR32MG24)ESP32 (variantes típicas)
ProcesadorARM Cortex-M33, hasta 78 MHzXtensa LX6/LX7, núcleo único o doble, hasta 240 MHz
Acelerador hardwareMVP (Matrix-Vector Processor para ML)Ninguno (algunas variantes ESP32 incluyen coprocesadores AI/ML, p.ej., ESP32-S3 con instrucciones vectoriales)
Memoria interna1536 kB flash, 256 kB RAM~448–520 kB SRAM, PSRAM externa en algunos módulos
Memoria externa4 MB flash SPI (en placa XIAO)Típicamente 4–16 MB flash, PSRAM opcional
InalámbricoMatter (Thread), Bluetooth 5.3Wi-Fi 2.4 GHz, Bluetooth 4.2/5.0 (según variante)
SeguridadHardware Secure Vault (arranque seguro, almacenamiento de claves)Arranque seguro, cifrado de flash (varía según variante)
EcosistemaSoportado en Arduino, SDKs oficiales de Silicon LabsArduino, ESP-IDF, MicroPython, CircuitPython, gran comunidad
Eficiencia energéticaUltra bajo consumo, corriente en modo sueño en rango de µAModos de bajo consumo disponibles, pero con consumo típicamente mayor
Más adecuado paraNodos IoT de bajo consumo, dispositivos Matter/Thread, aplicaciones BLEProyectos con Wi-Fi, servidores web, streaming en tiempo real, proyectos maker de propósito general

Instalación del Core

Antes de poder programar el XIAO MG24 o XIAO MG24 Sense con el IDE de Arduino, necesitas instalar el core de la placa. Pero, ¿qué es exactamente un core de placa?

Un core en el ecosistema Arduino es esencialmente un conjunto de archivos de software que permite al IDE de Arduino entender y comunicarse con un tipo específico de microcontrolador. Incluye el compilador, linker, archivos de inicio, librerías y definiciones de placa necesarias para compilar y cargar código en ese microcontrolador. Sin un core, el IDE de Arduino no sabría cómo convertir tus sketches en código máquina que el microcontrolador pueda ejecutar.

Añadir URL a Preferencias

El XIAO MG24 usa el microcontrolador Silicon Labs EFR32MG24, que no está incluido en la instalación por defecto de Arduino. Para añadir soporte para esta placa, sigue estos pasos.

Primero, abre el IDE de Arduinoy ve a Archivo → Preferencias:

Luego, en el campo URLs adicionales del Gestor de Placas, añade la URL para el paquete de Seeed Studio. La URL actual es:

https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json

Puedes añadir la URL como texto en el campo de edición. Si ya tienes otras URLs listadas, sepáralas con una coma.

O haz clic en el icono a la derecha, que abre un editor separado donde puedes añadir la URL. En la captura de pantalla abajo puedes ver que ya he instalado el core ESP8266 y el core ESP32 también:

Instalar placas

Luego, abre el Gestor de Placas yendo a Herramientas → Placa → Gestor de Placas…y escribe «MG24» en la barra de búsqueda. Verás Silicon Labsy un texto que lista la placa soportada. Pulsa el botón INSTALL. La captura de pantalla abajo muestra cómo se ve después de instalar el core (el botón INSTALLse convierte en un botón REMOVE ):

Una vez instalado, selecciona una placa desde el selector desplegable bajo la barra de menú: en el ejemplo abajo se muestra Arduino Uno como placa seleccionada, por ejemplo:

Bord selector

Al hacer clic en el nombre de la placa actualmente seleccionada (Arduino Uno), se abrirá el diálogo de selección de placa. En el cuadro de búsqueda escribe «mg24» y selecciona «Seeed Studio XIAO MG24 (Sense)» como se muestra abajo:

Si la placa está conectada a tu PC vía USB, también deberías poder seleccionar el puerto COM. En la captura de pantalla arriba es COM8, pero en tu caso podría ser otro puerto COM.

Después de la instalación, el IDE de Arduino trata al MG24 como cualquier otra placa soportada. Puedes acceder a librerías, usar GPIO, I²C, SPI, ADC e incluso aprovechar ejemplos integrados para la placa, como el clásico sketch Blink, que implementaremos en la siguiente sección.

Código Blink

Una vez instalado el core para el MG24, probémoslo para ver si realmente funciona. Usamos el programa común Blink para nuestra prueba. A continuación está el código:

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  Serial.println("OFF");
  digitalWrite(LED_BUILTIN, HIGH);  
  delay(1000);                      

  Serial.println("ON");
  digitalWrite(LED_BUILTIN, LOW);   
  delay(1000);   

Hace parpadear el LED integrado cada segundo y también imprime el estado del LED en el monitor serial. Nota que la lógica está invertida. Escribir un valor HIGH en el pin del LED hace que el LED se apague y viceversa.

Sube el código a tu placa pulsando el icono de subir en el IDE de Arduino. Asegúrate de tener seleccionada la placa correcta (Seeed Studio XIAO MG24):

Deberías ver el siguiente estado de compilación y programación en la terminal de salida. No te dejes engañar por el color rojo. Si puedes leer «** Programming Finished **» todo está bien.

Luego cambia a la salida del monitor serial. Deberías ver una secuencia de mensajes «ON» y «OFF» apareciendo. Al mismo tiempo, el LED naranja de la placa XIAO MG24 debería estar parpadeando.

Si todo esto funciona, ¡felicidades, ya puedes programar tu XIAO MG24 Sense ; )

En las siguientes secciones probaremos la Unidad de Medición Inercial (IMU) y el micrófono del XIAO MG24 Sense.

Código IMU

El siguiente sketch muestra cómo leer datos de movimiento del LSM6DS3, una IMU de 6 ejes que combina un acelerómetro de 3 ejes y un giroscopio de 3 ejes.

Antes de poder ejecutarlo, necesitarás instalar la Seeed_Arduino_LSM6DS3 librería. Descarga la librería como archivo .ZIP desde el repositorio de Github e instálala vía Sketch → Include Library → Add .ZIP Library …

El programa de ejemplo inicializa el sensor, verifica errores y continuamente imprime las lecturas de aceleración y giroscopio en el monitor serial. Vamos a repasar el código paso a paso.

#include <LSM6DS3.h>
#include <Wire.h>

LSM6DS3 myIMU(I2C_MODE, 0x6A);  

void setup() {
  Serial.begin(115200);

  pinMode(PD5, OUTPUT);
  digitalWrite(PD5, HIGH);

  if (myIMU.begin() != 0) {
    Serial.println("Device error");
  } 
}

void loop() {
    Serial.print(myIMU.readFloatAccelX(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatAccelY(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatAccelZ(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatGyroX(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatGyroY(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatGyroZ(), 3);
    Serial.println();
    delay(500);
}

Importaciones

El sketch comienza incluyendo dos librerías esenciales. La primera es <LSM6DS3.h>, que proporciona una interfaz sencilla para la IMU LSM6DS3. La segunda es <Wire.h>, que habilita la comunicación I2C entre Arduino y el sensor. Sin estas, Arduino no puede comunicarse con la IMU.

#include <LSM6DS3.h>
#include <Wire.h>

Objetos

Después de las importaciones, el sketch crea un objeto llamado myIMU de la clase LSM6DS3. El constructor indica al programa usar comunicación I2C y establece la dirección I2C del sensor en 0x6A. Esta dirección depende de cómo estén conectados los pines del sensor y debe coincidir con la configuración hardware.

LSM6DS3 myIMU(I2C_MODE, 0x6A);

Setup

La función setup() se ejecuta una vez al inicio. Comienza abriendo el puerto serial a 115200 baudios para poder ver los datos del sensor en el Monitor Serial del IDE de Arduino.

Serial.begin(115200);

Luego, el código configura el pin PD5 como salida y lo pone en HIGH. Esto se usa para habilitar la IMU.

pinMode(PD5, OUTPUT);
digitalWrite(PD5, HIGH);

Finalmente, el sketch inicializa la IMU llamando a myIMU.begin(). Si la función devuelve un valor distinto de cero, el programa imprime "Device error" en el Monitor Serial, indicando que el sensor no pudo ser detectado o inicializado correctamente.

if (myIMU.begin() != 0) {
  Serial.println("Device error");
}

Loop

La función loop() se ejecuta continuamente después del setup. En cada ciclo, el sketch lee datos de aceleración y giroscopio de la IMU y los imprime en el Monitor Serial en formato separado por comas.

Las lecturas del acelerómetro se toman en las direcciones X, Y y Z. Cada llamada a readFloatAccelX(), readFloatAccelY() y readFloatAccelZ() devuelve un valor flotante en g’s, que mide la aceleración relativa a la gravedad. El segundo argumento 3 indica al Monitor Serial imprimir tres dígitos después del punto decimal.

Serial.print(myIMU.readFloatAccelX(), 3);
Serial.print(',');
Serial.print(myIMU.readFloatAccelY(), 3);
Serial.print(',');
Serial.print(myIMU.readFloatAccelZ(), 3);

Luego, se leen los valores del giroscopio en las direcciones X, Y y Z. Las funciones readFloatGyroX(), readFloatGyroY() y readFloatGyroZ() devuelven la velocidad angular en grados por segundo. Nuevamente, el sketch imprime cada valor con tres decimales, separados por comas.

Serial.print(',');
Serial.print(myIMU.readFloatGyroX(), 3);
Serial.print(',');
Serial.print(myIMU.readFloatGyroY(), 3);
Serial.print(',');
Serial.print(myIMU.readFloatGyroZ(), 3);

Al final de cada ciclo, el sketch imprime un salto de línea para que cada conjunto completo de lecturas aparezca en su propia línea. Luego pausa 500 milisegundos antes de repetir. Este retraso mantiene la salida legible y evita saturar el Monitor Serial.

Serial.println();
delay(500);

Si subes y ejecutas este código, deberías ver una secuencia de números en tu Monitor Serial que cambia si mueves el XIAO MG24 Sense:

En las siguientes dos secciones probaremos el micrófono del XIAO MG24 Sense, usando dos librerías diferentes.

Código de micrófono con la librería SiliconLabs

El siguiente código muestra cómo capturar muestras de audio del micrófono, calcular el nivel promedio de la señal y mapear ese nivel al brillo del LED. Usa un sistema de callback para manejar los datos del micrófono eficientemente. Vamos a explorar el código por partes.

#include <SilabsMicrophoneAnalog.h>

#define MIC_DATA_PIN PC9
#define MIC_PWR_PIN PC8
#define NUM_SAMPLES 128
#define MIC_VAL_MIN 735
#define MIC_VAL_MAX 900

uint32_t mic_buffer[NUM_SAMPLES];
uint32_t mic_buffer_local[NUM_SAMPLES];

volatile bool data_ready_flag = false;
MicrophoneAnalog micAnalog(MIC_DATA_PIN, MIC_PWR_PIN);

void mic_samples_ready_cb() {
  memcpy(mic_buffer_local, mic_buffer, NUM_SAMPLES * sizeof(uint32_t));
  data_ready_flag = true;
}

void calculate_and_display_voice_level() {
  static uint32_t avg = 0;

  micAnalog.stopSampling();

  uint32_t level = (uint32_t)micAnalog.getAverage(mic_buffer_local, NUM_SAMPLES);
  level = constrain(level, MIC_VAL_MIN, MIC_VAL_MAX);
  avg = (level + avg) / 2;

  int brightness = map(avg, MIC_VAL_MIN, MIC_VAL_MAX, 0, 255);
  analogWrite(LED_BUILTIN, 255 - brightness);
  Serial.println(avg);

  micAnalog.startSampling(mic_samples_ready_cb);
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);

  micAnalog.begin(mic_buffer, NUM_SAMPLES);
  Serial.println("Microphone initialized...");

  micAnalog.startSampling(mic_samples_ready_cb);
  Serial.println("Sampling started...");
}

void loop() {
  if (data_ready_flag) {
    data_ready_flag = false;
    calculate_and_display_voice_level();
  }
}

Importaciones

El sketch comienza incluyendo la librería SilabsMicrophoneAnalog.h. Esta librería proporciona funciones para inicializar el micrófono, iniciar y detener el muestreo, y procesar los datos recogidos.

#include <SilabsMicrophoneAnalog.h>

Constantes

Luego, el programa define varias constantes. MIC_DATA_PIN y MIC_PWR_PIN especifican los pines conectados a las líneas de datos y alimentación del micrófono. NUM_SAMPLES determina cuántas muestras de audio se recogerán a la vez. MIC_VAL_MIN y MIC_VAL_MAX definen el rango esperado de valores del micrófono para normalización. Estos límites ayudan a filtrar ruido no deseado y aseguran un buen mapeo del brillo del LED.

#define MIC_DATA_PIN PC9
#define MIC_PWR_PIN PC8
#define NUM_SAMPLES 128
#define MIC_VAL_MIN 735
#define MIC_VAL_MAX 900

Buffers

Dos buffers almacenan las muestras del micrófono. mic_buffer contiene muestras crudas del micrófono, mientras que mic_buffer_local guarda una copia segura de esas muestras para procesamiento. Esta separación previene errores si llegan nuevos datos mientras se realizan cálculos.

uint32_t mic_buffer[NUM_SAMPLES];
uint32_t mic_buffer_local[NUM_SAMPLES];

Flags y objetos

La variable data_ready_flag indica al programa cuándo un nuevo conjunto de muestras está disponible. Está marcada como volatile porque se actualiza dentro de una interrupción o callback. El objeto micAnalog se crea a partir de la clase MicrophoneAnalog. Toma como parámetros los pines de datos y alimentación del micrófono.

volatile bool data_ready_flag = false;
MicrophoneAnalog micAnalog(MIC_DATA_PIN, MIC_PWR_PIN);

Callback del micrófono

La función mic_samples_ready_cb() se ejecuta automáticamente cada vez que el micrófono termina de recoger un lote de muestras. Copia el contenido de mic_buffer en mic_buffer_local y pone data_ready_flag a true, señalando que los datos están listos para procesar.

void mic_samples_ready_cb() {
  memcpy(mic_buffer_local, mic_buffer, NUM_SAMPLES * sizeof(uint32_t));
  data_ready_flag = true;
}

Procesamiento de niveles de voz

La función calculate_and_display_voice_level() procesa los datos de audio y actualiza el brillo del LED. Primero, detiene el muestreo del micrófono para evitar interferencias durante los cálculos. Luego calcula el valor promedio de la señal usando micAnalog.getAverage(). Este valor se limita entre MIC_VAL_MIN y MIC_VAL_MAX para suavizar picos extremos.

Para que el LED responda más suavemente, el valor promedio se combina con el promedio anterior usando un filtro simple. El resultado se mapea del rango del micrófono al rango de brillo del LED de 0 a 255. Finalmente, se ajusta el brillo del LED usando analogWrite(). Un nivel de sonido más alto hace que el LED sea más brillante.

La función también imprime el valor promedio en el Monitor Serial y luego reinicia el muestreo del micrófono.

void calculate_and_display_voice_level() {
  static uint32_t avg = 0;

  micAnalog.stopSampling();

  uint32_t level = (uint32_t)micAnalog.getAverage(mic_buffer_local, NUM_SAMPLES);
  level = constrain(level, MIC_VAL_MIN, MIC_VAL_MAX);
  avg = (level + avg) / 2;

  int brightness = map(avg, MIC_VAL_MIN, MIC_VAL_MAX, 0, 255);
  analogWrite(LED_BUILTIN, 255 - brightness);
  Serial.println(avg);

  micAnalog.startSampling(mic_samples_ready_cb);
}

Setup

La función setup() prepara el monitor serial y el LED. También inicializa el micrófono con el buffer y el número de muestras. Una vez inicializado, el sketch comienza a muestrear e imprime mensajes de confirmación en el Monitor Serial.

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);

  micAnalog.begin(mic_buffer, NUM_SAMPLES);
  Serial.println("Microphone initialized...");

  micAnalog.startSampling(mic_samples_ready_cb);
  Serial.println("Sampling started...");
}

Loop

La función loop() verifica si hay datos nuevos listos. Si data_ready_flag es verdadero, limpia la bandera y llama a calculate_and_display_voice_level(). Esto asegura que los datos del micrófono se procesen solo cuando hay muestras frescas disponibles.

void loop() {
  if (data_ready_flag) {
    data_ready_flag = false;
    calculate_and_display_voice_level();
  }
}

Después de subir el código, deberías ver el brillo del LED integrado cambiar según los niveles de volumen ambiente. Cuanto más alto, más brillante.

Código de micrófono con la librería Seeed_Arduino_Mic

Este sketch inicializa un micrófono usando la librería Seeed_Arduino_Mic, recoge un número fijo de muestras de audio y las muestra como datos crudos. Demuestra cómo configurar parámetros del micrófono, manejar callbacks y procesar datos de audio entrantes.

Necesitarás instalar la librería Seeed_Arduino_Mic antes de poder ejecutar este código. Descarga la librería como archivo .ZIP desde el repositorio de Github e instálala vía Sketch → Include Library → Add .ZIP Library …

Echa un vistazo rápido al sketch completo primero y luego entraremos en sus detalles:

#include <mic.h>

#define DEBUG 1  // Enable pin pulse during ISR
#define SAMPLES 800

mic_config_t mic_config{
  .channel_cnt = 1,
  .sampling_rate = 16000,
  .buf_size = 1600,
  .debug_pin = LED_BUILTIN  // Toggles each DAC ISR (if DEBUG is set to 1)
};

MG24_ADC_Class Mic(&mic_config);

int16_t recording_buf[SAMPLES];
volatile uint8_t recording = 0;
volatile static bool record_ready = false;

static void audio_rec_callback(uint16_t *buf, uint32_t buf_len) {
  static uint32_t idx = 0;

  for (uint32_t i = 0; i < buf_len; i++) {
    // Convert 12-bit unsigned ADC value to 16-bit PCM (signed) audio value
    recording_buf[idx++] = buf[i];
    if (idx >= SAMPLES) {
      idx = 0;
      recording = 0;
      record_ready = true;
      break;
    }
  }
}

void setup() {
  Serial.begin(115200);
  Mic.set_callback(audio_rec_callback);

  if (!Mic.begin()) {
    Serial.println("Mic initialization failed");
    while (1)
      ;
  }
  Serial.println("Mic initialization done.");
}

void loop() {
  if (record_ready) {
    Serial.println("Finished sampling");
    for (int i = 0; i < SAMPLES; i++) {
      int16_t sample = recording_buf[i];
      Serial.println(sample);
    }
    record_ready = false;
  }
}

Importaciones

El programa comienza incluyendo el archivo de cabecera mic.h. Esta librería proporciona herramientas para configurar y controlar el hardware del micrófono en las plataformas de Seeed.

#include <mic.h>

Constantes

Se definen dos constantes. La primera, DEBUG, permite habilitar el pulso del pin durante interrupciones para depuración. Si DEBUG está en 1, el pin del LED parpadea cada vez que ocurre una interrupción, dando una indicación visual de la actividad de muestreo. La segunda constante, SAMPLES, especifica el número de muestras de audio a grabar antes de procesar.

#define DEBUG 1  // Enable pin pulse during ISR
#define SAMPLES 800

Configuración del micrófono

El micrófono se configura usando una estructura mic_config_t. Aquí, el micrófono se ajusta para usar un canal, una tasa de muestreo de 16 kHz y un tamaño de buffer de 1600 muestras. El debug_pin está vinculado a LED_BUILTIN, por lo que el LED integrado parpadea durante cada interrupción si la depuración está habilitada.

mic_config_t mic_config{
  .channel_cnt = 1,
  .sampling_rate = 16000,
  .buf_size = 1600,
  .debug_pin = LED_BUILTIN
};

El programa luego crea un objeto micrófono llamado Mic usando la clase MG24_ADC_Class. Este objeto toma la configuración del micrófono como entrada y gestiona la recolección de datos.

MG24_ADC_Class Mic(&mic_config);

Buffers y flags

El array recording_buf almacena las muestras grabadas, con un tamaño igual a la constante SAMPLES. Dos variables gestionan el proceso de grabación: recording controla el estado de grabación, y record_ready indica cuando el buffer está lleno y listo para procesar. Ambas se declaran volatile porque se modifican dentro de un callback de interrupción.

int16_t recording_buf[SAMPLES];
volatile uint8_t recording = 0;
volatile static bool record_ready = false;

Callback

El núcleo del proceso de grabación ocurre en la función audio_rec_callback(). Este callback se ejecuta automáticamente cada vez que el buffer del micrófono se llena. La función copia datos de audio del buffer de entrada al principal recording_buf.

Cada valor ADC crudo de 12 bits del micrófono se convierte en una muestra PCM firmada de 16 bits. La función lleva un seguimiento del índice actual en el buffer con una variable estática idx. Cuando el buffer alcanza su tamaño máximo (SAMPLES), la función reinicia el índice, limpia la bandera de grabación y pone record_ready a verdadero para que el loop sepa que los datos están listos para procesar.

static void audio_rec_callback(uint16_t *buf, uint32_t buf_len) {
  static uint32_t idx = 0;

  for (uint32_t i = 0; i < buf_len; i++) {
    // Convert 12-bit unsigned ADC value to 16-bit PCM (signed) audio value
    recording_buf[idx++] = buf[i];
    if (idx >= SAMPLES) {
      idx = 0;
      recording = 0;
      record_ready = true;
      break;
    }
  }
}

Setup

Dentro de setup(), el Monitor Serial se inicializa a 115200 baudios. El programa asigna audio_rec_callback como la función que manejará los datos de audio entrantes cada vez que el micrófono recoja muestras.

Luego se inicia el micrófono usando Mic.begin(). Si la inicialización falla, el programa imprime un mensaje de error y entra en un bucle infinito. De lo contrario, confirma la inicialización exitosa.

void setup() {
  Serial.begin(115200);
  Mic.set_callback(audio_rec_callback);

  if (!Mic.begin()) {
    Serial.println("Mic initialization failed");
    while (1);
  }
  Serial.println("Mic initialization done.");
}

Loop

La función loop() verifica si la grabación ha terminado mirando record_ready. Si es verdadero, el programa imprime "Finished sampling" y luego recorre el buffer, imprimiendo cada muestra de audio grabada. Después de imprimir, reinicia record_ready a false para que el sistema pueda grabar de nuevo.

void loop() {
  if (record_ready) {
    Serial.println("Finished sampling");
    for (int i = 0; i < SAMPLES; i++) {
      int16_t sample = recording_buf[i];
      Serial.println(sample);
    }
    record_ready = false;
  }
}

Si subes este sketch y abres el Serial Plotter verás una señal de audio que varía según el sonido detectado por el micrófono:

¡Y eso es todo! Estas instrucciones y ejemplos de código deberían ayudarte a comenzar rápidamente con el XIAO MG24 Sense.

Conclusiones

En este tutorial aprendiste cómo empezar con el XIAO MG24 Sense de Seeed Studio. Para información adicional, echa un vistazo a la Getting Started Wiki de Seeed Studio. Los ejemplos de código en este tutorial derivan de los ejemplos en las librerías Seeed_Arduino_Mic y Seeed_Arduino_LSM6DS3. Allí encontrarás más ejemplos de código.

Con el micrófono integrado y el Matrix-Vector Processor (MVP), el XIAO MG24 Sense es especialmente adecuado para aplicaciones TinyML como detección de palabras clave, control por voz o clasificación de sonidos.

Una alternativa de microcontrolador es el ESP32 basado en XIAO-ESP32-S3-Sense – también de Seeed Studio. También incluye un micrófono y, aunque carece de IMU, tiene una cámara en su lugar. Puede usarse para aplicaciones de voz, consulta también nuestro Voice control with XIAO-ESP32-S3-Sense and Edge Impulse, pero consume más energía.

Sin embargo, si te interesa la detección de objetos, el XIAO ESP32 Sense es la mejor opción debido a la cámara integrada. Consulta nuestros tutoriales Face Detection with XIAO ESP32-S3-Sense and SenseCraft AI y Edge AI Room Occupancy Sensor with ESP32 and Person Detection para más detalles.

Si tienes alguna pregunta, no dudes en dejarla en la sección de comentarios.

¡Feliz bricolaje! 😉