Pular para o conteúdo principal

Uso do Sensor Integrado Seeed Studio XIAO MG24 Sense

IMU do XIAO MG24 Sense

Visão geral dos sensores integrados

IMU (Unidade de Medição Inercial) de 6 eixos Sensores como o LSM6DS3TR-C integram acelerômetros e giroscópios para medir o movimento e a orientação de um objeto no espaço tridimensional. Especificamente, o LSM6DS3TR-C possui as seguintes características:

Função de acelerômetro:

  • Mede a aceleração de um objeto ao longo dos eixos X, Y e Z. Ele é capaz de detectar o movimento do objeto (por exemplo, em repouso, aceleração, desaceleração) e mudanças de inclinação (por exemplo, o ângulo do objeto).
  • Pode ser usado para detectar marcha, mudanças de posição, vibrações etc.

Função de giroscópio (Gyroscope):

  • Mede a velocidade angular de um objeto em torno dos eixos X, Y e Z, ou seja, a rotação do objeto.
  • Pode ser usado para detectar rotação, taxa de rotação e mudança de direção.
  • O ângulo do eixo X ( Roll ) é o ângulo na direção de rotação em torno do eixo X.
  • O ângulo do eixo Y ( Pitch ) é o ângulo na direção de rotação em torno do eixo Y.
  • O ângulo do eixo Z ( Yaw ) é o ângulo na direção de rotação em torno do eixo Z.

Preparação de Software

Clique no link de download do GitHub para controlar o sensor de seis eixos.

Implementação do Código


#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();
}
}
}
dica

Devido à atualização da biblioteca LSM6DS3, se você já adicionou essa biblioteca anteriormente ao usuário, será necessário baixar novamente a versão 2.0.4 ou superior e adicionar o arquivo ZIP ao Arduino.

Visão geral das funções

  • Incluir Bibliotecas

      #include <LSM6DS3.h> 
    #include <Wire.h>
    • Inclui a biblioteca para comunicação com o sensor LSM6DS3.
    • Inclui a biblioteca para comunicação I2C.
  • Criar Instância do Sensor

    • LSM6DS3 myIMU(I2C_MODE, 0x6A) Cria uma instância da classe LSM6DS3 para o sensor IMU, especificando o modo de comunicação I2C e o endereço do dispositivo 0x6A.
  • Variáveis e Constantes

    • float aX, aY, aZ, gX, gY, gZ: Variáveis para armazenar dados do acelerômetro e do giroscópio.
    • const float accelerationThreshold = 2.5: O valor de limiar em G's para detectar movimento significativo.
    • const int numSamples = 119: O número de amostras a serem coletadas após detectar movimento significativo.
    • int samplesRead = numSamples: Inicializa o contador de amostras com o número total de amostras, indicando que nenhum dado foi coletado ainda.
  • Configurações Básicas

      pinMode(PD5,OUTPUT);
    digitalWrite(PD5,HIGH);
    • Liga o pino de habilitação do giroscópio.
  • Processamento de Dados

    aX = myIMU.readFloatAccelX();:
    aY = myIMU.readFloatAccelY();:
    aZ = myIMU.readFloatAccelZ();:
    float aSum = fabs(aX) + fabs(aY) + fabs(aZ);
    • Lê a aceleração ao longo de X.
    • Lê a aceleração ao longo de Y.
    • Lê a aceleração ao longo de Z.
    • Calcula a soma dos valores absolutos dos dados de aceleração,fabs()Retorna o valor absoluto.
      // check if it's above the threshold
    if (aSum >= accelerationThreshold) {
    // reset the sample read count
    samplesRead = 0;
    break;
    }
    • Se a soma dos valores absolutos da aceleração for maior ou igual ao limiar definido, redefine a contagem de amostras samplesRead para 0 e sai do loop.
  • Verificar Dados

    while (samplesRead < numSamples) {
    samplesRead++;
    .
    .
    .
    .
    .
    if (samplesRead == numSamples) {
    // add an empty line if it's the last sample
    Serial.println();
    }
    }
    • Vai para outro loop e verifica se o número necessário de amostras foi lido.
    • Aumenta a contagem de samplesRead.
    • Se todas as amostras tiverem sido lidas, imprime uma linha em branco para separar a saída de dados.

Gráfico de Resultados

Mais

Se você quiser mais códigos de exemplo, clique em: "File" -> Example -> Seeed Arduino LSM6DS3"

Demo Avançado de IMU

Preparação de Hardware

Seeeduino-XIAO-Expansion-BoardSeeed Studio XIAO MG24 Sense

Preparação de Software

dica

Precisamos selecionar a pilha correspondente na barra de ferramentas para gravar o programa.

Código do Programa
#include <LSM6DS3.h>
#include "Wire.h"

#define DEVICE_NAME "XIAO MG24 Mouse"

#define IMU_ACC_X_THRESHOLD 10
#define IMU_ACC_Y_THRESHOLD 10

// Mouse button events
#define LMB_PRESSED 1

