Livre d'or audio esp32 dev-kit (débutant++)

bonjour a tous
je vous présente mon livre d'or audio.

Crée par mes soins avec l'aide de GPT ( oui ca risque de faire grincé les dents de certain ^^)
Mais par manque de temps et une forte envie de le confectionner pour que le jour de mon mariage je puisse dire c'est moi qui l'ou "fait" ^^
bref revenont a nos moutons:

materiel:

  • téléphone année 80
  • ESP32 dev-kit
  • module SD
  • DF Player mini
  • enceinte 3ohm
  • SPH0645LM4H adafruit
  • 1 résistance 1K
  • embout mâle type-C
  • câble ondulé 9 fils
  • prise adaptateur type-C
  • 2 carte SD ( attention faire des test car même si elle est en format FAT32 il est possible que la vitesse d'écriture fasse planter le projet)
  • un interrupteur (j'ai pris celui existant dans la téléphone)
  • huile de coude

et avec tous ca voici la photo du projet final :

je vous met aussi quelque photo du montage du combiné, oui j'ai soudé un fil avant de penser a mettre la gaine thermo ^^' ne me jugé pas lol



pour l'alimentation je voulais garder la prise PTT pour le gardé le côté marrant donc j'ai perdu une heure ( prévoir moins mais je voulais que tous tienne sans avoir besoin de colle et une bière devait certainement trainer près de moi lol) le peu de colle que l'on aperçois c'est dans la prise type-C car cette chinoiserie ne ce verrouillais pas fermé...

et c'est la que le massacre commence ^^. J'ai fixé comme j'ai pu les composant dans le téléphone, n'étant pas bon en logiciel 3d je n'ai pus crée un support en petg ou pla pour maintenir cela. du coups colle :person_shrugging: :rofl:

pour ceux que ça intéresse voici le câblage :

ainsi que le code généré par IA ( il ne doit surment pas être opti opti, mais ca fonction et c'est le principal non!?? :rofl:

#include <Arduino.h>
#include <SPI.h>
#include <SD.h>
#include <FS.h>
#include <driver/i2s.h>
#include <DFRobotDFPlayerMini.h>

// --- CONFIGURATION PINS ---
#define PIN_SWITCH 15
#define DFPLAYER_RX 17
#define DFPLAYER_TX 16 
#define SD_CS 5

#define I2S_WS 27 // LRCL
#define I2S_SD 33 // DOUT
#define I2S_SCK 14 // BCLK

#define SAMPLE_RATE 16000
#define MAX_RECORD_SECONDS 600

DFRobotDFPlayerMini dfplayer;
File recordingFile;
bool isRecording = false;
unsigned long recordingStartTime = 0;
HardwareSerial dfSerial(1);

// --- I2S CONFIG avec lecture en 32 bits (compatible SPH0645LM4H) ---
void setupI2SMic() {
  i2s_config_t i2s_config = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = I2S_COMM_FORMAT_I2S,
    .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
    .dma_buf_count = 8,
    .dma_buf_len = 1024,
    .use_apll = false,
    .tx_desc_auto_clear = false,
    .fixed_mclk = 0
  };

  i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_SCK,
    .ws_io_num = I2S_WS,
    .data_out_num = I2S_PIN_NO_CHANGE,
    .data_in_num = I2S_SD
  };

  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_0, &pin_config);
  i2s_zero_dma_buffer(I2S_NUM_0);
}

// --- HEADER WAV ---
void writeWavHeader(File file, uint32_t sampleRate, uint32_t dataLength) {
  uint32_t fileSize = dataLength + 36;
  file.seek(0);
  file.write((const uint8_t*)"RIFF", 4);
  file.write((const uint8_t*)&fileSize, 4);
  file.write((const uint8_t*)"WAVE", 4);
  file.write((const uint8_t*)"fmt ", 4);

  uint32_t subchunk1Size = 16;
  uint16_t audioFormat = 1;
  uint16_t numChannels = 1;
  uint32_t byteRate = sampleRate * numChannels * 2;
  uint16_t blockAlign = numChannels * 2;
  uint16_t bitsPerSample = 16;

  file.write((const uint8_t*)&subchunk1Size, 4);
  file.write((const uint8_t*)&audioFormat, 2);
  file.write((const uint8_t*)&numChannels, 2);
  file.write((const uint8_t*)&sampleRate, 4);
  file.write((const uint8_t*)&byteRate, 4);
  file.write((const uint8_t*)&blockAlign, 2);
  file.write((const uint8_t*)&bitsPerSample, 2);

  file.write((const uint8_t*)"data", 4);
  file.write((const uint8_t*)&dataLength, 4);
}

