понедељак, 27. фебруар 2012.

Arduino and Android parking assistance 2 (ANDROID communication part )


Hi guys,

hope you have enjoyed reading our last post about „Matrix led display controlled by Arduino and Android - the coding part“. Now we want to build on the previous post about Arduino and Android parking assistance. Just now we’ll talk about Android Parking assistance app. As we could see in  previous post how look like Android app interface,  in this post we’ll describe how were implemented bluetooth protocol.

We all know Android is very popular now, especially ADK (Android Open Accessory Development Kit), which allows external 0pen source hardware to connect with Android system by USB and interact with an Android-powered device in a special “accessory” mode.
To make the communication between Android and Arduino easy, we would like show you a new way that android interact with Arduino and other similar boards. Bluetooth for example.

Step one: Make a APP to Android which could communicate with other devices by bluetooth.
Step two: Android APP connect to Arduino by Bluetooth Mate Silver.

This APP allows Android connect to each other by bluetooth, so you need at least two Android devices for this app.

Bluetooth

            The Android platform includes support for the Bluetooth network stack, which allows a device to wirelessly exchange data with other Bluetooth devices. The application framework provides access to the Bluetooth functionality through the Android Bluetooth APIs. These APIs let applications connect wirelessly to other Bluetooth devices, enabling point-to-point and multipoint wireless features.

The Basics

All of the Bluetooth APIs are available in the Android bluetooth package. Here is a summary of the classes you will need to create as below.

ü  BluetoothAdapter: Represents the local Bluetooth adapter (Bluetooth radio)
ü  BluetoothDevice: Represents a remote Bluetooth device, query information such as its name, address, class, and bonding state.
ü  BluetoothSocket: Represents the interface for a Bluetooth socket (similar to a TCP Socket).
ü  BluetoothServerSocket: Represents an open server socket that listens for incoming requests (similar to a TCP ServerSocket).
ü  BluetoothClass: Describes the general characteristics and capabilities of a Bluetooth device.

Bluetooth Permissions

                In order to use Bluetooth features in your application, you need to declare at least one of two Bluetooth permissions: BLUETOOTH and BLUETOOTH_ADMIN.
Declare the Bluetooth permissionin your application’s AndroidManifest.xml as below.

AndroidManifest.xml
<manifest ... >
  <uses-permission android:name="android.permission.BLUETOOTH" />
  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
  ...
</manifest>
Let us see some code, really start from here. In order to connect by bluetooth, there should be four steps as below:
  • Setting Up Bluetooth
  •  Finding Device
  •  Connecting Device
  •   Managing Device


Setting Up Bluetooth

We made the App include eight java files. For now, we only need to use:

·         Main.java,
·         DiscoveryActivity.java
·         ClientSocketActivity.java

Before your application can communicate with Bluetooth, you should verify Bluetooth is supported on the device and make sure that it is enabled. If Bluetooth is not supported, you should gracefully disable any Bluetooth features. If Bluetooth is supported, but disabled, you are able to request the user enable Bluetooth without leaving your application. So, at Main.java in Tab Settings we get five buttons, as below:

  Select “Enable Bluetooth” button make the device’s own Bluetooth adapter (the Bluetooth radio) working. There is one Bluetooth adapter for the entire system, and your application can interact with it when it is open.


public BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter(); 
...
public void EnableBluetooth(View v)
{
                Toast.makeText(this, "Bluetooth enable", Toast.LENGTH_LONG).show();
                _bluetooth.enable();  
               
                Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                startActivityForResult(enabler, REQUEST_DISCOVERABLE);
                               
}

/*
   There are two ways to enable bluetooth
1)
   Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
   startActivityForResult(enabler, REQUEST_DISCOVERABLE);
2)
   _bluetooth.enable();
*/




Create a new Intent as  
“Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)”, a dialog box will appear and request user permission to enable Bluetooth. Select “Yes” and the system will enable Bluetooth and focus will return to your application once the process completes.

            You need to ensure that Bluetooth is enabled and allowed other devices could discover it. Add the below code, and a dialog box will appear also, you should click “Yes”.