// HID report data
struct mouse_data {
int8_t delta_x;
int8_t delta_y;
uint8_t buttons;
};
static mouse_data report;

// HID report data buffer
static uint8_t report_array[] = { 0x00, 0x00, 0x00 };

static uint8_t connection_handle = SL_BT_INVALID_CONNECTION_HANDLE;
static uint32_t bonding_handle = SL_BT_INVALID_BONDING_HANDLE;
static uint16_t hid_report;

// Device information service
const uint8_t manufacturer[] = "Silicon Labs";
const uint8_t model_no[] = "1";
const uint8_t serial_no[] = "1";
const uint8_t hw_rev[] = "1";
const uint8_t fw_rev[] = "1";
const uint8_t sw_rev[] = "1";

static bd_addr ble_address = { 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u };
static bool button_press = false;
static bool button_press_prev = false;
static int32_t acc_x = 0, acc_y = 0;
static sl_status_t sc = SL_STATUS_OK;

static void ble_initialize_gatt_db();
static void ble_start_advertising();
static void mouse_button_callback();

// Optionally connect a button for left click
#define MOUSE_BUTTON D1

LSM6DS3 myIMU(I2C_MODE, 0x6A);

void setup()
{
// Initialize report data
memset(&report, 0, sizeof(report));

// Enable the IMU power
pinMode(PD5, OUTPUT);
digitalWrite(PD5, HIGH);
delay(300);

pinMode(MOUSE_BUTTON, INPUT_PULLUP);
attachInterrupt(MOUSE_BUTTON, mouse_button_callback, CHANGE);

Serial.begin(115200);

Serial.println("XIAO MG24 BLE mouse");

myIMU.begin();
Serial.println("---");
Serial.println("IMU initialized");
}

void loop()
{
// Update 'left mouse button' bit
if (button_press) {
report.buttons |= LMB_PRESSED;
if (!button_press_prev) {
button_press_prev = true;
Serial.println("Button pressed");
}
} else {
button_press_prev = false;
report.buttons &= ~LMB_PRESSED;
}

// Change x and y for correct orientation of the boards
acc_y = (int32_t)(myIMU.readFloatAccelX() * 10.0f);
acc_x = (int32_t)(myIMU.readFloatAccelY() * 10.0f * -1.0f);

// In case the acceleration value would surpass the threshold value
// in positive or negative direction assign the threshold value
if (acc_x > IMU_ACC_X_THRESHOLD) {
report.delta_x = IMU_ACC_X_THRESHOLD;
} else if (acc_x < (-1 * IMU_ACC_X_THRESHOLD)) {
report.delta_x = (-1 * IMU_ACC_X_THRESHOLD);
} else {
report.delta_x = acc_x;
}

if (acc_y > IMU_ACC_Y_THRESHOLD) {
report.delta_y = IMU_ACC_Y_THRESHOLD;
} else if (acc_y < (-1 * IMU_ACC_Y_THRESHOLD)) {
report.delta_y = (-1 * IMU_ACC_Y_THRESHOLD);
} else {
report.delta_y = acc_y;
}

memcpy(report_array, &report, sizeof(report));
if (connection_handle != SL_BT_INVALID_CONNECTION_HANDLE && bonding_handle != SL_BT_INVALID_BONDING_HANDLE) {
// Indicate report data change with GATT notification
sc = sl_bt_gatt_server_notify_all(hid_report, sizeof(report_array), report_array);
if (sc != SL_STATUS_OK) {
Serial.print("sl_bt_gatt_server_notify_all() returned with error code 0x");
Serial.println(sc, HEX);
} else {
Serial.print("cursor [delta-X: ");
Serial.print(report.delta_x, DEC);
Serial.print(" delta-Y: ");
Serial.print(report.delta_y, DEC);
Serial.print(" ] LMB: ");
Serial.println(report.buttons, HEX);
}
}
}

/******************************************************************************
* Mouse button callback
*****************************************************************************/
void mouse_button_callback()
{
if (digitalRead(MOUSE_BUTTON) == LOW) {
button_press = true;
} else {
button_press = false;
}
}

/******************************************************************************
* Bluetooth stack event handler
* Called when an event happens on BLE the stack
*
* @param[in] evt Event coming from the Bluetooth stack
*****************************************************************************/
void sl_bt_on_event(sl_bt_msg_t* evt)
{
sl_status_t sc = SL_STATUS_OK;
uint8_t ble_address_type;

switch (SL_BT_MSG_ID(evt->header)) {
// -------------------------------
// This event indicates the device has started and the radio is ready
case sl_bt_evt_system_boot_id:
{
// Get BLE address and address type
sc = sl_bt_system_get_identity_address(&ble_address, &ble_address_type);
app_assert_status(sc);

// Print welcome message
Serial.begin(115200);
Serial.println();
Serial.println("BLE stack booted");

// Initialize the application specific GATT DB
ble_initialize_gatt_db();

// HID input devices requires mandatory secure level and bonding
sc = sl_bt_sm_configure(0, sl_bt_sm_io_capability_noinputnooutput);
app_assert_status(sc);

// Allow bonding
sc = sl_bt_sm_set_bondable_mode(1);
app_assert_status(sc);

ble_start_advertising();
}
break;

// -------------------------------
// This event indicates that a BLE connection has been opened
case sl_bt_evt_connection_opened_id:
{
// Store the connection handle which will be needed for sending indications
connection_handle = evt->data.evt_connection_opened.connection;
bonding_handle = evt->data.evt_connection_opened.bonding;
Serial.print("Connection opened - handle 0x");
Serial.println(connection_handle, HEX);

if (bonding_handle == SL_BT_INVALID_BONDING_HANDLE) {
Serial.println("Connection not bonded yet");
} else {
Serial.println("Connection bonded");
}

Serial.println("Increase security");
sc = sl_bt_sm_increase_security(evt->data.evt_connection_opened.connection);
app_assert_status(sc);
}
break;

// -------------------------------
// This event indicates that bonding was successful
case sl_bt_evt_sm_bonded_id:
{
Serial.print("Bonded - handle: 0x");
Serial.print(evt->data.evt_sm_bonded.connection, HEX);
bonding_handle = evt->data.evt_sm_bonded.bonding;
connection_handle = evt->data.evt_sm_bonded.connection;

Serial.print(" - security mode: 0x");
Serial.println(evt->data.evt_sm_bonded.security_mode, HEX);
}
break;

// -------------------------------
// This event indicates that a BLE connection has closed
case sl_bt_evt_connection_closed_id:
{
Serial.print("Connection closed - handle: 0x");
Serial.print(connection_handle, HEX);
Serial.print(" reason: 0x");
Serial.println(evt->data.evt_connection_closed.reason, HEX);

connection_handle = SL_BT_INVALID_CONNECTION_HANDLE;
bonding_handle = SL_BT_INVALID_BONDING_HANDLE;

sc = sl_bt_sm_delete_bondings();
Serial.println("Deleted bondings");
app_assert_status(sc);

ble_start_advertising();
}
break;

// -------------------------------
// This event indicates that the connection parameters have changed
case sl_bt_evt_connection_parameters_id:
{
Serial.print("Set connection parameters, security_mode: ");
Serial.println(evt->data.evt_connection_parameters.security_mode, HEX);
}
break;

// -------------------------------
// This event indicates that bonding has failed
case sl_bt_evt_sm_bonding_failed_id:
{
Serial.print("Bonding failed, reason: 0x");
Serial.println(evt->data.evt_sm_bonding_failed.reason, HEX);
Serial.println("Delete bondings.");

sc = sl_bt_sm_delete_bondings();
app_assert_status(sc);

Serial.println("Bondings deleted");
Serial.print("Close connection - handle: 0x");
Serial.println(evt->data.evt_sm_bonding_failed.connection, HEX);
}
break;

// -------------------------------
// Default event handler
default:
break;
}
}

/******************************************************************************
* Starts BLE advertisement
* Initializes advertising if it's called for the first time
*****************************************************************************/
static void ble_start_advertising()
{
static uint8_t advertising_set_handle = 0xff;
static bool init = true;
sl_status_t sc;

if (init) {
// Create an advertising set
sc = sl_bt_advertiser_create_set(&advertising_set_handle);
app_assert_status(sc);

// Set advertising interval to 100ms
sc = sl_bt_advertiser_set_timing(
advertising_set_handle,
160, // Minimum advertisement interval (milliseconds * 1.6)
160, // Maximum advertisement interval (milliseconds * 1.6)
0, // Advertisement duration
0); // Maximum number of advertisement events
app_assert_status(sc);

init = false;
}

// Generate data for advertising
sc = sl_bt_legacy_advertiser_generate_data(advertising_set_handle, sl_bt_advertiser_general_discoverable);
app_assert_status(sc);

// Start advertising and enable connections
sc = sl_bt_legacy_advertiser_start(advertising_set_handle, sl_bt_advertiser_connectable_scannable);
app_assert_status(sc);

Serial.print("Started advertising as '");
Serial.print(DEVICE_NAME);
Serial.print("' address: ");
// Print address in format 'FF:FF:FF:FF:FF:FF'
for (uint8_t i = (sizeof(bd_addr) - 1); i > 0; i--) {
Serial.print(ble_address.addr[i], HEX);
Serial.print(":");
}
Serial.println(ble_address.addr[0], HEX);
}