String generateUniqueFilename() {
  int index = 1;
  String filename;
  do {
    filename = "/RECORD" + String(index++) + ".WAV";
  } while (SD.exists(filename));
  return filename;
}

void startRecording() {
  String filename = generateUniqueFilename();
  recordingFile = SD.open(filename, FILE_WRITE);
  if (!recordingFile) {
    Serial.println("Erreur ouverture fichier !");
    return;
  }

  Serial.println("Enregistrement : " + filename);
  uint8_t header[44] = {0};
  recordingFile.write(header, 44);
  isRecording = true;
  recordingStartTime = millis();
}

void stopRecording() {
  if (!isRecording) return;
  size_t dataSize = recordingFile.size() - 44;
  writeWavHeader(recordingFile, SAMPLE_RATE, dataSize);
  recordingFile.close();
  Serial.println("Fin de l'enregistrement.");
  isRecording = false;
}

void setup() {
  Serial.begin(115200);
  pinMode(PIN_SWITCH, INPUT_PULLUP);

  if (!SD.begin(SD_CS)) {
    Serial.println("Erreur carte SD !");
    while (true);
  }

  setupI2SMic();

  dfSerial.begin(9600, SERIAL_8N1, DFPLAYER_TX, DFPLAYER_RX);
  if (!dfplayer.begin(dfSerial)) {
    Serial.println("DFPlayer non détecté !");
  } else {
    dfplayer.volume(15);
  }
}

void loop() {
  static bool combinéDécroché = false;
  bool interrupteurActif = digitalRead(PIN_SWITCH) == LOW;

  if (interrupteurActif && !combinéDécroché) {
    combinéDécroché = true;
    dfplayer.play(random(1, 4));
    delay(2000);
    startRecording();
  }

  if (combinéDécroché && isRecording) {
    const int bufferSize = 1024;
    uint8_t buffer[bufferSize];
    size_t bytesRead = 0;
    esp_err_t result = i2s_read(I2S_NUM_0, buffer, bufferSize, &bytesRead, 100);

    if (result == ESP_OK && bytesRead > 0) {
      int32_t* samples32 = (int32_t*)buffer;
      int sampleCount = bytesRead / 4;

      int16_t sample16;
      int32_t sum = 0;

      for (int i = 0; i < sampleCount; i++) {
        sample16 = samples32[i] >> 15; // Converti 32 bits -> 16 bits signé
        sum += abs(sample16);
        recordingFile.write((uint8_t*)&sample16, 2);
      }

      int moyenne = sum / sampleCount;
      Serial.print("Niveau audio : ");
      Serial.println(moyenne);
    }

    if (!interrupteurActif || (millis() - recordingStartTime > MAX_RECORD_SECONDS * 1000)) {
      stopRecording();
      combinéDécroché = false;
    }
  }

  delay(10);
}

voila voila bonne journée a tous :smiley:

Bonjour,

Super

Mais en fait, ça fait quoi tout ça?

Bonne journée.

Ba un livre d'or audio, les invités à son mariage, décroche le téléphone et laisse un message à la destinnation des mariés.
Ils pourront alors se repasser la clé USB pendant les longs soirées d'hiver et le faire écouter à leur petit enfants dans des dizaines d'années

1 Like

Bonjour qu3nt1n01

Oui, je vais me permettre :wink:
C'est super, c'est le genre de truc que j'adore, bravo!

Je ne vois pas pourquoi, je l'utilise pour quasiment tout mes projets comme support, ça me permet d'aller plus loin et de faire des programmes plus performants, d'apprendre pas mal de trucs etc.
Alors, ne te gêne pas, c'est "l'outil d'aujourd'hui" :wink:

Cordialement
jpbbricole

Oups, je suis pas à la mode moi, je ne me suis marié qu'une fois à une époque où on écrivait sur les livres!

