Chapter 28 Bluetooth Media by DAC

ESP32 integrates Classic Bluetooth and Bluetooth Low Energy(BLE). It can transmit not only simple data and orders, but also files including texts and audios. In this section, we will utilize the audio’s receiving function of Bluetooth to receive music from mobile phones and play it.

Project 28.1 Playing Bluetooth Music through DAC

Use the Bluetooth audio receiving function of ESP32 to transcode the audio data from mobile phones and play the music through DAC output pin.

The accuracy of ESP32’s DAC is only eight bits, so the music would be distorted to some extent using this tutorial. In order to highlight the difference between having and not having an iis decoder, we recommend learning Chapter 29.

Component List

ESP32-WROVER x1

Chapter01_00

GPIO Extension Board x1

Chapter01_01

Micro USB Wire x1

Chapter08_00

Speaker

Chapter28_00

NPN transistorx1 (S8050)

Chapter07_02

Diode x1

Chapter17_01

Resistor 1kΩ x1

Chapter07_03

Capacitor 10uF x1

Chapter28_01

(Optional)

Component knowledge

signal conversion

Bluetooth devices receive music data from mobile devices, which cannot play through earphones and speakers directly. To output DAC signal, Bluetooth devices need to decode these data with I2S decoding chip. The power of these audio signals is so small that it can only drives low-power music listening devices, such as earphone. Amplify the power of these DAC signals with power amplifier chip, so that it can drive relatively bigger-power music playing devices, such as speakers.

../../../_images/Chapter28_02.png

Circuit

Schematic diagram

Chapter28_03

Chapter28_04

Please note that some kits do not include the 10uF capacitor.

Even if you do not have the capacitor in your kit, you can still build the circuit

without it, which won’t affect the function. If the sound is too low to hear,

please try holding the speaker closer to your ear.

Hardware connection

If you need any support, please feel free to contact us via: support@freenove.com

Chapter28_05

Please note that some kits do not include the 10uF capacitor.

Even if you do not have the capacitor in your kit, you can still build the circuit

without it, which won’t affect the function. If the sound is too low to hear,

please try holding the speaker closer to your ear.

Sketch

Sketch_28.1_Bluetooth_Music_by_DAC

../../../_images/Chapter28_06.png

Compile and upload the code to the ESP32-WROVER and open the serial monitor. ESP32 takes a few seconds to initialize the program. When you see the prompt as shown in the figure below, it means that the Bluetooth function of ESP32 is ready and waiting for the connection of other Bluetooth devices.

../../../_images/Chapter28_07.png

Please use your mobile phone to search and connect a Bluetooth device named “ESP32”. After the connection is successful, you can use ESP32 to play the audio files in your mobile phone.

../../../_images/Chapter28_08.png

The following is the program code:

 1/**********************************************************************
 2  Filename    : BluetoothByDAC
 3  Description : Use ESP32 to play the audio received via Bluetooth.
 4                Use your phone's Bluetooth connection to ESP32, 
 5                then open the music APP and play the music, 
 6                and you'll hear ESP32 play the phone's music
 7  Auther      : www.freenove.com
 8  Modification: 2024/06/20
 9**********************************************************************/
