Phone Controlled Mood Lighting

30K2776

Intro: Phone Controlled Mood Lighting



Dorm rooms are notorious for their dreadful lighting, so I wanted to make a cool alternative light source for my room at school. I made it phone controlled so there would be an easy and wireless way to change the color of the lighting.

The lighting consists of Tricolor LED Strips and are controlled by a phone through an app. The app is able communicate with the Arduino via bluetooth by using the Seeed Bluetooth Shield.

STEP 1: Materials

(x1) Arduino Uno (RadioShack #276-128)
(x3) Tricolor LED Strip (RadioShack #276-249)
(x1) Universal 1000mA AC Adapter (RadioShack #273-316)
(x1) M-type Adaptaplug (RadioShack #273-344)
(x1) Grid-Style PC Board (RadioShack #276-149)
(x1) Seeed Bluetooth Shield
(x1) Android Phone or Device
(x1) 36"x24"x1/4" plywood
(x1) 15"x11"x1/4" milky white acrylic
(x4) Wood screw #6 x 3/8"
(x8) Washer #6 small



STEP 2: Bluetooth Shield

Fit the bluetooth shield onto the Arduino. 

Arrange the jumpers on the board like in the first photo above. The first jumper should be connected to digital pin 7 and BT_RX and the second jumper should be connected to digital pin 6 and BT_TX. The shield will not be able to act as the bluetooth slave if the jumpers are not connected properly.

STEP 3: Arduino With Bluetooth

Load the following code onto the Arduino in order to set up your Arduino as the bluetooth slave:
/* 
Bluetooth Setup on Arduino
by Nicole Grimwood

Based upon:
Seeed Wiki Bluetooth slave code
http://www.seeedstudio.com/wiki/index.php?title=Bluetooth_Shield

This code is in the public domain.
*/

#include <SoftwareSerial.h> // Software Serial Port

#define RxD 6 // This is the pin that the Bluetooth (BT_TX) will transmit to the Arduino (RxD)
#define TxD 7 // This is the pin that the Bluetooth (BT_RX) will receive from the Arduino (TxD)

#define DEBUG_ENABLED 1

SoftwareSerial blueToothSerial(RxD,TxD);

#define DATA_1 (PORTC |=  0X01)    // DATA 1 
#define DATA_0 (PORTC &=  0XFE)    // DATA 0  
#define STRIP_PINOUT (DDRC=0xFF) 


void setup() { 
 pinMode(RxD, INPUT); // Setup the Arduino to receive INPUT from the bluetooth shield on Digital Pin 6
 pinMode(TxD, OUTPUT); // Setup the Arduino to send data (OUTPUT) to the bluetooth shield on Digital Pin 7
 setupBlueToothConnection(); // Used to initialize the Bluetooth shield 
} 

void loop() { 
 char recvChar;
 while(1){
  if(blueToothSerial.available()){ // check if there's any data sent from the remote bluetooth 
   recvChar = blueToothSerial.read();
   Serial.print(recvChar); // Print the character received to the Serial Monitor
  }
 }
} 



// The following code is necessary to setup the bluetooth shield
void setupBlueToothConnection(){
 blueToothSerial.begin(38400); //Set BluetoothBee BaudRate to default baud rate 38400
 blueToothSerial.print("\r\n+STWMOD=0\r\n"); //set the bluetooth work in slave mode
 blueToothSerial.print("\r\n+STNA=SeeedBTSlave\r\n"); //set the bluetooth name as "SeeedBTSlave"
 blueToothSerial.print("\r\n+STOAUT=1\r\n"); // Permit Paired device to connect me
 blueToothSerial.print("\r\n+STAUTO=0\r\n"); // Auto-connection should be forbidden here
 delay(2000); // This delay is required.
 blueToothSerial.print("\r\n+INQ=1\r\n"); //make the slave bluetooth inquirable 
 Serial.println("The slave bluetooth is inquirable!");
 delay(2000); // This delay is required.
 blueToothSerial.flush();
}




If the bluetooth is working correctly, a red and a green LED will flash one after the other in sequence on the shield. If this does not start happening a few seconds after you load the code onto the Arduino, try power cycling the Arduino and reloading the code. 

STEP 4: Processing and Android

I used Processing to create an app for my Android device. It provides good documentation for use with Android and is perfectly adequate for a simplistic app like the one I created for this project. Its format is also similar to the Arduino software, which makes it easy to use. I used a PC running Windows 8 and I tested the App on a Samsung Galaxy SIII and a Nexus tablet.

For the most part, you should follow the wiki to set everything up, but I have also included my own instructions below. I have simplified parts that I think the wiki does a good job of explaining and have expanded on other parts. I have also added additional tips that I used to get mine to work. Not everything worked perfectly every step of the way, so be patient. I have tried to include everything I did to get things working whenever I hit a road block. Note: If you are using a Mac, not all of my instructions will apply to you and I suggest you more closely follow the wiki page.


Here is the link for the wiki page on Processing with the Android:
http://wiki.processing.org/w/Android


USB Debugging
Once you have installed Processing, the Android SDK, and all of the necessary platforms and packages, you will need to enable USB debugging on your device.

On my Samsung Galaxy S III, I went to Settings then Developer options then checked USB Debugging. On a Nexus tablet, go to Settings then About tablet then click Build number seven times to activate USB debugging.


USB Drivers
If you haven't already, plug your phone into your computer and install USB drivers for your device. I was able to download everything for my phone from this site:
http://developer.samsung.com/android/tools-sdks/Samsung-Andorid-USB-Driver-for-Windows
This is only necessary if you are using a PC.


Running a sketch (first attempt)
Open processing and switch from Standard mode to Android mode by clicking on the drop down menu on the top right corner of the window and selecting Android. To switch to Android mode, you may need to restart Processing after you have done this. 

Copy and Paste the following code into your Processing sketch. This is a sketch that will turn the screen green if the Android device is able to find the Seeed Bluetooth and then turns purple once it has connected to the Seeed shield. The Android will also send the letter "a" to the Arduino's serial.

Have the Arduino's serial monitor open when you run the Android App so you be make sure that the two are communicating (Serial communication is how we will get the lighting to change later on). When you run the program, make sure you click "Run on Device." I bypassed running on a virtual device because I always had access to my phone and I decided it was more trouble than it was worth to get the virtual device working. The first time you run the program, it likely will not work correctly. Do not worry. That is the next step.

/*
 Bluetooth Connect and Send Bytes
 by Nicole Grimwood
 
 Based upon:
 SendReceiveBytes
 Created March 25 2013
 by ScottC
 
 This code is in the public domain 
*/

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.widget.Toast;
import android.view.Gravity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;

import java.util.UUID;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
public BluetoothSocket scSocket;

boolean foundDevice=false; //When true, the screen turns green.
boolean BTisConnected=false; //When true, the screen turns purple.

// Message types used by the Handler
public static final int MESSAGE_WRITE = 1;
public static final int MESSAGE_READ = 2;
String readMessage="";

//Get the default Bluetooth adapter
BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();

/*The startActivityForResult() within setup() launches an 
 Activity which is used to request the user to turn Bluetooth on. 
 The following onActivityResult() method is called when this 
 Activity exits. */
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 if (requestCode==0) {
  if (resultCode == RESULT_OK) {
   ToastMaster("Bluetooth has been switched ON");
  } 
  else {
   ToastMaster("You need to turn Bluetooth ON !!!");
  }
 }
}


/* Create a BroadcastReceiver that will later be used to 
 receive the names of Bluetooth devices in range. */
BroadcastReceiver myDiscoverer = new myOwnBroadcastReceiver();


/* Create a BroadcastReceiver that will later be used to
 identify if the Bluetooth device is connected */
BroadcastReceiver checkIsConnected = new myOwnBroadcastReceiver();


// The Handler that gets information back from the Socket
private final Handler mHandler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
  switch (msg.what) {
  case MESSAGE_WRITE:
  //Do something when writing
  break;
  case MESSAGE_READ:
  //Get the bytes from the msg.obj
  byte[] readBuf = (byte[]) msg.obj;
  // construct a string from the valid bytes in the buffer
  readMessage = new String(readBuf, 0, msg.arg1);
  break;
  }
 }
};


void setup() {
 orientation(LANDSCAPE);
 /*IF Bluetooth is NOT enabled, then ask user permission to enable it */
 if (!bluetooth.isEnabled()) {
  Intent requestBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
  startActivityForResult(requestBluetooth, 0);
 }


 /*If Bluetooth is now enabled, then register a broadcastReceiver to report any
 discovered Bluetooth devices, and then start discovering */
 if (bluetooth.isEnabled()) {
  registerReceiver(myDiscoverer, new IntentFilter(BluetoothDevice.ACTION_FOUND));
  registerReceiver(checkIsConnected, new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED));

  //Start bluetooth discovery if it is not doing so already
  if (!bluetooth.isDiscovering()) {
   bluetooth.startDiscovery();
  }
 }
}


void draw() {
 //Display a green screen if a device has been found,
 //Display a purple screen when a connection is made to the device
 if (foundDevice) {
  if (BTisConnected) {
   background(170, 50, 255); // purple screen
  }
  else {
   background(10, 255, 10); // green screen
  }
 }

 //Display anything received from Arduino
 text(readMessage, 10, 10);
}


/* This BroadcastReceiver will display discovered Bluetooth devices */
public class myOwnBroadcastReceiver extends BroadcastReceiver {
 ConnectToBluetooth connectBT;

 @Override
 public void onReceive(Context context, Intent intent) {
 String action=intent.getAction();
 ToastMaster("ACTION:" + action);

 //Notification that BluetoothDevice is FOUND
 if (BluetoothDevice.ACTION_FOUND.equals(action)) {
  //Display the name of the discovered device
  String discoveredDeviceName = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
  ToastMaster("Discovered: " + discoveredDeviceName);

  //Display more information about the discovered device
  BluetoothDevice discoveredDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  ToastMaster("getAddress() = " + discoveredDevice.getAddress());
  ToastMaster("getName() = " + discoveredDevice.getName());

  int bondyState=discoveredDevice.getBondState();
  ToastMaster("getBondState() = " + bondyState);

  String mybondState;
  switch(bondyState) {
   case 10: 
   mybondState="BOND_NONE";
   break;
   case 11: 
   mybondState="BOND_BONDING";
   break;
   case 12: 
   mybondState="BOND_BONDED";
   break;
   default: 
   mybondState="INVALID BOND STATE";
   break;
  }
 ToastMaster("getBondState() = " + mybondState);

 //Change foundDevice to true which will make the screen turn green
 foundDevice=true;

 //Connect to the discovered bluetooth device (SeeedBTSlave)
 if (discoveredDeviceName.equals("SeeedBTSlave")) {
  ToastMaster("Connecting you Now !!");
  unregisterReceiver(myDiscoverer);
  connectBT = new ConnectToBluetooth(discoveredDevice);
  //Connect to the the device in a new thread
  new Thread(connectBT).start();
 }
}

 //Notification if bluetooth device is connected
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
 ToastMaster("CONNECTED _ YAY");

 while (scSocket==null) {
   //do nothing
 }
 ToastMaster("scSocket" + scSocket);
 BTisConnected=true; //turn screen purple 
 if (scSocket!=null) {
  SendReceiveBytes sendReceiveBT = new SendReceiveBytes(scSocket);
  new Thread(sendReceiveBT).start();
  String testLetter = "a";
  byte[] myByte = stringToBytesUTFCustom(testLetter);
  sendReceiveBT.write(myByte);
 }
}
}
}
public static byte[] stringToBytesUTFCustom(String str) {
 char[] buffer = str.toCharArray();
 byte[] b = new byte[buffer.length << 1];
 for (int i = 0; i < buffer.length; i++) {
  int bpos = i << 1;
  b[bpos] = (byte) ((buffer[i]&0xFF00)>>8);
  b[bpos + 1] = (byte) (buffer[i]&0x00FF);
 }
 return b;
}

