Wm8960 Problème de bourdonnement

Bonjour, j'ai acheté pour tester du brouillage audio avec 2 wm8960 et 2 esp32-s3 .

J'arrive a un problème insoluble qui est un bourdonement sur la sortie audio.

Je n'arrive pas a trouver le problème.

J'ai essayé de diminuer la longueur des cables mais sa ne change rien.

Une photo de la carte utilisé:

Voici mes connections entre les 2 cartes:

ESP32-S3 Waveshare WM8960
GPIO8 SDA
GPIO9 SCL
GPIO5 CLK
GPIO6 WS
GPIO4 TXSDA
GPIO7 RXSDA
3V3 VCC (pin1 et pin2)
GND GND (pin 3 et pin4)

Si quelqu'un a une idée, voici mon code actuel de la partie brouillage audio:

#include <Arduino.h>
#include <Wire.h>
#include <math.h>

#include "AudioTools.h"
#include "AudioTools/AudioLibs/WM8960Stream.h"

// =====================================================
// ESP32-S3 + WAVESHARE WM8960
//
// EMBROUILLAGE AUDIO PAR INVERSION DU SPECTRE
//
// Micro integre -> Amplification x2
// -> Inversion des frequences -> Casque
//
// Frequence d'inversion : 3300 Hz
// =====================================================


// -----------------------------------------------------
// BROCHES I2C
// -----------------------------------------------------

#define I2C_SDA 8
#define I2C_SCL 9


// -----------------------------------------------------
// BROCHES I2S
// -----------------------------------------------------

#define I2S_BCLK 5
#define I2S_WS   6
#define I2S_DIN  4
#define I2S_DOUT 7


// -----------------------------------------------------
// PARAMETRES AUDIO
// -----------------------------------------------------

#define SAMPLE_RATE 44100

#define FREQUENCE_INVERSION 3300.0f

#define AMPLIFICATION 2.0f

#define PI_F 3.14159265358979323846f


// -----------------------------------------------------
// FILTRE FIR HILBERT
// -----------------------------------------------------

#define HILBERT_TAPS 63

#define HILBERT_DELAY ((HILBERT_TAPS - 1) / 2)

float coefficientsHilbert[HILBERT_TAPS];

float historique[HILBERT_TAPS];

int positionHistorique = 0;


// -----------------------------------------------------
// FILTRE PASSE-BAS
// -----------------------------------------------------

#define LP_TAPS 63

float coefficientsPasseBas[LP_TAPS];

float historiqueSortie[LP_TAPS];

int positionSortie = 0;


// -----------------------------------------------------
// OSCILLATEUR
// -----------------------------------------------------

float phase = 0.0f;

float incrementPhase =
    2.0f * PI_F * FREQUENCE_INVERSION / SAMPLE_RATE;


// -----------------------------------------------------
// WM8960
// -----------------------------------------------------

WM8960Stream audio;


// -----------------------------------------------------
// BUFFERS AUDIO
// -----------------------------------------------------

uint8_t bufferLecture[512];

int16_t bufferSortie[256];


// =====================================================
// CREATION DU FILTRE HILBERT
// =====================================================

void initialiserHilbert() {

  for (int i = 0; i < HILBERT_TAPS; i++) {

    int k = i - HILBERT_DELAY;

    float coefficient = 0.0f;

    if (k != 0 && (abs(k) % 2) == 1) {

      coefficient = 2.0f / (PI_F * k);
    }

    // Fenetre de Hamming
    float fenetre =
        0.54f -
        0.46f * cosf(
          2.0f * PI_F * i / (HILBERT_TAPS - 1)
        );

    coefficientsHilbert[i] = coefficient * fenetre;

    historique[i] = 0.0f;
  }
}


// =====================================================
// CREATION DU FILTRE PASSE-BAS
// =====================================================

void initialiserPasseBas() {

  const float coupure = 3200.0f;

  const float fc = coupure / SAMPLE_RATE;

  float somme = 0.0f;

  for (int i = 0; i < LP_TAPS; i++) {

    int k = i - (LP_TAPS - 1) / 2;

    float coefficient;

    if (k == 0) {

      coefficient = 2.0f * fc;

    } else {

      coefficient =
          sinf(2.0f * PI_F * fc * k) /
          (PI_F * k);
    }

    float fenetre =
        0.54f -
        0.46f * cosf(
          2.0f * PI_F * i / (LP_TAPS - 1)
        );

    coefficientsPasseBas[i] = coefficient * fenetre;

    somme += coefficientsPasseBas[i];

    historiqueSortie[i] = 0.0f;
  }

  // Normalisation
  for (int i = 0; i < LP_TAPS; i++) {

    coefficientsPasseBas[i] /= somme;
  }
}