A part of code for each button activity in Main.class as bellow:

Main.java
public void openBluetooth(View v)
    {
       Toast.makeText(this, "Bluetooth enable ...", Toast.LENGTH_LONG).show();
       _bluetooth.enable();      
       Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
              startActivityForResult(enabler, REQUEST_DISCOVERABLE);
             
    }

       public void closeBluetooth(View v)
    {        
             ........

       _bluetooth.disable();
       Toast.makeText(this, "Bluetooth disable ...", Toast.LENGTH_LONG).show();
      
              ........
    }
   
    public void searchDevices(View v)
    {
       Intent search = new Intent();
       search.setClass(c, DiscoveryActivity.class);
       startActivity(search);
    }
   
    public void openClientSocketButton(View v)
    {
       Intent enabler = new Intent(c,ClientSocketActivity.class);
       startActivity(enabler);
    }




Finding Device

            With Discovery Activity.java file, we will find around device. The process is asynchronous and the method will immediately return with a boolean indicating whether discovery has started successfully. The discovery process usually involves an inquiry scan of about 12 seconds, followed by a page scan of each found device to retrieve its Bluetooth name. Your application must register a BroadcastReceiver for the ACTION_FOUND. Intent in order to receive information about each device discovered.

/* Register Receiver*/
IntentFilter discoveryFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(_discoveryReceiver, discoveryFilter);
IntentFilter foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(_foundReceiver, foundFilter);

/**
 * Receiver
 * When the discovery finished be called.
 */
private BroadcastReceiver _foundReceiver = new BroadcastReceiver()
{
       public void onReceive(Context context, Intent intent) {
       /* get the search results */
       BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
       /* push in ArrayList */
       _devices.add(device);
       /* show the devices list */
       showDevices();
       }
};

private BroadcastReceiver _discoveryReceiver = new BroadcastReceiver() {
              @Override
       public void onReceive(Context context, Intent intent) 
       {
       /* unRegister Receiver */
       Log.d("EF-BTBee", ">>unregisterReceiver");
             
       unregisterReceiver(_foundReceiver);
       unregisterReceiver(this);
       _discoveryFinished = true;
       }
};
      


After discovery will return remote device’s MAC address, device name and class. Using this information, the device performing discovery can then choose to initiate a connection with the discovered device. The following figure is click the “Search Device” button.


Connecting Device and Managing Device

            In order to create a connection between your application and two devices, you must implement the both server-side and client-side mechanisms, because one device must open a server socket and the other one must initiate the connection (use the server device’s MAC address to initiate a connection). So you must used a same UUID.

As Client:
UUID for Android App
socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));




The full code of class ClientSocketActivity.java
package com.android;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;

public class ClientSocketActivity  extends Activity
{
  private static final String TAG = ClientSocketActivity.class.getSimpleName();
  private static final int REQUEST_DISCOVERY = 0x1;;
   private Handler _handler = new Handler();
   private BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter();
   private BluetoothSocket socket = null;
      
       protected void onCreate(Bundle savedInstanceState)
       {
              super.onCreate(savedInstanceState);
              getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
              WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
              setContentView(R.layout.client_socket);
              if (!_bluetooth.isEnabled())
             {
                     finish();
                return;
              }

             Intent intent = new Intent(this, DiscoveryActivity.class);   
             /* Prompted to select a server to connect */
             Toast.makeText(this, "select device to connect", Toast.LENGTH_SHORT).show();
              /* Select device for list */
              startActivityForResult(intent, REQUEST_DISCOVERY);
       }
      
      
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
/*The integer request code originally supplied to startActivityForResult(), allowing you to identify who this result came from */
             
             if (requestCode != REQUEST_DISCOVERY)
              {
                     return;
              }
/*resultCode  The integer result code returned by the child activity through
               * its setResult() */
              if (resultCode != RESULT_OK) {
                     return;
              }
             