public class ConnectToBluetooth implements Runnable {
 private BluetoothDevice btShield;
 private BluetoothSocket mySocket = null;
 private UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

 public ConnectToBluetooth(BluetoothDevice bluetoothShield) {
  btShield = bluetoothShield;
  try {
   mySocket = btShield.createRfcommSocketToServiceRecord(uuid);
  }
  catch(IOException createSocketException) {
   //Problem with creating a socket
   Log.e("ConnectToBluetooth", "Error with Socket");
  }
 }

 @Override
 public void run() {
  /* Cancel discovery on Bluetooth Adapter to prevent slow connection */
  bluetooth.cancelDiscovery();

  try {
   /*Connect to the bluetoothShield through the Socket. This will block
   until it succeeds or throws an IOException */
   mySocket.connect();
   scSocket=mySocket;
  } 
  catch (IOException connectException) {
   Log.e("ConnectToBluetooth", "Error with Socket Connection");
   try {
    mySocket.close(); //try to close the socket
   }
   catch(IOException closeException) {
   }
   return;
  }
 }

 /* Will cancel an in-progress connection, and close the socket */
 public void cancel() {
  try {
   mySocket.close();
  } 
  catch (IOException e) {
  }
 }
 
}


private class SendReceiveBytes implements Runnable {
 private BluetoothSocket btSocket;
 private InputStream btInputStream = null;
 private OutputStream btOutputStream = null;
 String TAG = "SendReceiveBytes";