// =====================================================
// FILTRE PASSE-BAS
// =====================================================

float filtrerPasseBas(float entree) {

  historiqueSortie[positionSortie] = entree;

  float resultat = 0.0f;

  int index = positionSortie;

  for (int i = 0; i < LP_TAPS; i++) {

    resultat +=
        coefficientsPasseBas[i] *
        historiqueSortie[index];

    index--;

    if (index < 0) {
      index = LP_TAPS - 1;
    }
  }

  positionSortie++;

  if (positionSortie >= LP_TAPS) {
    positionSortie = 0;
  }

  return resultat;
}


// =====================================================
// INVERSION DU SPECTRE
// =====================================================

float inverserSpectre(float entree) {

  historique[positionHistorique] = entree;

  // Signal retarde pour alignement de phase
  int indexRetard =
      positionHistorique - HILBERT_DELAY;

  if (indexRetard < 0) {
    indexRetard += HILBERT_TAPS;
  }

  float signalI = historique[indexRetard];

  // Transformee de Hilbert
  float signalQ = 0.0f;

  int index = positionHistorique;

  for (int i = 0; i < HILBERT_TAPS; i++) {

    signalQ +=
        coefficientsHilbert[i] *
        historique[index];

    index--;

    if (index < 0) {
      index = HILBERT_TAPS - 1;
    }
  }

  positionHistorique++;

  if (positionHistorique >= HILBERT_TAPS) {
    positionHistorique = 0;
  }

  // Oscillateur 3300 Hz
  float c = cosf(phase);
  float s = sinf(phase);

  phase += incrementPhase;

  if (phase >= 2.0f * PI_F) {
    phase -= 2.0f * PI_F;
  }

  // Inversion du spectre
  float resultat = signalI * c + signalQ * s;

  return resultat;
}


// =====================================================
// CONVERSION EN 16 BITS
// =====================================================

int16_t convertir16bits(float valeur) {

  if (valeur > 32767.0f) {
    valeur = 32767.0f;
  }

  if (valeur < -32768.0f) {
    valeur = -32768.0f;
  }

  return (int16_t)valeur;
}


// =====================================================
// INITIALISATION
// =====================================================

void setup() {

  Serial.begin(115200);

  delay(1500);

  Serial.println();
  Serial.println("====================================");
  Serial.println(" ESP32-S3 + WM8960");
  Serial.println(" EMBROUILLAGE PAR INVERSION DU SPECTRE");
  Serial.println("====================================");

  Wire.begin(I2C_SDA, I2C_SCL);

  Wire.setClock(100000);

  auto config = audio.defaultConfig(RXTX_MODE);

  config.sample_rate = SAMPLE_RATE;
  config.channels = 2;
  config.bits_per_sample = 16;

  config.wire = &Wire;

  config.pin_bck = I2S_BCLK;
  config.pin_ws = I2S_WS;

  config.pin_data_rx = I2S_DIN;
  config.pin_data = I2S_DOUT;

  config.is_master = true;

  // Oscillateur 24 MHz de la carte
  config.vs1053_mclk_hz = 24000000;
  config.vs1053_enable_pll = true;

  // Microphone et casque
  config.features =
      WM8960_FEATURE_MICROPHONES |
      WM8960_FEATURE_HEADPHONE;

  config.default_volume = 0.40;

  if (!audio.begin(config)) {

    Serial.println("ERREUR WM8960");

    while (true) {
      delay(1000);
    }
  }

  // Gain analogique du microphone
  mtb_wm8960_adjust_input_volume(0x10);

  // Volume casque
  mtb_wm8960_adjust_heaphone_output_volume(0x79);

  // Initialisation des filtres
  initialiserHilbert();
  initialiserPasseBas();

  Serial.println("WM8960 initialise");
  Serial.println("Microphone integre actif");
  Serial.println("Amplification numerique x2");

  Serial.print("Frequence audio : ");
  Serial.println(SAMPLE_RATE);

  Serial.print("Frequence inversion : ");
  Serial.println(FREQUENCE_INVERSION);

  Serial.println("Embrouillage actif");
}


// =====================================================
// BOUCLE PRINCIPALE
// =====================================================

