Introduction: Bluetooth Mobile Phone Accessory for Missed Calls and SMS

Picture of Bluetooth Mobile Phone Accessory for Missed Calls and SMS

When at home, I do not carry my phone with me everywhere... so sometimes phone rings or an SMS comes in and I do not hear that. With the volume of music played by the teenagers at home, that is not a surprise :-) so I decided to build a small accessory that will show up the number of missed calls and unread SMS. In order to ensure it is very visible I use a 7 Segment LED display so it can be viewed from distance.

The display shows up the battery status, Missed calls count and Unread SMS on 8 digits 7 Segment display module. The communication with the accessory is using Bluetooth and one Arduino board that interfaces with the display and the Bluetooth unit.

You need to run the program once (per boot of the phone), and even if the program is in the background, when the accessory and the phone are in range of Bluetooth communication, the display will show the status of your phone. Pretty much like Car hands free set, that automatically connects with your phone.

The code runs on Android phone and source code of the Arduino accessory and the Android phone code are shared here in step 4.

Updated code can be found in here:
https://github.com/zmashiah/PhoneInfo
Made several small enhancements and fixed an issue some where complaining about, where connection was not always made from phone to the device. The problem as I learned was in new Firmware of RN-42 that required a bit of configuration to work with Android. Those changes include using commands SI,0200 and SJ,0200 for the BT module.



Step 1: What You Need to Assemble It?

Picture of What You Need to Assemble It?

1. Arduino board: You can use Arduino Pro Mini (5V) or Uno or a Mega with this sketch. Mega made it easy to debug, but Arduino pro-mini is cheaper (~$ 10 on eBay). Cost for Mini is ~ $ 19 at Sparkfun. Any Arduino board should work fine (328, not sure the 168 are good enough). Use 5V flavors as the 7Segment Display requires 5V and not 3.3V
2. Bluetooth module like this one, cost is ~$ 40 at Sparkfun. To use cheaper one ($ 10 on eBay) you will need minor code modifications which I tend to do for a new assembly of this.
3. 7 Segment display , cost is ~ $10 (or LED Matrix  for $3 a piece)
4. Wires for connecting and potentially a power supply for driving the accessory and enclosure. I did not complete this part yet.

Do yourself a favor and look for the items on eBay. It will save you money.
Total cost, if assembled by items you shop on eBay can be about $ 30. If you go for traditional on-line stores, cost will be higher.

Step 2: How to Assemble?

Picture of How to Assemble?

Below are the steps for connecting the hardware pieces
1. Connect the Bluetooth module to Arduino serial port:
Module Pin       Arduino Pin
Vcc                  3,3V
GND                GND
Tx-o                 Rx (if Mega, connect to 18, if other Arduino, connect to Digital 0)
Rx-I                  Tx (if Mega, connect to 17, if other Arduino, connect to Digital 1)

2. Connect the display module to Arduino (you can reassign pins in the code if you like)
Module Pin      Arduin Pin
GND                GND
+5V                 5V
DIN                  Digital 4
CS                   Digital 5
CLK                 Digital 6

Step 3: Pairing the Devices

Picture of Pairing the Devices
To use the device with your phone, first pair the devices:
On the phone go to "Settings|Wireless and networks|Bluetooth settings" touch the "Scan for devices" and select the "RN-42-4376" device. The pairing code is "1234". The pictures here shows all the screens in this process.

After initial pairing was done, you need to setup the the Bluetooth module to always connect to your phone. To do that you can use an Arduino Mega for the setup, an FTDI or some other tool. In every step below, unless specifically written, you need to type something and press Enter.
If you are using Arduino Mega
  1. Load the MultiSerialMega sketch to your assembly
  2. Open a Terminal like Tera-Term with connection to your Arduino Mega port (the Arduino IDE built-in terminal is not good enough)
  3. Press $$$ (no enter), the module will reply back with CMD
  4. Make your phone discoverable
  5. Type I on the terminal connected to your Bluetooth module
  6. The module will reply with "Inquiry, COD=0 then it should find your device and list the MAC address of your Bluetooth,firendly name of your device. See portion of terminal window below for an example
  7. Type SR,<the address> into the terminal
  8. Then type C in the terminal
Your are now ready to go.

If you do not have Arduino Mega, but have FTDI: 
  1. Connect the BT module through an FTDI to your PC (3.3V, and remember to cross Tx and Rx between FTDI and the Bluetooth module).
  2. Then open a terminal like Tera-Term with connection to your FTDI. Then continue form step 3 above.