 public SendReceiveBytes(BluetoothSocket socket) {
  btSocket = socket;
  try {
   btInputStream = btSocket.getInputStream();
   btOutputStream = btSocket.getOutputStream();
  } 
  catch (IOException streamError) { 
   Log.e(TAG, "Error when getting input or output Stream");
  }
 }


 public void run() {
  byte[] buffer = new byte[1024]; // buffer store for the stream
  int bytes; // bytes returned from read()

  // Keep listening to the InputStream until an exception occurs
  while (true) {
   try {
    // Read from the InputStream
    bytes = btInputStream.read(buffer);
    // Send the obtained bytes to the UI activity
    mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
    .sendToTarget();
   } 
   catch (IOException e) {
    Log.e(TAG, "Error reading from btInputStream");
    break;
   }
  }
 }


 /* Call this from the main activity to send data to the remote device */
 public void write(byte[] bytes) {
  try {
   btOutputStream.write(bytes);
  } 
  catch (IOException e) { 
   Log.e(TAG, "Error when writing to btOutputStream");
  }
 }


 /* Call this from the main activity to shutdown the connection */
 public void cancel() {
  try {
   btSocket.close();
  } 
  catch (IOException e) { 
   Log.e(TAG, "Error when closing the btSocket");
  }
 }
}