void loop() {

  int n = audio.readBytes(
    bufferLecture,
    sizeof(bufferLecture)
  );

  if (n <= 0) {
    return;
  }

  int nombreTrames = n / 4;

  int16_t *echantillons =
      (int16_t *)bufferLecture;

  for (int i = 0; i < nombreTrames; i++) {

    // Micro integre : canal gauche
    float micro = (float)echantillons[i * 2];

    // Amplification numerique x2
    micro *= AMPLIFICATION;

    // Filtrage de la bande vocale
    micro = filtrerPasseBas(micro);

    // Inversion des frequences
    float brouille = inverserSpectre(micro);

    // Conversion 16 bits
    int16_t sortie = convertir16bits(brouille);

    // Sortie stereo
    bufferSortie[i * 2] = sortie;
    bufferSortie[i * 2 + 1] = sortie;
  }

  // Envoi vers le casque
  audio.write(
    (uint8_t *)bufferSortie,
    nombreTrames * 4
  );
}

Bonjour,

Même sans le brouillage?
Comment est alimenté l'ensemble?

J'ai testé du code qui genere une onde sinusoidale sur la sortie HP qui fonctionne sans bourdonement puis j'ai testé du code qui capte le son au micro integré sur la carte et le restitue sur la sortie hp et la il y a un bourdonement du genre 50htz.

J'ai également modifié la longueur des câbles, je suis passé de 40cm a 10cm , sans résultats, toujours ce bourdonnement.

J'ai également essayé d'alimenté avec une batterie externe le montage mais sa ne change rien.

Bonjour

-un oscilloscope disponible pour valider le ressenti '50Hz' du bourdonnement et mettre en évidence un bruit éventuel sur le 3V3 ?
-le bourdonnement est aussi intense sur la sortie casque en déconnectant les fils vers le(s) HP ?

Je vais vérifier ça, oui j'ai un oscilloscope.

J'ai quelques oscillations sur le 3v, j'ai essayé de mettre un 100nf et un 10uf mais sa ne change rien aux perturbation que je vois sur le canal 1. J'ai toujours le bourdonement.

bourdonement.zip (622,0 Ko)

Si la sinusoïde sort propre et que le souci n'apparaît qu'en passant par le micro, je regarderais du côté du gain d'entrée : le boost micro du WM8960 monte jusqu'à +29 dB et ramasse vite le bruit d'alim et ce que rayonne l'ESP32. Essaie de mettre le boost et le PGA au minimum pour voir si le bourdonnement baisse avec. Si le HP est tout près de la carte, un casque à la place permet aussi d'écarter un petit larsen grave.

Voicii le code utilisé pour tester, sa ecoute le micro integré a la carte et le resitue sur la sortie jack des ecouteurs.

Toujours le même bourdonement.

#include <Arduino.h>
#include <Wire.h>

#include "AudioTools.h"
#include "AudioTools/AudioLibs/WM8960Stream.h"

// =====================================================
// ESP32-S3 + WAVESHARE WM8960
//
// TEST AUDIO : MICROPHONE -> CASQUE
//
// Gain microphone : 0x00
// Amplification numerique : x4
// Volume casque : 0x79
// Frequence audio : 44100 Hz
// =====================================================


// -----------------------------------------------------
// BROCHES I2C
// -----------------------------------------------------

#define I2C_SDA 8
#define I2C_SCL 9


// -----------------------------------------------------
// BROCHES I2S
// -----------------------------------------------------

#define I2S_BCLK 5
#define I2S_WS   6
#define I2S_DIN  4
#define I2S_DOUT 7


// -----------------------------------------------------
// PARAMETRES AUDIO
// -----------------------------------------------------

#define SAMPLE_RATE 44100

#define AMPLIFICATION 4.0f

#define GAIN_MICRO 0x00

#define VOLUME_CASQUE 0x79


// -----------------------------------------------------
// CODEC WM8960
// -----------------------------------------------------

WM8960Stream audio;


// -----------------------------------------------------
// BUFFERS AUDIO
// -----------------------------------------------------

uint8_t bufferLecture[512];

int16_t bufferSortie[256];


// =====================================================
// CONVERSION AUDIO 16 BITS
// =====================================================

int16_t convertir16bits(float valeur) {

  if (valeur > 32767.0f) {
    valeur = 32767.0f;
  }

  if (valeur < -32768.0f) {
    valeur = -32768.0f;
  }

  return (int16_t)valeur;
}


// =====================================================
// INITIALISATION
// =====================================================

void setup() {

  Serial.begin(115200);

  delay(1500);

  Serial.println();
  Serial.println("====================================");
  Serial.println(" ESP32-S3 + WM8960");
  Serial.println(" TEST MICROPHONE -> CASQUE");
  Serial.println("====================================");


  // ---------------------------------------------------
  // INITIALISATION I2C
  // ---------------------------------------------------

  Wire.begin(I2C_SDA, I2C_SCL);

  Wire.setClock(100000);


  // ---------------------------------------------------
  // CONFIGURATION AUDIO
  // ---------------------------------------------------

  auto config = audio.defaultConfig(RXTX_MODE);

  config.sample_rate = SAMPLE_RATE;

  config.channels = 2;

  config.bits_per_sample = 16;

  config.wire = &Wire;


  // ---------------------------------------------------
  // BROCHES I2S
  // ---------------------------------------------------

  config.pin_bck = I2S_BCLK;

  config.pin_ws = I2S_WS;

  config.pin_data_rx = I2S_DIN;

  config.pin_data = I2S_DOUT;


  // ---------------------------------------------------
  // HORLOGE
  // ---------------------------------------------------

  config.is_master = true;

  config.vs1053_mclk_hz = 24000000;

  config.vs1053_enable_pll = true;


  // ---------------------------------------------------
  // ACTIVATION MICROPHONE ET CASQUE
  // ---------------------------------------------------

  config.features =
      WM8960_FEATURE_MICROPHONES |
      WM8960_FEATURE_HEADPHONE;

  config.default_volume = 0.40;


  // ---------------------------------------------------
  // INITIALISATION WM8960
  // ---------------------------------------------------

  if (!audio.begin(config)) {

    Serial.println("ERREUR : WM8960 non initialise");

    while (true) {
      delay(1000);
    }
  }


  // ---------------------------------------------------
  // GAIN ANALOGIQUE MICROPHONE
  // ---------------------------------------------------

  mtb_wm8960_adjust_input_volume(GAIN_MICRO);


  // ---------------------------------------------------
  // VOLUME CASQUE
  // ---------------------------------------------------

  mtb_wm8960_adjust_heaphone_output_volume(VOLUME_CASQUE);


  Serial.println("WM8960 initialise");

  Serial.println("Microphone integre actif");

  Serial.print("Gain microphone : 0x");
  Serial.println(GAIN_MICRO, HEX);

  Serial.print("Amplification numerique : x");
  Serial.println(AMPLIFICATION);

  Serial.print("Volume casque : 0x");
  Serial.println(VOLUME_CASQUE, HEX);

  Serial.print("Frequence audio : ");
  Serial.println(SAMPLE_RATE);

  Serial.println();
  Serial.println("Transmission microphone -> casque active");
}


// =====================================================
// BOUCLE PRINCIPALE
// =====================================================

void loop() {

  // Lecture du microphone

  int n = audio.readBytes(
    bufferLecture,
    sizeof(bufferLecture)
  );

  if (n <= 0) {
    return;
  }


  // Chaque trame stereo contient 4 octets :
  //
  // 2 octets canal gauche
  // 2 octets canal droit

  int nombreTrames = n / 4;

  int16_t *echantillons =
      (int16_t *)bufferLecture;


  // ---------------------------------------------------
  // TRAITEMENT AUDIO
  // ---------------------------------------------------

  for (int i = 0; i < nombreTrames; i++) {

    // Microphone integre : canal gauche

    float micro = (float)echantillons[i * 2];


    // Amplification numerique x4

    micro *= AMPLIFICATION;


    // Limitation et conversion 16 bits

    int16_t sortie = convertir16bits(micro);


    // Restitution sur les deux canaux du casque

    bufferSortie[i * 2] = sortie;

    bufferSortie[i * 2 + 1] = sortie;
  }


  // ---------------------------------------------------
  // ENVOI AUDIO VERS LE CASQUE
  // ---------------------------------------------------

  audio.write(
    (uint8_t *)bufferSortie,
    nombreTrames * 4
  );
}

Les principaux réglages son ceux ci:

Fréquence d'échantillonnage 44 100 Hz
Résolution 16 bits
Gain analogique microphone 0x00 (minimum)
Amplification numérique ×4
Volume casque 0x79
Boost microphone 0 dB (configuration de la bibliothèque)
Fréquence I2C 100 kHz
Horloge configurée 24 MHz

Je viens de tester en alimentant le wm8960 avec une alim de labo en 3.3v en conservant la masse commune avec l'esp32-s3 et j'entend toujours un bourdonement.

Peu etre que les 2 cartes ont un default?

  1. L'ampli classe D 1W rayonne également.
    Le bourdonnement est il le même sur casque quand aucun fil n'est raccordé aux sorties vers HP ?

En réalité je n'utilise que la sortie jack, je n'utiliee pas la sortie hp.

Puisque l'alim de labo ne change rien, je regarderais du côté de la masse par l'USB : si l'ESP32 reste branché au PC pendant le test, essaie de l'alimenter sur une batterie ou un chargeur de téléphone. Autre test simple : coupe l'entrée micro dans le WM8960 en laissant tourner le reste du code. Si le bourdonnement disparaît, il entre par le micro ou son câblage, sinon il vient de l'alimentation ou de la masse de la carte. Et l'amplification numérique x4 n'aide pas, elle remonte le bruit autant que la voix.

J'ai déjà essayé d'alimenter le montage avec une batterie externe et toujours le bourdonnement.

D'accord, donc ce n'est ni l'alim ni la masse USB. Tu as pu essayer en coupant l'entrée micro dans le WM8960 ? Si le bourdonnement disparaît, c'est le micro de la carte qui ramasse le bruit de l'ESP32, sinon il faut regarder du côté des horloges I2S.

Oui, j'ai déjà effectué plusieurs essais pour identifier l'origine du bourdonnement.

J'ai notamment testé la réduction du gain du microphone du WM8960 au minimum, ainsi que différentes configurations des entrées microphone. Le bourdonnement reste présent.

J'ai également remplacé les échantillons audio reçus par des valeurs nulles dans le programme de l'ESP32-S3. Dans ce cas, le casque semble silencieux.

J'ai ensuite étudié les horloges I2S à l'oscilloscope. En configurant le WM8960 en maître I2S, j'avais initialement un signal WS d'environ 43,87 kHz, mais aucun signal BCLK.

En examinant la bibliothèque Arduino, j'ai constaté que le registre CLK2, qui configure le diviseur BCLK, n'était pas initialisé explicitement.

Après avoir ajouté cette configuration, j'obtiens maintenant :

  • WS : 43,87 kHz

  • BCLK : environ 1,4 MHz

Depuis cette modification, j'entends correctement ma voix dans le casque, mais un bourdonnement permanent subsiste, même lorsque je ne parle pas.

J'ai également constaté que lorsque je réduis l'amplification numérique de ×4 à ×1, le volume de la voix et celui du bourdonnement diminuent simultanément.

Je soupçonne donc un bruit présent dans le signal audio numérisé, mais je n'ai pas encore déterminé s'il provient du microphone, de l'ADC du WM8960 ou d'un problème de synchronisation I2S.

Il reste notamment à tester la désactivation complète du chemin microphone dans le WM8960, plutôt que la simple réduction de son gain.

Bien vu pour le registre CLK2. Si le bourdonnement baisse en même temps que la voix quand tu réduis le gain numérique, c'est qu'il est déjà dans les échantillons, donc côté micro ou ADC. Pour trancher, coupe complètement l'entrée micro dans le registre R25 (bits AINL, AINR et MICB) en laissant l'ADC actif : si le bruit reste, c'est l'ADC ou les horloges. Au passage, 43,87 kHz au lieu de 44,1 laisse penser que les diviseurs ne tombent pas juste. Enregistrer quelques secondes pour mesurer la fréquence du bourdonnement aiderait aussi, 50 ou 100 Hz pointerait plutôt l'alimentation.

Je pense stopper ce projet pour le moment car je ne trouve pas l'origine du problème. Je me suis grandement aidé de chat gpt pour essayer de resoudre ce problème mais je tourne en rond. (plusieur jours passé a tester differentes config)

Je pense peut etre essayer un autre modèle de carte wm8960 pour voir si ce boudonement est lié a la conception de la carte.

Dommage, mais changer de carte est un bon test : si le bourdonnement reste le même avec un autre module, ça viendra plutôt de l'alim ou du câblage. Si vous reprenez, essayez d'abord de tout alimenter sur une batterie plutôt que par l'USB du PC, ça élimine d'un coup la piste de la boucle de masse.

J'ai reçu une nouvelle référence de carte prevu a la base pour raspberry py.

J'ai alimenté comme ceci:

