Tuesday, December 18, 2012

It Worked For Me - Evil Mad Scientist Arduino ISP Shield

I recently decided to try my hand at programming another member of the AVR family. After doing some reading I decided on the ATtiny85. Online I found a good tutorial on programming the ATtiny85 using a breadboard. I ordered up some ATtiny85s and followed the instructions on the tutorial and was quickly able to program it.

Plugging the ATtiny85 into and taking it out of the breadboard got old fast. Poking around the MicroCenter website I noticed that my local store had several Evil Mad Scientist Arduino ISP Shield kits in stock. On the Evil Mad Scientist website I found a link to an Instructable for hacking the shield to allow programming of the ATtiny85.

I picked one of the kits up from MicroCenter, built it with the great instructions on the Evil Mad Scientist website and then made the mods outlined in the Instructable to allow programming ATtiny85s.

View of the top of the shield.


View of the bottom of the shield.

Note the wire wrap wires used for the ATmega168/328 to ATtiny85 mod.


A Hack of My Own

I extended the mod from the Instructable to allow for multiple clock speeds for both the ATtiny86 and thge ATmega126/328. I connected the the clocking pins from the standard ATmega168/328 location to the ATtiny85 pins. I did this using wire wrap wire as done with the other pins. I then installed female headers in place of the capacitors and crystal. I took the capacitors and crystal and soldered them to sets of mail header pins. This way I can plug in different speed crystals.


Thanks to the folks at Evil Mad Scientist for producing such an affordable and hackable product, thanks to the folks at the High Low-Tech Group at the MIT Media Lab for instruction on how to program ATtiny85s using the Ardunio IDE and thanks to rleyland for posting instructions for his hack.

Monday, October 22, 2012

Heart Rate Monitor Project – Phase 1: Software

Over the weekend I developed some initial code to work with the hardware setups posted last week. The code was developed in Arduino 1.0.1.

Ant+ Heart Rate Monitor Code for Arduino

Sunday, October 14, 2012

Heart Rate Monitor Project – Phase 1: ANT + Arduino Hardware Setup

As outlined in a previous post I am working on a project to interface an ANT+ Garmin Hear Rate Monitor Strap to an Android tablet.  The first phase is to get heart rate statistics sent via ANT from the heart rate monitor to an Arduino.

I am working on solutions with two ANT modules: Sparkfun’s USB ANT Stick and Dynastream Innovations ANT11TS33M4IB Module

Sparkfun USB ANT Stick Hardware Setup

Both modules run at 3.3V so I wired up an 8Mhz breadboard Arduino running at 3.3V.  Connecting the Sparkfun USB ANT Stick was easy.  All that was required was soldering four pins into the holes located on the board.  If you look at the insert of the board in the picture below you will see the four pins.

SparkfunSetup

Once the pins were connected the board was plugged into the breadboard with power connected to the power rail running at 3.3v, ground to the ground rail, receive to D7 and transmit to D8 on the Arduino.

Dynastream Innovations ANT11TS33M4IB Module Hardware Setup

Connecting the Dynastream module was a bit more of a challenge than the Sparkfun module.  The Dynastream module is a square board that measures roughtly 0.75” of an inch. On two sides of the board there are 7 holes / pads and on a third there are 3. Given the spacing of the holes and their locations the module isn’t breadboard friendly.

I found that the individual wires in a Cat5 LAN cable were the right size to fit into the holes. I cut a section of Cat5 cable, extracted the individual wires and soldered them to the board and then plugged them into the breadboard.

DynastreamSetup

Additional pictures from the sides showing the connections:

      

The following pin out was used.

Module Pin Pin Name Connected To
1 GND GND
2 /RESET 3.3v
3 Vcc 3.3v
4 GND GND
5 GND GND
6 /SUSPEND 3.3v
7 SLEEP GND
8 GND GND
9 GND GND
10 BR2 GND
11 TXD0 D7
12 RXD0 D8
13 BR1 GND
14 BR3 GND
15 GND GND
16 GND GND
17 RTS D12 w/1Mohm to 3.3v

The 1M ohm pull up resister on pin 17 is key. If you don't have it the board goes into sensRcore mode and will not respond to async communications.