If you do not have FTDI either:
  1. Get the MAC address of the Bluetooth of your phone (see below)
  2. Modify the Arduino source so that the line 'initString in function setup() contains your Phone Bluetooth MAC address
  3. Add InitString as the first item in initVector, before initString1
  4. Un-comment the line the line for the initString
  5. The above steps will make the accessory hard-coded with your phone.
After that you can run the PhoneInfo application and if all is well it will connect to the accessory.

The PhoneInfo Android application I wrote here have a menu option to list the MAC address of your phone. This can help you setup the accessory as above.

Also, you can download a program from Google Play that is a Terminal application over Bluetooth (I worked with SENA BTerm and it seems to work nicely).

Step 4: Loading Software to Arduino and Android

Picture of Loading Software to Arduino and Android
Connect the Arduino to your PC to upload the software to it, you will need the Arduino IDE for that. Download the Arduino IDE from here.

In the attached ZIP file of sources you have
Arduino\ with all sources for Arduino
Mega\ sub directory Arduino Mega sources
Mega\MultiSerialMega\ sub directory with Arduino Mega source to have PC terminal communicate with the assembled Bluetooth module that connected to the Arduino Mega. This helps if you want to change name etc. for the module
Modified\ sub directory with a minor modification to one of the libraries shipped with Arduino, LedControl. The LedControl basically designed for interfacing with 7Segment displays driven by MAX7219 chip. The 7 Segment display is pretty limited to numbers, but with some creativity you can display some letters on it too, but not nice ones and not all letters. My modification simply added more letters that can be displayed than the original library had.
Standard\ sub directory with code for standard Arduino (non Mega) code.
Android\ with all the code for Android written in Java for Eclipse.


Copy the content of Modified sub directory to libraries\LedControl sub directory of the Arduino IDE installation.

Load the right sketch for your Arduino to the IDE and then upload it to the board you have. if all is connected as it should, you will see the 7 Segment display showing 'dcon' message on it (meaning the Phone is not connected).
 

I will not explain here how to install Eclipse for Android development, but if you are new to this like I was... do expect to spend time on installing the basic package. You can connect the phone to your PC and copy the APK file from 'Android\myPhoneInfoWithService\bin' sub directory to your phone and install it there. Make sure to enable "Unknown Sources" on the Android phone in by "Settings|Applications" of your phone.

Step 5: What Was Tested?

The Android application was tested on Android 2.2 and Android 2.3.6 devices, LG Optimus 2X and Samsung Note respectively.
I believe based on what the code does that it should work fine on other devices too, but can't be sure about that. If you have any issue with your device, please let me know, and preferably include the logging information as the Android program is well populated with debug logging.

The Android application for Android v2.2 is the same as for Android 2.3 although some changes to the Bluetooth interface were made by Google. From my testing the 2.2 code continues to work on the 2.3 device without any issue. Colors on the other hand might look somewhat different between the Android versions. Have no clue why, but the UI in this application is the least important in my view, so did not spent cycles investigating that. I suspect it has to do with colors defined on 2.3 but not on 2.2

Step 6: How This Works?

Picture of How This Works?

First, lets talk about Bluetooth:
The protocol is more than simple wireless communication, it also includes pairing and like USB communication some application protocol identification. The Bluetooth has a UUID for each protocol, some well known and some up to you to implement. I used the Serial over Bluetooth for simplicity of course rather than implementing a brand new one. Next, in Bluetooth like in USB there is the notion of Host and client. The host is waiting for calls while clients generate them. For me, it took some time to figure this out, and placed the Phone in host mode and the accessory in client mode. The accessory that is expected to be powered by a power supply will try connecting all the time, and the phone which is obviously battery powered will do the less power consuming task of waiting for a Bluetooth connection.

Next, Android...
Well if you are an Arduino programmer this might look very strange to you, but programs in Android are not monolithic like in Arduino. An application is really a collection of code fragments that gets executed in certain conditions or cases. Of course the language to use is Java, so that too would be different. Let me give you an example: To have the information about battery state (how much you have left, if it is full or not etc.) there is no API function to call and poll it. You actually register a function/method you write that gets called by the system once something about the battery changes. Same thing about missed calls, you don't get that information from a query to an API... you register a callback function with the system so that once there is a change to the call log database on the system, it will also call your registered function. When your Android app. wants to examine these logs of calls or SMS or the listen to Battery broadcasts, you also need to add permissions to your application so that it can do that. Otherwise, the system will silently ignore your request to be notified or be a listener to these message.