/******************************************************************************
* Initializes the GATT database
* Creates a new GATT session and adds certain services and characteristics
*****************************************************************************/
static void ble_initialize_gatt_db()
{
sl_status_t sc;
uint16_t gattdb_session_id;
uint16_t service;
uint16_t characteristic;
uint16_t descriptor;

// Create a new GATT database
sc = sl_bt_gattdb_new_session(&gattdb_session_id);
app_assert_status(sc);

// Generic access service
uint8_t generic_access_service_uuid[] = { 0x00, 0x18 };
sc = sl_bt_gattdb_add_service(gattdb_session_id,
sl_bt_gattdb_primary_service,
SL_BT_GATTDB_ADVERTISED_SERVICE,
2,
generic_access_service_uuid,
&service);
app_assert_status(sc);

// Device name characteristic
sl_bt_uuid_16_t device_name_uuid = { .data = { 0x00, 0x2A } };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
(SL_BT_GATTDB_CHARACTERISTIC_READ | SL_BT_GATTDB_CHARACTERISTIC_WRITE),
0,
0,
device_name_uuid,
sl_bt_gattdb_fixed_length_value,
strlen(DEVICE_NAME),
strlen(DEVICE_NAME),
(uint8_t *)DEVICE_NAME,
&characteristic);
app_assert_status(sc);

// Appearance characteristic
sl_bt_uuid_16_t appearence_uuid = { .data = { 0x01, 0x2A } };
const uint8_t appearance_value[] = { 0xC2, 0x03 };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
0,
0,
appearence_uuid,
sl_bt_gattdb_fixed_length_value,
2,
sizeof(appearance_value),
appearance_value,
&characteristic);
app_assert_status(sc);

// Generic access service start
sc = sl_bt_gattdb_start_service(gattdb_session_id, service);
app_assert_status(sc);

// Battery service
const uint8_t battery_service_uuid[] = { 0x0F, 0x18 };
sc = sl_bt_gattdb_add_service(gattdb_session_id,
sl_bt_gattdb_primary_service,
0,
sizeof(battery_service_uuid),
battery_service_uuid,
&service);
app_assert_status(sc);

// Battery level characteristic
const sl_bt_uuid_16_t battery_level_uuid = { .data = { 0x19, 0x2A } };
const uint8_t battery_level_init_value = 100;
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
0,
0,
battery_level_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(battery_level_init_value),
sizeof(battery_level_init_value),
&battery_level_init_value,
&characteristic);
app_assert_status(sc);

// Characteristic presentation format descriptor
const sl_bt_uuid_16_t chara_presentation_format_descriptor_uuid = { .data = { 0x04, 0x29 } };
const uint8_t chara_presentation_format_value[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
sc = sl_bt_gattdb_add_uuid16_descriptor(gattdb_session_id,
characteristic,
SL_BT_GATTDB_DESCRIPTOR_READ,
0,
chara_presentation_format_descriptor_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(chara_presentation_format_value),
sizeof(chara_presentation_format_value),
chara_presentation_format_value,
&descriptor);
app_assert_status(sc);

// Client characteristic configuration descriptor
const sl_bt_uuid_16_t client_configuration_descriptor_uuid = { .data = { 0x02, 0x29 } };
const uint8_t client_configuration_value[] = { 0x00, 0x00 };
sc = sl_bt_gattdb_add_uuid16_descriptor(gattdb_session_id,
characteristic,
(SL_BT_GATTDB_DESCRIPTOR_READ | SL_BT_GATTDB_DESCRIPTOR_WRITE),
0,
client_configuration_descriptor_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(client_configuration_value),
sizeof(client_configuration_value),
client_configuration_value,
&descriptor);
app_assert_status(sc);

// Battery service start
sc = sl_bt_gattdb_start_service(gattdb_session_id, service);
app_assert_status(sc);

// Device information service
const uint8_t device_info_service_uuid[] = { 0x0A, 0x18 };
sc = sl_bt_gattdb_add_service(gattdb_session_id,
sl_bt_gattdb_primary_service,
0,
sizeof(device_info_service_uuid),
device_info_service_uuid,
&service);
app_assert_status(sc);

// Manufacturer name string characteristic
const sl_bt_uuid_16_t manufacturer_uuid = { .data = { 0x29, 0x2A } };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
0,
0,
manufacturer_uuid,
sl_bt_gattdb_fixed_length_value,
(sizeof(manufacturer) - 1),
(sizeof(manufacturer) - 1),
manufacturer,
&characteristic);
app_assert_status(sc);

// Model number string characteristic
const sl_bt_uuid_16_t model_no_uuid = { .data = { 0x24, 0x2A } };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
0,
0,
model_no_uuid,
sl_bt_gattdb_fixed_length_value,
(sizeof(model_no) - 1),
(sizeof(model_no) - 1),
model_no,
&characteristic);
app_assert_status(sc);

// Serial number string characteristic
const sl_bt_uuid_16_t serial_no_uuid = { .data = { 0x25, 0x2A } };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
0,
0,
serial_no_uuid,
sl_bt_gattdb_fixed_length_value,
(sizeof(serial_no) - 1),
(sizeof(serial_no) - 1),
serial_no,
&characteristic);
app_assert_status(sc);

// Hardware revision string characteristic
const sl_bt_uuid_16_t hw_rev_uuid = { .data = { 0x27, 0x2A } };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
0,
0,
hw_rev_uuid,
sl_bt_gattdb_fixed_length_value,
(sizeof(hw_rev) - 1),
(sizeof(hw_rev) - 1),
hw_rev,
&characteristic);
app_assert_status(sc);

// Firmware revision string characteristic
const sl_bt_uuid_16_t fw_rev_uuid = { .data = { 0x26, 0x2A } };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
0,
0,
fw_rev_uuid,
sl_bt_gattdb_fixed_length_value,
(sizeof(fw_rev) - 1),
(sizeof(fw_rev) - 1),
fw_rev,
&characteristic);
app_assert_status(sc);

// Software revision string characteristic
const sl_bt_uuid_16_t sw_rev_uuid = { .data = { 0x28, 0x2A } };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
0,
0,
sw_rev_uuid,
sl_bt_gattdb_fixed_length_value,
(sizeof(sw_rev) - 1),
(sizeof(sw_rev) - 1),
sw_rev,
&characteristic);
app_assert_status(sc);

// System ID characteristic
const sl_bt_uuid_16_t sys_id_uuid = { .data = { 0x23, 0x2A } };
const uint8_t sys_id_initial_value[] = { 0x12, 0x34, 0x56, 0xFF, 0xFE, 0x9A, 0xBC, 0xDE };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
0,
0,
sys_id_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(sys_id_initial_value),
sizeof(sys_id_initial_value),
sys_id_initial_value,
&characteristic);
app_assert_status(sc);

// PnP ID characteristic
const sl_bt_uuid_16_t pnp_id_uuid = { .data = { 0x50, 0x2A } };
const uint8_t pnp_id_initial_value[] = { 0x02, 0x10, 0xC4, 0x00, 0x01, 0x00, 0x01 };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
0,
0,
pnp_id_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(pnp_id_initial_value),
sizeof(pnp_id_initial_value),
pnp_id_initial_value,
&characteristic);
app_assert_status(sc);

// Device information service start
sc = sl_bt_gattdb_start_service(gattdb_session_id, service);
app_assert_status(sc);

// HID service
uint8_t hid_service_uuid[] = { 0x12, 0x18 };
sc = sl_bt_gattdb_add_service(gattdb_session_id,
sl_bt_gattdb_primary_service,
SL_BT_GATTDB_ADVERTISED_SERVICE,
2,
hid_service_uuid,
&service);
app_assert_status(sc);

// Protocol mode characteristic
sl_bt_uuid_16_t hid_protocol_mode_uuid = { .data = { 0x4E, 0x2A } };
const uint8_t hid_protocol_mode_init_value[] = { 1 };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
(SL_BT_GATTDB_CHARACTERISTIC_READ | SL_BT_GATTDB_CHARACTERISTIC_WRITE_NO_RESPONSE),
0,
0,
hid_protocol_mode_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(hid_protocol_mode_init_value),
sizeof(hid_protocol_mode_init_value),
hid_protocol_mode_init_value,
&characteristic);
app_assert_status(sc);

// HID report characteristic
const sl_bt_uuid_16_t hid_report_uuid = { .data = { 0x4D, 0x2A } };
const uint8_t hid_report_init_value[] = { 0x00, 0x00, 0x00 };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
(SL_BT_GATTDB_CHARACTERISTIC_READ | SL_BT_GATTDB_CHARACTERISTIC_WRITE | SL_BT_GATTDB_CHARACTERISTIC_NOTIFY),
0,
0,
hid_report_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(hid_report_init_value),
sizeof(hid_report_init_value),
hid_report_init_value,
&characteristic);
app_assert_status(sc);
hid_report = characteristic;

// HID report reference descriptor
const sl_bt_uuid_16_t hid_report_reference_desc_uuid = { .data = { 0x08, 0x29 } };
const uint8_t hid_report_reference_desc_init_val[] = { 0x00, 0x01 };
sc = sl_bt_gattdb_add_uuid16_descriptor(gattdb_session_id,
characteristic,
SL_BT_GATTDB_DESCRIPTOR_READ,
SL_BT_GATTDB_ENCRYPTED_READ,
hid_report_reference_desc_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(hid_report_reference_desc_init_val),
sizeof(hid_report_reference_desc_init_val),
hid_report_reference_desc_init_val,
&descriptor);
app_assert_status(sc);

// HID report map characteristic
const sl_bt_uuid_16_t hid_report_map_uuid = { .data = { 0x4B, 0x2A } };
const uint8_t hid_report_map_init_value[] = { 0x05, 0x01, // Usage page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x09, 0x01, // UsageId (Pointer)
0xA1, 0x00, // Collection (Physical)
0x09, 0x30, // UsageId (x)
0x09, 0x31, // UsageId (y)
0x15, 0x80, // LogicalMinimum(-128)
0x25, 0x7F, // LogicalMaximum(127)
0x95, 0x02, // ReportCount(2)
0x75, 0x08, // ReportSize(8)
0x81, 0x06, // Input(Data, Variable, Relative, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
0x05, 0x09, // UsagePage(Button)
0x19, 0x01, // UsageIdMin(Button 1)
0x29, 0x03, // UsageIdMax(Button 3)
0x15, 0x00, // LogicalMinimum(0)
0x25, 0x01, // LogicalMaximum(1)
0x95, 0x03, // ReportCount(3)
0x75, 0x01, // ReportSize(1)
0x81, 0x02, // Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
0x95, 0x01, // ReportCount(1)
0x75, 0x05, // ReportSize(5)
0x81, 0x03, // Input(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
0xC0, // EndCollection()
0xC0 }; // EndCollection()
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
SL_BT_GATTDB_ENCRYPTED_READ,
0,
hid_report_map_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(hid_report_map_init_value),
sizeof(hid_report_map_init_value),
hid_report_map_init_value,
&characteristic);
app_assert_status(sc);