ESP32-S3 N16R8 CL-WM8960 (broche physique Raspberry Pi) Fonction
5V Pin 2 Alimentation 5 V
3V3 Pin 1 Alimentation 3,3 V
GND Pin 6 Masse commune
GPIO 12 Pin 3 I2C SDA
GPIO 15 Pin 5 I2C SCL
GPIO 5 Pin 12 I2S BCLK (horloge audio)
GPIO 6 Pin 35 I2S LRCLK (synchronisation audio)
GPIO 7 Pin 40 I2S DAC (ESP32 → WM8960)
GPIO 4 Pin 38 I2S ADC (WM8960 → ESP32)

J'ai testé ce programme mais la communication i2c ne fonctionne pas.

#include <Arduino.h>
#include <Wire.h>
#include "AudioTools.h"
#include "AudioTools/AudioLibs/WM8960Stream.h"

using namespace audio_tools;

// =====================================
// BROCHES ESP32-S3
// =====================================

#define I2C_SDA 12
#define I2C_SCL 15

#define I2S_BCLK 5
#define I2S_LRCLK 6
#define I2S_DOUT 7

// =====================================
// PARAMETRES AUDIO
// =====================================

#define SAMPLE_RATE 44100
#define FREQUENCE 1000

// =====================================
// OBJETS AUDIO
// =====================================

WM8960Stream audio;

SineWaveGenerator<int16_t> sine;
GeneratedSoundStream<int16_t> sound(sine);

StreamCopy copier(audio, sound);

// =====================================
// SETUP
// =====================================

void setup() {

  Serial.begin(115200);
  delay(2000);

  Serial.println();
  Serial.println("==============================");
  Serial.println(" TEST WM8960 AUDIO HAT");
  Serial.println(" ESP32-S3 N16R8");
  Serial.println("==============================");

  // Initialisation I2C
  Wire.begin(I2C_SDA, I2C_SCL);

  // Verification du WM8960
  Wire.beginTransmission(0x1A);

  if (Wire.endTransmission() != 0) {
    Serial.println("ERREUR : WM8960 non detecte !");
    while (true) {
      delay(1000);
    }
  }

  Serial.println("WM8960 detecte sur I2C 0x1A");

  // Configuration audio
  auto config = audio.defaultConfig(TX_MODE);

  config.sample_rate = SAMPLE_RATE;
  config.bits_per_sample = 16;
  config.channels = 2;

  config.pin_bck = I2S_BCLK;
  config.pin_ws = I2S_LRCLK;
  config.pin_data = I2S_DOUT;

  config.pin_mck = -1;

  Serial.println("Initialisation WM8960...");

  if (!audio.begin(config)) {
    Serial.println("ERREUR initialisation WM8960 !");
    while (true) {
      delay(1000);
    }
  }

  // Volume de depart modere
  audio.setVolume(0.35);

  Serial.println("WM8960 initialise");

  // Generation sinus
  auto cfg = sine.defaultConfig();

  cfg.sample_rate = SAMPLE_RATE;
  cfg.channels = 2;
  cfg.bits_per_sample = 16;

  sine.begin(cfg, FREQUENCE);

  Serial.println("Generation tonalite 1000 Hz");
  Serial.println("Volume : 35%");
  Serial.println("Test en cours...");
}

// =====================================
// LOOP
// =====================================

void loop() {

  copier.copy();

}

J'obtiend: ```

ERREUR : WM8960 non detecte !

Par curiosité j'ai verifié si le 3.3v est bien sur la pin 1, et il n'est pas present hors il y a un regulateur abaisseur qui devrait faire du 3.3v depuis le 5v. D'apres ce schema:

Une idée?
Je mesure aucune tension sur le 3.3v.

Je pense avoir correctement connecté la carte...

Bonsoir

Pas de résistances de pullup I2C sur le 'Hat' WM8960, s'il n'y en pas sur ta carte à ESP32 le bus I2C ne peut pas fonctionner, empếchant la détection du WM8960
Le Hat est conçu pur être raccordé à une carte Raspberry Pi dotée de pull-up sur l'I2C

3V3 Pin 1 Alimentation 3,3 V

je ne vois pas l'intérêt de cette liaison entre ESP32 et HAT WM8960 puisque le HAT produit son 3,3V avec un régulateur linéaire RT9193 à partir du 5V reçu.
Oublies le marquage 3V3 du connecteur Raspberry Pi si tu ne raccordes pas le Hat à un Raspberry Pi qui enverrait 3V3 sur cette broche. Je suppose que sur le HAT la pin 1 du connecteur Raspberry GPIO n'est pas reliée.

si tu veux tester la présence du 3V3 va par exemple sur une borne du bouton poussoir K1, côté pull-up

Par ailleurs as-tu testé ce HAT avec un Raspberry Pi ?