RN52 Library Command Guide

This Arduino library was originally written for our development board, the Bluetooth Audio Link, which can be found on our tindie store. However it will work for any RN52 based project, with the serial port connected to an Arduino. The library was adapted from the Software Serial library by Thomas Cousins and additional functions written by Thomas McQueen. For any help or queries about the library, please email: thom @ doayee dot co dot uk

If there is a function not implemented by the library which Microchip document in their guide, you can use RN52.println() to send characters as if in a terminal application.

BAL

Contents

Setup

#include - including the library

RN52 rn52() - declaring an instance of the library

begin() - begin communication with the RN52

 

General Commands

reboot() - reboot the RN52

setDiscoverability() - sets whether new devices can discover RN52

toggleEcho() - toggles the command interface echo

factoryReset() - perform a factory reset

idlePowerDownTime() - set or get the idle power down time

name() - set or get the connection name for the RN52

volumeOnStartup() - set or get the startup volume

 

Serial Commands

println() - send data to the RN52 with a newline character

print() - send data to the rn52 without new line character

available() - get the number of bytes waiting to be read from the RN52

 

Audio Commands

volumeUp() - Turns the volume up

volumeDown() - Turns the volume down

playPause() - Plays/Pauses the track

nextTrack() - Skips to the next track

prevTrack() - Skips to the previous track

trackTitle() - Gets the track title

album() - Gets the album

artist() - Gets the artist

genre() - Gets the genre

trackNumber() - Gets the track number

trackCount() - Gets the total track count

getMetaData() - Gets the entire metadata

 

GPIO Commands

GPIOPinMode() - Change the pin mode of an RN52 GPIO pin

GPIODigitalWrite() - Change the state of an RN52 GPIO Pin

GPIODigitalRead() - Read the state of an RN52 GPIO Pin

 

Event/Status Register

getEventReg() - Read the current value of the event register

trackChanged() - Determine if the track has changed

isConnected() - Determine if a device is connected

 

 

RN52 Extended Features - Functions

AVRCPButtons() - GPIO Buttons to control music

powerUpReconnect() - RN52 reconnecting on startup

startUpDiscoverable() - RN52 discoverable on startup

rebootOnDisconnect() - RN52 rebooting when disconnected from

volumeToneMute() - Mute volume tones

systemTonesDisabled() - Disable system tones

powerDownAfterPairingTimout() - Power down after a pairing timeout

resetAfterPowerDown() - Reset after a power down

reconnectAfterPanic() - Reconnect after a panic situation

tonesAtFixedVolume() - Fix all system tones at a single volume

autoAcceptPasskey() - Disables the passkey feature

 

RN52 Extended Features - Advanced

setExtFeatures() - Sets the extended features register

getExtFeatures() - Gets the contents of the extended features register

 

A2DP Audio Routing

A2DPRoute() - Get or set the A2DP routing

sampleWidth() - Get or set the sample width of the output

sampleRate() - Get or set the sample rate of the output


Setup

#include <RN52.h>

Whenever you are using the RN52 library, you must include it at the top of your sketch. This allows the IDE to recognise commands from the library.

RN52 rn52(RX, TX);

Parameters:

int RX - the Arduino pin used as RX

int TX - the Arduino pin used as TX

To begin using the library you must first define the class, in this case ‘rn52’, but you could call it anything. The pins you are connecting to the RN52 with must be specified in the RX and TX fields.

The library is based off the SoftwareSerial library, and the same limitations apply when using it:

  • If using multiple software serial ports, only one can receive data at a time.
  • Not all pins on the Mega and Mega 2560 support change interrupts, so only the following can be used for RX: 10, 11, 12, 13, 14, 15, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64), A11 (65), A12 (66), A13 (67), A14 (68), A15 (69).
  • Not all pins on the Leonardo and Micro support change interrupts, so only the following can be used for RX: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI).
RN52 rn52(10,11);    //Set RX to 10 and TX to 11

From now on all commands must start with your class name, then a dot. This links the command to the library, and without it the sketch will not be able to compile.