// HID external report reference descriptor
const sl_bt_uuid_16_t hid_external_report_reference_descriptor_uuid = { .data = { 0x07, 0x29 } };
const uint8_t hid_external_report_reference_value[] = { 0x00, 0x00 };
sc = sl_bt_gattdb_add_uuid16_descriptor(gattdb_session_id,
characteristic,
SL_BT_GATTDB_DESCRIPTOR_READ,
0,
hid_external_report_reference_descriptor_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(hid_external_report_reference_value),
sizeof(hid_external_report_reference_value),
hid_external_report_reference_value,
&descriptor);
app_assert_status(sc);

// HID information characteristic
const sl_bt_uuid_16_t hid_info_uuid = { .data = { 0x4A, 0x2A } };
const uint8_t hid_info_init_value[] = { 0x01, 0x11, 0x00, 0x02 };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_READ,
0,
0,
hid_info_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(hid_info_init_value),
sizeof(hid_info_init_value),
hid_info_init_value,
&characteristic);
app_assert_status(sc);

// HID control point characteristic
const sl_bt_uuid_16_t hid_control_point_uuid = { .data = { 0x4C, 0x2A } };
const uint8_t hid_control_point_init_value[] = { 0x00 };
sc = sl_bt_gattdb_add_uuid16_characteristic(gattdb_session_id,
service,
SL_BT_GATTDB_CHARACTERISTIC_WRITE_NO_RESPONSE,
0,
0,
hid_control_point_uuid,
sl_bt_gattdb_fixed_length_value,
sizeof(hid_control_point_init_value),
sizeof(hid_control_point_init_value),
hid_control_point_init_value,
&characteristic);
app_assert_status(sc);

// HID service start
sc = sl_bt_gattdb_start_service(gattdb_session_id, service);
app_assert_status(sc);

// Commit the GATT DB changes
sc = sl_bt_gattdb_commit(gattdb_session_id);
app_assert_status(sc);
}

#ifndef BLE_STACK_SILABS
#error "This example is only compatible with the Silicon Labs BLE stack. Please select 'BLE (Silabs)' in 'Tools > Protocol stack'."
#endif

Gráfico de Resultados

Quando pressionamos o botão na placa de expansão, podemos observar que o evento do mouse é disparado!

XIAO MG24 Sense Microphone(Seeed Studio Demo)

Visão Geral dos Sensores Integrados

Sensor de Microfone como o MSM381ACT001 é um microfone MEMS (Micro-Electro-Mechanical Systems) projetado para capturar sinais de áudio com alta sensibilidade e baixo ruído. Especificamente, o MSM381ACT001 possui as seguintes características:

Função do Microfone:

  • Captura ondas sonoras e as converte em sinais elétricos, possibilitando a detecção de entrada de áudio em vários ambientes.
  • Possui uma ampla faixa de resposta em frequência, tipicamente de 20 Hz a 20 kHz, adequada para uma variedade de aplicações de áudio, incluindo reconhecimento de voz e reprodução de música.

Principais Características

  • Alta Sensibilidade: Capaz de detectar sons fracos, tornando-o ideal para aplicações que exigem captura de áudio precisa.
  • Baixo Ruído: Projetado para fornecer uma alta relação sinal-ruído (SNR), garantindo saída de áudio clara mesmo em ambientes ruidosos.
  • Tamanho Compacto: A tecnologia MEMS permite um formato pequeno, facilitando a integração em dispositivos portáteis como smartphones e wearables.
  • Saída Digital: Oferece opções de saída de sinal digital (por exemplo, I2S), simplificando a interface com processadores de sinal digital (DSPs) e microcontroladores.

Preparação de Software

Clique no link de download do GitHub para acionar o sensor de microfone.

dica

Atualmente precisamos modificar manualmente o arquivo de substituição; posteriormente a biblioteca poderá ser usada diretamente após o download, aguarde a atualização do nosso wiki.

  • [Arquivos de Substituição] gsdk.a

Alterando o caminho do arquivo

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

Implementação de Código

#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;
}
}
}

}

Visão Geral da Função