Next Steps

With the hardware all setup the next step will be to program the Arduino and test communications from the heart rate monitor strap through the ANT module to the Arduino.  This will be the subject of the next post.

Heart Rate Monitor Project

As the summer drew to a close I decided that monitoring my hear rate as part of my indoor training regime would make for an interesting project and might make cycling indoors a bit more interesting. To do this I decided to interface the heart rate monitor with my Android tablet.

BikeStrapTablet

After doing some research I decided that there were three approaches I could take.

  1. Get a bluetooth heart rate band and interface with the tablet via bluetooth.
  2. Get an ANT capable heart rate band and interface with the tablet using ANT and the android open accessory protocol.
  3. Get a heart rate band from Polar and interface with the tablet using a Polar wireless interface board and the android open accessory protocol.

I decided to go with the ANT approach. This was partly because of cost but also due to the fact that there are other sensors including ones that measure cadence and speed that make use of ANT.

What is ANT?

ANT is a 2.4GHz wireless networking protocol and embedded system solution designed for low power wireless sensor networks. It has a focus on sensors for measuring various aspects of exercise and while it isn’t restricted to this it does seem to be a popular us case.

For the most part ANT sensors are used in combination with GPSes which provide readout and recording of the sensors. There are also a few smart phones that are ANT capable.

Heart Rate Belt

An ANT heart rate monitor consists of the sensors for picking up your heart beat and a small lower power transmitter attached to a belt or strap that is worn across the chest. The sensor picks up the heart beats and then broadcasts them so they can be picked up by an ANT receiver.

For my project I chose the Garmin Soft Strap model HRM2-SS which I found on Amazon for $44.

ANT Modules

I started by purchasing Sparkfun’s USB ANT Stick.  This was a very nice module because it got me both a USB interface that could be plugged into a PC.  Also the board broke out power, ground, transmit and receive which facilitated connecting them to a microprocessor.  Unfortunately, shortly after I purchase this from Sparkfun they discontinued the product with no replacement.

I also ordered a Dynastream Innovations ANT11TS33M4IB Module as I felt the form factor of this module would work better in the final design.  The Dynastream module is I purchased is the module on the ANT website that is recommended for prototyping. It can be purchased from several sources. I purchased mine from Digikey.

Next Steps

My plan for moving forward is to start by interfacing the ANT modules with an Arduino.  Once I have done this I plan to leverage the Circuits@Home USB Host Shield that I purchased and tested out last spring to interface with Android.

Time Flies – June through September 2012

I was on a roll the first part of 2012 with 14 posts.  Over the summer I got busy with other things and see that I haven’t posted anything since May.  Now with the days getting shorter I have time again for a projects and some new ideas.

Tuesday, May 29, 2012

Arduino to Android – Turning an LED On and Off using ADK and the Circuits@Home USB Shield

This is the same example conceptually as the previous post Arduino to Android – Turning an LED On and Off except that it uses the Android Open Accessory Development Kit (ADK) and a USB connection via a Circuits@Home USB Shield rather than bluetooth to communicate between the Android tablet and the Arduino.

The Android device connects using ADK over USB to the Ardunio which is running in a loop waiting for data from the USB Shield.  If the Android device sends a 1 then the Arduino turns the LED on. If a 0 is sent the LED is turned off.

Hardware Setup

For this example I used:

  1. A breadboard Arduino with a Sparkfun FTDI 3.3v board.
  2. An Acer Iconia Tab A100 running Ice Cream Sandwich 4.0.3.
  3. A Circuits@Home USB Host Shield for Arduino Pro Mini.
  4. A red LED. Connected to the Arduino on digital pin 8.
  5. A 470 ohm resistor connecting the LED to ground.

The picture below shows how the hardware is setup.

ADKSetup
The USB shield was wired to the Arduino as shown in the diagram below.

uhm11_manual
Starting from the top left of the board and working around the board clockwise.

USB Shield Arduino
INT (D9) Digital Pin 9
GND GND
RESET Reset
GND GND
3.3v 3.3v
SCK Digital Pin 13
MISO Digital Pin 12
MOSI Digital Pin 11
SS (D10) Digital Pin 10

Software Setup

This example assumes you have the eclipse Android development environment and the Arduino development environment.

If you are using the Circuits@Home USB Shield you will need to download the 2.0 libraries for the shield and put them in your Arduino libraries directory. The libraries and example files are on GitHub.

Ardunio Sketch
#include <avrpins.h>
#include <max3421e.h>
#include <usbhost.h>
#include <usb_ch9.h>
#include <Usb.h>
#include <usbhub.h>
#include <avr/pgmspace.h>
#include <address.h>

#include <adk.h>

#include <printhex.h>
#include <message.h>
#include <hexdump.h>
#include <parsetools.h>

USB Usb;
USBHub hub0(&Usb);
USBHub hub1(&Usb);
ADK adk(&Usb,"Digitalhack",
            "LEDOnOffADK",
            "DemoKit Arduino Board",
            "1.0",
            "http://www.android.com",
            "0000000012345678");
uint8_t  b, b1;

#define  LED       8

void setup();
void loop();

void setup() {
  Serial.begin(115200);
  Serial.println("\r\nADK demo start");
        
  digitalWrite(LED, LOW);
  pinMode(LED, OUTPUT);

  if (Usb.Init() == -1) {
    Serial.println("OSCOKIRQ failed to assert");
    while(1); //halt
  }
}

void loop() {
  uint8_t rcode;
  uint8_t msg[3] = { 0x00 };
  Usb.Task();
   
  if (adk.isReady() == false) {
    Serial.println("Waiting for adk.");
  } else {
    uint16_t len = sizeof(msg);
   
    rcode = adk.RcvData(&len, msg);
    if( rcode && rcode != hrNAK) {
      Serial.print("Data rcv rcode: ");
      Serial.println(rcode);
    } 

    if(len > 0) {
      Serial.println("Data Packet.");
      // assumes only one command per packet
      if (msg[0] == 0x2) {
        switch( msg[1] ) {
          case 0:
            digitalWrite(LED, LOW);
            break;
          case 1:
            digitalWrite(LED, HIGH);
            break;
         }  
       }
    }
    delay( 10 );
  }
}
LEDOnOFFADK.java
goes in ProjectRoot>\src\com\example\ledonoffadk\
package com.example.ledonoffadk;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import com.example.ledonoffadk.R;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;

public class LEDOnOffADK extends Activity {
  private static final String TAG = "LEDOnOffADK";
  
  private static final String ACTION_USB_PERMISSION = "com.example.LEDOnOffADK.USB_PERMISSION";
  
  private UsbManager mUsbManager;
  private PendingIntent mPermissionIntent;
  private boolean mPermissionRequestPending;
 
  UsbAccessory mAccessory;
  ParcelFileDescriptor mFileDescriptor;
  FileInputStream mInputStream;
  FileOutputStream mOutputStream;
 
  Button btnOn, btnOff;

  private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      if (ACTION_USB_PERMISSION.equals(action)) {
        synchronized (this) {
          UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
          if (intent.getBooleanExtra(
              UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
            openAccessory(accessory);
          } else {
            Log.d(TAG, "permission denied for accessory "
                + accessory);
          }
          mPermissionRequestPending = false;
        }
      } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
        UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
        if (accessory != null && accessory.equals(mAccessory)) {
          closeAccessory();
        }
      }
    }
  };

  
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.d(TAG, "In onCreate()");

    mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
    filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
    registerReceiver(mUsbReceiver, filter);
 
    if (getLastNonConfigurationInstance() != null) {
      mAccessory = (UsbAccessory) getLastNonConfigurationInstance();
      openAccessory(mAccessory);
    }
 
    setContentView(R.layout.main);

    btnOn = (Button) findViewById(R.id.btnOn);
    btnOff = (Button) findViewById(R.id.btnOff);

    btnOn.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        byte[] buffer = new byte[2];
        buffer[0]= 0x2;        
        
        buffer[1]=(byte)1; // button says on, light is off
        if (mOutputStream != null) {
          try {
            mOutputStream.write(buffer);
          } catch (IOException e) {
            Log.e(TAG, "write failed", e);
          }
        }
        Toast msg = Toast.makeText(getBaseContext(),
            "You have clicked On", Toast.LENGTH_SHORT);
        msg.show();
      }
    });

    btnOff.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        byte[] buffer = new byte[2];
        buffer[0]= 0x2;        
        
        buffer[1]=(byte)0; // button says on, light is off
        if (mOutputStream != null) {
          try {
            mOutputStream.write(buffer);
          } catch (IOException e) {
            Log.e(TAG, "write failed", e);
          }
        }
        Toast msg = Toast.makeText(getBaseContext(),
            "You have clicked Off", Toast.LENGTH_SHORT);
        msg.show();
      }
    });
  }
 
  @Override
  public Object onRetainNonConfigurationInstance() {
    if (mAccessory != null) {
      return mAccessory;
    } else {
      return super.onRetainNonConfigurationInstance();
    }
  }
 
  @Override
  public void onResume() {
    super.onResume();
 
    if (mInputStream != null && mOutputStream != null) {
      return;
    }
 
    UsbAccessory[] accessories = mUsbManager.getAccessoryList();
    UsbAccessory accessory = (accessories == null ? null : accessories[0]);
    if (accessory != null) {
      if (mUsbManager.hasPermission(accessory)) {
        openAccessory(accessory);
      } else {
        synchronized (mUsbReceiver) {
          if (!mPermissionRequestPending) {
            mUsbManager.requestPermission(accessory,mPermissionIntent);
            mPermissionRequestPending = true;
          }
        }
      }
    } else {
      Log.d(TAG, "mAccessory is null");
    }
  }

  @Override
  public void onPause() {
    super.onPause();
    closeAccessory();
  }
 
  @Override
  public void onDestroy() {
    unregisterReceiver(mUsbReceiver);
    super.onDestroy();
  }
 
  private void openAccessory(UsbAccessory accessory) {
    mFileDescriptor = mUsbManager.openAccessory(accessory);
    if (mFileDescriptor != null) {
      mAccessory = accessory;
      FileDescriptor fd = mFileDescriptor.getFileDescriptor();
      mInputStream = new FileInputStream(fd);
      mOutputStream = new FileOutputStream(fd);
      Log.d(TAG, "accessory opened");
    } else {
      Log.d(TAG, "accessory open fail");
    }
  }
 
  private void closeAccessory() {
    try {
      if (mFileDescriptor != null) {
        mFileDescriptor.close();
      }
    } catch (IOException e) {
    } finally {
      mFileDescriptor = null;
      mAccessory = null;
    }
  }
}
strings.xml
goes in <ProjectRoot>\res\values\
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">LED On Off (ADK)</string>

</resources>
main.xml
goes in <ProjectRoot>\res\layout\
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btnOn"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:text="Turn LED On" />

    <Button
        android:id="@+id/btnOff"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:text="Turn LED Off" />

</LinearLayout>
accessory_filter.xml
goes in <ProjectRoot>\res\xml\
<?xml version="1.0" encoding="utf-8"?>
<resources>
  <usb-accessory manufacturer="Digitalhack" model="LEDOnOffADK" version="1.0" /> 
</resources>
AndroidManifest.xml
goes in <ProjectRoot>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.ledonoffadk"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />

<application android:icon="@drawable/ic_launcher" android:label="@string/app_name"> 
  <activity android:name=".LEDOnOffADK"
   android:label="@string/app_name">
   <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" /> 
   </intent-filter>
   <intent-filter>
    <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" /> 
   </intent-filter>
   <meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
    android:resource="@xml/accessory_filter" />
  </activity> 
 </application>
</manifest>
Screen Capture from Acer A100

LEDOnOffADK

Notes:

  1. I cannot think how you would get this to work with the emulator so I didn't try.
  2. This example is built upon the work of others. I post it here not as an example of original work but rather as a complete working example for reference. If I didn't appropriately credit you for your work please let me know and I will add you.

Monday, May 14, 2012

Arduino to Android – Turning an LED On and Off

This example shows you how to program an Android device to communicate with an Arduino over bluetooth and turn on or turn off an LED.

The Android device connects via the bluetooth to the Arduino which is running in a loop waiting for data from the bluetooth inteface. The data is read from the bluetooth interface using the software serial library. If the Arduino reads a 1 it turns an LED on pin 13 on. If it finds a 0 then it turns the LED off. If it reads anything else it doesn't change the state of the LED.

If you are using the Sparkfun Bluetooth Mate when you successfully connect to it from your Android program the Red Stat LED will turn off and the Green Connect LED will turn on solid.

For this example I used the same setup as I did for my earlier Arduino to Android tutorial: Arduino to Android – Basic Bluetooth Connectivity with the addition of an LED connected to pin 13 on the Arduino.

Download Zip Archive of Android Source Files

Arduino Sketch
#include <SoftwareSerial.h>

SoftwareSerial mySerial(6, 5);
int dataFromBT;

void setup() {
  Serial.begin(57600);
  Serial.println("LEDOnOff Starting...");

  // The data rate for the SoftwareSerial port needs to 
  // match the data rate for your bluetooth board.
  mySerial.begin(115200);
  pinMode(13, OUTPUT);   
}

void loop() {
  if (mySerial.available())
    dataFromBT = mySerial.read();

  if (dataFromBT == '0') {
    // Turn off LED
    digitalWrite(13, LOW);
  } else if (dataFromBT == '1') {
    // Turn on LEFD
    digitalWrite(13, HIGH);
  }
}
LEDOnOFF.java
goes in <ProjectRoot>\src\com\example\ledonoff\
package com.example.ledonoff;

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

import com.example.ledonoff.R;

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.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class LEDOnOff extends Activity {
  private static final String TAG = "LEDOnOff";
  
  Button btnOn, btnOff;
  
  private static final int REQUEST_ENABLE_BT = 1;
  private BluetoothAdapter btAdapter = null;
  private BluetoothSocket btSocket = null;
  private OutputStream outStream = null;
  
  // Well known SPP UUID
  private static final UUID MY_UUID =
      UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

  // Insert your server's MAC address
  private static String address = "00:00:00:00:00:00";
  
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Log.d(TAG, "In onCreate()");

    setContentView(R.layout.main);

    btnOn = (Button) findViewById(R.id.btnOn);
    btnOff = (Button) findViewById(R.id.btnOff);
    
    btAdapter = BluetoothAdapter.getDefaultAdapter();
    checkBTState();

    btnOn.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        sendData("1");
        Toast msg = Toast.makeText(getBaseContext(),
            "You have clicked On", Toast.LENGTH_SHORT);
        msg.show();
      }
    });

    btnOff.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        sendData("0");
        Toast msg = Toast.makeText(getBaseContext(),
            "You have clicked Off", Toast.LENGTH_SHORT);
        msg.show();
      }
    });
  }
  
  @Override
  public void onResume() {
    super.onResume();

    Log.d(TAG, "...In onResume - Attempting client connect...");
  
    // Set up a pointer to the remote node using it's address.
    BluetoothDevice device = btAdapter.getRemoteDevice(address);
  
    // Two things are needed to make a connection:
    //   A MAC address, which we got above.
    //   A Service ID or UUID.  In this case we are using the
    //     UUID for SPP.
    try {
      btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
    } catch (IOException e) {
      errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
    }
  
    // Discovery is resource intensive.  Make sure it isn't going on
    // when you attempt to connect and pass your message.
    btAdapter.cancelDiscovery();
  
    // Establish the connection.  This will block until it connects.
    Log.d(TAG, "...Connecting to Remote...");
    try {
      btSocket.connect();
      Log.d(TAG, "...Connection established and data link opened...");
    } catch (IOException e) {
      try {
        btSocket.close();
      } catch (IOException e2) {
        errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
      }
    }
    
    // Create a data stream so we can talk to server.
    Log.d(TAG, "...Creating Socket...");

    try {
      outStream = btSocket.getOutputStream();
    } catch (IOException e) {
      errorExit("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + ".");
    }
  }

  @Override
  public void onPause() {
    super.onPause();

    Log.d(TAG, "...In onPause()...");

    if (outStream != null) {
      try {
        outStream.flush();
      } catch (IOException e) {
        errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + ".");
      }
    }

    try     {
      btSocket.close();
    } catch (IOException e2) {
      errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
    }
  }
  
  private void checkBTState() {
    // Check for Bluetooth support and then check to make sure it is turned on

    // Emulator doesn't support Bluetooth and will return null
    if(btAdapter==null) { 
      errorExit("Fatal Error", "Bluetooth Not supported. Aborting.");
    } else {
      if (btAdapter.isEnabled()) {
        Log.d(TAG, "...Bluetooth is enabled...");
      } else {
        //Prompt user to turn on Bluetooth
        Intent enableBtIntent = new Intent(btAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
      }
    }
  }

  private void errorExit(String title, String message){
    Toast msg = Toast.makeText(getBaseContext(),
        title + " - " + message, Toast.LENGTH_SHORT);
    msg.show();
    finish();
  }

  private void sendData(String message) {
    byte[] msgBuffer = message.getBytes();

    Log.d(TAG, "...Sending data: " + message + "...");

    try {
      outStream.write(msgBuffer);
    } catch (IOException e) {
      String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
      if (address.equals("00:00:00:00:00:00")) 
        msg = msg + ".\n\nUpdate your server address from 00:00:00:00:00:00 to the correct address on line 37 in the java code";
      msg = msg +  ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";
      
      errorExit("Fatal Error", msg);       
    }
  }
}
strings.xml
goes in <ProjectRoot>\res\values\
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">LED On Off</string>

</resources>
main.xml
goes in <ProjectRoot>\res\layout\
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btnOn"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:text="Turn LED On" />

    <Button
        android:id="@+id/btnOff"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:text="Turn LED Off" />

</LinearLayout>

AndroidManifest.xml
goes in <ProjectRoot>

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.ledonoff"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".LEDOnOff"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

</manifest>

Screen Capture from Acer A100

Notes:

  1. As the SDK Emulator doesn’t emulate bluetooth and probably wouldn't be able to make a connection even if it did this example will not run in the emulator.
  2. This example is built upon the work of others. I post it here not as an example of original work but rather as a complete working example for reference. If I didn't appropriately credit you for your work please let me know and I will add you.

Tuesday, May 8, 2012

Quick Note - Android - Activity Lifecycle Notes

When you run an app it goes through the following states: onCreate, onStart and onResume.

When you press home the app goes through: onPause and onStop.

When you go back to the app it goes through: onStart and onResume.

When you press back the app goes through: onPause, onStop and onDestroy

Sunday, May 6, 2012

Arduino to Android – Basic Bluetooth Connectivity Tutorial

This tutorial will show you how to configure an Ardunio to communicate over bluetooth with an Android device.

It assumes you have a basic knowledge of the Arduino, the Arduino IDE and installing Android applications from Google Play.

For this tutorial you will need the following items:

  1. An Arduino board.
  2. An Android device with bluetooth.
  3. A bluetooth serial board capable of connecting to the Arduino. 
  4. An Android bluetooth terminal program

You will also need the Arduino IDE.  The Android SDK and a breadboard are not required but are helpful.

What I used:

  1. A breadboard Arduino with a Modern Devices USB BUB.
  2. An Acer Iconia Tab A100 running Ice Cream Sandwich 4.0.3.
  3. A Sparkfun Bluetooth Mate Silver.
  4. BlueTerm by pymasde.es available on Google Play.

Arduino Configuration

Connect GND, VCC, RX and TX from the bluetooth device to the appropriate Arduino pins.  For my setup I connected GND to GND, VCC to +5V, RX to D5 and TX to D6.

Arduino Sketch

The Arduino sketch makes use of the SoftwareSerial library to communicate via two digital pins to the bluetooth device. You will need to make sure you set the SoftwareSerial baud rate to match the baud rate of your bluetooth device.

Android Setup

You will a program on Android that can connect to the bluetooth and host an SPP connection. I used BlueTerm from Google Play but you should be able to use another bluetooth terminal.

Run your bluetooth terminal. If you are using BlueTerm follow the steps below:

Select the three vertical dots to get the menu.

This next step is optional.  To make typing on your Android device easier you may want to turn on local echo.  Press preferences

and then select Local Echo. 

Return to the menu screen by pressing previous and select Connect Device.

Select your bluetooth device.  Mine is named mymate. If you are using the Sparkfun Bluetooth Mate when you successfully connect your Android device to it the blinking red LED marked "Stat" (red arrow in the above picture of the breadboard Arduino) will turn off and the green LED marked "Connect" (green arrow in the above picture) will turn on.

Compile and run the Arduino sketch and you should see output in BlueTerm and the Arduino serial monitor.

Serial Monitor

If you type characters on the Android device they should show up in the Arduino Serial Monitor.

Notes:

  1. As the SDK Emulator doesn’t emulate bluetooth and probably wouldn't be able to make a connection even if it did this example will not run in the emulator.
  2. This example is built upon the work of others. I post it here not as an example of original work but rather as a complete working example for reference. If I didn't appropriately credit you for your work please let me know and I will add you.

Saturday, May 5, 2012

Android Example - Bluetooth Discover and List Devices and Services

This example does a bluetooth device discovery followed by a service discovery for every device it finds. The devices and services are listed as they are found.

There is one mystery that has me perplexed. Two identical sets of services are returned for each device. In the Android documentation it states that fetchUuidsWithSdp() will:
If there is an error in getting the SDP records or if the process takes a long time, ACTION_UUID intent is sent with the UUIDs that is currently present in the cache.
It is conceivable that the first set of responses is from cache and the second is from the remote device.

This example also demonstrates the use of a BroadcastReceiver, Intent Filters and a scrolling TextArea.

I have included the files that have content that is key to setting up the application.

You should be able to create a new Android project in eclipse and then copy the code included below into the appropriate file. Because fetchUUidsWithSDP() is called directly this example requires ICS or higher.

Below the code attachments you will find a screen capture of what it looks like running on my Acer A100.

If you have any suggestions or questions please post them as comments.

Download Zip Archive of Android Source Files

DiscoverDevicesAndServices.java
goes in <ProjectRoot>\src\com\example\discoverdevicesandservices\
strings.xml
goes in <ProjectRoot>\res\values\
main.xml
goes in <ProjectRoot>\res\layout\
AndroidManifest.xml
goes in <ProjectRoot>
Screen Capture from Acer A100

Notes:

  1. Due to fetchUuidsWithSDP() this requires API Release 15
  2. As the SDK Emulator doesn’t emulate bluetooth this example will not run in the emulator.
  3. This example is built upon the work of others. I post it here not as an example of original work but rather as a complete working example for reference. If I didn't appropriately credit you for your work please let me know and I will add you.

Android Example - Bluetooth Simple SPP Client and Server

This example has both a client and a server. The client runs on Android and in my case I ran the server on Windows 7 x64. I tested both java server and a perl server.

A useful freeware tool for listing the services / UUIDs on a device is Medieval Software's Bluetooth Network Scanner.

I have included the files that have content that is key to setting up the application.

You should be able to create a new Android project in eclipse and then copy the code included below into the appropriate file.

Below the code attachments you will find a screen capture of what it looks like running on my Acer A100.

If you have any suggestions or questions please post them as comments.


Android SPP Client

The Android application is based on this post: Serial over Bluetooth simple test client. from anddev.org.

ConnectTest.java
goes in <ProjectRoot>\src\com\example\connecttest\
strings.xml goes in <ProjectRoot>\res\values\ main.xml
goes in <ProjectRoot>\res\layout\
AndroidManifest.xml
goes in <ProjectRoot>
Screen Capture from Acer A100


Java SPP Server

The java server was based on this the SimpleSPPSever example from JSR-82 Sample : SPP Server and Client. To get to run on Windows I used the bluecove-2.1.1-SNAPSHOT.jar library.

SimpleSPPServer.java
goes in <ProjectRoot>\src\
Screen Capture from PC


Perl Server

The perl server was built using the Net::Bluetooth module.

SimpleSPPServer.pl

Notes:

  1. As the SDK Emulator doesn’t emulate bluetooth this example will not run in the emulator.
  2. This example is built upon the work of others. I post it here not as an example of original work but rather as a complete working example for reference. If I didn't appropriately credit you for your work please let me know and I will add you.