Arduino to Arduino by Bluetooth

Updated 12.06.2016: Added example 2

In the Connecting 2 Arduinos by Bluetooth using a HC-05 and a HC-06: Pair, Bind, and Link post I explained how to connect a HC-05 to a HC-06 so that when powered they automatically made a connection. Here we look at using that connection to get Arduinos talking over Bluetooth. Before continuing you need to have the Arduinos and BT modules set up as per the previous post. Here I am using 2 HC-05s. One in master mode the other in slave mode. The setup process for the slave mode HC-05 is the same as the HC-06 in the previous post.

Arduino2ArdionoBT_Breadboards_01_1600

Set Up

I am using 5V Arduino Nanos but any kind of 5V AVR based Arduino can be used.
I have designated one of the Arduinos as the master device. This is the one that initiates the connection and in the first example it is the one that sends the commands. Having a master and slave setup makes the programming a little easier.

To communicate with the BT modules I am using AltSoftSerial which uses pin 8 and pin 9. The AltSoftSerial library can be downloaded from https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html and it will need to be added before you can compile the example sketches.

Both BT modules are set with a communication baud rate of 9600. This can be changed but make sure you match the baud rate used when opening the software serial connection.

    //  open software serial connection to the Bluetooth module.
    BTserial.begin(9600);

Connecting the Bluetooth Modules

Most HC-05s and HC-06s have 3.3v TX and RX pins. 5V Arduinos will read 3.3v as HIGH so the BT modules TX pin can be connected directly to the Arduino RX pin. However, the Arduino TX pin needs to be converted to 3.3v before connecting to the BT modules RX pin. A simple way to do this is by using a voltage divider made from 2 resistors; I generally use 1 x 1K and 1 x 2K.

Arduino RX (pin 8) to BT module TX pin
Arduino TX (pin 9) to BT module RX pin via a voltage divider

Both Arduinos have the same connections to the BT modules.

Arduino2Arduino_1200

 
 

Example 1: Remote Control an LED

In the first example we get one Arduino to control an LED connected to a second Arduino. Communication is one way only and there is no error checking. Arduino #1 simply sends the commands LEDON and LEDOFF to the Arduino #2. When the Arduino #2 gets the commands it sets the LED accordingly.

Example 1: Circuit

Arduino #1, the master device, just has the Bluetooth module. Arduino #2, the slave device we have the Bluetooth module and an LED (with a suitable resistor) on pin D3.

Arduino2ArduinoExample1_circuit_1800

Arduino2ArdionoBT_Breadboards_01_1600

Example 1: Sketches

The Sketch on Arduino #1, the master device connected to the HC-05, simply sends the command LEDON, waits a second, sends the commands LEDOFF waits another second and then repeats indefinitely.

/*
* Sketch: Arduino2Arduino_MASTER_01
* By Martyn Currey
* 08.04.2016
* Written in Arduino IDE 1.6.3
*
* Send commands through a serial connection to turn a LED on and OFF on a remote Arduino
* There is no error checking and this sketch sends only
* Commands should be contained within the start and end markers < and >
*
* D8 - AltSoftSerial RX
* D9 - AltSoftSerial TX
*
*/
 
// AltSoftSerial uses D9 for TX and D8 for RX. While using AltSoftSerial D10 cannot be used for PWM.
// Remember to use a voltage divider on the Arduino TX pin / Bluetooth RX pin
// Download AltSoftSerial from https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
 
#include <AltSoftSerial.h>
AltSoftSerial BTserial; 
 
// Change DEBUG to true to output debug information to the serial monitor
boolean DEBUG = true;
 
void setup()  
{
    if (DEBUG)
    {
        // open serial communication for debugging and show 
        // the sketch filename and the date compiled
        Serial.begin(9600);
        Serial.println(__FILE__);
        Serial.println(__DATE__);
        Serial.println(" ");
    }
 
    //  open software serial connection to the Bluetooth module.
    BTserial.begin(9600); 
    if (DEBUG)  {   Serial.println("BTserial started at 9600");     }
 
} // void setup()
 
 
void loop()  
{
    BTserial.println("<LEDON>");
    if (DEBUG) {Serial.println("LEDON command sent");}    
    delay (1000);
 
    BTserial.println("<LEDOFF>");
    if (DEBUG) {Serial.println("LEDOFF command sent");}      
    delay (1000);    
}