begin(baudRate);

Parameters:

long baudRate - the baud rate of communication

Returns:

None

To start communication with the RN52, you must use the begin command. Within the begin command you must specify the baud rate you are communicating at. We recommend using a baud rate of 38400 or below, as above this the library can be temperamental due to the interrupt service routines onboard the AVR micro-controllers. If you are using the library with a BAL then the RN52 will already be set to communicate at 38400, but if not you will have to set this yourself.

rn52.begin(38400);    //Begin communication with the RN52 at 38400baud

General Commands

reboot();

Parameters:

None

Returns:

None

rn52.reboot();    //Reboots the RN52.

setDiscoverability(discoverabilityState);

Parameters:

boolean discoverabilityState - TRUE for discoverable, FALSE for not discoverable

Returns:

None

rn52.setDiscoverability(1);    //Sets the module discoverable

toggleEcho();

Parameters:

None

Returns:

None

Command used to toggle the echo feature of the RN52, which simply sends back every character you send it, giving you a real time view of what you are sending to it. Useful for debugging code.

rn52.toggleEcho();           

factoryReset();

Parameters:

None

Returns:

None

Does what it says on the tin, requires a restart after use.

rn52.factoryReset()

idlePowerDownTime(Optional: newTime);

Parameters (OPTIONAL):

int newTime - the idle power down time

Returns:

None - in the case that a new time is set

int - the current idle power down time, in the case no new time is set

The idle power down time is the time it takes for the RN52 to power down when it is receiving no input. By default it is set to 0, which means it will never power down.

rn52.idlePowerDownTime(30);    //Sets the idle power down time to 30 secs
int i = rn52.idlePowerDownTime();    //reads the idle power down time into the integer i.

name(Optional: “newName”, normalised or not);

Parameters (OPTIONAL):

String newName - The new name for the RN52

boolean normalised - Whether the name is normalised

Returns:

None - in the case that a new name is set

String - the current name, in the case no new name is set