/* My ToastMaster function to display a messageBox on the screen */
void ToastMaster(String textToDisplay) {
 Toast myMessage = Toast.makeText(getApplicationContext(), 
 textToDisplay, 
 Toast.LENGTH_SHORT);
 myMessage.setGravity(Gravity.CENTER, 0, 0);
 myMessage.show();
}


Edit Android Manifest.xml
The Android Manifest only shows up after you have attempted to run the program once. It can be found in the folder containing the .pde file for your code. Edit Android Manifest.xml by adding the following two lines in between the second and third lines in the original manifest:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
Reference the screenshot shown above to make sure you have it right.

Connect
Now run the sketch again. Everything should work now. Open the Arduino's serial monitor to make sure it receives the letter "a" when the bluetooth is connected. If it does not, here are a few things you can try to get it to work properly:
1. Make sure that the Bluetooth shield is set up properly and the red and green lights are flashing when you run the Android program.
2. Run the App again on your device
3. Restart your Android Device
4. Restart your computer
I got mine to work using some combination of these additional steps.

Important tip: Every time you reconnect the bluetooth, you should reset or power cycle the Arduino and close your App and reopen it.


STEP 5: Cut Enclosure

Cut the attached pattern for the enclosure out of the plywood.

Cut out the attached pattern for the acrylic out of the acrylic sheet.

STEP 6: LED Strips

Cut the LED strip into nine smaller strips with nine LEDs each. Be sure to cut each strip in the middle of the flat copper sections. 

Note where the wires from the original strip are soldered. Every strip should have wires soldered to the same side. The strip should have arrows on it to help determine the correct direction. 

For the strips that do not have wires already attached, cut away the plastic casing covering the flat copper areas and solder wires onto them. You should solder a red wire for Vin, a black wire for ground, and a green wire for pin 12.

Important: Your LED strips will only light up if you have the AC Adapter plugged into the Arduino. They require more power than the USB cable provides. 

STEP 7: Glue

Tape down the LED strips to the bottom of the enclosure with even spacing between them. When you're happy with how they're arranged, glue them in place with epoxy.

STEP 8: Solder and Glue Some More

Solder the green wires of each of the LED strips to the PC board. All of them should be connected and an additional green wire should be soldered to connect to pin 12 on the Arduino. 

Solder all of the red wires of the LED strips to the PC board. They should all be connected to one red wire that should connect to Vin on the Arduino.