Next, I wanted the accessory to auto-connect once the phone is in range, to do that you need to have something working in the background as I am not expecting the application to be the active application all the time. For that it is not enough to write an Android activity, but you need to have an Android service too. The service gets executed by the Android activity as it starts. But to display things on the phone screen... you need an Activity and not a service. OK, so service needs to tell the activity about what it found. To do that it sends information in a publish-subscribe mechanism to which the activity registered earlier. The service is also the piece of code that communicates over Bluetooth with the accessory. That is important because it is not wise to call blocking calls (like network or wireless read and writes) from the activity. Activity has to be there fully ready to interact with the end user.

Last, I wanted to have the phone controlling the intensity of the display. To do that the activity that is a UI component, needs to tell the service what the user decided the intensity to be. Another thing to register for... But how do I know what the intensity is now? Well, for that I had the Arduino code answer to query by the phone, the Service will issue this query on connection, and update the activity about the current intensity level. Sounds complex? Not really but certainly tedious to implement.

To get the information about Battery, I register a BroadcastReceiver and found that it is getting called every 30 seconds.
The missed calls thing works perfect, but the SMS information is somewhat tricky. There is a notification about new incoming SMS, but no notification when user reads an SMS. So, I am polling the SMS log every time I am getting the battery notification too. That means that on incoming SMS the display will update immediately to show there is one, but once you read the SMS it might take up to 30 seconds for the display to show there are no unread SMS messages anymore. For me this is an acceptable compromise and if I will find a better way, I will use it.

Please bare in mind that this is actually my first Android program. It has been quite a while since I wrote any Java code too (more than a decade). I never did anything with Bluetooth either... The code got started from existing Android sample code too, mainly the BluetoothChat example.



Comments

jyee9 (author)2016-03-19

Sorry..I wasn't whether if this is a silly question. I wonder if it is possible to replace RN-42 with HC-06 Bluetooth module?

zmashiah (author)jyee92016-03-22

Mot a silly question at all.
As I got few devices already built, this could be a money saving change.
I got one unit at home for my phone, one at work, one for my Wife, and one built for a friend. However the HC-06 does not have all the features required by this project and could not make it to work for this one.

Sorry, you need to buy the more expensive unit.

Cheers,
Zakei

rajanjamuindia (author)2014-03-28

Hey Zakie,

I am making a data logging device where accessory comes ON every 1 hour, transfers logged data to android mobile and goes back to OFF. I am using Arduino Uno connected to Bluetooth Mate Gold which is acting as a client and Samsung Galaxy Note 3 running 4.4.2 as host (AcceptThread). Accessory is able to connect to mobile for the first time but does not connect when it comes ON for the second time. Android code is not a service but an activity. I am currently keeping the application always ON. Can you guess what is going wrong here? It will be of great help. Thanks !

zmashiah (author)rajanjamuindia2014-03-31

First ensure the BT module on the Arduino is properly configured. Depending on the module itself you will need to send it some AT commands to program it to auto initiate the conversation with the Android unit. I found this part pretty tricky to be honest, until I figured it out. On the RN-42 I think it was SM,3.

Make sure the Android BT MAC is registered with the Arduino BT module too. That saves on the search time as I noticed.

JOHNA_D (author)2013-06-12

hey, first of all, thanks for the wonderful project

currently im facing a problem. when i tried to replace the listenUsingInsecure with createInsecure, there is an error that says createInsecure is undefined. In my opinion, that has got something to do with the API version issue since createInsecure was only introduced later on.

is there anyone who could enlighten me in how to overcome this problem? total noob here, so any help would be much appreciated.

thanks

zmashiah (author)JOHNA_D2013-07-05

I just built a new one of this, for my wife. It turns out Rover Networks changed the Firmware of the BT module, and for it to work better with Android you need to do
SI,0200
SJ,0200
It took me few days to figure that out. Now it works perfect!
The changes I made includes 3 units of 8x8 LED Matrix (7219 based) and few minor changes to Android code. All code available in github

sgtpepperaut (author)2013-03-03

hey there also working with Galaxy S3 phone which has ICS 4.0.3.
the original code from zmashia works when replacing with createInsecureRfcommSocketToServiceRecord ...

