Skip to main content

Usage of Seeed Studio XIAO MG24 Sense built-in Sensor

XIAO MG24 Sense IMU

Overview of Built-in Sensors

6-Axis IMU (Inertial Measurement Unit) Sensors like the LSM6DS3TR-C integrate accelerometers and gyroscopes to measure the motion and orientation of an object in three-dimensional space. Specifically, the LSM6DS3TR-C has the following features:

Accelerometer function:

  • Measures the acceleration of an object along the X, Y, and Z axes. It is able to sense object motion (e.g., rest, acceleration, deceleration) and tilt changes (e.g., angle of the object).
  • It can be used to detect gait, position changes, vibrations, etc.

Gyroscope function (Gyroscope):

  • Measures the angular velocity of an object around the X, Y, and Z axes, i.e., the rotation of the object.
  • Can be used to detect rotation, rate of rotation, and change in direction.
  • The X-axis angle ( Roll ) is the angle in the direction of rotation around the X-axis.
  • The Y-axis angle ( Pitch ) is the angle in the direction of rotation around the Y-axis.
  • The Z-axis angle ( Yaw ) is the angle in the direction of rotation around the Z-axis.

Software Preparation

Click on the github download link to drive the six-axis sensor.

Code Implementation


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

//Create a instance of class LSM6DS3
LSM6DS3 myIMU(I2C_MODE, 0x6A); //I2C device address 0x6A
float aX, aY, aZ, gX, gY, gZ;
const float accelerationThreshold = 2.5; // threshold of significant in G's
const int numSamples = 119;
int samplesRead = numSamples;

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while (!Serial);

pinMode(PD5,OUTPUT);
digitalWrite(PD5,HIGH);
//Call .begin() to configure the IMUs
if (myIMU.begin() != 0) {
Serial.println("Device error");
} else {
Serial.println("aX,aY,aZ,gX,gY,gZ");
}
}

void loop() {
// wait for significant motion
while (samplesRead == numSamples) {
// read the acceleration data
aX = myIMU.readFloatAccelX();
aY = myIMU.readFloatAccelY();
aZ = myIMU.readFloatAccelZ();

// sum up the absolutes
float aSum = fabs(aX) + fabs(aY) + fabs(aZ);

// check if it's above the threshold
if (aSum >= accelerationThreshold) {
// reset the sample read count
samplesRead = 0;
break;
}
}

// check if the all the required samples have been read since
// the last time the significant motion was detected
while (samplesRead < numSamples) {
// check if both new acceleration and gyroscope data is
// available
// read the acceleration and gyroscope data

samplesRead++;

// print the data in CSV format
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();

if (samplesRead == numSamples) {
// add an empty line if it's the last sample
Serial.println();
}
}
}
tip

Due to the update of the LSM6DS3 library, if you have previously added this library to the user, you will need to re-download version 2.0.4 or higher and add the ZIP file to the Arduino.

Function Overview

  • Include Libraries

      #include <LSM6DS3.h> 
    #include <Wire.h>
    • Includes the library for communicating with the LSM6DS3 sensor.
    • Includes the library for I2C communication.
  • Create Sensor Instance

    • LSM6DS3 myIMU(I2C_MODE, 0x6A) Creates an instance of the LSM6DS3 class for the IMU sensor, specifying I2C communication mode and the device address 0x6A.
  • Variables and Constants

    • float aX, aY, aZ, gX, gY, gZ: Variables to store accelerometer and gyroscope data.
    • const float accelerationThreshold = 2.5: The threshold value in G's for detecting significant motion.
    • const int numSamples = 119: The number of samples to collect after detecting significant motion.
    • int samplesRead = numSamples: Initializes the sample counter to the total number of samples, indicating no data has been collected yet.
  • Basic Settings

      pinMode(PD5,OUTPUT);
    digitalWrite(PD5,HIGH);
    • Turn on the gyro enable pin.
  • Data Processing

    aX = myIMU.readFloatAccelX();:
    aY = myIMU.readFloatAccelY();:
    aZ = myIMU.readFloatAccelZ();:
    float aSum = fabs(aX) + fabs(aY) + fabs(aZ);
    • Reads the acceleration along X.
    • Reads the acceleration along Y.
    • Reads the acceleration along Z.
    • Calculate the sum of the absolute values of the acceleration data,fabs()Returns the absolute value.
      // check if it's above the threshold
    if (aSum >= accelerationThreshold) {
    // reset the sample read count
    samplesRead = 0;
    break;
    }
    • If the sum of the absolute acceleration values is greater than or equal to the set threshold, reset the sample count samplesRead to 0 and exit the loop.
  • Check Data

    while (samplesRead < numSamples) {
    samplesRead++;
    .
    .
    .
    .
    .
    if (samplesRead == numSamples) {
    // add an empty line if it's the last sample
    Serial.println();
    }
    }
    • Go to another loop and check if the required number of samples have been read.
    • Increase the count of samplesRead.
    • If all samples have been read, print a blank line to separate the data output.

Results Chart

Greater

If you want more sample code , Please Click : "File" -> Example -> Seeed Arduino LSM6DS3"

XIAO MG24 Sense Microphone

Overview of Built-in Sensors

Microphone Sensorlike the MSM381ACT001 is a MEMS (Micro-Electro-Mechanical Systems) microphone designed to capture audio signals with high sensitivity and low noise. Specifically, the MSM381ACT001 has the following features:

Microphone Function:

  • Captures sound waves and converts them into electrical signals, enabling the detection of audio input in various environments.
  • It features a wide frequency response range, typically from 20 Hz to 20 kHz, suitable for a variety of audio applications, including voice recognition and music playback.

Key Features

  • High Sensitivity: Capable of detecting faint sounds, making it ideal for applications requiring precise audio capture.
  • Low Noise: Designed to provide a high signal-to-noise ratio (SNR), ensuring clear audio output even in noisy environments.
  • Compact Size: MEMS technology allows for a small form factor, facilitating easy integration into portable devices like smartphones and wearables.
  • Digital Output: Offers digital signal output options (e.g., I2S), simplifying the interface with digital signal processors (DSPs) and microcontrollers.

Software Preparation

Click on the github download link to drive the microphone sensor.

tip

Currently we need to manually modify the replacement file, the subsequent direct download library can be used, please wait for our wiki update.

Changing the file path

  • /Users/yourname/Library/Arduino15/packages/SiliconLabs/hardware/silabs/2.2.0/variants/xiao_mg24/ble_silabs/

Code Implementation

#include <mic.h>
#if defined(WIO_TERMINAL)
#include "processing/filters.h"
#endif

// Settings
#if defined(WIO_TERMINAL)
#define DEBUG 1 // Enable pin pulse during ISR
#define SAMPLES 16000*3
#elif defined(ARDUINO_ARCH_NRF52840)
#define DEBUG 1 // Enable pin pulse during ISR
#define SAMPLES 800
#elif defined(ARDUINO_SILABS)
#define DEBUG 1 // Enable pin pulse during ISR
#define SAMPLES 800
#endif

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

#if defined(WIO_TERMINAL)
DMA_ADC_Class Mic(&mic_config);
#elif defined(ARDUINO_ARCH_NRF52840)
NRF52840_ADC_Class Mic(&mic_config);
#elif defined(ARDUINO_SILABS)
MG24_ADC_Class Mic(&mic_config);
#endif

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

#if defined(WIO_TERMINAL)
FilterBuHp filter;
#endif

void setup() {

Serial.begin(115200);
while (!Serial) {delay(10);}

#if defined(WIO_TERMINAL)
pinMode(WIO_KEY_A, INPUT_PULLUP);
#endif

Mic.set_callback(audio_rec_callback);

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

Serial.println("Mic initialization done.");

}

void loop() {

#if defined(WIO_TERMINAL)
if (digitalRead(WIO_KEY_A) == LOW && !recording) {

Serial.println("Starting sampling");
recording = 1;
record_ready = false;
}
#endif

#if defined(WIO_TERMINAL)
if (!recording && record_ready)
#elif defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_SILABS)
if (record_ready)
#endif
{
Serial.println("Finished sampling");

for (int i = 0; i < SAMPLES; i++) {

//int16_t sample = filter.step(recording_buf[i]);
int16_t sample = recording_buf[i];
Serial.println(sample);
}

record_ready = false;
}
}

static void audio_rec_callback(uint16_t *buf, uint32_t buf_len) {

static uint32_t idx = 0;
// Copy samples from DMA buffer to inference buffer
#if defined(WIO_TERMINAL)
if (recording)
#endif
{
for (uint32_t i = 0; i < buf_len; i++) {

// Convert 12-bit unsigned ADC value to 16-bit PCM (signed) audio value
#if defined(WIO_TERMINAL)
recording_buf[idx++] = filter.step((int16_t)(buf[i] - 1024) * 16);
//recording_buf[idx++] = (int16_t)(buf[i] - 1024) * 16;
#elif defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_SILABS)
recording_buf[idx++] = buf[i];
#endif

if (idx >= SAMPLES){
idx = 0;
recording = 0;
record_ready = true;
break;
}
}
}

}

Function Overview

Microphone Configuration

