Sitelet https://github.com/riccibitti/tob_IA
Skip to content

Latest commit

 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tob_IA — Installazione artistica sonora ESP-NOW + Mozzi

Installazione sonora generativa per più moduli ESP32-C3-SUPERMINI. Ogni modulo produce un paesaggio sonoro ambientale che evolve autonomamente e reagisce alla presenza degli altri dispositivi nella rete ESP-NOW, creando un'esperienza collettiva e site-specific.


Concetto

Ogni modulo genera un drone ambientale basato su sintesi FM a 3 voci (libreria Mozzi). Il suono attraversa ciclicamente cinque stati emotivi (Serene, Mysterious, Restless, Ethereal, Warm) con crossfade lenti (~20s). La presenza di altri dispositivi altera il timbro:

  • Personalità unica: ogni dispositivo ha un'impronta sonora deterministica derivata dal proprio MAC address (hash FNV-1a) che influenza detuning, rapporti FM, brillantezza e velocità di modulazione.
  • Distanza = intensità: il livello RSSI (dBm) determina il peso dell'influenza. Dispositivi vicini colorano il suono in modo più marcato.
  • Isolamento vs. folla: un modulo solo tende verso stati contemplativi (Serene, Ethereal). Più dispositivi nelle vicinanze spingono verso stati più energetici (Restless, Mysterious).

Il pulsante BOOT attiva un accent momentaneo (burst FM + filtro aperto) e invia un broadcast immediato.


Hardware

ESP32-C3-SUPERMINI

ESP32-C3-SUPERMINI pinout

Pin Funzione nel progetto
GPIO0 I2S DOUT → MAX98357 DIN
GPIO1 I2S BCLK → MAX98357 BCLK
GPIO2 I2S LRCLK → MAX98357 LRCLK
GPIO8 LED integrato (active LOW)
GPIO9 Pulsante BOOT (active LOW)

MAX98357 — Amplificatore I2S Mono 3W

MAX98357 schema

MAX98357 ESP32-C3 Note
VDD 3V3 Usare 3.3V: a 5V VIH = 3.5V, oltre il livello alto dell'ESP32 (3.3V)
GND GND Massa comune
DIN GPIO0 Dati I2S (3 pin adiacenti in basso a destra sulla scheda)
BCLK GPIO1
LRCLK GPIO2
SD_MODE (n.c.) Pull-up interno → amplificatore sempre attivo
GAIN (n.c.) Default 9 dB

Architettura di sintesi

Catena del segnale

processControl() @ 64 Hz
├─ Avanza transizione stato emotivo (interpolazione lineare)
├─ Applica influenza dispositivi rilevati (MAC→personalità, RSSI→peso)
├─ Legge 4 LFO → modula profondità FM, cutoff filtro, ampiezza, pitch
├─ Cachea valori integer per audio rate
└─ Imposta frequenze oscillatori e parametri filtro

processSample() @ 16384 Hz
┌─────────────────────────────────────────────────┐
│  mod_0 ──phMod──► carrier_0 (sub, 55-110 Hz)   │
│  mod_1 ──phMod──► carrier_1 (mid, 110-440 Hz)  ├─► MIX ─► StateVariable LP ─► Volume ─► I2S
│  mod_2 ──phMod──► carrier_2 (high, 220-880 Hz) │
└─────────────────────────────────────────────────┘

Componenti Mozzi

  • 6× Oscil<SIN2048, AUDIO_RATE> (3 carrier + 3 modulator)
  • 4× Oscil<SIN2048, CONTROL_RATE> (LFO)
  • 1× StateVariable<AUDIO_RATE> (filtro LP risonante)

Budget CPU stimato: ~58% utilizzato, ~42% headroom per WiFi ISR.

10 stati emotivi

# Nome Carattere Frequenze FM ratios Filtro
0 SERENE Consonante, caldo, dolce C2 G3 E4 1:2:3 800 Hz, Q dolce
1 MYSTERIOUS Irrazionale, oscuro C#2 A3 A4 √2, φ, √5 600 Hz, Q media
2 RESTLESS Dissonante, brillante, agitato D2 Bb3 F#4 1.5, 2.33, 3.5 2000 Hz, Q stretta
3 ETHEREAL Armonici alti, aereo, lentissimo C2 E3 B4 2:3:5 3000 Hz, Q dolce
4 WARM Ottave e quinte, basso, pieno E2 E3 B3 1:2:1.5 500 Hz, Q bassa
5 TENSE Tritoni, respiro trattenuto, irrisolto G2 C#3 G4 1.125, 2.125, 1.875 1400 Hz, Q alta
6 DESOLATE Subsonico, vuoto, immobile A1 A2 E3 1:2:3 (depth ~0) 350 Hz, Q nulla
7 ECSTATIC Gioioso, brillante, pulsante C3 G3 G4 1:2:4 2800 Hz, Q dolce
8 HYPNOTIC Trance, ottave che interferiscono A1 A2 A3 3:2:1.5 1000 Hz, Q media
9 SACRED Devozionale, quinta aperta, glaciale D2 A2 A3 2:3:4 700 Hz, Q dolce