             final BluetoothDevice device = data.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
              connect(device);          
       }
      
      
       protected void connect(BluetoothDevice device)
       {
              //BluetoothSocket socket = null;
              try {
    //Create a Socket connection: need the server's UUID number of registered
              socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
                    
                     Singleton.remote_soket=socket;
                     Intent i=new Intent();
                     i.setClass(this.getApplicationContext(), Main.class);
                     startActivity(i);
                     finish();
                     return;
                    
              } catch (IOException e) {
                     Log.e("EF-BTBee", "", e);
              }
       }
}




When user selects device which he wants to connect, it looks like on picture above:


So, if anyone have some problem, with code, leave a comment and we will try to answer and solve the problem. As we mentioned earlier, we hope to post some more videos about how system is working and also write about some new projects (some stuff about using Arduino in Smart houses, so very interesting topics)...anyway, see you soon

M&M

понедељак, 20. фебруар 2012.

Matrix led display controlled by Arduino and Android - the coding part

HI guys,

  hope you have enjoyed reading our last post about matrix led display. As we mentioned earlier, this post is going to be about coding Arduino and Android so we could use it to control our system...

 We can start with Arduino code. So, what is actually needed? Of course, because we use MAX7219 martix led drivers you guess we will use some code and libraries that are (closely) connected with this drivers. Very usefull page about that and our initial guide to get more information about Arduino coding was http://www.pjrc.com/teensy/td_libs_Matrix.html, so thanks to people who made this page. First, readers can get some basic info about hw parts and more important and more usefull they can find some basic about used libraries. Those are Matrix.h and Sprite.h.  About them, you can find more at http://wiring.org.co/reference/libraries/Matrix/index.html  and 
http://wiring.org.co/reference/libraries/Sprite/index.html . So, if you write any code based on those two libraries, it is good to start with this because some elementary code about almost every command is present on those links. So, let's see onde again picture of our system.


Now we will try to explaine most important parts of our Arduino code, and if anyone needs more explination, try to contact us via mail or better, write comment, and we will send our code. Get in mind that for  first couple lines of code - it is connected with bluetooth configuration and more about that you can find in our post about Bluetooth - http://arduinoandroid.blogspot.com/2011/11/post-number-2-work-version.html


ArduinoSolution
#include <NewSoftSerial.h> // Bluetooth library
#include <Sprite.h>  // Sprite before Matrix
#include <Matrix.h>
// instance of Matrix class with Arduino digital pins we use for DIN, CLOCK and //LOAD, respectively
//                     DIN, CLK, LOAD, #chips
Matrix myLeds = Matrix(12, 11, 10, 3);
byte byteNiz[200]; //  Array for readed characters
int pokByte =0; // pointer for the currently read character

int i=23; // column value from where characters are started moving on display
byte proc;  //  character currently being worked with
int maks=0; // total length of text that will rotate on display
int razlika = 0; // this is actually maks - length of display(23, because 3 matrix //8x8)
int citao = 0; // for 0, character is being read, for 1 just shown rotating on display
int krajnjaPozicija = 23; // max column value of display (depends of number of led matrices)

int bluetoothTx = 2;  // TX-O pin for bluetooth mate, Arduino D2
int bluetoothRx = 3;  // RX-I pin for bluetooth mate, Arduino D3
NewSoftSerial bluetooth(bluetoothTx, bluetoothRx); // instances of bluetooth, //will be used for receiving characters from android app
...                         
... // for every letter (or better), for every sing you want to see on display, define //instances of Sprite, set height and witdh...with red colour, we wanted to show //you what sign is specified...define this for every letter you need
Sprite letter_A = Sprite(5, 7,
  B01110,
  B10001,
  B10001,
  B11111,
  B10001,
  B10001,
  B10001
);