mic_config_t mic_config{
.channel_cnt = 1,
.sampling_rate = 16000,
.buf_size = 1600,
#if defined(WIO_TERMINAL)
.debug_pin = 1
#elif defined(ARDUINO_ARCH_NRF52840)
.debug_pin = LED_BUILTIN
#elif defined(ARDUINO_SILABS)
.debug_pin = LED_BUILTIN
#endif
};
  • mic_config_t: Defines a microphone configuration structure.
  • channel_cnt: set to 1 for mono.
  • sampling_rate: Set to 16000 Hz for sampling frequency.
  • buf_size: set to 1600 for buffer size.
  • ebug_pin: set debug pin according to platform, used for signal indication during debugging.

Microphone instantiation

#if defined(WIO_TERMINAL)
DMA_ADC_Class Mic(&mic_config);
#elif defined(ARDUINO_ARCH_NRF52840)
NRF52840_ADC_Class Mic(&mic_config);
#elif defined(ARDUINO_SILABS)
MG24_ADC_Class Mic(&mic_config);
#endif
  • Conditional compilation: create the appropriate microphone class instances for different platforms, using the previously defined configuration.

Recording buffers and flags

int16_t recording_buf[SAMPLES];
volatile uint8_t recording = 0;
volatile static bool record_ready = false;
  • recording_buf: Define an array of SAMPLES to store recording samples.
  • recording: a volatile variable that marks whether recording is currently in progress to prevent compiler optimization.
  • record_ready: a volatile static variable that indicates if the recording is complete and ready for further processing.

Filter Example (for WIO Terminal)

#if defined(WIO_TERMINAL)
FilterBuHp filter;
#endif
  • If on the WIO Terminal, create an instance of a high-pass filter for filter processing.

setup

void setup() {
Serial.begin(115200);
while (!Serial) {delay(10);}

#if defined(WIO_TERMINAL)
pinMode(WIO_KEY_A, INPUT_PULLUP);
#endif

Mic.set_callback(audio_rec_callback);

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

Serial.println("Mic initialization done.");
}

-Initialize Serial Port: Start serial communication at 115200 baud rate and wait for the serial port to be ready.

  • Set Pin Mode: On WIO Terminal, set the key pins to input pull-up mode.
  • Set callback function: call Mic.set_callback(audio_rec_callback) to specify the callback function when recording audio.
  • Initialize the microphone: call Mic.begin(), if the initialization fails, print an error message and enter a dead loop.

loop

void loop() { 
#if defined(WIO_TERMINAL)
if (digitalRead(WIO_KEY_A) == LOW && !recording) {
Serial.println("Starting sampling");
recording = 1;
record_ready = false;
}
#endif

#if defined(WIO_TERMINAL)
if (!recording && record_ready)
#elif defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_SILABS)
if (record_ready)
#endif
{
Serial.println("Finished sampling");

for (int i = 0; i < SAMPLES; i++) {
int16_t sample = recording_buf[i];
Serial.println(sample);
}

record_ready = false;
}
}
  • Detect Key: On the WIO Terminal, starts recording when it detects that a key has been pressed and is not recording.
  • Finished sampling:Prints “Finished sampling” if not recording and record_ready is set to true.
  • Iterates through the recording buffer and prints each sample value.

Audio recording callback function

static void audio_rec_callback(uint16_t *buf, uint32_t buf_len) {
static uint32_t idx = 0;
#if defined(WIO_TERMINAL)
if (recording)
#endif
{
for (uint32_t i = 0; i < buf_len; i++) {
#if defined(WIO_TERMINAL)
recording_buf[idx++] = filter.step((int16_t)(buf[i] - 1024) * 16);
#elif defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_SILABS)
recording_buf[idx++] = buf[i];
#endif

if (idx >= SAMPLES){
idx = 0;
recording = 0;
record_ready = true;
break;
}
}
}
}
  • Callback function: called during audio recording, responsible for copying samples from the DMA buffer to the recording buffer.
  • Conditional Compilation: Processes the input using filters if on the WIO Terminal.
  • Converts 12-bit unsigned ADC values to 16-bit PCM (signed) audio values.
  • Sample Fill: copies samples into recording_buf and updates index idx.
  • Finish recording: if the number of filled samples reaches SAMPLES, resets the index, marks the end of recording and sets record_ready to true.

Results Chart

Here is the waveform of the recognized sound, when you blow, you can clearly see that the waveform oscillation amplitude becomes bigger.

Greater

If you want more sample code , Please Click : -> "Example -> Seeed Arduino Mic"

Resources

For Seeed Studio XIAO MG24 Sense

Tech Support & Product Discussion

Thank you for choosing our products! We are here to provide you with different support to ensure that your experience with our products is as smooth as possible. We offer several communication channels to cater to different preferences and needs.

Loading Comments...