Command used to either set, or read the name of the RN52. If the “New Name” field is left blank it will return the current name of the RN52 as a String. If the “New Name” field is included, you must specify whether the name should be normalized or not (appended with the latter four digits of the MAC address of the RN52.

rn52.name(“BAL-New”, 0)    //Sets the name to BAL-New, not normalized
String currentName = rn52.name();    //Sets the string currentName to the current name of the RN52

volumeOnStartup(Optional: newVolume);

Parameters (OPTIONAL):

int newVolume - The new output volume for the RN52

Returns:

None - in the case that a new volume is set

int - the current volume, in the case no new volume is set

Command used to either set, or read the volume level on the RN52 start-up. If the New Volume field is left blank it will return the volume as an int. Volume is between 1 and 15.

rn52.volumeOnStartup(10);    //Sets the volume on start-up to 10.
int i = rn52.volumeOnStartup();    //Sets the integer i to the current volume on start-up.

Serial Commands

println(dataToSend);

Parameters:

String dataToSend - the data which will be sent

Returns:

None

Command used to send the raw ascii data input to the RN52, as you would if you were using a command line interface.

rn52.println(“v”);    //Request RN52 firmware version

print(“data to send);

Parameters:

String dataToSend - the data which will be sent

Returns:

None

Command used to send the raw ascii data input to the RN52, as you would if you were using a command line interface. Does not include the newline character which is necessary for the RN52 to accept the command. For this use println (see above).

rn52.print(“v”);    //send “v” character to RN52

available();

Parameters:

None

Returns:

int - the number of available bytes to read

Command used to return the number of bytes of data in the input buffer sent from the RN52.

int i = rn52.available();    //sets an integer i to the number of bytes sent from the RN52 since data was last read ie. 
                             //After a command is sent the RN52 responds with “AOK” which in this case would set i to 3
                             //(one byte per character)

Audio Commands

Most of these commands are fairly self-explanatory.

volumeUp();

Parameters:

None

Returns:

None

rn52.volumeUp();

 

volumeDown();

Parameters:

None

Returns:

None

rn52.volumeDown();

 

playPause();

Parameters:

None

Returns:

None

rn52.playPause();

 

nextTrack();

Parameters:

None

Returns:

None

rn52.nextTrack();

 

prevTrack();

Parameters:

None

Returns:

None

rn52.prevTrack();

 

trackTitle();

Parameters:

None

Returns:

String - the current track title

String title = rn52.trackTitle();      

 

album();

Parameters:

None

Returns:

String - the current track album

String album =  rn52.album();    

 

artist();

Parameters:

None

Returns:

String - the current track artist

String artist = rn52.artist();   

 

genre();

Parameters:

None

Returns:

String - the current genre

String genre = rn52.genre();

 

trackNumber();

Parameters:

None

Returns:

int- the number of the current track in the queue

int trackNumber = rn52.trackNumber();

 

trackCount();

Parameters:

None

Returns:

int- the number of the final track in the queue

int trackCount = rn52.trackCount();

 

getMetaData();

Parameters:

None

Returns:

String - the full MetaData

Outputs the entire available MetaData as one long string. This may vary depending upon the audio source capabilities. It may include genre or track length, in addition to title, album and artist. Be careful with very long track names, the Arduino UNO especially can fail to handle a string this long if not considered properly.

String data = rn52.getMetaData();

GPIO Commands

Only GPIO pins 5, 6, 10, 11, 12, and 13 are available for use as GPIO on the BAL. The others have separate reserved functions. Changing the mode on any pins other than these will have no effect on the RN52, as the library prohibits it.

GPIOPinMode(pin, state);

Parameters:

int pin - the GPIO pin to alter

boolean state - TRUE for output, FALSE for input

Returns:

boolean - TRUE for success, FALSE for error

This command is used to set the pinMode of the desired pin. It works exactly like the normal pinMode command used by the Arduino IDE. The pin field specifies which pin you are declaring as an input or output, and the state field specifies which state it should be.

rn52.GPIOPinMode(12, 1);    //Sets pin 12 to an output

GPIODigitalWrite(pin, state);

This command is used to set an output as logic high or logic low, or to enable or disable the internal pull-up resistors on an input. It works exactly like the normal digitalWrite command used by the Arduino IDE. The pin field specifies which pin you want to change, and the state field specifies which state to change it to.

Parameters:

int pin - the GPIO pin to alter

boolean state - TRUE for high, FALSE for low

Returns:

None

rn52.GPIODigitalWrite(12, 0);    //Writes pin 12 low

GPIODigitalRead(pin);

Parameters:

int pin - the GPIO pin to read

Returns:

boolean - TRUE for high, FALSE for low

This command reads back the state of any pin, output or input. It is a boolean function, so it returns either a 1 or a 0 depending on the state of the pin (1 for HIGH, 0 for LOW).

while(rn52.GPIODigitalRead(11));    //Waits while pin 11 is high

Extended Features - Functions

These commands all alter the extended features of the RN52. They all accept either a Boolean input (1 or 0 – 1 for true, 0 for false), or read back the current state of that particular feature.

Parameters (OPTIONAL):

boolean state - the new state of the option

Returns:

None - in the case where a new state was written

boolean - the current state, in the case where no parameters specified

This format follows for all the following commands.

AVRCPButtons();

This setting converts certain GPIO pins into dedicated buttons for controlling volume and tracks, as well as a play/pause button. Buttons should be connected from the module to ground. Internal pull-up resistors are present in the RN52.

See above for usage

rn52.AVRCPButtons(1);    
//turn AVRCP buttons on.

boolean state = rn52.AVRCPButtons();    
//reads the current state of the AVRCP buttons into the state variable.

 

GPIO10 Volume Down
GPIO11 Previous Track
GPIO12 Next Track
GPIO13 Play/Pause
GPIO5 Volume Up

powerUpReconnect();

See above for usage

Determines whether the RN52 will attempt a reconnect on power up, it will attempt to reconnect with any device previously paired.

startUpDiscoverable();

See above for usage

Determines whether the RN52 is discoverable on start-up.

rebootOnDisconnect();

See above for usage

Determines whether the RN52 will restart after a disconnect, this is useful as after a disconnect the RN52 will not be discoverable.

volumeToneMute();

See above for usage

Mutes the volume tone (a tone which sounds whenever you change the volume).

systemTonesDisabled();

See above for usage

Disables the system tones, which will sound on power up and on connection.

powerDownAfterPairingTimout();

See above for usage

Enables the feature which will power down the RN52 after pairing is unsuccessful after a certain time.

resetAfterPowerDown();

See above for usage

Enables the reset after power down on the RN52, which will cause it to reset on every power cycle.

reconnectAfterPanic();

See above for usage

Panic is a mode the RN52 enters when it encounters a situation it has not been programmed for (like an overload of data). This feature enables the RN52 to reconnect after entering panic mode.

tonesAtFixedVolume();

See above for usage

Keeps the tones at a fixed volume independent of the media volume.

autoAcceptPasskey();

See above for usage

Disables the passkey.

Extended Features - Advanced

All the previous functions rely on the following two functions to operate correctly, if you’d rather edit the 16 bit Hexadecimal value yourself, you can use the following two functions to achieve this.

setExtFeatures(Option 1: 16-Bit Hex Value. Option 2: Boolean State, Int bit);

Parameters OPTION 1:

short settings - a new extended features setting written as a two-byte hex value

Parameters OPTION 2:

boolean state - the new state of the bit you are setting

int bit - the index of the bit

Returns:

None

This command can be used to either set a new hex value, or to alter the state of a particular bit in the hex value. The bits are as follows:

Bit 0 – Enable AVRCP buttons
Bit 1 – Enable reconnect on power-on
Bit 2 – Bluetooth Discoverable on start up
Bit 3 – Codec indicators PIO7 (AAC) and PIO6 (aptX)
Bit 4 – Reboot after disconnect (otherwise must power cycle)
Bit 5 – Mute volume up/down tones
Bit 6 – Enable voice command button on PIO4
Bit 7 – Disable system tones
Bit 8 – Power off after pairing timeout
Bit 9 – Reset after power off
Bit 10 – Enable list reconnect after panic
Bit 11 – Enable latch event indicator PIO2
Bit 12 – Enable track change event
Bit 13 – Enable tones playback at fixed volume
Bit 14 – Enable auto-accept passkey in Keyboard I/O Authentication mode
Bit 15 – Blank
Bit 16 – Blank
rn52.setExtFeatures(0x50F6);    //Set the extended features hex to 50F6.
rn52.setExtFeatures(1, 7);    //Disable the system tones.

getExtFeatures();

Parameters:

None

Returns:

Short - the two-byte value of the extended features

This command returns the current value of the extended features. It is returned as a short i.e. two byte (16 bit) value.

Serial.println(rn52.getExtFeatures(), HEX);    //Prints the current extended features value as a hexadecimal 
                                               //value to the Serial port from the Arduino.

Event/Status Register

The RN52 has a register for monitoring statuses and events as documented on page 35 of their official command guide. The implementation of this within the RN52 Arduino library is as follows. Note that in the official RN52 command guide Byte 0 refers to the most significant byte, but Bit 0 within that refers to the least significant bit. The event bits (11 & 12) in byte 0 are cleared whenever the register is requested from the device, this is handled by the library for all our functions that use it, and so polling the track change will still return accurately even if other requests have been made since the event.

getEventReg();

Parameters:

None

Returns:

Short - the two byte value of the event/status register

The bits are as follows:

(Byte 1)
Bit 0 – Bits 0-3 indicate the connection state. See below for a listing of the possible states
Bit 1 – Above
Bit 2 – Above
Bit 3 – Above
Bit 4 – HFP audio volume level change from audio gateway (phone)
Bit 5 – HFP audio microphone level change from audio gateway (phone)
Bit 6 – Reserved
Bit 7 – Reserved
(Byte 0)
Bit 8 – iAP wireless active connection to remote device
Bit 9 – SPP active connection to remote device
Bit 10 – A2DP active connection to remote device
Bit 11 – HFP/HSP active connection to remote device
Bit 12 – Caller ID notification event from audio gateway
Bit 13 – Track change event notification
Bit 14 – Reserved
Bit 15 – Reserved

The connection state (Bits 0-3 of Byte 1 as described above) is interpreted as follows :

Value
0 – Limbo - Logically off, but physically on
1 – Connectable - The module is connectable, page scanning
2 – Connectable and discoverable - The module is connectable and discoverable, page and inquiry scanning
3 – Connected The module is connected to an audio gateway
4 – Outgoing call established - The connected audio gateway has an outgoing call in progress
5 – Incoming call established - The connected audio gateway has an active call in progress and the audio
is in the headset
6 – Active call - The connected audio gateway has an active call in progress and the audio
is in the headset
7 – Test mode - The headset is in Test mode
8 – Three-way call waiting - The connected audio gateway has an active call and a second call on hold
9 – Three-way call on hold - The connected audio gateway has an active call and a second call on hold
10 – Three-way call multi-call - The connected audio gateway has an active call and a second call on hold
11 – Incoming call on hold - The connected audio gateway has an incoming call on hold
12 – Active call - The connected audio gateway has an active call and the audio is in the
handset
13 – Audio streaming - The headset is streaming A2DP audio
14 – Low battery - The system has a low battery
short state = rn52.getEventReg(); //Returns the event register as a short.

 

trackChanged();

Parameters:

None

Returns:

bool - TRUE if the audio track has changed since the last call to this function,  FALSE otherwise

boolean trackChanged = rn52.trackChanged(); //Returns a bool indicating whether the audio track has changed.

 

isConnected();

Parameters:

None

Returns:

bool - TRUE if there is a Bluetooth device connected,  FALSE otherwise

This function tests if any of Bits 8-11 are true, and returns true if that is the case.

boolean isConnected = rn52.isConnected(); //Returns a bool indicating whether there is an active Bluetooth connection.

A2DP Audio Output Routing

The RN52 by default outputs audio to the analog pins to be amplified by your own circuitry, however it is possible to redirect this to a digital output to be used as input to another system in the form of I2S or S/PDIF. You are also able to control the sample rate and the sample width.

A2DPRoute();

Parameters (OPTIONAL):

int - an indicator of the new routing to be used (see below)

Returns:

int - the current indicator of the routing in use (see below) - returned if no new state was written

none - in the case that a new state was written

The indicators are as follows:

0 - Analog Routing (default)
1 - I2S Output
3 - S/PDIF Output
4 - Intercom DAC mode

int currentRouting = rn52.A2DPRoute(); //Returns the current audio routing as an int
rn52.A2DPRoute(1); //sets the audio routing to I2S

 

sampleWidth();

Parameters (OPTIONAL):

int - an indicator of the new sample width to be used (see below)

Returns:

int - the current indicator of the sample width in use (see below) - returned if no new sample width was written

none - in the case that a new sample width written

The indicators are as follows:

0 - 24 bits per sample
1 - 32 bits per sample

int currentSampleWidth = rn52.sampleWidth(); //Returns the current sample width as an int
rn52.sampleWidth(1); //sets the sample width to 32 bits per sample

 

sampleRate();

Parameters (OPTIONAL):

int - an indicator of the new sample rate to be used (see below)

Returns:

int - the current indicator of the sample rate in use (see below) - returned if no new sample rate was written

none - in the case that a new sample rate written

The indicators are as follows:

0 - 8K samples per second
1 - 32K samples per second
2 - 44K1 samples per second
3 - 48K samples per second

int currentSampleRate = rn52.sampleRate(); //Returns the current sample rate indicator as an int
rn52.sampleRate(1); //sets the sample rate to 32K samples per second