Personalità dispositivi (da MAC)

Parametro Range Effetto
detune[0/1/2] 0.98×…1.02× (±34 ct) Detuning indipendente per ciascuna voce
fmRatioBias -0.2…+0.2 Consonanza/dissonanza FM
brightness 0.0…1.0 Influenza cutoff filtro
modulationRate 0.5×…2.0× Velocità LFO

Progetto PlatformIO

Struttura

tob_IA/
├── platformio.ini
├── README.md
├── claude.md
├── documenti/
│   ├── esp32-c3-super-mini.jpg
│   └── MAX98357 I2S Modulo Amplificatore Audio Digitale 3W Classe D.webp
└── src/
    ├── main.cpp           ← Mozzi lifecycle, ESP-NOW, I2S output
    ├── soundscape.h       ← SoundscapeEngine API
    ├── soundscape.cpp     ← Sintesi FM, stati emotivi, personalità
    ├── serial_cli.h       ← SerialCLI API
    └── serial_cli.cpp     ← Interfaccia a riga di comando via UART

platformio.ini

[env:esp32-c3-supermini]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
board = lolin_c3_mini
framework = arduino
monitor_speed = 115200

lib_deps =
    sensorium/Mozzi

build_flags =
    -DMOZZI_AUDIO_MODE=MOZZI_OUTPUT_EXTERNAL_CUSTOM
    -DMOZZI_AUDIO_RATE=16384
    -DMOZZI_CONTROL_RATE=64
    -DMOZZI_AUDIO_CHANNELS=1
Scelta Motivazione
pioarduino ESP-IDF 5.x aggiornato con le librerie che espongono la RSSI nella callback ESP-NOW
lolin_c3_mini Board ID PlatformIO più compatibile con l'ESP32-C3 SuperMini
Mozzi EXTERNAL_CUSTOM ESP32-C3 non ha DAC interno → I2S_DAC non disponibile. I2S gestito manualmente.
16384 Hz Rate Mozzi ottimale (potenza di 2); MAX98357 lo accetta via auto-detect BCLK

API SoundscapeEngine

Sintesi e controllo

engine.begin();                          // init dopo startMozzi()
engine.processControl();                 // da updateControl() @ 64 Hz
int16_t sample = engine.processSample(); // da updateAudio() @ 16384 Hz

Presenza dispositivi

engine.reportDevice(mac, rssi);          // nuovo pacchetto ESP-NOW ricevuto
engine.ageDevices(millis());             // rimuove dispositivi non visti da 10s

Controllo stati emotivi

engine.setTargetState(STATE_MYSTERIOUS); // forza transizione
engine.triggerAccent();                  // burst momentaneo (~1.5s)
engine.setAutoMode(true/false);          // abilita/disabilita ciclo autonomo
engine.setTransitionTime(20.0f);         // durata crossfade (secondi)
engine.setCycleTime(45.0f);              // permanenza in uno stato (secondi)

Override parametri (per sperimentazione)

engine.setVoiceFreq(0, 80.0f);          // voce 0 a 80 Hz
engine.setVoiceFmRatio(1, 1.618f);      // voce 1 rapporto aureo
engine.setVoiceFmDepth(2, 0.4f);        // voce 2 FM profondo
engine.setFilterCutoff(1200.0f);         // filtro a 1200 Hz
engine.setFilterResonance(100.0f);       // risonanza moderata (0=max, 255=min)
engine.setMasterVolume(0.6f);            // volume 60%

Monitoraggio

engine.getCurrentState();                // stato corrente (0–4)
engine.getTargetState();                 // stato verso cui si transita
engine.getTransitionProgress();          // 0.0–1.0
engine.getActiveDeviceCount();           // dispositivi attivi
engine.getLiveParams();                  // snapshot parametri correnti