Configuração do Microfone

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: Define uma estrutura de configuração de microfone.
  • channel_cnt: definido como 1 para mono.
  • sampling_rate: Definido como 16000 Hz para a frequência de amostragem.
  • buf_size: definido como 1600 para o tamanho do buffer.
  • ebug_pin: define o pino de depuração de acordo com a plataforma, usado para indicação de sinal durante a depuração.

Instanciação do Microfone

#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
  • Compilação condicional: cria as instâncias adequadas de classes de microfone para diferentes plataformas, utilizando a configuração definida anteriormente.

Buffers e flags de gravação

int16_t recording_buf[SAMPLES];
volatile uint8_t recording = 0;
volatile static bool record_ready = false;
  • recording_buf: Define um array de SAMPLES para armazenar amostras de gravação.
  • recording: uma variável volátil que indica se a gravação está em andamento, para evitar otimização pelo compilador.
  • record_ready: uma variável estática volátil que indica se a gravação foi concluída e está pronta para processamento posterior.

Exemplo de Filtro (para WIO Terminal)

#if defined(WIO_TERMINAL)
FilterBuHp filter;
#endif
  • Se estiver no WIO Terminal, crie uma instância de um filtro passa‑altas para o processamento de filtragem.

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: Inicia a comunicação serial a 115200 bauds e aguarda a porta serial estar pronta.

  • Definir modo do pino: No WIO Terminal, define os pinos das teclas como modo de entrada com pull-up.
  • Definir função de callback: chama Mic.set_callback(audio_rec_callback) para especificar a função de callback ao gravar áudio.
  • Inicializar o microfone: chama Mic.begin(); se a inicialização falhar, imprime uma mensagem de erro e entra em um loop infinito.

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;
}
}
  • Detectar tecla: No WIO Terminal, inicia a gravação quando detecta que uma tecla foi pressionada e não está gravando.
  • Amostragem concluída: Imprime “Finished sampling” se não estiver gravando e record_ready estiver definido como true.
  • Itera pelo buffer de gravação e imprime cada valor de amostra.

Função de callback de gravação de áudio

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;
}
}
}
}
  • Função de callback: chamada durante a gravação de áudio, responsável por copiar amostras do buffer DMA para o buffer de gravação.
  • Compilação condicional: processa a entrada usando filtros se estiver no WIO Terminal.
  • Converte valores ADC de 12 bits sem sinal para valores de áudio PCM de 16 bits (com sinal).
  • Preenchimento de amostras: copia amostras para recording_buf e atualiza o índice idx.
  • Finalizar gravação: se o número de amostras preenchidas atingir SAMPLES, reinicia o índice, marca o fim da gravação e define record_ready como verdadeiro.

Gráfico de Resultados

Aqui está a forma de onda do som reconhecido; quando você assopra, é possível ver claramente que a amplitude de oscilação da forma de onda aumenta.

Mais

Se você quiser mais códigos de exemplo, por favor clique em: -> "Example -> Seeed Arduino Mic"

XIAO MG24 Sense Microphone(Silicon Labs Demo)

dica

Precisamos baixar o pacote mais recente para a placa (2.3.0) para encontrar o código oficial mais recente no exemplo

Preparação de Software

Implementação do Código

/*
Analog microphone volume example

The example showcases the usage of analog MEMS microphones and dims the
on-board LED based on the microphone's input volume.
This example is compatible with all Silicon Labs Arduino boards, however
it requires an analog microphone on-board or connected to the specified pin.

Author: Áron Gyapjas (Silicon Labs)
*/

#include <SilabsMicrophoneAnalog.h>

// This configuration is for the MSM381ACT001 microphone on the Seeed Studio XIAO MG24
// Change it according to your hardware
#define MIC_DATA_PIN PC9
#define MIC_PWR_PIN PC8
#define NUM_SAMPLES 128
#define MIC_VALUE_MIN 735
#define MIC_VALUE_MAX 900

// Buffers for storing samples
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();
void calculate_and_display_voice_level();

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();
}
}

// Called when the requested amount of samples are available from the microphone
void mic_samples_ready_cb()
{
// Copy data to the local buffer in order to prevent it from overwriting
memcpy(mic_buffer_local, mic_buffer, NUM_SAMPLES * sizeof(uint32_t));
data_ready_flag = true;
}

void calculate_and_display_voice_level() {
// Rolling average for smoothing the voice level
static uint32_t rolling_average = 0u;

// Stop sampling in order to prevent overwriting the current data
micAnalog.stopSampling();

// Get the average of the sampled values
uint32_t voice_level = (uint32_t)micAnalog.getAverage(mic_buffer_local, NUM_SAMPLES);
// Adjust the voice level relative to minimum/maximum of the microphone's output
voice_level = constrain(voice_level, MIC_VALUE_MIN, MIC_VALUE_MAX);
// Calculate the rolling average
rolling_average = (voice_level + rolling_average) / 2;

// Map the current average level to brightness
int brightness = map(rolling_average, MIC_VALUE_MIN, MIC_VALUE_MAX, 0, 255);
if (LED_BUILTIN_ACTIVE == LOW) {
analogWrite(LED_BUILTIN, 255 - brightness);
} else {
analogWrite(LED_BUILTIN, brightness);
}
// Print the average voice level (you can use the Serial Plotter to view this value on a graph)
Serial.println(rolling_average);

// Restart sampling
micAnalog.startSampling(mic_samples_ready_cb);
}