You will notice that the commands are contained within start and end markers, < and >.

    BTserial.println("<LEDON>");
    BTserial.println("<LEDOFF>");

Using start and end markers allows the receiving device to check that it has a full command before acting upon it.

 
The Sketch on Arduino #2, the slave device, checks for data and if there is a start marker it starts to put the recieved data in to the variable receivedChars[ ]. When an end marker is received it sets the newData flag to TRUE. Any data not within the start and end markers is ignored.

When newData is TRUE we know we have a command to process. In this case we set pin D3 HIGH or LOW to turn the LED on or off.

    if      (strcmp ("LEDON",receivedChars) == 0)  { digitalWrite(3,HIGH);   }
    else if (strcmp ("LEDOFF",receivedChars) == 0) { digitalWrite(3,LOW);    }

 

/*
* Sketch: Arduino2Arduino_SLAVE_01
* By Martyn Currey
* 08.04.2016
* Written in Arduino IDE 1.6.3
*
* Receive commands through a serial connection and turn a LED on or OFF
* There is no error checking and this sketch receives only
* Commands should be contained within the start and end markers < and >
*
* D8 - software serial RX
* D9 - software serial TX
* D3 - LED
*
*/
 
// AltSoftSerial uses D9 for TX and D8 for RX. While using AltSoftSerial D10 cannot be used for PWM.
// Remember to use a voltage divider on the Arduino TX pin / Bluetooth RX pin
// Download AltSoftSerial from https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
 
#include <AltSoftSerial.h>
AltSoftSerial BTserial; 
 
// Change DEBUG to true to output debug information to the serial monitor
boolean DEBUG = true;
 
 
// Variables used for incoming data
 
 
const byte maxDataLength = 20;          // maxDataLength is the maximum length allowed for received data.
char receivedChars[maxDataLength+1] ;
boolean newData = false;               // newData is used to determine if there is a new command
 
 
 
void setup()  
{
    // LED on pin 3
    pinMode(3, OUTPUT); 
    digitalWrite(3,LOW);
 
 
    if (DEBUG)
    {
        // open serial communication for debugging and show the sketch name and the date compiled
        Serial.begin(9600);
        Serial.println(__FILE__);
        Serial.println(__DATE__);
        Serial.println(" ");
    }
 
    //  open software serial connection to the Bluetooth module.
    BTserial.begin(9600); 
    if (DEBUG)  {   Serial.println(F("AltSoftSerial started at 9600"));     }
 
    newData = false;
 
} // void setup()
 
 
 
void loop()  
{
         recvWithStartEndMarkers();                // check to see if we have received any new commands
         if (newData)  {   processCommand();  }    // if we have a new command do something
}
 
 
void processCommand()
{
    newData = false;
    if (DEBUG)  {   Serial.print("recieved data = ");  Serial.println(receivedChars);         }
 
    if      (strcmp ("LEDON",receivedChars) == 0)  { digitalWrite(3,HIGH);   }
    else if (strcmp ("LEDOFF",receivedChars) == 0) { digitalWrite(3,LOW);    }
}
 
// function recvWithStartEndMarkers by Robin2 of the Arduino forums
// See  http://forum.arduino.cc/index.php?topic=288234.0
void recvWithStartEndMarkers() 
{
     static boolean recvInProgress = false;
     static byte ndx = 0;
     char startMarker = '<';
     char endMarker = '>';
 
     if (BTserial.available() > 0) 
     {
          char rc = BTserial.read();
          if (recvInProgress == true) 
          {
               if (rc != endMarker) 
               {
                    if (ndx < maxDataLength) { receivedChars[ndx] = rc; ndx++;  }
               }
               else 
               {
                     receivedChars[ndx] = '\0'; // terminate the string
                     recvInProgress = false;
                     ndx = 0;
                     newData = true;
               }
          }
          else if (rc == startMarker) { recvInProgress = true; }
     }
 
}

 
 

Example 2: Remote Temperature Monitor

This example is a little more complex and unlike example 1, where the master device starts to send data as soon as it runs, this time it requests data from the slave. The slave receives the request from the master device and replies.

Arduino2Ardiono_Example2_01_1600

The slave device waits until it it gets the “sendTemp” request, it then reads the value of the temperature sensor on pin A0, converts the value to degrees celsius and then sends it out as ascii via the software serial channel. The sketches use the same recvWithStartEndMarkers() function as before and so the data is wrapped in the < start marker and the > end marker.

As before, the Bluetooth modules are set to automatically connect on start up. However, this time I an using 2 HC-05s; one in master mode, 1 in slave mode.

On start up, the master device initialises the LCD and starts a timer. When the timer finishes it sends out a request for the temperature. The Timer is then reset. Within the main loop, the sketch is continuously checking for received data. When it receives a temperature it displays it on the LCD.

The slave simply sits and waits for the request. When it receives the request it sends out the temperature and then goes back to waiting.

Example 2: Circuit

Arduino2ArduinoExample2Circuit_1800

Example 2: Sketches

The sketch on the master device is fairly simple. Once a second it sends a request to the slave device and waits for a reply. You can change the frequency of the request by changing the value of waitTime. There is no error checking or time out and the sketch does not know if it ever gets a reply or not.

/*
* Sketch: Arduino2Arduino_example2_RemoteTemp_Master
* By Martyn Currey
* 11.05.2016
* Written in Arduino IDE 1.6.3
*
* Send a temperature reading by Bluetooth
* Uses the following pins
*
* D8 - software serial RX
* D9 - software serial TX
* A0 - single wire temperature sensor
*
*
* AltSoftSerial uses D9 for TX and D8 for RX. While using AltSoftSerial D10 cannot be used for PWM.
* Remember to use a voltage divider on the Arduino TX pin / Bluetooth RX pin
* Download from https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
*/
#include <AltSoftSerial.h>
AltSoftSerial BTserial; 
 
 
// If you don't have an LCD you can use the serial monitor.
 
#include <Wire.h>  
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
 
// define the pattern for a custom degree character. You can also use chr 233
byte degreeChr[8] = { B00111, B00101, B00111, B00000, B00000, B00000, B00000,}; 
 
 
 
// Set DEBUG to true to output debug information to the serial monitor
boolean DEBUG = true;
 
 
// Variables used for incoming data
const byte maxDataLength = 20;
char receivedChars[21] ;
boolean newData = false;
 
// Variables used for the timer
unsigned long startTime = 0;
unsigned long waitTime = 1000;
 
const byte TEMP_PIN = A0;
 
 
void setup()  
{
  lcd.begin(20,4); 
  lcd.createChar(1, degreeChr);
  lcd.setCursor(0,0);  lcd.print("Remote Temp Monitor"); 
  lcd.setCursor(0,1);  lcd.print("Starting..."); 
 
  if (DEBUG)
  {
       // open serial communication for debugging
       Serial.begin(9600);
       Serial.println(__FILE__);
       Serial.println(" ");
  }
 
    BTserial.begin(9600); 
    if (DEBUG)  {  Serial.println("AltSoftSerial started at 9600");     }
 
    newData = false; 
    startTime = millis();
 
} // void setup()
 
 
 
 
void loop()  
{
    if (  millis()-startTime > waitTime ) 
    {
       BTserial.print("<sendTemp>");  
       if (DEBUG) { Serial.println("Request sent"); }
       startTime = millis();
    }
 
    recvWithStartEndMarkers(); 
    if (newData)  
    {    
         if (DEBUG) { Serial.println("Data received"); }
         lcd.setCursor(0,1);   lcd.print("Temp = "); 
         lcd.setCursor(7,1);   lcd.print(receivedChars);  
         lcd.write(1);  lcd.print("C"); 
         newData = false;  
         receivedChars[0]='\0';     
    }    
}
 
 
 
 
// function recvWithStartEndMarkers by Robin2 of the Arduino forums
// See  http://forum.arduino.cc/index.php?topic=288234.0
/*
****************************************
* Function recvWithStartEndMarkers
* reads serial data and returns the content between a start marker and an end marker.
* 
* passed:
*  
* global: 
*       receivedChars[]
*       newData
*
* Returns:
*          
* Sets:
*       newData
*       receivedChars
*
*/
void recvWithStartEndMarkers()
{
     static boolean recvInProgress = false;
     static byte ndx = 0;
     char startMarker = '<';
     char endMarker = '>';
     char rc;
 
     if (BTserial.available() > 0) 
     {
          rc = BTserial.read();
          if (recvInProgress == true) 
          {
               if (rc != endMarker) 
               {
                    receivedChars[ndx] = rc;
                    ndx++;
                    if (ndx > maxDataLength) { ndx = maxDataLength; }
               }
               else 
               {
                     receivedChars[ndx] = '\0'; // terminate the string
                     recvInProgress = false;
                     ndx = 0;
                     newData = true;
               }
          }
          else if (rc == startMarker) { recvInProgress = true; }
     }
}

The slave device sketch is equally simple. It waits for a request, when it gets the request it sends out the current temperature.

/*
* Sketch: Arduino2Arduino_example2_RemoteTemp_Slave
* By Martyn Currey
* 11.05.2016
* Written in Arduino IDE 1.6.3
*
* Send a temperature reading by Bluetooth
* Uses the following pins
*
* D8 - software serial RX
* D9 - software serial TX
* A0 - single wire temperature sensor
*
*
* AltSoftSerial uses D9 for TX and D8 for RX. While using AltSoftSerial D10 cannot be used for PWM.
* Remember to use a voltage divider on the Arduino TX pin / Bluetooth RX pin
* Download from https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
*/
#include <AltSoftSerial.h>
AltSoftSerial BTserial; 
 
// Set DEBUG to true to output debug information to the serial monitor
boolean DEBUG = true;
 
 
// Variables used for incoming data
const byte maxDataLength = 20;
char receivedChars[21] ;
boolean newData = false;
 
const byte TEMP_PIN = A0;
 
 
void setup()  
{
    if (DEBUG)
    {
        // open serial communication for debugging
        Serial.begin(9600);
        Serial.println(__FILE__);
        Serial.println(" ");
    }
 
    //  open a software serial connection to the Bluetooth module.
    BTserial.begin(9600); 
    if (DEBUG)  {   Serial.println(F("AltSoftSerial started at 9600"));     }
    newData = false;
 
} // void setup()
 
 
 
 
void loop()  
{
    recvWithStartEndMarkers(); 
    if (newData)  {   processCommand();  }    
}
 
 
 
 
/*
****************************************
* Function getTemp
* read a analogue pin and converts the value to a temperature
* based on the adafruit thermistor guide https://learn.adafruit.com/thermistor/testing-a-thermistor 
* 
* passed:
*  
* global: 
*
* Returns:
*        float temp  
* Sets:
*
*/
float getTemp()
{
    float reading = analogRead(TEMP_PIN);
    reading = 1023 / reading - 1;
    reading = 10000  / reading;
    float steinhart;
    steinhart = reading / 10000;          // (R/Ro)
    steinhart = log(steinhart);           // ln(R/Ro)
    steinhart /= 3950;                    // 1/B * ln(R/Ro)
    steinhart += 1.0 / (25 + 273.15);     // + (1/To)
    steinhart = 1.0 / steinhart;          // Invert
    steinhart -= 273.15;                  // convert to C
    return steinhart;
 
}
 
 
 
/*
****************************************
* Function processCommand
* parses data commands contained in receivedChars[]
* receivedChars[] has not been checked for errors
* 
* passed:
*  
* global: 
*       receivedChars[]
*       newData
*
* Returns:
*          
* Sets:
*       receivedChars[]
*       newData
*
*/
void processCommand()
{
 
     Serial.println(receivedChars);
 
     if (strcmp ("sendTemp",receivedChars) == 0) 
     { 
         float temp = getTemp();
         BTserial.print("<");  BTserial.print( temp ); BTserial.print(">");
         if (DEBUG) { Serial.print("Temp is ");   Serial.print(temp);  Serial.println("");   }
     }
 
     newData = false;
     receivedChars[0]='\0'; 
 
}
 
 
 
 
 