Serial CLI

Connettendosi a 115200 baud via USB è possibile modificare qualsiasi parametro in tempo reale senza reflashare. I comandi vengono letti in modo non bloccante da updateControl() (64 Hz) e applicati immediatamente al ciclo di sintesi successivo.

Comandi

Comando Argomenti Descrizione
help / ? — Lista comandi
status — Snapshot completo di tutti i parametri live
vol <0-100> Volume globale % (sopravvive alle transizioni)
mvol <0-100> Master volume stato corrente %
state [0-9 | nome] Forza / mostra stato target
auto [on | off] Abilita/disabilita ciclo autonomo
transit <s> Durata crossfade tra stati (secondi)
cycle <s> Permanenza per stato (secondi)
preset <0-9 | nome> Ripristina parametri di fabbrica di uno stato
accent — Trigger accent burst
freq <v 0-2> <hz> Frequenza carrier voce
fmratio <v 0-2> <r> Rapporto FM modulatore/carrier
fmdepth <v 0-2> <0-1> Profondità FM
amp <v 0-2> <0-1> Ampiezza voce
filter <hz> [ris 0-255] Cutoff filtro LP + risonanza (0=max Q, 255=min Q)
lfo <i 0-3> <hz> [depth] Rate e profondità LFO

I nomi degli stati sono accettati case-insensitive (serene, WARM, Tense, …): 0=serene · 1=mysterious · 2=restless · 3=ethereal · 4=warm · 5=tense · 6=desolate · 7=ecstatic · 8=hypnotic · 9=sacred

I target dei 4 LFO: 0 = FM depth · 1 = filter cutoff · 2 = amp balance · 3 = pitch drift.

Esempio di sessione

> vol 40
[CLI] volume globale → 40%

> state mysterious
[CLI] stato target → MYSTERIOUS

> filter 1200 80
[CLI] filtro → cutoff=1200 Hz, ris=80

> lfo 1 0.08 0.6
[CLI] LFO 1 → rate=0.0800 Hz, depth=0.6000

> fmratio 0 1.618
[CLI] voce 0 FM ratio → 1.6180

> status
── Stato ──────────────────────────────────────────
  SERENE → MYSTERIOUS  (transizione 23%)
  auto=on  dispositivi=1
  vol globale=40%  master=65%
── Voci ────────────────────────────────────────────
  [0] 65.4 Hz  ratio=1.6180  depth=0.3000  amp=0.6000
  [1] 220.0 Hz  ratio=1.4142  depth=0.4000  amp=0.5000
  [2] 440.0 Hz  ratio=2.2361  depth=0.3500  amp=0.4000
── Filtro ──────────────────────────────────────────
  cutoff=1200 Hz  ris=80
── LFO ─────────────────────────────────────────────
  [0] FM depth       rate=0.0500 Hz  depth=0.3000
  [1] filter         rate=0.0800 Hz  depth=0.6000
  [2] amp balance    rate=0.0300 Hz  depth=0.2000
  [3] pitch drift    rate=0.1200 Hz  depth=0.0800
───────────────────────────────────────────────────

Output seriale (esempio)

Avvio:

[INIT] Sound installation — ESP-NOW + Mozzi
[INIT] ESP-IDF v5.1.4
[INIT] MAC: A4:E5:7C:12:34:56
[I2S] Configured at 16384 Hz, 16-bit mono
[SOUND] Engine ready — state: SERENE
[INIT] Ready — autonomous soundscape active
[INIT] Press BOOT for accent + broadcast
[CLI] Pronta. Digita 'help' per i comandi disponibili.
[CLI] Prompt: <comando> [arg1] [arg2]  (invio per eseguire)

Ricezione dispositivo:

[RECV] A4:E5:7C:78:9A:BC RSSI -52 dBm
[SOUND] New device A4:E5:7C:78:9A:BC — freq+3.2 ratio+0.08 bright0.67 modRate1.34

Status periodico:

[STATUS] state=SERENE→MYSTERIOUS (45%) devices=2 auto=on

Accent:

[BTN] Accent + broadcast
[SOUND] Accent triggered

Flash e utilizzo

# Compilare e flashare (collegare il modulo via USB)
pio run --target upload

# Aprire il monitor seriale
pio device monitor

Flash lo stesso firmware su tutti i moduli. Non è richiesta nessuna configurazione manuale. Ogni modulo genera suono autonomamente all'accensione e reagisce alla presenza degli altri.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages