Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

Componentes e Materiais

Arduino Nano 33 BLE × 1
Amplificador de Microfone Eletreto MAX9814 × 1
Display OLED I2C 0.91" 128x32 pixels × 1
Capacitor 4.7 nF — Depende do filtro RC passa-baixa e frequência de corte escolhida × 1
Capacitor 470 µF × 1
Resistor 2K Ω — Depende do filtro RC passa-baixa e frequência de corte escolhida × 1

Aplicativos e Serviços Online

Sobre o Projeto

Introdução

Veja um gráfico de barras responder a música e som num pequeno display OLED. Frequências mais graves à esquerda, mais agudas à direita.

Construção

Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

Conexões

Ruído de baixa frequência?

O ruído vem de dispositivos elétricos próximos funcionando. Todos operam em frequência e tensão fixas de corrente alternada (CA): 50 Hz ou 60 Hz conforme o país. Use uma gaiola de Faraday para eliminar: coloque o circuito numa caixa metálica e conecte a caixa ao terra. Aterre bem o circuito.

Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real
Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

Usando analogRead() do core Arduino no Nano 33 BLE, obtemos ~35.000 amostras/segundo. Não dá para usar FFT acima de 17.5 kHz (Nyquist). Como lemos o clock e fazemos comparações em loop de espera ocupada, vamos ser conservadores e limitar a 8 kHz. Um filtro RC passa-baixa simples evita frequências acima disso.

Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

R = 180Ω, C = 0.1µF → frequência de corte fc = 8842 Hz

Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

Aqui: resistor 2K Ω e capacitor 4.7 nF → fc = 17000 Hz

Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

Cálculo Aproximado da Taxa Máxima de Amostragem

analogRead() normal é lento para amostragem de áudio. Vamos estimar o máximo.

Programa de teste para estimar taxa com Arduino Nano 33 BLE:

/* Cálculo aproximado da taxa máxima de amostragem com AnalogRead */
#define ANALOG_PIN A0
#define SAMPLES 1000000.0
int newTime;
int analogValue;

void setup() {
  Serial.begin(9600);
  Serial.println("Amostrando... aguarde.");
}

void loop() {
  newTime = micros();
  for (int i = 0; i < (int)SAMPLES; i++) {
    analogValue = analogRead(ANALOG_PIN);
  }
  float elapsedTimePerSampleUs = (micros() - newTime) / SAMPLES;
  Serial.print("Tempo por amostra (us): ");
  Serial.println(elapsedTimePerSampleUs);
  Serial.print("Freq. máx. amostragem (Hz): ");
  Serial.println(pow(10,6) / elapsedTimePerSampleUs);
}
Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

Resultado: ~35.000 amostras/seg. Requisito de Nyquist (2x) limita visualizador a <17 kHz. Usamos filtro passa-baixa para cortar acima disso. Como há overhead de leitura de clock e comparações em busy wait, limitamos a 8 kHz.

// Captura de amostras
for (int i = 0; i < SAMPLES; i++) {
  unsigned long newTime = micros();
  int value = analogRead(ANALOG_PIN);
  vReal[i] = value;
  vImag[i] = 0;
  while (micros() < (newTime + sampling_period_us)) {
    yield();
  }
}

Interface do Usuário

Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

A tela é dividida em 11 zonas de frequência com escala logarítmica, agrupando frequências similarmente à percepção auditiva humana.

Ouvimos de ~20 Hz a 20 kHz (bebês ouvem ligeiramente acima; adultos 15-17 kHz). Usamos zonas 3 a 13 (11 zonas).

Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

Cada barra mostra: valor máximo na banda (linhas tracejadas) e valor médio (retângulo preenchido). Valores em decibéis com referência pré-selecionada heuristicamente.

Como Funciona

Amostras de áudio → espectro de frequência via FFT (Transformada Rápida de Fourier). Espectro dividido/agrupado em 14 zonas; 11 representadas em dB.

Sobre o Módulo de Microfone

Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real
Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real
Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

Microfone Eletreto

Eletreto é dielétrico quasi-permanentemente carregado. Feito aquecendo material cerâmico, colocando em campo magnético e resfriando no campo. Equivalente eletrostático de ímã permanente. No microfone eletreto, uma fatia desse material faz parte do dielétrico de um capacitor onde o diafragma forma uma placa. Pressão sonora move o diafragma → variação de capacitância → variação de tensão (devido à carga fixa do dielétrico). Capacitor eletreto conectado a amplificador FET embutido. Microfones eletretos são pequenos, excelente sensibilidade, ampla resposta em frequência e custo muito baixo.

Amplificador MAX9814

Amplificador de microfone com controle automático de ganho (AGC), bias de microfone de baixo ruído e algumas opções configuráveis no breakout.

Sensibilidade

Sensibilidade = razão entre tensão de saída analógica (ou valor digital) e pressão de entrada. Especificação-chave de qualquer microfone. Mapear unidades acústicas para elétricas determina magnitude do sinal de saída para entrada conhecida.

Sensibilidade = resposta elétrica na saída para entrada acústica padrão. Referência padrão: onda senoidal 1 kHz a 94 dB SPL (1 Pa). Microfone com maior sensibilidade = maior nível de saída para mesma entrada acústica. Sensibilidade em dB costuma ser negativa; maior sensibilidade = menor valor absoluto.

Para microfones analógicos, sensibilidade típica em dBV (dB referenciado a 1.0 V rms).

Nível de Referência e Resposta em Frequência

Resposta em frequência = nível de saída ao longo do espectro. Limites alto/baixo = pontos onde resposta cai 3 dB abaixo do nível de referência a 1 kHz. Nível de referência a 1 kHz usualmente normalizado a 0 dB.

Display OLED I2C 0.91" 128x32

Display pequeno, ~1" diagonal. 128x32 pixels OLED brancos individuais, cada um ligado/desligado pelo controlador. Sem backlight → menor consumo.

Modelo usado tem 4 pinos, comunica via I2C. Sem pino RESET. Conecte ao Arduino Nano I2C: SDA (A4), SCL (A5).

Para controlar: bibliotecas adafruit_SSD1306.h e adafruit_GFX.h. Instale via Gerenciador de Bibliotecas.

Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real
Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real
Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

Próximos passos: Arduino Nano 33 BLE pode fazer leituras analógicas melhores. Próxima versão usarei FFT e entrada analógica otimizada para nRF52840.

Código

Visualizador de Espectro de Som para Arduino Nano 33 BLE Arduino

Usa arduinoFFT, Adafruit_GFX, Adafruit_SSD1306

/* Sound Spectrum Visualizer for Arduino Nano 33 BLE
   Arduino based sound visualizer
   @author Enrique Albertos
   Hardware:
   - Arduino Nano 33 BLE
   - Display OLED SSD1306 I2C 128x32
   - Amplificador Microfone Eletreto MAX9814
   - Opcional: bateria para uso portátil (senão USB)
   Software:
   - arduinoFFT
   - Adafruit_GFX
   - Adafruit_SSD1306
   Conexões:
   - Mic GAIN: VCC=40dB, GND=50dB, flutuante=60dB
   - A0 → mic amp OUT
   - 3.3V, GND, SDA (A4), SCL (A5) → SSD1306 I2C
   @uses arduinoFFT, Adafruit_GFX, Adafruit_SSD1306
   Licença: GPL v3 ou posterior
*/
#include "arduinoFFT.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SAMPLES 1024        // potência de 2
#define SAMPLING_FREQ 24000 // 12 kHz Fmax = sampleF/2
#define AMPLITUDE 100       // sensibilidade
#define FREQUENCY_BANDS 14
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define BARWIDTH 11
#define BARS 11
#define ANALOG_PIN A0
#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
double vImag[SAMPLES];
double vReal[SAMPLES];
unsigned long sampling_period_us;
arduinoFFT fft = arduinoFFT(vReal, vImag, SAMPLES, SAMPLING_FREQ);
float reference = log10(50.0);
double coutoffFrequencies[FREQUENCY_BANDS];

void setup() {
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    for (;;); // loop forever
  }
  display.clearDisplay();
  display.display();
  display.setRotation(0);
  display.invertDisplay(false);
  sampling_period_us = (1.0 / SAMPLING_FREQ) * pow(10.0, 6);

  // Frequências de corte - escala logarítmica
  double basePot = pow(SAMPLING_FREQ / 2.0, 1.0 / FREQUENCY_BANDS);
  coutoffFrequencies[0] = basePot;
  for (int i = 1; i < FREQUENCY_BANDS; i++) {
    coutoffFrequencies[i] = basePot * coutoffFrequencies[i - 1];
  }

  // Linhas tracejadas separando bandas
  for (int i = 0; i < BARS - 1; i++) {
    for (int j = 0; j < SCREEN_HEIGHT; j += 4) {
      display.writePixel((i + 1) * BARWIDTH + 2, j, SSD1306_WHITE);
    }
  }
  display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SSD1306_WHITE);
}

int oldHeight[20];
int oldMax[20];
double maxInFreq;

void loop() {
  // Captura amostras
  for (int i = 0; i < SAMPLES; i++) {
    unsigned long newTime = micros();
    int value = analogRead(ANALOG_PIN);
    vReal[i] = value;
    vImag[i] = 0;
    while (micros() < (newTime + sampling_period_us)) {
      yield();
    }
  }

  // FFT
  fft.DCRemoval();
  fft.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  fft.Compute(FFT_FORWARD);
  fft.ComplexToMagnitude();

  double median[20];
  double max[20];
  int index = 0;
  double hzPerSample = (1.0 * SAMPLING_FREQ) / SAMPLES;
  double hz = 0;
  double maxinband = 0;
  double sum = 0;
  int count = 0;

  for (int i = 2; i < (SAMPLES / 2); i++) {
    count++;
    sum += vReal[i];
    if (vReal[i] > max[index]) max[index] = vReal[i];
    if (hz > coutoffFrequencies[index]) {
      median[index] = sum / count;
      sum = 0.0; count = 0; index++;
      max[index] = 0; median[index] = 0;
    }
    hz += hzPerSample;
  }

  if (sum > 0.0) {
    median[index] = sum / count;
    if (median[index] > maxinband) maxinband = median[index];
  }

  int bar = 0;
  for (int i = FREQUENCY_BANDS - 1; i >= 3; i--) {
    int newHeight = 0, newMax = 0;
    if (median[i] > 0 && max[i] > 0) {
      newHeight = 20.0 * (log10(median[i]) - reference);
      newMax = 20.0 * (log10(max[i]) - reference);
    }
    if (newHeight < 0 || newMax < 0) { newHeight = 1; newMax = 1; }
    if (newHeight >= SCREEN_HEIGHT - 2) newHeight = SCREEN_HEIGHT - 3;
    if (newMax >= SCREEN_HEIGHT - 2) newMax = SCREEN_HEIGHT - 3;

    int barX = bar * BARWIDTH + 5;

    // Apaga nível médio antigo
    if (oldHeight[i] > newHeight) {
      display.fillRect(barX, newHeight + 1, 7, oldHeight[i], SSD1306_BLACK);
    }
    // Apaga pico antigo
    if (oldMax[i] > newHeight) {
      for (int j = oldMax[i]; j > newHeight; j -= 2) {
        display.drawFastHLine(barX, j, 7, SSD1306_BLACK);
      }
    }
    // Desenha novo pico
    for (int j = newMax; j > newHeight; j -= 2) {
      display.drawFastHLine(barX, j, 7, SSD1306_WHITE);
    }
    // Desenha novo nível médio
    display.fillRect(barX, 1, 7, newHeight, SSD1306_WHITE);
    oldMax[i] = newMax;
    oldHeight[i] = newHeight;
    bar++;
  }
  display.drawFastHLine(0, SCREEN_HEIGHT - 1, SCREEN_WIDTH, SSD1306_WHITE);
  display.display();
}

Esquemáticos

soundspectrumvisualizer_qLzRsVPVlc.fzz
Visualizador de Espectro de Som com Arduino Nano 33 BLE: Display de Áudio em Tempo Real

Processo de manufatura

  1. Construa o Clássico Jogo Pong no Arduino UNO com Display OLED – Tutorial Passo a Passo
  2. Sensor K30 CO₂: Monitoramento de Qualidade do Ar Interno em Tempo Real
  3. Facilitando Comunicação Surdo-Cego com 1Sheeld e Arduino
  4. Mealheiro Inteligente: Controlar Aceitador de Moedas com Arduino Nano
  5. Controlar um LED via Bluetooth com Arduino – Guia DIY Simples
  6. Controle Dois Motores de Passo com Arduino Nano e Joystick – Tutorial Simples
  7. Transmissão de Dados de Áudio com Arduino Nano 33 BLE Sense
  8. Contador Geiger Portátil com Arduino Nano: Construa o Seu
  9. Medição Precisa de Radiação Solar com Arduino UNO e Ethernet Shield
  10. Robô Comedor com Arduino Nano – Guia Passo a Passo