This was built so that I could very easily create peer-to-peer connections between my physical computing projects, both old and new. The idea is to lower the barrier to entry for a project to become wireless and interoperable, using a wireless protocol inspired by MIDI, and device-specific Bluetooth LE profiles, auto-generated for each project.
Originally developed for my ITP '14 masters thesis, I have rebuilt it from the ground up during my residency at ITP this past year.
The Patchbay breakout board connects over hardware SPI, which are pins D13
, D12
, and D11
on the Arduino Uno. The breakout also uses pins D10
, D9
, D8
, D7
, and D2
for SPI handshaking with both radios, and one additional reset pin for the nRF51822.
On the Arduino Uno, this leaves digital pins D0
, D1
, D3
, D4
, D5
, and D6
available, as well as all Analog pins.
Include the Patchbay library in your Arduino sketch, and initialize it with the mesh ID, the name of your device, and the number of physical inputs
and outputs
you would like it to expose.
#include <Patchbay.h>
#define ID 1
#define total_inputs 2
#define total_outputs 1
Patchbay myPatch( ID , "Device-Name" , total_inputs , total_outputs );
All inputs
and outputs
are stored in two arrays for each type, and each is referenced through the API by their index. This means that if you have three inputs
, the first has an identifier of 0
, the second 1
, and so on.
Once initialzed at the top of your sketch, simple call .begin()
inside of the Arduino setup()
function. This function will begin SPI communication with both radios, set your network ID, as well as setup your device's custom GATT profile.
void setup(){
myPatch.begin();
}
inputs
and outputs
can be assigned names to show up in the Patchbay interface. These are strings or char arrays of less than 20 characters. Names should be assigned once inside the Arduino setup()
function.
myPatch.inputName( 0 , "knob-1");
myPatch.inputName( 1 , "knob-2");
myPatch.outputName( 0 , "LED");
Patchbay relies on very fast communication and update cycles with the breakout board. .update()
handles all of this for you, checking for any BLE connections and updates, as well sending and receiving any necessary data over the RFm69.
Call .update()
as often as possible. If your sketch uses any blocking functions, either try and avoid it, or call .update()
multiple times inside your loop()
.
void loop(){
myPatch.update();
}
.update()
will also return a boolean
for whether this devices' outputs
have received a new value. If it returns true
, your code should read the output
values and handle them in whatever way your sketch needs to.
void loop(){
if(myPatch.update()) {
// update your sketch as necessary
}
}
Patchbay inputs
can be physical inputs like sensors, and must be represented as an integer between 0
and 255
.
int knob_1_value = analogRead(0) / 4; // map the value to 0-255
int knob_2_value = analogRead(1) / 4;
An input
is then written to, and automatically sent out over any wireless links that might exist.
myPatch.inputWrite( 0 , knob_1_value ); // set the values
myPatch.inputWrite( 1 , knob_2_value );
myPatch.update(); // send the values wireless
Patchbay outputs
can be physical outputs like lights or motors, and must be represented as an integer between 0
and 255
.
int new_LED_value = myPatch.outputRead( 0 ); // get the value
When an outputs
value has been updated, .update()
will return true, allowing the sketch to update physical outputs only when necessary.
In addition, each output
can be tested to see if it has changed or not with the .outputChanged()
function. This is useful if your sketch has multiple outputs
.
if( myPatch.update() ) { // update all radio communications
for( int i=0; i<total_outputs; i++ ) { // loop through all outputs
if( myPatch.outputChanged( i ) ) { // test to see if this one has changed
Serial.print("Output "); // use the new value
Serial.print(i);
Serial.print(" has changed to ");
Serial.println( myPatch.outputRead(i) );
}
}
}
I have developed Patchbay so far on my own in my free time, and none of this would have been possible without the wonderful open-source software and hardware from the following people.
The Arduino library currently depends on LowPowerLab's RFm69 library, and Adafruit's Bluefruit LE firmware and library.
The HTML5 interface uses hammer.js for touch events, and connects over BLE using Rand Dusing's cordova plugin, allowing the app to be available on iOS and Android.