Como testamos os sistemas de microfone no STM32: a experiência dos desenvolvedores de dispositivos Yandex



Olá, sou Gennady "Crail" Kruglov da equipe de soluções de hardware Yandex.

A seleção de microfones para a matriz do microfone é uma parte complexa e interessante do nosso trabalho: testamos modelos com vários parâmetros, experimentamos várias configurações da matriz e melhoramos os algoritmos de processamento de som.

É conveniente para os desenvolvedores que criam algoritmos de redução de eco e ruído não apenas processar dados brutos que foram retirados anteriormente de um dispositivo em laboratório, mas também interagir, por exemplo, com uma nova matriz de microfone em tempo real, conectando-a ao laptop.

Parece simples apenas à primeira vista. Neste artigo, explicarei como resolvemos o problema de transferir som de sete microfones com uma interface PDM para um computador via USB, que nuances de hardware e software encontramos e como superá-las (spoiler: essa abordagem pode ser adaptada para matrizes com número de microfones ≤ 8 ) No final do post, compartilharei um link para o fluxo, onde mostro o processo de desenvolvimento no microcontrolador STM32 e falo sobre a próxima série.

Formulação do problema


Um pouco de fundo: para criar um feixe controlado de sensibilidade, para o primeiro Yandex.Station, um circuito com sete microfones (analógicos) foi selecionado, para a versão Mini - com quatro (já digitais). Para outros produtos, várias configurações são consideradas, mas ainda assim a matriz de sete microfones é básica, clássica.

Então, dado: sete microfones digitais, a necessidade de testá-los. Encontre: não é muito difícil de implementar e é uma maneira flexível de interagir com eles. É lógico dividir a tarefa em duas:

1. Obtenha dados de microfones.

2. Envie-os para um computador.

No dispositivo final, quando o usuário entra em contato com Alice, os sinais dos microfones digitais são enviados diretamente ao processador central (é mais correto chamá-lo SoC - System-on-Chip, mas o "processador" é mais familiar e conveniente), e possui energia suficiente para processá-los. Porém, para algoritmos de depuração, é muito mais conveniente obter esses dados diretamente no computador do desenvolvedor. A maneira mais fácil é conectar via USB: portanto, a placa deve ter um microcontrolador com a unidade apropriada. Adoramos o controlador STM32, mas é impossível enviar o fluxo de som dos microfones diretamente para ele: não há unidade de recepção de sinal PDM (modulação de densidade de pulso) - a interface de saída de microfones digitais.

Outra opção é conectar a placa do microfone à placa de depuração do fabricante do SoC usado. Mas essa decisão está vinculada ao alsamixer do Linux e seus parâmetros afetam fortemente o resultado da conversão do PDM em PCM. Esses blocos podem diferir não apenas para processadores de fabricantes diferentes, mas também para dois modelos do mesmo fornecedor. Lembro que precisávamos de uma solução simples, transparente e previsível.

Solução de hardware


Aceite a incapacidade do STM32 de aceitar o PDM multicanal. Pode-se usar o bloco SPI para receber um sinal PDM, mas apenas um microfone pode ser conectado a um barramento SPI. Trabalhamos com o controlador STM32L476RC, onde existem apenas três desses barramentos. Complexidade adicional: o sinal PDM é bastante frequente; é necessário dizimar, calcular a média, processar e filtrar - para sete microfones, essa tarefa é bastante complicada.

Como estamos falando de uma placa de depuração, e não de um protótipo para produção em massa, nos concentraremos em um chip especializado TSDP18xx. Ele faz todo o necessário: gera as frequências e sinais necessários para o PDM, calcula a média e processa o sinal do PDM, transforma tudo em um sinal I2S. Mais precisamente, TDM (Time Division Multiplexing), porque o barramento I2S assume dois canais e, se você passar mais pelos mesmos fios, não será mais correto chamá-lo de I2S.

A vantagem dessa abordagem é que todo o trabalho de preparação e cálculo da média é realizado pelo TSDP. Menos - todos os algoritmos estão bem conectados dentro deste microcircuito e não podem ser alterados. Em particular, você não pode ajustar o volume modificando os parâmetros de média. Mas para depuração, isso não é crítico.