Sprite letter_B = Sprite(5, 7,
  B11110,
  B10001,
  B10001,
  B11110,
  B10001,
  B10001,
  B11110
);
... // // Setup function - being executed only once, when program is being //started
void setup()
{
  Serial.begin(9600);  // Serial communication at 9600bps
  bluetooth.begin(115200);  // BaudRate for Bluetooth module is 115200bps  bluetooth.print("$$$");  // Get into Bluetooth mode command mode
  delay(100);  // Short delay, so Bluetooth can answer with CMD  bluetooth.println("U,9600,N");  // get back to 9600, because 115200 can be to fast for NewSoftSerial  
  bluetooth.begin(9600);  // baudrate for bluetooth modul now is 9600     bluetooth.print("$$$");
  delay(100);
  bluetooth.println("w");
  delay(1000);
  bluetooth.println("---");/ exit from command mode
  // Finished configuration od BT mate
 
  myLeds.clear();// clear led display 
  myLeds.setBrightness(15); // set value for Led brightness        Serial.begin(9600);
  // niz u koji se smestaju karakteri se popuni nulama
  for( int brojac=0; brojac<200; brojac++ )
    byteNiz[brojac] = 0;
    pokByte = 0; 
}

// loop function, repeats all the time while the program is running
void loop()
{
  myLeds.clear();// to refresh the display     
  readLetter();//  function used for character reading   
if( citao == 1 )
       drawLetter(); // function for showing text on led display
}

