Hardware components | ||||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
| ||||||
| ||||||
Hand tools and fabrication machines | ||||||
|
A musical chair to play the game of musical chairs, with random household sounds. Made using Adafruit's Circuit Playground, Processing, Pure Data and a 3D-printed chair.
Record soundsTo use random household sounds, you need to record some. Grab a recording device, like a camera or your phone, and record some weird sounds.
The next step is making a chair. I chose to 3D print this one I found on Thingiverse, which I edited to make space for the Circuit Playground.
The Circuit Playground has all sorts of cool sensors, and the idea is to get the data from these sensors to Pure Data, which will make the sounds.
The straightforward way to do this, is to send the data from the Circuit Playground straight to Pure Data via serial communication. After many, many failed attempts and no proper tutorials on how to accomplish this, it was time for plan Z.
In this elaborate plan Z, the data is sent from the Circuit Playground to Processing via serial communication. Processing then sends this forward via OSC to Pure Data.
It's a bit of a loop, certainly a hassle, but the only way I managed to get it working. Tips on how to get the serial data to Pure Data would be highly appreciated.
The code for all of these parts can be found in the attachments below.
Put it all togetherIt's time to assemble all the parts! Upload the code to the Circuit Playground, attach it to your computer and run the Processing and Pure Data scripts at the same time. As if by magic, this should work!
You'll be the life of any party with this awesome chair!
// Media in Performance
// Musical Chair
// Nicole Horward - 2018
// Sources used:
// Connecting Arduino to Processing, Sparkfun, via https://learn.sparkfun.com/tutorials/connecting-arduino-to-processing
// Import libraries
import processing.serial.*;
import oscP5.*;
import netP5.*;
OscP5 oscP5;
NetAddress myRemoteLocation;
// Global variables
// Variables for serial communication with the Adafruit Circuit Playground
Serial myPort;
String val;
// String array to contain data from serial communication
String[] data;
boolean firstContact = false;
// SETUP
void setup(){
// Size
size(200, 200);
// Set background to white
background(255);
// Array to contain data received via serial communication
// From Circuit Playground
data = new String[4];
data[0] = "0"; // X motion of Cirucit Playground = Y position in Processing
data[1] = "0"; // Y motion of Cirucit Playground = X position in Processing
data[2] = "0"; // Z motion of Cirucit Playground
data[3] = "0"; // LED color of Cirucit Playground
print(Serial.list()[0]);
// Setup serial port for communication
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.bufferUntil('\n');
/* start oscP5, listening for incoming messages at port 12000 */
oscP5 = new OscP5(this,12000);
myRemoteLocation = new NetAddress("127.0.0.1",12000);
}
void draw(){
// Draw white background
background(255);
// Load the ledcolor
//ledcolor = color(int(data[3]));
//// Divide the color into RGB values
//R = red(ledcolor);
//G = green(ledcolor);
//B = blue(ledcolor);
// Send sensor data to Pure Data via OSC
oscP5.send("/CircuitPlayground",new Object[] {new Float(data[0]), new Float(data[1]) , new Float(data[2])}, myRemoteLocation);
println(data[2]);
}
// CIRCUIT PLAYGROUND
// The serial communication with the Circuit Playground
void serialEvent(Serial myPort){
// Read the serial uitput until an enter symbol
val = myPort.readStringUntil('\n');
// If the value is not null
if(val != null){
// Trim the String
val = trim(val);
//println(val);
// Split it into 4 seperate data strings
// Split on " "
data = val.split(" ");
}
// If there has been no contact yet
if(firstContact == false){
// Check if the Circuit Playground is sending "A"
if(val.equals("A")){
// If "A" has been received, contact has been established
myPort.clear();
firstContact = true;
myPort.write("A");
println("contact");
}
}
}
#include <Adafruit_CircuitPlayground.h>
// Global variables
char val; // Data received serial port
//int ledPin = 13;
boolean ledState = LOW;
float X, Y, Z, C;
float color;
void setup() {
//pinMode(LED_BUILTIN, OUTPUT);
// Setup serial communication
Serial.begin(9600);
color = 1;
CircuitPlayground.begin();
establishContact();
}
void loop() {
// Get data from the sensors
X = CircuitPlayground.motionX();
Y = CircuitPlayground.motionY();
Z = CircuitPlayground.motionZ();
C = CircuitPlayground.colorWheel(color);
// Set the colors of the LEDS
// For each of the 10 LEDS
for(int pixel = 0; pixel < 10; pixel++){
// Set the color
CircuitPlayground.setPixelColor(pixel, CircuitPlayground.colorWheel(color));
// If the last LED is turned on
// And has the last RGB color
// Change the color
if(pixel == 9){
if(color >= 254){
color = 0;
}
else{
color += 1;
}
}
}
// Serial send sensor data
Serial.println(String(X) + " " + String(Y) + " " + String(Z) + " " + String(C));
delay(100);
}
// Check if contact has been established
void establishContact(){
while (Serial.available() <= 0){
Serial.println("A");
delay(300);
}
}
#N canvas -9 -9 1920 976 16;
#X declare -lib mrpeach;
#X obj 840 306 soundfiler;
#X floatatom 841 403 10 0 0 0 - - -;
#X obj 978 434 expr 44100 / $f1;
#X floatatom 990 494 5 0 0 0 - - -;
#X obj 839 81 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
-1;
#X msg 839 136 open robot.wav;
#X obj 839 27 loadbang;
#X msg 839 237 read -resize \$1 Robot;
#N canvas 0 0 450 300 (subpatch) 0;
#X array Robot 80640 float 2;
#X coords 0 1 80640 -1 200 140 1;
#X restore 516 697 graph;
#X obj 604 239 hsl 128 15 -10 10 0 0 empty empty empty -2 -8 0 10 -262144
-1 -1 6350 1;
#X floatatom 601 289 5 0 0 0 - - -;
#X obj 893 693 phasor~;
#X obj 922 754 *~ 1;
#X obj 1259 899 *~;
#X obj 1242 963 dac~;
#X obj 970 835 tabread4~ Robot;
#X obj 1031 337 s RobotSamples;
#X obj 1002 705 r RobotSamples;
#X floatatom 893 553 5 0 0 0 - - -;
#X obj 893 492 f;
#X obj 625 450 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
-1 -1;
#X obj 1845 832 vsl 15 128 0.01 1 1 0 empty empty empty 0 -9 0 10 -262144
-1 -1 8400 1;
#X floatatom 1845 984 5 0 0 0 - - -;
#X obj 1731 982 line~;
#X msg 1731 935 \$1 25;
#X obj 601 397 t b f;
#X obj 893 602 * 2;
#X obj -54 67 udpreceive 12000;
#X obj -55 188 unpackOSC;
#X obj 266 290 print;
#X obj -55 257 routeOSC /CircuitPlayground;
#X floatatom 49 602 5 0 0 0 - - -;
#X obj -55 400 unpack f f f;
#X obj 515 848 hsl 200 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
-1 -1 14357 1;
#X obj 731 859 snapshot~;
#X obj 731 766 metro 25;
#X obj 731 703 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
1;
#X obj 43 992 s XMotion;
#X floatatom -20 832 5 0 0 0 - - -;
#X obj 115 757 s YMotion;
#X obj 277 536 s ZMotion;
#X floatatom 192 376 5 0 0 0 - - -;
#X obj 601 180 r XMotion;
#X obj 1507 303 soundfiler;
#X floatatom 1508 400 10 0 0 0 - - -;
#X obj 1640 419 expr 44100 / $f1;
#X floatatom 1661 469 5 0 0 0 - - -;
#X obj 1506 78 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
-1 -1;
#X obj 1506 24 loadbang;
#N canvas 0 0 450 300 (subpatch) 0;
#X array Eyes 49920 float 2;
#X coords 0 1 49920 -1 200 140 1 0 0;
#X restore 1217 539 graph;
#X obj 1330 227 hsl 128 15 -10 10 0 0 empty empty empty -2 -8 0 10
-262144 -1 -1 6350 1;
#X floatatom 1327 277 5 0 0 0 - - -;
#X obj 1560 649 phasor~;
#X obj 1618 722 *~ 1;
#X floatatom 1560 550 5 0 0 0 - - -;
#X obj 1560 489 f;
#X obj 1526 444 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
-1 -1;
#X obj 1327 436 t b f;
#X obj 1560 599 * 2;
#X obj 1215 690 hsl 200 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
-1 -1 9959 1;
#X obj 1431 701 snapshot~;
#X obj 1431 608 metro 25;
#X obj 1431 545 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1
1 1;
#X msg 1506 133 open googlyeyes.wav;
#X msg 1506 234 read -resize \$1 Eyes;
#X obj 1698 334 s EyesSamples;
#X obj 1684 649 r EyesSamples;
#X obj 1327 168 r YMotion;
#X obj 1619 783 tabread4~ Eyes;
#X obj 2215 243 soundfiler;
#X floatatom 2254 306 10 0 0 0 - - -;
#X obj 2353 340 expr 44100 / $f1;
#X floatatom 2369 409 5 0 0 0 - - -;
#X obj 2214 18 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
-1 -1;
#X obj 2214 -36 loadbang;
#N canvas 0 0 450 300 (subpatch) 0;
#X array Snowglobe 88320 float 2;
#X coords 0 1 88320 -1 200 140 1 0 0;
#X restore 1908 543 graph;
#X obj 1978 88 hsl 128 15 -10 10 0 0 empty empty empty -2 -8 0 10 -262144
-1 -1 12579 1;
#X floatatom 1975 138 5 0 0 0 - - -;
#X obj 2268 589 phasor~;
#X obj 2326 662 *~ 1;
#X floatatom 2268 490 5 0 0 0 - - -;
#X obj 2268 429 f;
#X obj 2234 384 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
-1 -1;
#X obj 1975 306 t b f;
#X obj 2268 539 * 2;
#X obj 1907 694 hsl 200 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
-1 -1 12741 1;
#X obj 2123 705 snapshot~;
#X text 2123 660 Audio naar control;
#X obj 2123 612 metro 25;
#X obj 2123 549 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1
1 1;
#X msg 2214 73 open snowglobe.wav;
#X obj 2368 272 s SnowglobeSamples;
#X obj 2392 589 r SnowglobeSamples;
#X msg 2214 174 read -resize \$1 Snowglobe;
#X obj 1975 29 r ZMotion;
#X obj 2327 723 tabread4~ Snowglobe;
#X floatatom -20 992 5 0 0 0 - - -;
#X obj -20 886 expr if($f1 > 1 || $f1 < -1 \, $f1 \, 0);
#X floatatom 49 756 5 0 0 0 - - -;
#X obj 49 643 expr if($f1 > 1 || $f1 < -1 \, $f1 \, 0);
#X floatatom 192 535 5 0 0 0 - - -;
#X obj 192 425 expr if($f1 < -8 \, 0 \, $f1);
#X obj -53 16 import mrpeach;
#X text -50 -31 Media in Performance - Nicole Horward;
#X text -46 150 Receive OSC on port 12000;
#X text -39 223 Unpack OSC message;
#X text -41 293 Route to /CircuitPlayground;
#X text -47 366 Unpack 3 floats;
#X text 1604 198;
#X text 259 376 Z Motion Sensor;
#X text 113 604 Y Motion Sensor;
#X text 46 835 X Motion Sensor;
#X text 396 486;
#X text 262 460 If Z sensor value <-8 \, the chair is not moving \,
so set speed 0;
#X text 117 678 If Y sensor value > 1 or < -1 \, the chair is moving
\, so set speed to sensor value;
#X text 56 924 If X sensor value > 1 or < -1 \, the chair is moving
\, so set speed to sensor value;
#X text 851 57 On load of PD file;
#X text 1519 52 On load of PD file;
#X text 1068 56;
#X text 599 109 Receive X Motion value;
#X text 855 104 Open sample robot.wav;
#X text 499 212;
#X text 980 388 Speed of phasor is 44100 / number of samples;
#X text 606 322 Trigger when the value changes to recalculate speed
;
#X text 903 654 Sawtooth wave;
#X text 737 812;
#X text 975 787 Read signal from Robot sample;
#X text 1205 1000 Audio output;
#X text 847 186 Read file \, resize to sample length and send to Robot
array;
#X text 1341 196;
#X text 1516 103 Open sample googlyeyes.wav;
#X text 1518 179 Read file \, resize to sample length and send to Eyes
array;
#X text 1327 95 Receive Y Motion value;
#X text 854 268;
#X text 963 306 Get the number of samples;
#X text 1627 301 Get the number of samples;
#X text 1651 374 Speed of phasor is 44100 / number of samples;
#X text 1332 340 Trigger when the value changes to recalculate speed
;
#X text 1605 609 Sawtooth wave;
#X text 1680 726 Read signal from Eyes sample;
#X text 1431 656;
#X text 2229 205;
#X text 2234 -6 On load of PD file;
#X text 2230 40 Open sample snowglobe.wav;
#X text 2236 110 Read file \, resize to sample length and send to Snowglobe
array;
#X text 1991 107;
#X text 1973 -33 Receive Z Motion value;
#X text 1982 195 Trigger when the value changes to recalculate speed
;
#X text 2362 234 Get the number of samples;
#X text 2439 372 Speed of phasor is 44100 / number of samples;
#X text 2335 549 Sawtooth wave;
#X text 2346 759 Read signal from Snowglobe sample;
#X connect 0 0 1 0;
#X connect 0 0 2 0;
#X connect 0 0 16 0;
#X connect 2 0 3 0;
#X connect 2 0 19 1;
#X connect 4 0 5 0;
#X connect 5 0 7 0;
#X connect 6 0 4 0;
#X connect 7 0 0 0;
#X connect 9 0 10 0;
#X connect 10 0 25 0;
#X connect 11 0 12 0;
#X connect 11 0 34 0;
#X connect 12 0 15 0;
#X connect 13 0 14 0;
#X connect 13 0 14 1;
#X connect 15 0 13 0;
#X connect 17 0 12 1;
#X connect 18 0 26 0;
#X connect 19 0 18 0;
#X connect 20 0 19 0;
#X connect 21 0 22 0;
#X connect 22 0 24 0;
#X connect 23 0 13 1;
#X connect 24 0 23 0;
#X connect 25 0 20 0;
#X connect 25 1 26 1;
#X connect 26 0 11 0;
#X connect 27 0 28 0;
#X connect 28 0 30 0;
#X connect 30 0 32 0;
#X connect 30 0 29 0;
#X connect 31 0 99 0;
#X connect 32 0 38 0;
#X connect 32 1 31 0;
#X connect 32 2 41 0;
#X connect 34 0 33 0;
#X connect 35 0 34 0;
#X connect 36 0 35 0;
#X connect 38 0 97 0;
#X connect 41 0 101 0;
#X connect 42 0 9 0;
#X connect 43 0 44 0;
#X connect 43 0 45 0;
#X connect 43 0 65 0;
#X connect 45 0 46 0;
#X connect 45 0 55 1;
#X connect 47 0 63 0;
#X connect 48 0 47 0;
#X connect 50 0 51 0;
#X connect 51 0 57 0;
#X connect 52 0 53 0;
#X connect 52 0 60 0;
#X connect 53 0 68 0;
#X connect 54 0 58 0;
#X connect 55 0 54 0;
#X connect 56 0 55 0;
#X connect 57 0 56 0;
#X connect 57 1 58 1;
#X connect 58 0 52 0;
#X connect 60 0 59 0;
#X connect 61 0 60 0;
#X connect 62 0 61 0;
#X connect 63 0 64 0;
#X connect 64 0 43 0;
#X connect 66 0 53 1;
#X connect 67 0 50 0;
#X connect 68 0 13 0;
#X connect 69 0 70 0;
#X connect 69 0 71 0;
#X connect 69 0 91 0;
#X connect 71 0 72 0;
#X connect 71 0 81 1;
#X connect 73 0 90 0;
#X connect 74 0 73 0;
#X connect 76 0 77 0;
#X connect 77 0 83 0;
#X connect 78 0 79 0;
#X connect 78 0 86 0;
#X connect 79 0 95 0;
#X connect 80 0 84 0;
#X connect 81 0 80 0;
#X connect 82 0 81 0;
#X connect 83 0 82 0;
#X connect 83 1 84 1;
#X connect 84 0 78 0;
#X connect 86 0 85 0;
#X connect 88 0 86 0;
#X connect 89 0 88 0;
#X connect 90 0 93 0;
#X connect 92 0 79 1;
#X connect 93 0 69 0;
#X connect 94 0 76 0;
#X connect 95 0 13 0;
#X connect 97 0 96 0;
#X connect 97 0 37 0;
#X connect 99 0 98 0;
#X connect 99 0 39 0;
#X connect 101 0 40 0;
#X connect 101 0 100 0;
Comments