Solder the black wire of the each LED strips to together on the PC board and attach an additional wire to go to ground on the Arduino.

Glue on the sides of the box.

STEP 9: Power

Thread the wire of the AC adapter through the hole in the bottom your box. Plug the Adaptaplug into the AC adapter. The tip of the Adaptaplug should be facing the side of the AC adapter labeled "TIP." Plug the Adaptaplug into the Arduino.


STEP 10: Incorporate LED Strips

Now that you connect to the Seeed Bluetooth shield on the Arduino and send characters, it is time to start controlling the LED strips.


Run the following sketch on the Arduino:

/* 
Phone Controlled Mood Lighting - Arduino Code
by Nicole Grimwood

Based upon:
Seeed Wiki Bluetooth slave code
http://www.seeedstudio.com/wiki/index.php?title=Bluetooth_Shield

Pololu LED Strip Example Code
https://github.com/pololu/pololu-led-strip-arduino

This code is in the public domain.
*/

#include <avr/pgmspace.h>
#include <SoftwareSerial.h> // Software Serial Port
#include <PololuLedStrip.h>

#define RxD 6 // This is the pin that the Bluetooth (BT_TX) will transmit to the Arduino (RxD)
#define TxD 7 // This is the pin that the Bluetooth (BT_RX) will receive from the Arduino (TxD)

#define DEBUG_ENABLED 1

// Create an ledStrip object on pin 12.
PololuLedStrip<12> ledStrip;

// Create a buffer for holding 3 colors.  Takes 180 bytes.
#define LED_COUNT 3
rgb_color colors[LED_COUNT];

SoftwareSerial blueToothSerial(RxD,TxD);

#define DATA_1 (PORTC |=  0X01)    // DATA 1 
#define DATA_0 (PORTC &=  0XFE)    // DATA 0  
#define STRIP_PINOUT (DDRC=0xFF) 


void setup() { 
 // Set interrupt friendly to true so that the LED 
 // strips work with the bluetooth shield
 PololuLedStripBase::interruptFriendly=true; 
 
 pinMode(RxD, INPUT); // Setup the Arduino to receive INPUT from the bluetooth shield on Digital Pin 6
 pinMode(TxD, OUTPUT); // Setup the Arduino to send data (OUTPUT) to the bluetooth shield on Digital Pin 7

 setupBlueToothConnection(); // Used to initialize the Bluetooth shield 

} 

void loop() { 
 char recvChar;
 while(1){
  if(blueToothSerial.available()){ // check if there's any data sent from the remote bluetooth shield
   recvChar = blueToothSerial.read();
   Serial.print(recvChar); // Print the character received to the Serial Monitor (if required)
   // if the character received is a, use the white pattern
   if(recvChar=='a'){
    delay(500); // necessary for LED strips to work with bluetooth shield
    //used to assign colors to each of the 3 sections of the LED strips
    colors[0]=(rgb_color){250,250,250};
    colors[1]=(rgb_color){250,250,250};
    colors[2]=(rgb_color){250,250,250};
    ledStrip.write(colors, LED_COUNT);
   }
   // if character received is b, use the pink pattern
   if(recvChar=='b'){
    delay(500);
    colors[0]=(rgb_color){250,220,0};
    colors[1]=(rgb_color){250,220,0};
    colors[2]=(rgb_color){250,220,0};
    ledStrip.write(colors, LED_COUNT);
   }
   // if character received is c, use the red and orange pattern
   if(recvChar=='c'){
    delay(500);
    colors[0]=(rgb_color){250,0,0};
    colors[1]=(rgb_color){250,0,230};
    colors[2]=(rgb_color){250,0,0};
    ledStrip.write(colors, LED_COUNT);
   }
   // if character received is d, use the blue and purple pattern
   if(recvChar=='d'){
    delay(500);
    colors[0]=(rgb_color){0,220,0};
    colors[1]=(rgb_color){50,220,0};
    colors[2]=(rgb_color){0,220,0};
    ledStrip.write(colors, LED_COUNT);
   }
  }
 }
} 



// The following code is necessary to setup the bluetooth shield
void setupBlueToothConnection(){
 blueToothSerial.begin(38400); //Set BluetoothBee BaudRate to default baud rate 38400
 blueToothSerial.print("\r\n+STWMOD=0\r\n"); //set the bluetooth work in slave mode
 blueToothSerial.print("\r\n+STNA=SeeedBTSlave\r\n"); //set the bluetooth name as "SeeedBTSlave"
 blueToothSerial.print("\r\n+STOAUT=1\r\n"); // Permit Paired device to connect me
 blueToothSerial.print("\r\n+STAUTO=0\r\n"); // Auto-connection should be forbidden here
 delay(2000); // This delay is required.
 blueToothSerial.print("\r\n+INQ=1\r\n"); //make the slave bluetooth inquirable 
 Serial.println("The slave bluetooth is inquirable!");
 delay(2000); // This delay is required.
 blueToothSerial.flush();
}






Run the following sketch on the Android device:

/* 
Phone Controlled Mood Lighting - Android Sketch
by Nicole Grimwood

Based upon: BluetoothApp1
created on March 25, 2013
by ScottC
*/




import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.widget.Toast;
import android.view.Gravity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;




import java.util.UUID;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.os.Handler;
import android.os.Message;
import android.util.Log;




import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import apwidgets.*;
public BluetoothSocket scSocket;








//Used for the GUI**************************************
APWidgetContainer widgetContainer; 
APButton whiteButton, pinkButton, redOrangeButton, blueButton;
String buttonText="";
int buttonWidth=0;
int buttonHeight=0;
int n=5; //number of buttons
int gap=10; //gap between buttons




boolean foundDevice=false; //When true, the screen turns green.
boolean BTisConnected=false; //When true, the screen turns purple.




// Message types used by the Handler
public static final int MESSAGE_WRITE = 1;
public static final int MESSAGE_READ = 2;
String readMessage="";




//Used to send bytes to the Arduino
SendReceiveBytes sendReceiveBT=null;




//Get the default Bluetooth adapter
BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();




/*The startActivityForResult() within setup() launches an 
 Activity which is used to request the user to turn Bluetooth on. 
 The following onActivityResult() method is called when this 
 Activity exits. */
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 if (requestCode==0) {
  if (resultCode == RESULT_OK) {
   ToastMaster("Bluetooth has been switched ON");
  } 
  else {
   ToastMaster("You need to turn Bluetooth ON !!!");
  }
 }
}








/* Create a BroadcastReceiver that will later be used to 
 receive the names of Bluetooth devices in range. */
BroadcastReceiver myDiscoverer = new myOwnBroadcastReceiver();




/* Create a BroadcastReceiver that will later be used to
 identify if the Bluetooth device is connected */
BroadcastReceiver checkIsConnected = new myOwnBroadcastReceiver();








// The Handler that gets information back from the Socket
private final Handler mHandler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
  switch (msg.what) {
   case MESSAGE_WRITE:
   //Do something when writing
   break;
   case MESSAGE_READ:
   //Get the bytes from the msg.obj
   byte[] readBuf = (byte[]) msg.obj;
   // construct a string from the valid bytes in the buffer
   readMessage = new String(readBuf, 0, msg.arg1);
   break;
  }
 }
};












void setup() {
 orientation(LANDSCAPE);




 //Setup GUI********************************
 buttonWidth=((width/n)-(n*gap));
 buttonHeight=(height/2);
 widgetContainer = new APWidgetContainer(this); //create new container for widgets
 whiteButton =new APButton((buttonWidth*(n-5)+(gap*1)), gap, buttonWidth, buttonHeight, "White"); //Create a color fade button
 pinkButton = new APButton((buttonWidth*(n-4)+(gap*2)), gap, buttonWidth, buttonHeight, "Pink"); //Create a pattern button
 redOrangeButton = new APButton((buttonWidth*(n-3)+(gap*3)), gap, buttonWidth, buttonHeight, "Red Orange"); //Create a red orange button
 blueButton = new APButton((buttonWidth*(n-2)+(gap*4)), gap, buttonWidth, buttonHeight, "Blue"); //Create a blue button
 widgetContainer.addWidget(whiteButton); //place color fade button in container
 widgetContainer.addWidget(pinkButton); //place pattern fade button in container
 widgetContainer.addWidget(redOrangeButton);//place red orange button in container
 widgetContainer.addWidget(blueButton);//place blue button in container
 background(0); //Start with a black background




 /*IF Bluetooth is NOT enabled, then ask user permission to enable it */
 if (!bluetooth.isEnabled()) {
 Intent requestBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
 startActivityForResult(requestBluetooth, 0);
 }




 /*If Bluetooth is now enabled, then register a broadcastReceiver to report any
 discovered Bluetooth devices, and then start discovering */
 if (bluetooth.isEnabled()) {
  registerReceiver(myDiscoverer, new IntentFilter(BluetoothDevice.ACTION_FOUND));
  registerReceiver(checkIsConnected, new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED));




 //Start bluetooth discovery if it is not doing so already
  if (!bluetooth.isDiscovering()) {
   bluetooth.startDiscovery();
  }
 }
}








void draw() {
 //Display a green screen if a device has been found,
 //Display a purple screen when a connection is made to the device
 if (foundDevice) {
  if (BTisConnected) {
   background(200, 70, 255); // purple screen
  }
  else {
   background(0, 200, 50); // green screen
  }
 }








 //Change the text based on the button being pressed.
 text(buttonText, 20, buttonHeight+(buttonHeight/2));
 
}












/* This BroadcastReceiver will display discovered Bluetooth devices */
public class myOwnBroadcastReceiver extends BroadcastReceiver {
 ConnectToBluetooth connectBT;




 @Override
 public void onReceive(Context context, Intent intent) {
  String action=intent.getAction();
  ToastMaster("ACTION:" + action);




  //Notification that BluetoothDevice is FOUND
  if (BluetoothDevice.ACTION_FOUND.equals(action)) {
   //Display the name of the discovered device
   String discoveredDeviceName = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
   ToastMaster("Discovered: " + discoveredDeviceName);




   // Display more information about the discovered device
   BluetoothDevice discoveredDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);




   //Change foundDevice to true which will make the screen turn green
   foundDevice=true;




   //Connect to the discovered bluetooth device (SeeedBTSlave)
   if (discoveredDeviceName.equals("SeeedBTSlave")) {
    ToastMaster("Connecting you Now !!");
    unregisterReceiver(myDiscoverer);
    connectBT = new ConnectToBluetooth(discoveredDevice);
    //Connect to the the device in a new thread
    new Thread(connectBT).start();
   }
  }




  //Notification if bluetooth device is connected
  if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
   ToastMaster("CONNECTED _ YAY");
   int counter=0;
   while (scSocket==null) {
    //do nothing
   }
   ToastMaster("scSocket" + scSocket);
   BTisConnected=true; //turn screen purple 
   if (scSocket!=null) {
    sendReceiveBT = new SendReceiveBytes(scSocket);
    new Thread(sendReceiveBT).start();
    String begin = "a";
    byte[] myByte = stringToBytesUTFCustom(begin);
    sendReceiveBT.write(myByte);
   }
  }
 }
}




public static byte[] stringToBytesUTFCustom(String str) {
 char[] buffer = str.toCharArray();
 byte[] b = new byte[buffer.length << 1];
 for (int i = 0; i < buffer.length; i++) {
  int bpos = i << 1;
  b[bpos] = (byte) ((buffer[i]&0xFF00)>>8);
  b[bpos + 1] = (byte) (buffer[i]&0x00FF);
 }
 return b;
}




public class ConnectToBluetooth implements Runnable {
 private BluetoothDevice btShield;
 private BluetoothSocket mySocket = null;
 private UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");




 public ConnectToBluetooth(BluetoothDevice bluetoothShield) {
 btShield = bluetoothShield;
 try {
  mySocket = btShield.createRfcommSocketToServiceRecord(uuid);
 }
 catch(IOException createSocketException) {
  //Problem with creating a socket
  Log.e("ConnectToBluetooth", "Error with Socket");
 }
}




 @Override
 public void run() {
  /* Cancel discovery on Bluetooth Adapter to prevent slow connection */
  bluetooth.cancelDiscovery();




  try {
   /*Connect to the bluetoothShield through the Socket. This will block
   until it succeeds or throws an IOException */
   mySocket.connect();
   scSocket=mySocket;
  } 
  catch (IOException connectException) {
   Log.e("ConnectToBluetooth", "Error with Socket Connection");
   try {
    mySocket.close(); //try to close the socket
   }
   catch(IOException closeException) {
   }
  return;
  }
}




 // Will allow you to get the socket from this class
 public BluetoothSocket getSocket() {
  return mySocket;
 }




 /* Will cancel an in-progress connection, and close the socket */
 public void cancel() {
  try {
   mySocket.close();
  } 
  catch (IOException e) {
  }
 }
}












private class SendReceiveBytes implements Runnable {
 private BluetoothSocket btSocket;
 private InputStream btInputStream = null;
 ;
 private OutputStream btOutputStream = null;
 String TAG = "SendReceiveBytes";




 public SendReceiveBytes(BluetoothSocket socket) {
  btSocket = socket;
  try {
   btInputStream = btSocket.getInputStream();
   btOutputStream = btSocket.getOutputStream();
  } 
  catch (IOException streamError) { 
   Log.e(TAG, "Error when getting input or output Stream");
  }
 }




 public void run() {
  byte[] buffer = new byte[1024]; // buffer store for the stream
  int bytes; // bytes returned from read()




  // Keep listening to the InputStream until an exception occurs
  while (true) {
   try {
   // Read from the InputStream
   bytes = btInputStream.read(buffer);
   // Send the obtained bytes to the UI activity
   mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
   .sendToTarget();
   } 
   catch (IOException e) {
   Log.e(TAG, "Error reading from btInputStream");
   break;
   }
  }
 }




 /* Call this from the main activity to send data to the remote device */
 public void write(byte[] bytes) {
  try {
   btOutputStream.write(bytes);
  } 
  catch (IOException e) { 
   Log.e(TAG, "Error when writing to btOutputStream");
  }
 }




 /* Call this from the main activity to shutdown the connection */
 public void cancel() {
  try {
   btSocket.close();
  } 
  catch (IOException e) { 
   Log.e(TAG, "Error when closing the btSocket");
  }
 }
}












/* My ToastMaster function to display a messageBox on the screen */
void ToastMaster(String textToDisplay) {
 Toast myMessage = Toast.makeText(getApplicationContext(), 
 textToDisplay, 
 Toast.LENGTH_SHORT);
 myMessage.setGravity(Gravity.CENTER, 0, 0);
 myMessage.show();
}
















//onClickWidget is called when a widget is clicked/touched
void onClickWidget(APWidget widget) {
 String sendLetter = "";




 //Disable the previous Background colour changers
 foundDevice=false;
 BTisConnected=false;




 if (widget == whiteButton) { //if the red button was clicked
  buttonText="white";
  background(0, 255, 100);
  sendLetter = "a";
 }
 else if(widget == pinkButton){
  buttonText = "Pink";
  background(0, 200,200); 
  sendLetter = "b";
 }
 else if (widget == redOrangeButton) { //if the blue button was clicked
  buttonText="Red Orange";
  background(255, 90, 0);
  sendLetter = "c";
 }
 else if (widget == blueButton) { //if the off button was clicked
  buttonText="Blue";
  background(50,100,155);
  sendLetter = "d";
 }




 byte[] myByte = stringToBytesUTFCustom(sendLetter);
 sendReceiveBT.write(myByte);
}




Once you have all of this code running, you should be able to press the buttons on the app to change the color of the LED strips. Note: If the phone is inactive for too long, you will lose bluetooth connection and you should close the app on your phone and unplug the light board. You can then plug in the board again and reopen the app and it should connect again.

STEP 11: Drill

Line up the cut out acrylic sheet with the pattern on the top of the enclosure and mark with a pencil the location of the holes.

Drill pilot holes using the 3/32" drill bit where you made markings on your enclosure.

Screw the acrylic onto the top of the enclosure using the wood screws and two washers (to prevent the screws from going all the way through the wood).

STEP 12: Close and Use

Glue the top on the enclosure, hang up your lighting board and enjoy!

6 Comments

This is great. I am making some edge lit artworks at the moment, gives me the idea to control it with Android!

This is beautiful.

Hahah thanks chlobro

I love this! It would be awesome for my Christmas party. But I'm concerned about opening up my phone to vulnerabilities after reading on vpnexpress.net about hacks. Is this safe to do?
Sorry for the late response! I guess It's a little late for the Christmas party, but you still could for New Year's ;D. I have not read up much on VPN, but from the little I just did, I suspect that this is safe to do. You are only using Processing with your android device and I have not read anything bad about that software. Although, I guess that you assume some risk using any software with your phone. I personally would not worry about it.
What a brilliant idea. Beautiful wall art and an energy efficient light source.
Love it!