// FUNCTION FOR READING CHARACTERS
void readLetter()
{
 if ( bluetooth.available() > 0 )
 { // set values on initial state 
  i=23; 
  maks = i; // current length of text, it will grow
  citao = 0; // for 0 is reading , for 1 is drawLetter in loop()
  pokByte = 0; 
        // while BT recieves characters, they are recieved and ready for work
     while ( bluetooth.available() > 0 )
     {
       proc = bluetooth.read(); // recieved character is now in proc
       byteNiz[ pokByte ] = proc; // put proc in recieved characters array
       pokByte = pokByte+1; // set pointer for the new character
         // for every recieved character increase length of the text
         switch (proc)
         {
            case 'a' :
            case 'A' :
             maks = maks+6;
            break;
           
            case 'b' :
            case 'B' :
             maks = maks+6;
            break;
... // treba proveriti za svaki karakter od mogucih za ispis
...
     razlika = maks - 23; // difference between text length and display length
     citao = (citao+1)%2 ; // reading is finished and now text can be shown on display
    }
  else 
     citao = 1; // continue with showing old text if there is no new text  
}

//FUNCTION FOR SHOWING TEXT ON DISPLAY
void drawLetter()
{   
   if( i < 0-razlika+1 )  // if all text has passed on display
    i = krajnjaPozicija; //  start again with showing text
   
   int poz = i;   // temporary variable for showing text

  // ispis procitanih slova
  for( int brojac = 0; brojac <pokByte; brojac++ )
  { // conditions that serve us for showing just letters that are on visiable //part of display
   boolean uslov1 = poz >= -5 && poz < 24 ;
   boolean uslov2 = (poz >=- 4) && (poz < 24 ) ;
   boolean uslov3 = (poz >=- 2) && (poz < 24 ) ;
   boolean uslov4 = (poz >=- 3) && (poz < 24 ) ;
   
    // you get character, and depending on its value, you show adecvate //character on led display  
   switch( byteNiz[brojac] )
   { // examples for letters (A,a) and (B,b)
     case 'a' :
     case 'A' :
     if( uslov1 ) 
        myLeds.write( poz , 0 , letter_A ); // show on display
    poz = poz+6; // places needed for character + one blanco
      break;
      case 'b' : // examples for (B,b)
      case 'B' : 
       if( uslov1 )
        myLeds.write( poz , 0 , letter_B );
    poz = poz+6; // places needed for character + one blanco
...
...
...
i = i-1; move left for one position
citao = 1;  // text continues to show on display    
delay(225); // short delay that gives effect that text is moveing
}




So, after Arduino code we need to say something about Android code. Once again, we needed to create Android application in which user brings in text, and via bluetooth sends it to led display. Also, we created virtual display on our Android device, that shows virtualy how text is going on the display (we will show that in pictures just a little later). So, because of Bluetooth usage, we needed to use, i think API 2.2 or above (but i'm preety sure that it is 2.2), because form this vrsion, Bluetooth is enabled. Here is the class diagram for the Arduino code, and we will try to explain most important parts of most important classes.

Class PocetnaStrana.java is responsable for the look of application when it starts.
PocetnaStrana.java
public class PocetnaStrana extends Activity implements OnCheckedChangeListener  // implements View.OnClickListener
{
      EditText tvTextZaReklamu ; // text field where text is being input
      Button sendButton, prelaz
      RadioGroup rg; // choose text color for virtual display on ANdroid
      String boja="red"  ; // default color is red   
      Context c
      String txt;
...
...
...
// icinijalizacija promenljivih u metodi OnCreate()
protected void onCreate(Bundle savedInstanceState)
      {
            // TODO Auto-generated method stub
      super.onCreate(savedInstanceState);
      setContentView(R.layout.prvapage);
      c=this.getApplicationContext();
      tvTextZaReklamu = (EditText) findViewById( R.id.editTextPolje );
      sendButton = (Button) findViewById( R.id.buttonSendMessage );
      rg = (RadioGroup) findViewById(R.id.radioGroup1);
      prelaz = (Button)this.findViewById(R.id.bBTConn);
      rg.setOnCheckedChangeListener(this);
     
// part of method to choose color
public void onCheckedChanged(RadioGroup group, int checkedId)
      {
            switch( checkedId )
            {
              case R.id.radioRedBoja :
                    this.boja="red";
                    break;
           
              case R.id.radioGreenBoja :
                    this.boja="green";
                    break;   
...
...
// 
sendButton.setOnClickListener(new View.OnClickListener()
{
      @Override
      public void onClick(View v)
      {
        txt = tvTextZaReklamu.getText().toString();
      Bundle basket = new Bundle(); //pas the data to new activity
      basket.putString("txt", txt); // put the data                     basket.putString("boja", boja); // pass the color of the text
                       
      hand.post(tmp); //pass the data to threed which controls the Bluetooth
                       
                     
Intent a = new Intent(PocetnaStrana.this,LedDispleyCommercialActivity.class);
      a.putExtras(basket); // put all data in basket
      startActivity(a); // go to new activity
...
...
...

// code for goint to activity connected with Vluetooth part of the code
prelaz.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
   Intent i = new Intent();
   i.setClass(c, Settings.class); 
   startActivity(i);
   }

...
...
...

// Handler which controls sending to BT mate device
public Handler hand = new Handler();
    Runnable tmp = new Runnable()
     {
       public void run()
       {try
        {
          outputStream=Singleton.remote_soket.getOutputStream();             
          String send=txt;
          byte[] bytesend = new byte[1024];
          bytesend=send.getBytes();                  
          outputStream.write(bytesend);              
                 




   Here is the look of application when it starts

 If you click on button Bluetooth connection, it goes to :


When Bluetooth connection achieved, you click save and back to main menu and return to start page, so enter text and click send, and text is now sent to Arduino and starts rotating on Led display. The procudere and code for that is already described earlier in this post when we talked about Arduino code. Also, application has presentation of virtual led display where text is also rotated from left to right.

Now we will describe most important parts of code for that virtual text rotation.

LedDisplayCommercial.java
public class LedDispleyCommercialActivity extends Activity
{   // atributi klase
    private MotionRunner mRunner; // instance class MotionRunner
    private int delay = 100; // delay speed

    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        Bundle getBasket = getIntent().getExtras();
       
        // get the text and color from the start activity
        String s = getBasket.getString("txt"); // get text
        String boja = getBasket.getString("boja"); // get color
        // inicijalizacija instance klase MotionRunner
        mRunner = new MotionRunner(this  , s , boja );
        setContentView(mRunner);
        mRunner.startIt(delay); // start thread for drawing virtual display
}
// method for resuming activity 
protected void onResume()
{
   super.onResume();
   mRunner.startLooper(delay);
}
// method for stopping
protected void onStop()
{
  super.onStop();
  finish();
}




 Those are most important classes of Android application, so if anyone needs more information, write a comment and we will try to answer and help/solve the problem. In next posts we hope to set some videos ones who are interested may see how system actually works, and potential idea is to try to gather some other guys (and girls) from university who also worked with Arduino and try to make some video podcast about our projects.
See you soon,
  M&M team