Bluetooth!
It was the last remaining uncertainty: will the bluetooth chip I chose work ? And yes it works !!!!
Wiring detils
Top view (shield side up), antenna at the bottom:
31 30 29 28 27 26 25 24 23 22
+-------------------------------+
32 | | 21
33 | | 20
34 | | 19
35 | | 18
36 | | 17
37 | | 16
38 | | 15
39 | | 14
40 | | 13
41 | | 12
42 | | 11
43 | | 10
44 | | 9
45 | | 8
46 | | 7
47 | | 6
48 | | 5
49 | | 4
50 | | 3
51 | | 2
52 | | 1
| |
| ANTENNA |
+-------------------------------+- 1.0 mm pitch. Module 13.0 x 26.9 mm.
- Right edge: pins 1-21, bottom to top. Top edge: 22-31, right to left. Left edge: 32-52, top to bottom.
- Dead-bug (pads facing up), left and right swap: pin 1 is then on the left, pin 52 on the right.
- Keep the antenna end clear of metal and wires.
How I wired it to the nucleo
| Module pin | Name | Connect to | Notes |
|---|---|---|---|
| 33 | VBAT_IN | Nucleo 3V3 | 10 µF + 100 nF across pins 32/33, on the module |
| 36 | VDD_IO | Nucleo 3V3 | I/O level = 3.3 V |
| 32 | GND | GND | |
| 1, 22, 50, 52 | GND | GND | at least one more ground, for the radio |
| 34 | SYS_CTRL | PA15 | drive high > 20 ms after power-up to boot. No internal pull: never leave floating |
| 14 | BT_RX | PB6 (USART1 TX) | AT commands, 115200 8N1 |
| 13 | BT_TX | PB7 (USART1 RX) | |
| 4 | PCM_CLK | VS1053 GPIO6 (SCLK, LQFP pin 11) | I2S bit clock |
| 7 | PCM_SYNC | VS1053 GPIO4 (LROUT, LQFP pin 36) | I2S word clock |
| 5 | PCM_IN | VS1053 GPIO7 (SDATA, LQFP pin 12) | I2S data into the module |
| 8 | RESET | optional: GPIO, open-drain | internal pull-up, can stay unconnected |
| 17 | AIO0/LED0 | optional: LED + 1 k to 3V3 | open-drain. Blinks while pairing (reference design) |
Power the module before driving UART or I2S, otherwise it gets powered through its I/O pins.
I2S: VS1053 to module
VS1053 pin numbers are for its LQFP-48 package (datasheets/vs1053.pdf, pin table). Note the module pins are not in order.
| Signal | VS1053 pin | VS1053 LQFP pin | Module pin | Module signal |
|---|---|---|---|---|
| Word clock (48 kHz) | GPIO4 / I2S_LROUT | 36 | 7 | PCM_SYNC |
| Bit clock (1.536 MHz) | GPIO6 / I2S_SCLK | 11 | 4 | PCM_CLK |
| Data | GPIO7 / I2S_SDATA | 12 | 5 | PCM_IN |
Settings that match: the VS1053 as I2S master at 48 kHz (I2S_CONFIG = 0x4, MCLK off), and the module as slave, 48 kHz, 16-bit I2S: AT+AUXCFG=3 (I2S input) and AT+I2SCFG=3.
Minimal test code
#include <Arduino.h>
#include "sound/VS1053_driver.h"
#include "sound/startup_sound.h" // a short MP3, stored in flash
#define BT_SYS_CTRL PA15
Uart BT(PB7, PB6); // USART1: RX <- BT_TX, TX -> BT_RX
VS1053_driver vs(PA10, PA11, PA9, PB3); // XRESET, XCS, XDCS, DREQ
uint32_t pos = 0;
void setup() {
Serial.begin(115200);
// SYS_CTRL has no internal pull: high for > 20 ms boots the module.
digitalWrite(BT_SYS_CTRL, HIGH);
pinMode(BT_SYS_CTRL, OUTPUT);
BT.begin(115200); // 8N1, the module's default
vs.begin(1000000);
vs.setVolume(40, 40);
// GPIO4-7 as outputs, I2S_CONFIG = 0x4: master, 48 kHz, 16-bit words.
vs.setI2SOutput(true);
}
void loop() {
// Monitor <-> module. The monitor sends "\r\n" on Enter, which is what the
// AT commands expect.
while (Serial.available()) BT.write(Serial.read());
while (BT.available()) Serial.write(BT.read());
// Loop the clip, 32 bytes each time the VS1053 has room for them.
if (vs.dreqHigh()) {
uint32_t n = min((uint32_t)32, STARTUP_SOUND_LEN - pos);
vs.sendData(STARTUP_SOUND_MP3 + pos, n);
pos = (pos + n) % STARTUP_SOUND_LEN;
}
}The AT commands come from Feasycom's BT1035 programming user guide (the module's datasheet only says "ASCII commands over UART"). Run the monitor with echo on, to see what you type: pio device monitor --echo.
The commands, and what the module answered
> is what I typed, the rest is the module's answer as printed in the serial monitor.
1. Is anybody there?
> AT
OK
> AT+VER
+VER=FSC-BT1035,V6.1.1,20240521
OK
> AT+NAME
+NAME=FSC-BT1035
OK
> AT+ADDR
+ADDR=00025B00FF05
OKFirst try. Power, SYS_CTRL, and TX/RX the right way round.
2. Profiles
> AT+PROFILE
+PROFILE=341
OK341 is a bit field: 0b101010101 = SPP, GATT, HFP-AG (the phone side of a hands-free link), A2DP Source (bit 6) and AVRCP Target. A2DP Source is what makes it a transmitter, and it's on by default. Nothing to change.
3. Scan for receivers
Receiver in pairing mode, then:
> AT+SCAN=1
+DEVSTAT=9
OK
+SCAN=1,2,B40F3A9D1537,-55,12,BT5.3-Audio.,240404
+DEVSTAT=1Each result is index, address type (2 = classic BR/EDR), MAC, RSSI, name length, name, class of device. The guide says a scan ends with +SCAN=E; this firmware ends it with +DEVSTAT=1 (back to idle) instead.
4. Connect
> AT+A2DPCONN=B40F3A9D1537
+A2DPSTAT=2
OK
+PAIRED=B40F3A9D1537
+A2DPSTAT=3
+A2DPDEV=B40F3A9D1537,BT5.3-Audio
+A2DPSTAT=5
+A2DPENC=1
+A2DPSTAT=4
+AVRCPSTAT=2
+AVRCPSTAT=3
+HFPSTAT=2
+HFPSTAT=1The receiver said "connected" out loud. A2DPSTAT goes 2 (connecting), 3 (connected), 5 (paused), 4 (streaming). A2DPENC=1 is the codec: SBC. The HFPSTAT 2 -> 1 at the end is the module trying to open a hands-free (phone call) link, which the receiver declined: no problem for music.
From then on the module reconnects to it by itself at every power-on:
+A2DPSTAT=2
+AVRCPSTAT=2
+AVRCPSTAT=3
...
+A2DPSTAT=3
+A2DPDEV=B40F3A9D1537,BT5.3-Audio
+A2DPSTAT=5
+A2DPENC=1
+A2DPSTAT=45. Audio input: I2S
Connected and "streaming", but silence: by default the module streams its USB audio input. Switch it to I2S, as a slave (the VS1053 drives the clocks), 48 kHz, 16 bit:
> AT+AUXCFG=3
OK
> AT+I2SCFG=3
OK
> AT+AUXCFG
+AUXCFG=3
OK
> AT+I2SCFG
+I2SCFG=3
OKBoth settings are stored in the module's flash, so this is a one-time setup. I2SCFG is a bit field too: bit 0 enable, bit 1 slave, bit 2 44.1 kHz instead of 48, bit 3 right-justified, bit 4 no 1-bit data delay, bits 5-6 word size. 3 = enabled, slave, 48 kHz, standard I2S, 16 bit. That matches the VS1053: at 48 kHz its bit clock is 12.288 MHz / 8 = 1.536 MHz = 48 kHz x 2 channels x 16 bits.
6. Taddaa!
And just like that I had the thing playing my startup_sound mp3 file over bluetooth! Next I (I mean AI) will implement the whole UI for it: run scans, display the signal strength, rename, connect, forget etc. Beautifull!