sabato 6 febbraio 2021

Trasmettere streaming audio da Microfono via ESP32

Era da un pezzo che volevo ottenere uno streaming audio da poter ascoltare attraverso la rete, oggi mi sono deciso a fare dei test, seguendo questo articolo di Julian .
Il sistema e' molto semplice da realizzare, basta collegare un microfono a condensatore al pin ADC1 canale 0 del nostro ESP32, stando attenti al fatto che il pin ADC del ESP32 puo' ricevere soltanto tensioni fino ad 1 volt, quindi se l'uscita del microfono ha dei valori maggiori, dobbiamo provvedere a livellarli con un partitore di tensione.




Di seguito il circuitino:



 

Quindi collegato il microfono tra ADC channel0 e GND del ESP32,  per ottenere lo streaming basta caricare il codice che ha fornito Julian, sostituire utente , password del nostro router e numero IP del computer che ricevera' il flusso audio.

/* Audio streamer with ESP32 and Adafruit elected microphone board. 
 * Created by Julian Schroeter.
*/
#include <Arduino.h>
#include <WiFi.h>
#include <driver/adc.h>

#define AUDIO_BUFFER_MAX 800

uint8_t audioBuffer[AUDIO_BUFFER_MAX];
uint8_t transmitBuffer[AUDIO_BUFFER_MAX];
uint32_t bufferPointer = 0;

const char* ssid     = "YOUR SSID";
const char* password = "YOUR PASSWORD";
const char* host     = "YOUR SERVER IP ADDRESS";

bool transmitNow = false;

WiFiClient client;

hw_timer_t * timer = NULL; // our timer
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; 

void IRAM_ATTR onTimer() {
  portENTER_CRITICAL_ISR(&timerMux); // says that we want to run critical code and don't want to be interrupted
  int adcVal = adc1_get_voltage(ADC1_CHANNEL_0); // reads the ADC
  uint8_t value = map(adcVal, 0 , 40960255);  // converts the value to 0..255 (8bit)
  audioBuffer[bufferPointer] = value; // stores the value
  bufferPointer++;
 
  if (bufferPointer == AUDIO_BUFFER_MAX) { // when the buffer is full
    bufferPointer = 0;
    memcpy(transmitBuffer, audioBuffer, AUDIO_BUFFER_MAX); // copy buffer into a second buffer
    transmitNow = true; // sets the value true so we know that we can transmit now
  }
  portEXIT_CRITICAL_ISR(&timerMux); // says that we have run our critical code
}


void setup() {
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("MY IP address: ");
  Serial.println(WiFi.localIP());
  
  adc1_config_width(ADC_WIDTH_12Bit); // configure the analogue to digital converter
  adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_0db); // connects the ADC 1 with channel 0 (GPIO 36)

  const int port = 4444;
  while (!client.connect(host, port)) {
    Serial.println("connection failed");
    delay(1000);
  }

  Serial.println("connected to server");

  timer = timerBegin(080true); // 80 Prescaler
  timerAttachInterrupt(timer, &onTimer, true); // binds the handling function to our timer 
  timerAlarmWrite(timer, 125true);
  timerAlarmEnable(timer);

}

void loop() {
  if (transmitNow) { // checks if the buffer is full
    transmitNow = false;
    client.write((const uint8_t *)audioBuffer, sizeof(audioBuffer)); // sending the buffer to our server
  }
}

Per poter ascoltare lo streaming audio, possiamo creare una connessione attraverso, per esempio, il programma nc in linux

nc -l 4444 | aplay -r 8000 -f U8

Io ho utilizzato una Raspberry Pi che ho sulla scrivania, per ricevere il segnale dall' ESP32.

Il tutto funziona anche se dobbiamo utilizzare delle accortezze per schermare le connessioni audio, altrimenti il sistema "raccatta" un sacco di disturbi e l'audio ottenuto non e' eccellente.

Buon divertimento
TecnoGeppetto