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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
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!
Nice! Would this work for a Bluetooth BLE device? I am trying to send commands from the processing android mode to a BLE device, but it seems like the KATAI library does not have this functionality. Any idea how I could do it? Thanks!