Playground Express - LEDs amb FFT i Colors per Freqüència

Preparació del maquinari i programari

Maquinari necessari:

Preparació del programari:

  1. Instal·la l'Arduino IDE des del lloc web oficial d'Arduino.
  2. Afegeix el suport per a la placa Circuit Playground Express a l'Arduino IDE:
    • Ves a "Eines" > "Placa" > "Gestor de plaques"
    • Cerca "Adafruit Circuit Playground" i instal·la-ho
  3. Instal·la les biblioteques necessàries:
    • Ves a "Eines" > "Administrar biblioteques"
    • Cerca i instal·la "Adafruit Circuit Playground" i "ArduinoFFT"

Codi Arduino


// Inclou les biblioteques necessàries
#include <Adafruit_CircuitPlayground.h>
#include <arduinoFFT.h>

// Defineix les constants per a la FFT
#define SAMPLES 64           // Nombre de mostres per a FFT (ha de ser potència de 2)
#define SAMPLING_FREQUENCY 1000 // Freqüència de mostreig (Hz)

// Crea objectes per a la FFT i variables globals
arduinoFFT FFT = arduinoFFT();
unsigned int sampling_period_us;
double vReal[SAMPLES];
double vImag[SAMPLES];

void setup() {
  // Inicialitza la placa Circuit Playground
  CircuitPlayground.begin();
  
  // Calcula el període de mostreig en microsegons
  sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
}

void loop() {
  // 1. Captura mostres d'àudio
  for (int i = 0; i < SAMPLES; i++) {
    unsigned long start_time = micros();
    vReal[i] = CircuitPlayground.mic.soundPressureLevel();
    vImag[i] = 0;
    while (micros() - start_time < sampling_period_us) {
      // Espera fins al següent mostreig
    }
  }

  // 2. Aplica FFT a les mostres d'àudio
  FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
  FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);

  // 3. Processa les bandes de freqüència i assigna colors als LEDs
  for (int i = 0; i < 10; i++) {
    double magnitude = vReal[i + 2];  // Salta les primeres bandes (soroll baix)
    int intensity = map(magnitude, 0, 200, 0, 255);  // Ajusta la intensitat

    // Assigna un color en funció de la banda de freqüència
    if (i < 3) {
      CircuitPlayground.setPixelColor(i, 0, 0, intensity);  // Baixes freqüències (Blau)
    } else if (i < 6) {
      CircuitPlayground.setPixelColor(i, 0, intensity, 0);  // Mitjanes freqüències (Verd)
    } else {
      CircuitPlayground.setPixelColor(i, intensity, 0, 0);  // Altes freqüències (Vermell)
    }
  }

  // Mostra els colors als LEDs
  CircuitPlayground.showPixels();
  
  // Petita pausa per a una actualització suau
  delay(50);
}
    

Explicació detallada del codi Arduino

Aquest codi utilitza la transformada ràpida de Fourier (FFT) per analitzar l'àudio captat pel micròfon de la placa Circuit Playground Express i visualitzar les diferents freqüències utilitzant els LEDs integrats.

Codi CircuitPython


import time
import array
import math
import audiobusio
import board
import neopixel
import adafruit_fft as fft

# Configura el micròfon i els LEDs
mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000, bit_depth=16)
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=0.5, auto_write=False)

# Configura paràmetres d'FFT
num_samples = 128
samples = array.array('H', [0] * num_samples)

# Funció per analitzar les bandes de freqüència i escollir colors
def color_from_frequency(magnitude, index):
    if index < 3:  # Baixes freqüències
        return (0, 0, int(magnitude))  # Blau
    elif index < 6:  # Mitjanes freqüències
        return (0, int(magnitude), 0)  # Verd
    else:  # Altes freqüències
        return (int(magnitude), 0, 0)  # Vermell

while True:
    # Llegeix una mostra d'àudio
    mic.record(samples, len(samples))

    # Aplica l'FFT a la mostra d'àudio
    magnitude = fft.rfft(samples)

    # Assigna colors als LEDs segons la banda de freqüència
    for i in range(10):
        if i < len(magnitude):
            scaled_magnitude = int(magnitude[i] / 500)  # Ajusta la intensitat
            pixels[i] = color_from_frequency(scaled_magnitude, i)
        else:
            pixels[i] = (0, 0, 0)  # Apaga LEDs si no hi ha dades

    pixels.show()
    time.sleep(0.05)
    

Explicació detallada del codi CircuitPython

Aquest codi en CircuitPython realitza una funció similar al codi Arduino, però està adaptat per funcionar en la plataforma CircuitPython.