So, once you get processing for android all installed, if you’re like me the first thing you’ll want to do is get your phone talking with an Arduino over bluetooth. Well maybe not first thing but you get the Idea. Below is two pieces of code that I’ve used for this project. It’s very specific for this project, but it may help somebody and will likely help myself in the future so there you go.
Ardiuno Code:
const char EOPmarker = '.'; //This is the end of packet marker
char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming.
char serialbuf2[32];
#include <string.h> // we'll need this for subString
#define MAX_STRING_LEN 20 // like 3 lines above, change as needed.
#include <SoftwareSerial.h>
SoftwareSerial Ble(11, 10); // RX, TX
int Mode = 5;
int Shutter = 6;
int Focus = 7;
void setup(){
Serial.begin(9600);
Ble.begin(9600);
pinMode(Mode, INPUT);
pinMode(Shutter, OUTPUT);
pinMode(Focus, OUTPUT);
}
void loop() {
if (Serial.available() > 0) { //makes sure something is ready to be read
static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read
char inchar = Serial.read(); //assigns one byte (as serial.read()'s only input one byte at a time
if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
}
else { //once the end of package marker has been read
serialbuf[bufpos] = 0; //restart the buff
bufpos = 0; //restart the position of the buff
Expose(serialbuf,1);
}
}
if (Ble.available() > 0) { //makes sure something is ready to be read
static int bufpos2 = 0; //starts the buffer back at the first position in the incoming serial.read
char inchar2 = Ble.read(); //assigns one byte (as serial.read()'s only input one byte at a time
if (inchar2 != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
serialbuf2[bufpos2] = inchar2; //the buffer position in the array get assigned to the current read
bufpos2++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
delay(10);
}
else { //once the end of package marker has been read
serialbuf2[bufpos2] = 0; //restart the buff
bufpos2 = 0; //restart the position of the buff
Expose(serialbuf2,0);
}
}
}
void Expose(char* buf, int Mode){
int Type = atoi(subStr(buf, ",", 1));
int Exposures = atoi(subStr(buf, ",", 2));
int Delay = atoi(subStr(buf, ",", 3));
int Actual_Delay = Delay;
String Out = String("Mode: " + String(Mode) + " Type: " + String(Type) + " Exposures: " + String(Exposures) + " Delay: " + String(Delay));
Serial.println(Out);
for (int i = 0; i < Exposures; i++){
if (Type == 0){
digitalWrite(Shutter, HIGH); // turn the LED on (HIGH is the voltage level)
delay(30); // wait for a second
digitalWrite(Shutter, LOW); // turn the LED off by making the voltage LOW
delay(30);
if (Delay < 250){
Actual_Delay = 250;
}
else {
Actual_Delay = Delay;
}
}
if (Type == 1){
digitalWrite(Focus, HIGH); // turn the LED on (HIGH is the voltage level)
delay(30); // wait for a second
digitalWrite(Focus, LOW); // turn the LED off by making the voltage LOW
delay(30);
delay(100);
digitalWrite(Shutter, HIGH); // turn the LED on (HIGH is the voltage level)
delay(30); // wait for a second
digitalWrite(Shutter, LOW); // turn the LED off by making the voltage LOW
delay(30);
if (Delay < 700){
Actual_Delay = 700;
}
else {
Actual_Delay = Delay;
}
}
delay(Actual_Delay);
}
}
// below is just function logic, which I do not fully understand. but it works.
char* subStr (char* input_string, char *separator, int segment_number) {
char *act, *sub, *ptr;
static char copy[MAX_STRING_LEN];
int i;
strcpy(copy, input_string);
for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {
sub = strtok_r(act, separator, &ptr);
if (sub == NULL) break;
}
return sub;
}
Processing Code:
import apwidgets.*;
//App-Wide (General) Elements
APWidgetContainer General_Container;
APRadioButton General_Setup_RB;
APRadioButton General_Interact_RB;
APRadioGroup General_RadioGroup;
//Setup Mode Elements
APWidgetContainer SetupMode_Container;
APButton SetupMode_ConnectButton;
APButton SetupMode_DisconnectButton;
//Interact Mode Elements
APWidgetContainer InteractMode_Container;
APButton InteractMode_SendButton;
APEditText InteractMode_TypeTB;
APEditText InteractMode_ExposuresTB;
APEditText InteractMode_DelayTB;
/* -------------- Bluetooth Stuff -------------- */
//required for BT enabling on startup
import android.content.Intent;
import android.os.Bundle;
import ketai.net.bluetooth.*;
import ketai.ui.*;
import ketai.net.*;
import oscP5.*;
KetaiBluetooth bt;
String info = "";
KetaiList klist;
PVector remoteMouse = new PVector();
ArrayList<String> devicesDiscovered = new ArrayList();
boolean isConfiguring = true;
String UIText;
//********************************************************************
// The following code is required to enable bluetooth at startup.
//********************************************************************
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bt = new KetaiBluetooth(this);
}
void onActivityResult(int requestCode, int resultCode, Intent data) {
bt.onActivityResult(requestCode, resultCode, data);
}
void setup(){
//App-Wide (General) Elements
General_Container = new APWidgetContainer(this); //create new container for widgets
General_RadioGroup = new APRadioGroup(10, 10); //create a new radiogroup
General_RadioGroup.setOrientation(APRadioGroup.HORIZONTAL);
General_Setup_RB = new APRadioButton("Setup "); //create new radiobutton from label.
General_Interact_RB = new APRadioButton("Interact "); //create new radiobutton from label.
General_RadioGroup.addRadioButton(General_Setup_RB); //place radiobutton in radiogroup
General_RadioGroup.addRadioButton(General_Interact_RB); //place radiobutton in radiogroup
General_Container.addWidget(General_RadioGroup);
//Setup Mode Elements
SetupMode_Container = new APWidgetContainer(this);
SetupMode_ConnectButton = new APButton(5, 200, 900, 100, "Start Connection");
SetupMode_DisconnectButton = new APButton(5, 300, 900, 100, "Stop Connection");
SetupMode_Container.addWidget(SetupMode_ConnectButton);
SetupMode_Container.addWidget(SetupMode_DisconnectButton);
//Interact Mode Elements
InteractMode_Container = new APWidgetContainer(this);
InteractMode_SendButton = new APButton(5, 500, 900, 100, "SendToBT");
InteractMode_TypeTB = new APEditText(5, 150, 350, 100);
InteractMode_ExposuresTB = new APEditText(5, 250, 350, 100);
InteractMode_DelayTB = new APEditText(5, 350, 350, 100);
InteractMode_Container.addWidget(InteractMode_SendButton);
InteractMode_Container.addWidget(InteractMode_TypeTB);
InteractMode_Container.addWidget(InteractMode_ExposuresTB);
InteractMode_Container.addWidget(InteractMode_DelayTB);
//Finishing Touches
General_Setup_RB.setChecked(true); //Setup mode is selected by default
SetupMode_Container.hide();
InteractMode_Container.hide();
}
void draw(){
if(General_Setup_RB.isChecked()){
background(4, 49, 50);
SetupMode_Container.show();
InteractMode_Container.hide();
}
else if(General_Interact_RB.isChecked()){
background(50, 4, 48);
//creates text on screen
textSize(32);
text("Mode: " + InteractMode_TypeTB.getText(), 370, 200);
textSize(32);
text("Exposures: " + InteractMode_ExposuresTB.getText(), 370, 300);
textSize(32);
text("Delay: " + InteractMode_DelayTB.getText(), 370, 400);
SetupMode_Container.hide();
InteractMode_Container.show();
}
}
void onClickWidget(APWidget widget){
if(widget == SetupMode_ConnectButton){
bt.start(); //start listening for BT connections
if (bt.getDiscoveredDeviceNames().size() > 0) //If we have not discovered any devices, try prior paired devices
klist = new KetaiList(this, bt.getDiscoveredDeviceNames());
else if (bt.getPairedDeviceNames().size() > 0)
klist = new KetaiList(this, bt.getPairedDeviceNames());
}
if(widget == SetupMode_ConnectButton){
bt.stop(); //start listening for BT connections
}
if (widget == InteractMode_SendButton){
String m = InteractMode_TypeTB.getText() + ',' + InteractMode_ExposuresTB.getText() + ',' + InteractMode_DelayTB.getText() + '.'; //translates the selection by the user to
print(m.getBytes()+ " , "+ m);
bt.broadcast(m.getBytes()) ;
}
}
void onKetaiListSelection(KetaiList klist) { //Recives your selection
String selection = klist.getSelection();
text(str(bt.connectToDeviceByName(selection)),10,100);
//dispose of list for now
klist = null;
}
void onBluetoothDataEvent(String who, byte[] data) { //Call back method to manage data received
if (isConfiguring)
return;
//KetaiOSCMessage is the same as OscMessage
// but allows construction by byte array
KetaiOSCMessage m = new KetaiOSCMessage(data);
if (m.isValid())
{
if (m.checkAddrPattern("/remoteMouse/"))
{
if (m.checkTypetag("ii"))
{
remoteMouse.x = m.get(0).intValue();
remoteMouse.y = m.get(1).intValue();
}
}
}
}
String getBluetoothInformation(){
String btInfo = "Server Running: ";
btInfo += bt.isStarted() + "\n";
btInfo += "Discovering: " + bt.isDiscovering() + "\n";
btInfo += "Device Discoverable: "+bt.isDiscoverable() + "\n";
btInfo += "\nConnected Devices: \n";
ArrayList<String> devices = bt.getConnectedDeviceNames();
for (String device: devices)
{
btInfo+= device+"\n";
}
return btInfo;
}
Let me know if you ever use this!