(Et puis je vais ni aux mariages ni aux enterrements maintenant que je suis grand).

C'est vrai, maintenant, quand tu va chez un spécialiste, et qu'il "écrit" son compte rendu, il prend son dictaphone!

Où ais-je la tête!

Ben c'est un super projet alors.

Je me suis senti tellement seul quand j'ai soudé :rofl: :rofl:

merci :slight_smile:

d'accord je n'aurais pas pensé que c'était autant utilisé, car il faut lui poser les questions dans tous sens car il répond régulièrement a côté de la plaque!!

Je ne sais pas si c'est un effet de mode, mais j'ai trouvé le principe marrant les gens pourrons poser des messages a n'apporte qu'elle moment de la soirée et dans les états qu'ils le souhaite. Qui c'est on aura surement des révélations sur les messages poser a 4h du matin :rofl::rofl::rofl:

le plus chiant vas être de relire tes les clips audio!!! qui risque d'être hyper long :sweat_smile:

merci bien :smiley:

Bonjour qu3nt1n01

J'ai fait quelques projets avec et ai réussi à avoir un dialogue tout à fait constructif, avec des résultats au-delà de mes espérances.
Mais, c'est vrai, c'est tout un apprentissage :wink:

A+
jpbbricole

d'accord cool, avec votre expérience vous lui transmettez de meilleurs prompts! un jour j'y arriverai aussi xD

oui, un sacré apprentissage ^^

a une prochaine :waving_hand:

Ce n'est pas un problème d'expérience.
Tout est dans la manière d'exprimer un besoin.

C'est moins un problème d'expérience que de formulation du besoin.
C'est le même problème que tu rencontres lorsque tu demandes à quelqu'un de te fabriquer un appareil. Si tu donnes les infos dans le désordre sans liens entre elles en mettant au même niveau les contraintes et le superflu tu as peu de chance d'obtenir ce que tu veux.

Surtout que l'IA n'est déjà pas forte pour générer des schema de circuit, alors faire de la soudure :slight_smile:

Oui, c'est pour ça qu'a quelque execption près, les membres ne recommande pas l'IA au débutant.
L'IA est vraiment performattante pour les personnes non expertes, mais quand même initié.

Si il est clair que la maniére joue un grand role, cela n'est pas forcément suffisant.
Surtout que bien souvent le jeu de ping pong(question/réponse) est assez peu productif, en tout cas avec la version gratuite.
Sans parler, qu'il faut être capable de détecter les erreurs chronique de l'IA, donc avec une certaine expérience du code.

1 Like

Bonsoir;

L'IA reconnait son maitre, c'est comme ma chienne, quand je la rappelle, elle revient au pied :kissing_face_with_smiling_eyes:

Oui, enfin, des fois, .... :face_with_diagonal_mouth:
(l'IA oui, ma chienne non, elle ne revient que quand elle veut bien, et en ce moment, elle veut peu)

Dans les deux cas, c'est une question d'entrainement et de stimuli :slight_smile:

La chienne, avec quelques croquettes, elle finit par revenir.
Pas certain que ça fonctionne avec L'IA... :thinking:

C'est vrai que la motivation croquettes finit toujours par refaire surface quand vient le moment du constat "un lièvre ou un lapin, ça cours trop vite pour une vieille chienne".

Par contre, ma chienne, comme l'IA, ne me comprend pas vraiment si je ne respecte pas certaines bonnes pratiques, moins il y a de mots "alambiqués" mieux elle comprend.

"Viens ici", elle comprend.
"Très chère vieille canidé, s'il te plaît, approche de ton maître bien aimé", elle ne comprend pas.

Un peu comme l'IA.

Mais si je met le ton avant le sens, en criant bien fort juste son noms, elle comprend qu'il vaudrait mieux revenir, ou même si j'utilise un ton plaisantin, elle comprend que l'heure est au jeu.
Pas comme l'IA qui se fout du ton.

Tout est une question de stimuli, plus tu es un stimuli intéressant, plus elle aura tendance à revenir, donc mieux vaudrait utiliser un ton enjoué et la récompenser lorsqu'une revient à toi.
Car il faut l'avouer on est bien moins intéressant qu'un lapin :slight_smile: