Saltar al contenido principal

reSpeaker XVF3800 USB Mic Array con XIAO ESP32S3 DoA y VAD

Introducción

El ReSpeaker XVF3800 es una solución de procesamiento de voz con múltiples micrófonos basada en el XMOS XVF3800, diseñada para aplicaciones embebidas que requieren inteligencia de audio en tiempo real. El XVF3800 calcula internamente la Detección de Actividad de Voz (VAD) y la Dirección de Llegada (DoA) para indicar cuándo hay voz presente y desde qué dirección se origina. Estos resultados de inferencia pueden ser accedidos directamente por un MCU host a través de I2C usando comandos basados en recursos, lo que habilita funciones como activación por voz, localización de fuentes de sonido y retroalimentación consciente de la dirección sin procesar audio en bruto en el host.

pir

nota

El firmware que admite este código es respeaker_xvf3800_i2s_master_dfu_firmware_v1.0.x_48k_test5.bin y respeaker_xvf3800_i2s_dfu_firmware_v1.0.7.bin. Así que asegúrate de flashearlo primero

Código de Arduino

#include <Wire.h>

#define XMOS_ADDR 0x2C // I2C 7-bit address

#define GPO_SERVICER_RESID 20
#define GPO_SERVICER_RESID_LED_EFFECT 12
#define GPO_SERVICER_RESID_DOA 19
#define GPO_DOA_READ_NUM_BYTES 4

void setup() {
Serial.begin(115200);
while (!Serial);
Wire.begin();
delay(2000);
Serial.println("XVF3800 DoA Read Test Starting...");
write_led_effect(4);
}

void loop() {
uint16_t doa_values[2] = {0};
uint8_t status = 0xFF;

bool success = read_doa_values((uint8_t *)doa_values, &status);

if (success) {
Serial.print("I2C Communication SUCCESS. Status byte: 0x");
Serial.print(status, HEX);
Serial.print(" | DOA_VALUE: ");
Serial.print(doa_values[0]);
Serial.print(" | SPEECH_DETECTED: ");
Serial.println(doa_values[1]);
} else {
Serial.println("Failed to read DoA values.");
}

delay(1000);
}

bool read_versions(uint8_t *buffer, uint8_t *status) {
const uint8_t resid = 48;
const uint8_t cmd = 0 | 0x80;
const uint8_t read_len = 3;

// Step 1: Write command
Wire.beginTransmission(XMOS_ADDR);
Wire.write(resid);
Wire.write(cmd);
Wire.write(read_len + 1);
uint8_t result = Wire.endTransmission();

if (result != 0) {
Serial.print("I2C Write Error: ");
Serial.println(result);
return false;
}

// Step 2: Read response (status + payload)
Wire.requestFrom(XMOS_ADDR, (uint8_t)(read_len + 1));
if (Wire.available() < read_len + 1) {
Serial.println("I2C Read Error: Not enough data received.");
return false;
}

*status = Wire.read();
for (uint8_t i = 0; i < read_len; i++) {
buffer[i] = Wire.read();
}

return true;
}

bool read_doa_values(uint8_t *buffer, uint8_t *status) {
const uint8_t resid = GPO_SERVICER_RESID;
const uint8_t cmd = GPO_SERVICER_RESID_DOA | 0x80;
const uint8_t read_len = GPO_DOA_READ_NUM_BYTES;

// Step 1: Write command
Wire.beginTransmission(XMOS_ADDR);
Wire.write(resid);
Wire.write(cmd);
Wire.write(read_len + 1);
uint8_t result = Wire.endTransmission();

if (result != 0) {
Serial.print("I2C Write Error: ");
Serial.println(result);
return false;
}

// Step 2: Read response (status + payload)
Wire.requestFrom(XMOS_ADDR, (uint8_t)(read_len + 1));
if (Wire.available() < read_len + 1) {
Serial.println("I2C Read Error: Not enough data received.");
return false;
}

*status = Wire.read();
for (uint8_t i = 0; i < read_len; i++) {
buffer[i] = Wire.read();
}

return true;
}

void write_led_effect(uint8_t effect) {
Wire.beginTransmission(XMOS_ADDR); // Begin I2C transmission to XVF3800
Wire.write(GPO_SERVICER_RESID); // Write the resource ID
Wire.write(GPO_SERVICER_RESID_LED_EFFECT); // Write the command ID
Wire.write(1); // Write number of payload bytes
Wire.write(effect); // Write each payload byte
Wire.endTransmission(); // End the I2C transmission
}

Salida esperada

pir

Soporte técnico y debate sobre el producto

Gracias por elegir nuestros productos. Estamos aquí para ofrecerte diferentes tipos de soporte y garantizar que tu experiencia con nuestros productos sea lo más fluida posible. Ofrecemos varios canales de comunicación para adaptarnos a diferentes preferencias y necesidades.

Loading Comments...