Cuidado com as mãos: há sete microfones, oito canais no microcircuito. O que não é usado, a saída ainda está lá, então, no futuro, por simplicidade, falarei sobre o fluxo de áudio de oito canais.

Então, aumentamos o TDM de oito canais para STM32, obtemos um fluxo de áudio de oito canais. Como os dados são movidos:



Unidade de hardware SAI - STM32 para trabalhar com I2S / TDM. É muito flexível e permite implementar muitas opções de protocolo. Mas, por causa disso, é fácil ficar confuso nos requisitos de frequências.

A árvore do relógio merece um olhar mais atento. Um ressonador de quartzo de 12 MHz está conectado ao microcontrolador. Dividimos essa frequência antes de aplicar nos blocos PLL por 3 e obtemos 4 MHz. Então funciona assim:

1. Seria bom aumentar a frequência do núcleo para acompanhar tudo: por exemplo, o máximo para este controlador é 80 MHz. Usamos o primeiro bloco PLL: multiplicamos 4 MHz por 40 e dividimos por 2.

2. USB requer 48 MHz. Para fazer isso, use o segundo bloco PLL: multiplique 4 MHz por 24 e divida por 2.

3. Sobre microfones. Nossas placas de teste usam uma frequência de amostragem de Fs = 16 kHz, um padrão adotado no campo do reconhecimento de fala. A partir da frequência inicial de 4 MHz, você precisa obter algo que possa ser transformado em frequências de barramento TDM de 16 kHz (também conhecido como LRCK, também conhecido como FCK, também conhecido como FrameSync). Neste caso:

[frequência da sincronização de bits (BCLK, BitClk, Sync, SCK)] = Fs ∙ [número de canais] ∙ [número de bits por canal]

Ou seja: SCK = 16 kHz ∙ 8 ∙ 16 = 2048 kHz.

4. A folha de dados indica que a relação entre o Master Clock e a taxa de amostragem Fs é a seguinte: MasterClock = 16 kHz ∙ Divisor MCLK ∙ 256. Aqui 256 é uma constante e o divisor pode ser definido no registro. Vamos verificar o esquema - para a funcionalidade necessária, existem coeficientes para dividir a frequência PLL por 7 ou 17:



Para resumir o problema: é necessário selecionar um conjunto de fatores e divisores PLL e SAI para obter uma frequência de amostragem de 16 kHz e uma frequência de 128 vezes mais. Como o conjunto tinha um divisor obrigatório por 7 (ou 17), não funcionou para obter exatamente o resultado desejado. Eu tive que construir uma tabela de multiplicadores e divisores para obter 24.571 MHz. Dividindo essa frequência por 6 (MCLK Divider) e depois por 256 (constante), finalmente obtemos um número próximo o suficiente para 16 kHz. Agora vou explicar por que isso é tão importante.

Operação USB


O USB usa um tipo de transferência isócrono para trabalhar com dados multimídia: nesse caso, um certo valor de largura de banda e atraso é garantido no barramento USB. A entrega de dados não é garantida: se um pacote chegar com uma falha, ele será considerado perdido. Isso ocorre devido a prazos estritos: não há como perguntar novamente.

Com o tipo de transferência isócrona na velocidade USB FullSpeed ​​(é de 12 Mbit / s; é nessa velocidade que o bloco USB STM32 pode funcionar), o computador chega ao dispositivo para obter dados a cada milissegundo: após esse período, ele deve coletar os dados acumulados. Deixe-me lembrá-lo dos introdutórios: a frequência de amostragem é de 16 kHz, 8 canais, cada canal requer dois bytes, porque o som é de dezesseis bits. Total 16.000 ∙ 2 ∙ 8/1000 = 256 bytes por milissegundo. O tamanho de um pacote para um tipo de transmissão isócrono pode atingir 1023 bytes, portanto, não há problemas neste momento.

Portanto, o tamanho do pacote é de 256 bytes. Parece que está tudo bem. Dezesseis vezes recebemos dados no TDM, colocados no buffer, veio o USB, damos um pacote, repetimos ... Mas isso só acontece no mundo ideal. O problema é que, por um lado, temos 16 kHz imperfeitos (um pouco menos) e, como resultado, os dados chegam um pouco menos de uma vez a cada milissegundo. Por outro lado, o milissegundo do computador também flutua, pois está ocupado: quando pôde, veio. Ou seja, a frequência de polling do microfone difere de 16 kHz (mas sempre a mesma), e o milissegundo USB também varia em comprimento (a diferença, provavelmente, está flutuando: acontece um pouco mais, depois um pouco menos que um milissegundo ideal).