// function recvWithStartEndMarkers by Robin2 of the Arduino forums
// See  http://forum.arduino.cc/index.php?topic=288234.0
/*
****************************************
* Function recvWithStartEndMarkers
* reads serial data and returns the content between a start marker and an end marker.
* 
* passed:
*  
* global: 
*       receivedChars[]
*       newData
*
* Returns:
*          
* Sets:
*       newData
*       receivedChars
*
*/
void recvWithStartEndMarkers()
{
     static boolean recvInProgress = false;
     static byte ndx = 0;
     char startMarker = '<';
     char endMarker = '>';
     char rc;
 
     if (BTserial.available() > 0) 
     {
          rc = BTserial.read();
          if (recvInProgress == true) 
          {
               if (rc != endMarker) 
               {
                    receivedChars[ndx] = rc;
                    ndx++;
                    if (ndx > maxDataLength) { ndx = maxDataLength; }
               }
               else 
               {
                     receivedChars[ndx] = '\0'; // terminate the string
                     recvInProgress = false;
                     ndx = 0;
                     newData = true;
               }
          }
          else if (rc == startMarker) { recvInProgress = true; }
     }
 
}

 
 

14 thoughts on “Arduino to Arduino by Bluetooth

  1. i am using above code with arduino mega But its not working on the slave module ?? i am using build in led on Arduino mega at pin 13. so i changed the code accordingly.
    if i burn an empty code on both devices and start communicating. it transfer messages. i have linked both devices using AT+Link command ONly.

    • On thre mega, use one of the extra hardware serial connections rather than AltSoftSerial.

      Have you had the two BT modules talking to each other manually?

  2. Hi martyn,
    i am trying to have simultaneous communication between arduino via bluetooth. but it is not working.

  3. Hey Martyn,

    So tried doing this to connect a nano(master) to an uno(slave). Everything is paired correctly and the master seems to be sending the signal from the serial monitor but the LED isn’t turning on. Any advice/help?

    • Actually never mind. I managed to figure it out !

      But if you’re willing to help I’m trying to send gyroscope data over the bluetooth. Could really use the advice of someone who knows what they’re doing. I’m using the MPU 6050

      • Hi Roy,

        I can’t help with the MPU6050 but there are many guides online.

        I have added a second example which has 2 way communication between the Arduinos.

  4. Great tutorial! I haven’t messed with the Bluetooth modules much, but plan to soon as I have three hc-05 modules, and about to order three hc-06 modules to go with it. What I would like to do with them is incorporate them into a pixel poi setup.

    I’m building a POV poi setup with two teensy 3.2 controllers, because of the bigger flash memory. I was thinking that maybe I could use one teensy for one display and a trinket for the other display, connected to each other via Bluetooth, feeding the images from one to the other as images change. That way I can store all the images on one poi stick and not have to alter the other to sync with the first.

    Anyway it’s an idea, and if I can get it to work then it would make it possible to use a less expensive microcontroller for one display, and invest that money into a bigger flash memory. Also to be able to send other images via Bluetooth through a phone or other device would be awesome.

  5. Hi, I’m not very good at English. I can Connecting 2 Arduinos by Bluetooth using a HC-05 and a HC-06. I need help My project turn signal LED for bicycle.
    I need send Arduino to Arduino via Bluetooth HC-05(master) and HC-06(slave)
    This my code ,need you more help code send Arduino to Arduino.
    This code need use HC-05 and arduino
    int led1 = 0;
    int led2 = 1;
    int led3 = 2;
    int sw1 = 8; //turn left
    int sw2 = 9; // turn right
    int sw3 = 10; // middle signal
    int val;
    void setup()
    {
    pinMode(led1, OUTPUT);
    pinMode(led2, OUTPUT);
    pinMode(led3, OUTPUT);
    pinMode(sw1, INPUT);
    pinMode(sw2, INPUT);
    pinMode(sw3, INPUT);
    }
    void loop()
    {
    val=digitalRead(sw1);
    if(val==HIGH)
    {
    digitalWrite(led1, HIGH);
    delay(1000);

    {
    digitalWrite(led1,LOW);
    }
    val=digitalRead(sw2);
    if(val==HIGH)
    {
    digitalWrite(led2, HIGH);
    delay(1000);
    }
    if(val==HIGH)
    {
    digitalWrite(led2,LOW);
    }
    val=digitalRead(sw3);
    if(val==HIGH)
    {
    digitalWrite(led3, HIGH);
    delay(1000);
    }
    if(val==HIGH)
    {
    digitalWrite(led3,LOW);
    }
    }
    ——————————————————–
    and i need help make code for HC-06 recive

    • For the examples above any 5V Arduino can be used without any changes.

      3V Arduino can also be used but you would need to remove the voltage dividers and give the BT module at least 3.6v power

Leave a Reply

Your email address will not be published. Required fields are marked *


− four = 1

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>