10#include "BluetoothSerial.h"
11#include "driver/i2s.h"
12#include "nvs.h"
13#include "nvs_flash.h"
14
15#include "esp_bt.h"
16#include "bt_app_core.h"
17#include "bt_app_av.h"
18#include "esp_bt_main.h"
19#include "esp_bt_device.h"
20#include "esp_gap_bt_api.h"
21#include "esp_a2dp_api.h"
22#include "esp_avrc_api.h"
23
24#define CONFIG_CLASSIC_BT_ENABLED
25#define CONFIG_BT_ENABLED 
26#define CONFIG_BLUEDROID_ENABLED
27
28BluetoothSerial SerialBT;
29
30static void bt_av_hdl_stack_evt(uint16_t event, void *p_param){
31  if(event==0) {
32    /* initialize A2DP sink */
33    esp_a2d_register_callback(&bt_app_a2d_cb);
34    esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb);
35    esp_a2d_sink_init();
36    /* initialize AVRCP controller */
37    esp_avrc_ct_init();
38    esp_avrc_ct_register_callback(bt_app_rc_ct_cb);
39    /* set discoverable and connectable mode, wait to be connected */
40    esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
41  }
42}
43
44void setup() {
45  Serial.begin(115200);
46  SerialBT.begin("ESP32");
47  Serial.println("Init seccess!");
48
49  esp_err_t err = nvs_flash_init();
50  if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
51    ESP_ERROR_CHECK(nvs_flash_erase());
52    err = nvs_flash_init();
53  }
54  i2s_config_t i2s_config;
55  i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_PDM);
56  i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_24BIT;
57  i2s_config.sample_rate = 44100;
58  i2s_config.channel_format = I2S_CHANNEL_FMT_ALL_LEFT;  
59  i2s_config.communication_format = I2S_COMM_FORMAT_STAND_I2S;
60  i2s_config.intr_alloc_flags = 0;
61  i2s_config.dma_buf_count = 6;
62  i2s_config.dma_buf_len = 60;
63  i2s_config.tx_desc_auto_clear = true;
64  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
65  i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
66  i2s_set_pin(I2S_NUM_0, NULL);
67
68  esp_bluedroid_init();
69  esp_bluedroid_enable();
70  bt_app_task_start_up();
71  bt_app_work_dispatch(bt_av_hdl_stack_evt, 0, NULL, 0, NULL);
72  Serial.println("Please use your bluetooth device to connect the ESP32");
73}
74
75void loop(){
76  ;  
77}

Add program files related to Bluetooth and API interface files.

 1#include "BluetoothSerial.h"
 2#include "driver/i2s.h"
 3#include "nvs.h"
 4#include "nvs_flash.h"
 5
 6#include "esp_bt.h"
 7#include "bt_app_core.h"
 8#include "bt_app_av.h"
 9#include "esp_bt_main.h"
10#include "esp_bt_device.h"
11#include "esp_gap_bt_api.h"
12#include "esp_a2dp_api.h"
13#include "esp_avrc_api.h"

Set the Bluetooth in slave mode through macro definition and use it to receive data from other devices.

1#define CONFIG_CLASSIC_BT_ENABLED
2#define CONFIG_BT_ENABLED 
3#define CONFIG_BLUEDROID_ENABLED

Initialize the serial port and set the baud rate to 115200; initialize Bluetooth and name it as “ESP32”.

1Serial.begin(115200);
2SerialBT.begin("ESP32");
3Serial.println("Init seccess!");

Define an I2S interface variable and initialize it.

 1i2s_config_t i2s_config;
 2i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_PDM);
 3i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_24BIT;
 4i2s_config.sample_rate = 44100;
 5i2s_config.channel_format = I2S_CHANNEL_FMT_ALL_LEFT;  
 6i2s_config.communication_format = I2S_COMM_FORMAT_STAND_I2S;
 7i2s_config.intr_alloc_flags = 0;
 8i2s_config.dma_buf_count = 6;
 9i2s_config.dma_buf_len = 60;
10i2s_config.tx_desc_auto_clear = true;
11i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
12i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
13i2s_set_pin(I2S_NUM_0, NULL);

Initialize the Bluetooth hardware device, establish a Bluetooth thread task, and print out messages to prompt the user to take the next step.

1esp_bluedroid_init();
2esp_bluedroid_enable();
3bt_app_task_start_up();
4bt_app_work_dispatch(bt_av_hdl_stack_evt, 0, NULL, 0, NULL);
5Serial.println("Please use your bluetooth device to connect the ESP32");

Bluetooth thread task: Set Bluetooth to slave mode; initialize Bluetooth command resolution function; set Bluetooth to be visible to other devices and in waiting for connection mode.

 1static void bt_av_hdl_stack_evt(uint16_t event, void *p_param){
 2  if(event==0) {
 3    /* initialize A2DP sink */
 4    esp_a2d_register_callback(&bt_app_a2d_cb);
 5    esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb);
 6    esp_a2d_sink_init();
 7    /* initialize AVRCP controller */
 8    esp_avrc_ct_init();
 9    esp_avrc_ct_register_callback(bt_app_rc_ct_cb);
10    /* set discoverable and connectable mode, wait to be connected */
11    esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
12  }
13}