Por que isso é um problema? Você pode perder o pacote. Provavelmente é desnecessário explicar que dados completos são necessários para a depuração correta dos algoritmos. Como o pacote é perdido: eles acumularam 256 bytes de resultados, os colocaram no buffer e continuaram a medição. Um computador veio, levou o primeiro 256, ainda continuamos a medir. O computador voltou a aparecer, mas a medição ainda não foi concluída - o computador foi deixado com uma embalagem vazia. Depois terminamos de preencher o buffer e começamos a preencher outro, o próximo, até o computador chegar novamente. O computador leva apenas o último pacote e, como resultado, um pacote é perdido.



O problema é, de fato, conhecido. Existem três abordagens para lidar com isso:

  • . USB. — . «» — . USB . , , ( , 16 ), . , .
  • . .
  • Assíncrono é o melhor para esta tarefa. O dispositivo possui um gerador de frequência estável. A taxa de amostragem é mantida exatamente igual sem referência ao USB. Nesse caso, você precisa transferir dados para o dispositivo para que não haja discrepâncias significativas.

Tudo isso foi discutido mais de uma vez na Internet para o caso de reprodução de um computador para o alto-falante através de um dispositivo com codificador digital-analógico, em que o dispositivo como feedback informa quantos períodos de amostragem ocorreram desde o último pacote recebido.



Mas nossa tarefa é o oposto: a depuração requer o recebimento de dados de microfones para um computador, e a questão de gravar um sinal de microfones para um computador é mencionada apenas na melhor das hipóteses. Por que não fazer o mesmo: apresentar feedback do computador? Existe uma opção mais fácil.

Ali está ele


Usamos a adição freqüente de amostras e dois buffers para armazenar dados para envio. 16 vezes por milissegundo, adicionamos ao buffer selecionado a próxima amostra. Em algum momento, ocorre uma interrupção: o USB pegou o pacote anterior. Se o buffer nº 1 estiver cheio, ele alternará para o buffer nº 2. Quando o USB chegar para o próximo pacote, ele já estará preparado. Envie o buffer número 2 e volte para o número 1.



O USB vem para dados em diferentes momentos, o pacote inclui um número diferente de amostras. Pode ser mais e menos do que dezesseis anos; portanto, há uma chance de exceder um pacote de 256 bytes de tamanho; é melhor deixar espaço para manobra. Que seja 384 = 256 + 128: isso dará uma margem de meio milissegundo, ou seja, perdoará a fase de natação do sinal USB em 50% - essa margem deve ser mais que suficiente. Total: às vezes, mais ou menos 256 bytes são enviados, mas nunca um pacote vazio, o que evita a perda de dados. Ou seja, o problema de irregularidade foi resolvido aumentando o pacote, ao custo de aumentar parte da largura de banda do barramento alocada para o nosso dispositivo e reduzir essa parte para outros dispositivos.

Com isso, a entrega de dados ao computador chegou ao fim. Os desenvolvedores podem ser depurados e você pode fazer perguntas nos comentários se algum tipo de pacote de dados não for suficiente para um entendimento completo.

Meus fluxos e o próximo episódio


Ultimamente, transmiti duas vezes do meu laboratório de solda em casa. No começo, eu apenas mostrei o processo de solda e disse quais dispositivos eu uso. A segunda série foi dedicada apenas ao desenvolvimento do STM32.

Os fluxos continuam. Nesta sexta-feira às 19:00, meu colega da equipe de desenvolvimento de soluções de hardware Andrey Laptev organizará uma análise on-line do Yandex.Stations Mini - mostre o interior e compartilhe os históricos de produção. Para mais diversão, Andrey aparafusará a bateria na coluna - não é a mesma coisa, trabalha com o fio. Na final, você receberá um guia que permitirá repetir essa experiência por conta própria ou criar um design mais interessante.

inscrever-separa assistir o fluxo. Você receberá uma carta com um arquivo para o calendário e um lembrete no dia do ar. Obrigado pela leitura!

All Articles