Visão Geral das Funções

Introdução ao arquivo de cabeçalho

#include <SilabsMicrophoneAnalog.h>
  • Inclui o arquivo de cabeçalho SilabsMicrophoneAnalog.h, que contém as funções de biblioteca e definições necessárias para usar o microfone analógico.

Configuração de hardware

#define MIC_DATA_PIN  PC9
#define MIC_PWR_PIN PC8
#define NUM_SAMPLES 128
#define MIC_VALUE_MIN 735
#define MIC_VALUE_MAX 900
  • MIC_DATA_PIN: Define o pino de dados do microfone como PC9.

  • MIC_PWR_PIN: Define o pino de alimentação do microfone como PC8.

  • NUM_SAMPLES: Define o número de amostras por leitura como 128.

  • MIC_VALUE_MIN e MIC_VALUE_MAX: Definem o intervalo mínimo e máximo da saída do microfone.

Definição de buffers

uint32_t mic_buffer[NUM_SAMPLES];
uint32_t mic_buffer_local[NUM_SAMPLES];
  • mic_buffer: Usado para armazenar dados de amostra brutos coletados do microfone.

  • mic_buffer_local: Usado para armazenar temporariamente dados de amostra para evitar sobrescrita.

Flags e definições de objetos

volatile bool data_ready_flag = false;
MicrophoneAnalog micAnalog(MIC_DATA_PIN, MIC_PWR_PIN);
  • data_ready_flag: Uma flag para indicar se novos dados de amostra estão prontos.

  • micAnalog: Cria um objeto MicrophoneAnalog para controlar o microfone.

Declaração da função de callback

void mic_samples_ready_cb();
void calculate_and_display_voice_level();
  • mic_samples_ready_cb(): Uma função de callback chamada quando a amostragem é concluída.

  • calculate_and_display_voice_level(): Uma função para calcular o volume e controlar o brilho do LED.

Função setup()

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...");
}
  • Inicializa a comunicação serial com taxa de 115200 baud.

  • Define o pino do LED onboard como modo de saída.

  • Inicializa o microfone e especifica o buffer de amostras.

  • Inicia a amostragem e define a função de callback para quando a amostragem for concluída.

Função loop()

void loop()
{
if (data_ready_flag) {
data_ready_flag = false;
calculate_and_display_voice_level();
}
}
  • Verifica se data_ready_flag é true, indicando que novos dados estão prontos.

  • Se novos dados estiverem disponíveis, chama a função calculate_and_display_voice_level() para processá-los.


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

Copia os dados de amostra de mic_buffer para mic_buffer_local para evitar sobrescrita.

Define data_ready_flag como true para indicar que novos dados estão prontos.


void calculate_and_display_voice_level() {
static uint32_t rolling_average = 0u;

micAnalog.stopSampling();

uint32_t voice_level = (uint32_t)micAnalog.getAverage(mic_buffer_local, NUM_SAMPLES);
voice_level = constrain(voice_level, MIC_VALUE_MIN, MIC_VALUE_MAX);
rolling_average = (voice_level + rolling_average) / 2;

int brightness = map(rolling_average, MIC_VALUE_MIN, MIC_VALUE_MAX, 0, 255);
if (LED_BUILTIN_ACTIVE == LOW) {
analogWrite(LED_BUILTIN, 255 - brightness);
} else {
analogWrite(LED_BUILTIN, brightness);
}
Serial.println(rolling_average);

micAnalog.startSampling(mic_samples_ready_cb);
}
  • Interrompe a amostragem para evitar sobrescrita de dados.

  • Calcula a média dos dados de amostra e a restringe entre MIC_VALUE_MIN e MIC_VALUE_MAX.

  • Calcula uma média móvel para suavizar as variações de volume.

  • Mapeia a média móvel para a faixa de brilho do LED (0 a 255) e ajusta o brilho do LED.

  • Envia a média móvel via serial para observar as mudanças de volume.

  • Reinicia a amostragem para coletar novos dados de áudio.

Gráfico de Resultados

Quando assopramos no microfone, podemos ver que o LED na parte superior ficará mais claro e mais escuro de acordo com o som.

Mais

Se você quiser mais códigos de exemplo, por favor clique em: -> "Example -> SilabsMicrophoneAnalog -> MicrophoneVolume"

Recursos

Para Seeed Studio XIAO MG24 Sense

Suporte Técnico & Discussão de Produto

Obrigado por escolher nossos produtos! Estamos aqui para oferecer diferentes tipos de suporte para garantir que sua experiência com nossos produtos seja a mais tranquila possível. Oferecemos vários canais de comunicação para atender a diferentes preferências e necessidades.

Loading Comments...