however this connection only works ONCE?! The BT module connects automatically just fine....then lets say i walk out of range and walk back in the connection will not be restablished :(

any solution to this? do you know where it hangs? or waits around?

avnerm (author)2012-12-13

Hi Zakie, The related code in the MainActivity is:

// Indicator if the BluetoothSerialService is used a a server or as a client to establish the connection
public static final boolean useBluetoothSerialServiceAsServerForConnection = false;


If this indicator is set to true, the BluetoothSerialService (parallel to PhoneInfoServer in the example code) gets into a listening state and wait for incoming connections from the RN-42 BT This did not work for my Galaxy S3 phone which has ICS 4.0.3

If this indicator is set to false, the BluetoothSerialService gets into a connect state and tries to connect with the RN-42 BT The code is based on the app BlueTerm code which can be downloaded from http://pymasde.es/blueterm/ The related code in the BluetoothSerialService is:

private ConnectThread mConnectThread;

...

/** * Start the service. Depending on useBluetoothSerialServiceAsServerForConnection, either: * a) Start AcceptThread to begin listening for incoming connections (server mode), or * b) Start ConnectThread to initiate a connection (client mode) * Called by the Activity onResume() */

public synchronized void start() { Log.i(TAG, "BEG start"); Log.i(TAG, "mState: " + mState); // If we do not do that, accessory will disconnect foo5and connect again on application resume if (mState == STATE_CONNECTED) { return; } Log.i(TAG, "start() cleaning threads"); // Cancel any thread currently running a connection if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } Log.i(TAG, "start() creating AcceptThread"); if( MainActivity.useBluetoothSerialServiceAsServerForConnection == true ) { ////////////////////////////////////////////////////////////////////////// // Use the following connection configuration: // Android: server // RN-42 BT: client ////////////////////////////////////////////////////////////////////////// // Cancel any thread attempting to make a connection if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; } setState(STATE_LISTEN); // Initiate the thread attempting to accept a connection if (mInsecureAcceptThread == null) { mInsecureAcceptThread = new AcceptThread(false); mInsecureAcceptThread.start(); } } // if( MainActivity.useBluetoothSerialServiceAsServerForConnection == true ) else { ////////////////////////////////////////////////////////////////////////// // Use the following connection configuration: // Android: client // RN-42 BT: server ////////////////////////////////////////////////////////////////////////// // Cancel any thread attempting to accept a connection if (mInsecureAcceptThread != null) { mInsecureAcceptThread.cancel(); mInsecureAcceptThread = null; } // Initiate the thread attempting to make a connection if (mConnectThread == null) { mConnectThread = new ConnectThread(MainActivity.mRemoteDevice, false); mConnectThread.start(); setState(STATE_CONNECTING); } } // else if (D) Log.d(TAG, "END start"); }

/** * Start the ConnectedThread to begin managing a Bluetooth connection * @param socket The BluetoothSocket on which the connection was made * @param device The BluetoothDevice that has been connected * @param socketType The socket type: secured / insecured */
public synchronized void connected( BluetoothSocket socket, BluetoothDevice device, String socketType ) { if (D) Log.d(TAG, "BEG connected"); Log.d(TAG, "PhoneInfo.connected(): socket type:" + socketType + "Canceling other threads"); // Cancel any thread currently attempting to make a connection if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; } // Cancel any thread currently running a connection if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } // Cancel the accept thread because we only want to connect to one device if (mInsecureAcceptThread != null) { mInsecureAcceptThread.cancel(); mInsecureAcceptThread = null; } // Start the thread to manage the connection and perform transmissions Log.d(TAG, "PhoneInfo.connected(): Creating connected thread"); mConnectedThread = new ConnectedThread(socket, socketType); mConnectedThread.start(); // Send the name of the connected device back to the UI Activity Log.d(TAG, "PhoneInfo.connected(): Sending device name to calling activity"); sendDeviceNameToActivity(device.getName()); setState(STATE_CONNECTED); } // public synchronized void connected

// Stop all threads public synchronized
void stop() { Log.d(TAG, "PhoneInfo.stop(): stop all threads");// Cancel any thread attempting to make a connection if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; } // Cancel any thread running a connection if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } // Cancel any thread accepting a connection if (mInsecureAcceptThread != null) { mInsecureAcceptThread.cancel(); mInsecureAcceptThread = null; } setState(STATE_NONE); } // public synchronized void stop()

/** * This thread runs while attempting to make an outgoing connection * with a device. It runs straight through; the connection either * succeeds or fails. */
private class ConnectThread extends Thread
{
private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; private String mSocketType;

public ConnectThread(BluetoothDevice device, boolean secure) { mmDevice = device; BluetoothSocket tmp = null; mSocketType = secure ? "Secure":"Insecure"; // Get a BluetoothSocket for a connection with the // given BluetoothDevice try { // tmp = device.createRfcommSocketToServiceRecord(BT_SPP_UUID); tmp = device.createInsecureRfcommSocketToServiceRecord(BT_SPP_UUID); } catch (IOException e) { Log.e(TAG, "create() failed", e); } mmSocket = tmp; } // public ConnectThread

public void run() { Log.i(TAG, "BEGIN ConnectThread::mConnectThread"); setName("ConnectThread"); // Always cancel discovery because it will slow down a connection mAdapter.cancelDiscovery(); // Make a connection to the BluetoothSocket try { // This is a blocking call and will only return on a // successful connection or an exception mmSocket.connect(); } catch (IOException e) { connectionFailed(); // Close the socket try { mmSocket.close(); } catch (IOException e2) { Log.e(TAG, "unable to close() socket during connection failure", e2); } // Start the service over to restart listening mode //BluetoothSerial.this.start(); return; } // catch (IOException e) // Reset the ConnectThread because we're done synchronized (BluetoothSerialService.this) { mConnectThread = null; } // Start the connected thread // connected(mmSocket, mmDevice); // /// connected(socket, socket.getRemoteDevice(), mSocketType); connected(mmSocket, mmDevice, mSocketType); } // public void run()

public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "close() of connect socket failed", e); } }

} // private class ConnectThread

...


Sorry if the code appears messy. I didn't find a way to preview it properly.
I hope this helps,
Avner

avnerm (author)2012-12-11

I found a workaround for the problem of the Android phone (Galaxy S3 4.0.3) not being able to act as a server for automatic connection.
I added an option for the Android phone to act as the client and initiate insecure RfcommSocket to the RN-42 BT.
Replacing createRfcommSocketToServiceRecord with createInsecureRfcommSocketToServiceRecord results in a succefull connection.
The RN-42 BT light turns green and the device communicates, without having to punch in the password (1234).

(Zakie, I'm now living across the world but I was exited to find out that this useful reference comes from where I used to live. Thanks again for sharing your code and instructions. It was most useful to me).

zmashiah (author)avnerm2012-12-12

Hi Avner, and thanks for finding that issue with ICS and the code. If you don't mind sharing it, that will be useful once I upgrade my phone to Note II or something.

P.S.
Happy Hanukkah

avnerm (author)2012-12-10

I did - you can see the commands in the Arduino code snippets in the following links:
http://stackoverflow.com/questions/10732252/auto-connecting-to-paired-bluetooth-devices-on-android
http://stackoverflow.com/search?q=Auto+connecting+Arduino+to+Android+using+Paired+Bluetooth+Serial

Anyways, this seems to be a problem for Android ICW (I'm using 4.0.4).
It is reported in several places such as:
http://code.google.com/p/android/issues/detail?id=34161
http://stackoverflow.com/questions/11082819/bluetooth-connection-on-android-ics-not-possible

zmashiah (author)avnerm2012-12-11

Thanks Avner. I do not have any ICW based code device. My Samsung Note (first one, not the new II) is 2.3.6. See more comments I made in the StackOverflow link.

That was my first time writing something myself with BT and Android. I explored it to get hand-on on both.

avnerm (author)2012-12-10

Hi zmashiah,

I have a bluetooth serial device (RN42) that is connected to Arduino Uno.
I am able to connect to it from Android (Galxsy S3), but the connection has to be initiated from the Android phone every time.
Instead I am trying to set the Android phone as a host and set the bluetooth serial device to auto-connect mode.
Then the bluetooth serial device can serve as the client and initiate a connection automatically when it starts.
I'm am following your instructions and example code (thanks for sharing it)

However, I am not able to establish the connection from the Arduino to the Android phone.
The Bluetooth service is stuck in the AcceptThread on: socket = mmServerSocket.accept();
I posted my observations also in http://stackoverflow.com/search?q=Auto+connecting+Arduino+to+Android+using+Paired+Bluetooth+Serial

Do you have any ideas how I can debug this problem, to see why the connection is not established?

zmashiah (author)avnerm2012-12-10

Did you follow the section: Pairing the devices in my explanation?
This is step 3 in it.

Basically the RN42 is by default not doing this reconnect. You need to tell it to become one.

mazikowski (author)2012-08-09

Great project! You actually answered a few Arduino/Android/BT questions I was having with a project of my own.

zmashiah (author)mazikowski2012-08-09

Thank you.
I always found a working example to be one of the best ways to learn a particular area of technology. Certainly as a developer.

Always happy to help.

About This Instructable

24,351views

41favorites

License:

Bio: An experienced manager in Hi-Tech that never gets bored with technology or life
More by zmashiah:Turning Stereo Amplifer On and Off automaticallyColorful Countdown Clock for tight timeline managementBluetooth mobile phone accessory for Missed calls and SMS
Add instructable to: