Interfacing Android With Microcontroller

As I wrote in my previous post, for these days i’ve been working in a simple project with my friends. Actually it’s just a simple project, controlling an rgb lamp/led using android via bluetooth. The idea comes from this kickstarter project and i think it’s very feasible and likely easy, at least to make the prototype or demo. After around 4 days searching (component) and working, eventually i made the simple demo. My Xperia successfully controlled 3 pieces RGB led, driven by ATMega16’s pwm (pulse width modulation), and serial communication was done via bluetooth. I’ll make the complete tutorial, but for now i’ll just show you the basic : how the communication is established. First, look at video I captured below.

In this demo, i use my own AVR development board (ATMega16 chip) whose header for standard 16×2 LCD at PORTc. You can see the one blinking blue, that is HC-05 bluetooth module. I bought it from local store ANNAM electronics (www.anam-mahal.com) for IDR 145000 and i use my mobile phone Sony Xperia L running on android 4.2.2 as the bluetooth host. Interested? just follow tutorial below 🙂

Bluetooth module HC-05

Bluetooth Module HC-05 with MCU board (level converter)

1. Microcontroller Basic

First thing first, you have to know how serial communication in atmega works because HC-05 bluetooth is a serial module. So basically, atmega16 utilize USART to establish a communication. It’s very simple because we just need two pins of ATMega16, Rx (receive) and Tx (transmit) at PORT0 and 1, respectively. Let’s say you want to make communication between PC and AVR. All you need is just connect Rx of PC to Tx of AVR, and vice versa.

Then consider your android as PC above, and you want to make wireless communication. Bluetooth module is put in the middle to send-receive data wirelessly. A problem that would be an issue is, i think, just the baud rate. You must set the same baud rate for AVR and bluetooth. It’s a bit confusing for atmega because we must understand the register. But don’t worry, CVAVR’s wizard will help you!

2. HC-05 Bluetooth

HC-05 is a bluetooth serial module, used for converting serial port to bluetooth. HC-05 has two modes of operation : master and slave, but for now you just need it as a slave. If you prefer the cheaper module, you can pick HC-06 instead. The function of HC-06 and HC-05 are mutually compatible with each other. HC-06 is a former version that user can’t change the mode. But it’s ok since we only working with slave mode for bluetooth module.

To make this module run, you just need to connect 4 pins : vcc,gnd,rx,tx. But note that HC-05, as well as HC-06 works with 3.3 V voltage so you must convert this level into ATMega’s working voltage : 5 V. You can buy separately JY-MCU board for HC-05 or sometimes it comes with a board so you don’t need to add level converter (i recommend this one). Here is a useful page to visit.

The Board

3. Set Up Connection

To set up the connection/wiring, look at this illustration.

Illustration of the system

Be sure you’ve converted the logical level of Bluetooth module to ATMega’s working voltage (5V). Be careful of Vcc needed to power this module. Check the datasheet provided by manufacturer to ensure, because once the module wrongly powered (too high voltage), your project is ruined and waste of IDR 145000.

4. Program the chip – registers

Use CodeVision AVR C compiler to compile and build the hex file, because it will help you out of specifying register. But don’t worry i’ll describe the register so you understand the baud rate. Before setting the register, look at HC-05 specification. It says that : “Slave default Baud Rate : 9600, Data bits:8, Stop bit:1, Parity:No parity”. To satisfy these needs, configure :

USART Control and Status Register C – UCSRC

 

UCSRC

 

Leave URSEL and UCPOL as its default value. UMSEL = 0 for Asynchronous Operation. UPM is used to define type of parity, choose UPM1:0 = 00 to disable because we need no parity. UCSZ2:0 = 011 because character size is 8 bit for serial communication (But UCSZ2 is in another register). So we have value 0x86 or 0b10000110 for UCSRC. Please look at ATMega16 datasheet for details.

USART Control and Status Register B – UCSRB

UCSRB

We don’t use interrupt, so leave RXCIE and TXCIE 0. Leave UDRIE too, because it is a flag that indicate whether UDR is empty. Set RXEN because we want ATMega to receive data, and just let TXEN 0 because now we want to set up just one way communication. Finally value for UCSRB = 0x10 or 0b00010000.

USART Baud Rate Registers – UBRR

Baud Rate Calculation Table

Follow first row for async mode. Since the default baud rate for HC-05 is 9600, then UBRRf/(16×9600) – 1 . In my project, i use ATMega internal oscilator 8Mhz. So i’ll need UBRR = 51 or 0x33.

Last, set PORTC as output since we equip LCD at PORTC. DDRC = 0xFF

5. Program the chip – coding

First, include the corresponding library and initialization of LCD module

#include <mega16.h>
#include <stdio.h>

// Alphanumeric LCD Module functions
#asm
   .equ __lcd_port=0x15 ;PORTC
#endasm
#include <lcd.h>

Ah, don’t forget to set your system clock frequency when configure the wizard. If you forget, you can set manually by selecting Project -> configure and then click compiler tab.

Configure Clock

 

And then declare any global variable and set the register as i told you before.


void main(void)
{
// Declare your local variables here

unsigned int i;
char data;
char buffer[10];

PORTC=0x00;
DDRC=0xFF;

PORTD=0xFF;
DDRD=0x00;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: Off
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x10;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x33;

ACSR=0x80;
SFIOR=0x00;

lcd_init(16);

i=0;

while (1)
{
// Place your code here
}

Set PORTC as output. And then to set PORTD as input by typing DDRD = 0 (we just use pin Rx to receive, so ignore Tx). A step you must consider is writing logic one for input pin to activate pull up resistors. Pull up resistors will avoid pin having tri stated inputs. In input mode, when pull-up is enabled, default state of pin becomes ‘1’. So even if you don’t connect anything to pin and if you try to read it, it will read as 1. Now, when you externally drive that pin to zero(i.e. connect to ground / or pull-down), only then it will be read as 0.

However, if you configure pin as tri state. Then pin goes into state of high impedance. We can say, it is now simply connected to input of some OpAmp inside the uC and no other circuit is driving it from uC. In this case, if pin is left floating (i.e. kept unconnected) then even small static charge present on surrounding objects can change logic state of pin. If you try to read corresponding bit in pin register, its state cannot be predicted. This may cause your program to go haywire, because our program depends on input from particular pin, that is Rx. See datasheet page 52 for detailed information.

Main Program

So, you have understood about USART and uC. Now let’s begin the main section of the program. Take a look at this flowchart before go further

Flow chart

Waint until data is received can be implemented by checking the bit RXC at UCSRA. RXC is a flag that will be set when a data has been completely transmitted to Rx pin, and it’s not been read. This data is stored at register UDR, and to read that, simply assign a char with UDR. Then check data whether it is ‘#’ or not, because ‘#’ is used to terminate string. (i’ll explain later in android section). If data coming is not ‘#’, add it to a string buffer and wait for the next character. Else if data coming is ‘#’, it means that android has completed the transmit of one string and terminate string buffer. Finally, show the string to LCD. You may place below code inside the main loop.


while(!(UCSRA & (1<<RXC)))
{
//do nothing
}
data = UDR;
if (data != '#')
{
buffer[i] = data;
i++;
} else
{
buffer[i]='\0';
i=0;
lcd_clear();
lcd_gotoxy(0,0);
lcd_puts(buffer);
}

Download program

Compile program and fix maybe you find some errors. Download the program to your chip using any downloader you like. I use downloader USBASP programmer and software ProgISP. Don’t forget to set the fuse bit correctly. Because wrong clock will cause different UBRR value and the data will be read differently from what it has to be (different baud rate). I set fuse bit D9 E4 to utilize calibrated internal RC Oscillator. I’ll write some post related to fuse bit because it usually comes to an issue after one wrongly set fuse bit and thee chip is broken.

6. Android Programming

Now come to hardest part : make android application. If you’re an electronic hobbyist and don’t want to have a mess with android, you may download application in play store named “Arduino Bluetooth Terminal”. But if you are not a beginner in android, i’m sure you’ll find this easy. I’ll try to describe as simple as you ‘ll understand. ps : I use eclipse IDE to build android program.

Starting up

Make new project in eclipse. File -> new -> android application project. Fill in the blank for app name, package, etc. Then finish. See AndroidManifest.xml andd add 2 permissions : android.permission.BLUETOOTH and android.permission.BLUETOOTH_ADMIN. Make layout which contains 2 text fields and a button to go to the next page/activity. My layout looks like this

LayoutMain layout send

We will need 2 pages/activities so create another activity. File -> new -> other -> Android Activity. Change the activity name to Send.java and layout to activity_send.xml. The layout looks like above. You don’t need to add ListView because it is used to receive incoming data from uC. Android just send data to uC.

MainActivity

Before code the main program, i suggest you to read bluetooth documentation on android developer website. Click this.

So first thing we do is to verify that bluetooth is supported on the device, and ensure that it is enabled. Copy code below under onCreate method

SharedPreferences localSharedPreferences = getSharedPreferences("dataardubtterm", 0);
myBTadapter = BluetoothAdapter.getDefaultAdapter();
		if (this.myBTadapter == null) {
			Toast.makeText(getApplicationContext(),
					"Device doesn't support Bluetooth", Toast.LENGTH_SHORT)
					.show();
		}
		while (this.myBTadapter.isEnabled()) {
			return;
		}

if bluetooth adapter has been enabled, break from onCreate method. But if it’s not, request that bluetooth be enabled, call startActivityForResult() with the ACTION_REQUEST_ENABLE action intent.

startActivityForResult(new Intent(
				"android.bluetooth.adapter.action.REQUEST_ENABLE"),
				this.REQ_BT_ENABLE.intValue());
		Toast.makeText(getApplicationContext(), "Enabling Bluetooth!!",
				Toast.LENGTH_SHORT).show();

And then add method to handle activity result

protected void onActivityResult(int paramInt1, int paramInt2,
			Intent paramIntent) {
		if (paramInt1 == this.REQ_BT_ENABLE.intValue()) {
			if (paramInt2 == -1) {
				Toast.makeText(getApplicationContext(),
						"BlueTooth is now Enabled", Toast.LENGTH_SHORT).show();
			}
			if (paramInt2 == 0) {
				Toast.makeText(
						getApplicationContext(),
						"Error occured while enabling.Leaving the application..",
						Toast.LENGTH_SHORT).show();
				finish();
			}
		}
	}

Last, add code to listen for click button

public void save(View paramView) {
 SharedPreferences.Editor localEditor = getSharedPreferences(
 "dataardubtterm", 0).edit();
 this.edittxtDevName = ((EditText) findViewById(R.id.txtDevname));
 String str1 = this.edittxtDevName.getText().toString();
 this.edittxtuuid = ((EditText) findViewById(R.id.txtbtservice));
 String str2 = this.edittxtuuid.getText().toString();
 localEditor.putString("DevName", str1);
 localEditor.putString("btservice", str2);
 localEditor.commit();
 startActivity(new Intent(this, Send.class));
 }

I forgot. You can use android shared preferences to store data that has been entered to text fields (bluetooth shield name and service UUID). This data will be used again in the send activity. That’s why we declare localSharedPreferences in onCreate method.

Send Activity

Before establish communication, android must find and connect to the bluetooth shield. Again call BluetoothAdapter tofind remote bluetooth devices either through device discovery or by querying the list of paired (bonded) devices. In this case, we have already knew the name of shield we want to connect. So we don’t need to find any other shield, just querying paired devices and connect to desired shield with corresponding name. NOTE : you must pair bluetooth manually in the phone setting (bluetooth module default name = HC-05, pin = 1234) unless you do device discovery to search and requesting some information about each bluetooth enabled device in the local area.

void findBT() {

		// mengecek nama bluetooth slave yang akan dikirim data (sudah diset
		// pada activity sebelumnya)
		strDevname = getSharedPreferences("dataardubtterm", 0).getString(
				"DevName", strDevnamed);

		// mengecek apakah device mendukung bluetooth
		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
		if (mBluetoothAdapter == null) {
			myLabel.setText("No bluetooth adapter available");
		}
		if (!mBluetoothAdapter.isEnabled()) {
			startActivityForResult(new Intent(
					"android.bluetooth.adapter.action.REQUEST_ENABLE"), 0);
		}

		// mencari bluetooth slave yang sudah pair dengan device
		Set<BluetoothDevice> localSet = mBluetoothAdapter.getBondedDevices();
		Iterator localIterator = null;
		if (localSet.size() > 0) {
			localIterator = localSet.iterator();
		}
		for (;;) {

			// kondisi tidak ditemukan paired slave/device
			if (!localIterator.hasNext()) {
				return;
			}
			BluetoothDevice localBluetoothDevice = (BluetoothDevice) localIterator
					.next();

			// jika ditemukan bluetooth slave dengan nama yang sama dengan yang
			// telah diset, maka set itu menjadi device
			if (localBluetoothDevice.getName().equals(strDevname)) {
				mmDevice = localBluetoothDevice;
				myLabel.setText("Bluetooth shield available.");
				btdev = true;
				return;
			}
			myLabel.setText("No bluetooth shield available.");
		}
	}

In the above code, after querying for bonded devices, we check each one of the localSet to find whether there is a paired device of the same name with shield we want to connect. If found, we assign that bluetoothDevice of localSet to our global field BluetoothDevice. And then make one more method that aims to form serial connection between uC and android. Look at this to see complete instruction connecting devices.

void openBT() throws IOException {
		if (this.btdev) {
			this.strbtservice = getSharedPreferences("dataardubtterm", 0)
					.getString("btservice", "1101");
			UUID localUUID = UUID.fromString("0000" + strbtservice
					+ "-0000-1000-8000-00805f9b34fb");
			// UUID diatas digunakan saat device memerintahkan socket mengirim
			// data secara serial (1 bit/waktu)

			mmSocket = mmDevice.createRfcommSocketToServiceRecord(localUUID);
			mmSocket.connect();
			mmOutputStream = mmSocket.getOutputStream();
			mmInputStream = mmSocket.getInputStream();
			// beginListenForData();
			myLabel.setText("Bluetooth shield connected.");
		}
	}

Place method findBT() and openBT() in onStart() method. Actually, these work should take place in separate thread because forming a connection can block a thread for a significant amount of time. Up until now, all of the program’s code has been written in the main thread or UI thread. You will notice later a little lag when switching activity because between these activity, the connection is established. You may curious what is UUID. Here i quotes from android doc

A Universally Unique Identifier (UUID) is a standardized 128-bit format for a string ID used to uniquely identify information. The point of a UUID is that it’s big enough that you can select any random and it won’t clash. In this case, it’s used to uniquely identify your application’s Bluetooth service. To get a UUID to use with your application, you can use one of the many random UUID generators on the web, then initialize a UUID withfromString(String).

UUID for serial communication is 0000-1101-0000-1000-8000-00805f9b34fb

The last, make a method to sendData. This is as easy as getting text from text fields, write to the output stream, and flush the output stream to send data to bluetooth module.

void sendData() throws IOException {
		if (btdev) {
			String str = myTextbox.getText().toString() + '#';
			mmOutputStream.write(str.getBytes());
			mmOutputStream.flush();
			myLabel.setText("Data sent.");
		}
	}

Of course you have to make a clicklistener for button “Send”. The onCreate method become like this

public void onCreate(Bundle paramBundle) {
		super.onCreate(paramBundle);
		setContentView(R.layout.activity_send);
		//ArrayList list = new ArrayList();
		Button sendButton = (Button) findViewById(R.id.send);
		myLabel = ((TextView) findViewById(R.id.label));
		DataBt = ((TextView) findViewById(R.id.label2));
		myTextbox = ((EditText) findViewById(R.id.entry));
		listDevicesFound = ((ListView) findViewById(R.id.receivedata));
		btArrayAdapter = new ArrayAdapter(this,
				android.R.layout.simple_list_item_1);
		listDevicesFound.setAdapter(this.btArrayAdapter);
		sendButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View paramAnonymousView) {
				try {
					sendData();
					return;
				} catch (IOException localIOException) {
				}
			}
		});
	}

Ah, almost forget. Be sure you close the bluetooth connection when finish the application. Close any stream and socket. Place the code inside method onDestroy() or onStop()

void closeBT() throws IOException {
		if (btdev) {
			stopWorker = true;
			mmOutputStream.close();
			mmInputStream.close();
			mmSocket.close();
			myLabel.setText("Bluetooth closed.");
		}
	}

AAAND VOILA IT’S DONE 🙂

MinSys-001

Watch my first video above to look how this app run. HC-05 will differently blink when powered or connected. Slow flicker (1Hz) represents emtering communication mode while fast flicker (2Hz) represents “pairable mode” which it wait to be discovered and connected

with the complete code, program will run correctly. Feel free to ask or request for apk,hex,or project file at comment below 🙂 🙂

Advertisements

30 responses to “Interfacing Android With Microcontroller

  1. Pingback: DIY Home Automation, Berinteraksi Dengan Alat Elektronik | Adhitya Reza·

    • there are many ways to achieve that. Android can retrieve current time and date in many different formats.

      here i just tell the idea :
      1. retrieve data and time (just google that) ,
      2. convert to string with format that will be easy to be understand and parsed by AVR. (since programming in AVR is much more limited than in android)
      3. send and receive that data via bluetooth, serially of course

      maybe i’ll come with tutorial next post next time

  2. Hey wonderful tutorial , can you share the code ? i am actually doing a similar project where i have to glow leds on pressing buttons from android device . i am using PIC16F77A and HC05

  3. How to communicate between two bluetooth using microcontroller? Do we have set the 1’st bluetooth as master and the other as slave?

  4. hey man that was nice. I am myself building something like this. Can you please give me the android app you used.
    I am having a problem that the data i receive is not correct. lcd just displays a blop at that point. I know that i am receiving something but thats it.
    Thanks in advance

    • Basil, have you sent msg to my email? I’ll reply with the source code.
      That problem, i guest you are wrongly printing char to lcd

      • thanks man for the reply, but i did solve the problem.
        problem was with microcontroller fuses. it was assigned to work at 1MHZ whereas i was programming it at 8Mhz

  5. really nice and helpful. and em using the same uC in my bot.. what i need to know is if i want to operate my bot with any andriod app that can move my bot like Bluetooth Rc. how m i gonna do that please help!

  6. I need to know the pins you connected from the Rxd and Txd of the Bluetooth on the atmega 16 as well as the pins of rs,rw and e from lcd to the atmega

  7. i am the beginner for eclipse program and i use pic microcontroller . but now i want to controll pic by bluetooth. but now i can not connect and can not send data from phone to to pic to controll light. could you please sent the code for blue for pic micro controller and code for interface on eclipse with step for designing.

  8. Hey!
    I am designing a similar project using atmega8 but i am facing trouble as the bluetooth module is not receiving the text and hence not displaying on the lcd.
    Can u please send me the code of the MCU and also the source code of the android application.
    I need it urgently. :/
    this is my email id : sayema.mashhadi@hotmail.com

  9. aditya sir,
    i am doing this same,i made all the connections,the problem is in code
    i am getting error in assembly for .equ_lcd_port,
    and also warnings for #include as macros already defined

  10. Your project has been a great help to me. Can you pls send me the source code of the MCU and the android app? I have sent you an email. Thanks in advance 🙂

  11. hi, mate you could send me your project to my mail, because I need show data in lcd, but I can´t. I’ve searched in forums, google and nothing it working. please help me.
    thanks mate.

  12. Hi man,
    Nice tutorial I am doing a similar application for getting the readings from the Loadcell and displaying it on the Android.
    If yo can please share the full code of the android side so that I can use it in my project.

  13. thanks for the information
    but can you tell me what will be the file formet (for example json) for sending data from android app to hc 05 or esp8266 conneted to aurdino atmega 328

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s