Use the ESP32 and the Adafruit Electret Microphone Amplifier Board to stream your voice over WiFi to your Raspberry Pi.
Story
There are many things that do audio streaming nowadays. Smart assistants like Alexa and Google Home are great examples. This got me thinking about trying something with tone too. I decided to build an electret microphone and an amplifier using an operational amplifier. I connected it to an ESP8266 developer board. While the program worked, it sometimes had pauses while playing the audio in real-time. I tried using interrupts, but they didnāt solve the issue. Additionally, the signal was very noisy. So, I upgraded to an ESP32 board and Adafruitās Electret Microphone Amplifier Board. Making some adjustments to the code, it started working!
Step 1: Building the Circuit
Regrettably, the analog input range on our device is limited to 0-1V. Since our microphone outputs a voltage between 0 and 2.25V, we require a voltage divider to bring it within the acceptable range. The diagram below illustrates the voltage divider setup. Connect the yellow cable directly to the ADC of your ESP32 board. Donāt forget to also connect the ground and 5V (Vin) lines to your ESP32. When working with 5V levels and 3.3V logic, take necessary precautions to avoid any potential issues.
When you donāt have the resistors you can also use a 10kĪ© potentiometer and set it to 5.6k and 4.4k.
Step 2: Set up the code
Open the Arduino software on your computer. Paste the Arduino code from the CODE section below in the editor. (Donāt forget to remove the standard code before!) Now change your WiFi credentials in the following path of the code:
const char* ssid = "YOUR SSID";
const char* password = "YOUR PASSWORD";
Furthermore, you have to set the IP Address of your Raspberry Pi.
const char* host = "YOUR SERVER IP ADDRESS";
Now you can upload the code to your ESP32 board. To Tools-> Board and select your ESP32 board. Now select the Port at Tools-> Port. Now you click āuploadā to upload your Sectch.
Step 3: Get streaming
Configure your Raspberry Pi by connecting to it and verifying that the correct audio output is selected. Access the terminal and enter the command āsudo raspi-configā. A graphical interface will appear. Navigate to āAdvanced Optionsā and select it by pressing enter. Within the submenu, select āAudioā and press enter once more. To ensure proper functionality, choose āForce 3.5mm (āheadphoneā) jackā and confirm. Review the main menu, then select āFinishā to complete the setup process.
Now just type in the following command and hit enter:
nc -l 4444 | aplay -r 8000 -f U8
Now plug in your ESP32 module. (Donāt forget to connect a speaker or headphones to your Raspberry.) And listen to your stream.
IMPORTANT: first run the command and then connect the ESP32 to power.
Schematics
Code
/* 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 , 4096, 0, 255); // 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(0, 80, true); // 80 Prescaler timerAttachInterrupt(timer, &onTimer, true); // binds the handling function to our timer timerAlarmWrite(timer, 125, true); 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 } }
Source: ESP32 Voice Streamer