Clara Cheong and Paul Cooper
Installation view, Gaffa Gallery Sydney
Media: Custom software, Glass, Wooden and Metal Plinth, Arduino microcontrollers with audio recording and playback hardware
/* ===============================================================
Project: Multi Record/Playback Controller - An Ode to Alvin Lucier
Author: Paul Cooper
Collaborator: Clara Cheong
Created: January 2021
Modified: Feburary 2021
Description: Controls 6 audio recorders to simulate an automated
version of Alvin Lucier's "I am sitting in a room" recording.
We wanted to create a live version that allows for audience interruptions.
The record/plyback sequence will begin as soon as power is applied.
OPTIONAL: Audiences are invited to strike the tuning fork at anytime to 'reset'
the interruption.
Updated: 2-Mar-2021
Pause on restart awaiting trigger via ultrasonic sensors, then
auto shutdown and reboot sequence included to allow for some quiet time.
Sound Bulbs, once triggered will record and playback collected sounds
for ~8minutes, then reboot and wait ~8minutes before being able to be retriggered
================================================================== */
/*
HARDWARE:
1x Arduino UNO
6x Arduino Compatible Record and Playback Module (Jaycar XC4605)
3x HC-SR04 ultrasonic sensors
1x Expanded terinal sheild to provide 6x power terminal socket pairs
1x 5V - 12V power supply. Audio board requires only 5V
WIRING:
Audio Bd -- Arduino
VCC -- 5V
GND -- GND
Rec -- Digital Pin 2, 4, 6, 8, 10, 12
PlayL -- Digital Pin 3, 5, 7, 9, 11, 13
HC-SR04 Module -- Arduino
Vcc -- 5V
GND -- GND
Trig -- A0, A2, A4
Echo -- A1, A3, A5
Audio board internal mics are used in this project.
Sound quality is lo-fi, but suitable for this project.
To RECORD - set pin high for the duration of desired recording period (max'ed at 10seconds)
To PLAY - hold the PLAY-L pin high. Once low, play stops
*/
#include <Ultrasonic.h>
#include <avr/wdt.h>
//Variables
int RanREC;
int const PBut = 500;
int const RBut = 10000;
int REC[7] = {0, 2, 4, 6, 8, 10, 12}; // record pins
int PLAY[7] = {0, 3, 5, 7, 9, 11, 13}; // play pins
unsigned long Time0;
unsigned long Time1;
long const t = 120000; // 500000 is ~8 minutes and 15 seconds; test mode suggested setting is 120000 (2 minutes)
Ultrasonic uS1(A0, A1); // Ultrasonic sensor HC-04 TRIG, ECHO
Ultrasonic uS2(A2, A3);
Ultrasonic uS3(A4, A5);
void setup() {
Serial.begin(9600);
Serial.println("***** Sound Bulbs, 2021 *****");
Serial.println("by Paul Cooper & Clache Raong");
Serial.println();
Serial.println("setting up GPIOs");
randomSeed(analogRead(A0));
// GPIO Setup
for (int i = 1 ; i <= 6; i += 1) {
pinMode(REC[i], OUTPUT);
}
for (int i = 1 ; i <= 6; i += 1) {
pinMode(PLAY[i], OUTPUT);
}
// Turn off output lines
for (int i = 1 ; i <= 6; i += 1) {
digitalWrite(REC[i], LOW);
}
for (int i = 1 ; i <= 6; i += 1) {
digitalWrite(PLAY[i], LOW);
}
// Record reset
Serial.println("reset recordings");
for (int i = 1 ; i <= 6; i += 1) {
digitalWrite(REC[i], HIGH);
}
delay(RBut);
for (int i = 1 ; i <= 6; i += 1) {
digitalWrite(REC[i], LOW);
}
Serial.println("END SETUP");
Serial.println("now in pause mode");
delay(t/4); // silence is golden, about 8 minutes worth anyway
// End Setup
}
void loop(){
Serial.println("awaiting movement");
Time0 = millis();
Serial.print("Time0 = ");
Serial.println(Time0);
Serial.print("uS1 = ");
Serial.println(uS1.distanceRead());
Serial.print("uS2 = ");
Serial.println(uS2.distanceRead());
Serial.print("uS3 = ");
Serial.println(uS3.distanceRead());
if ((uS1.distanceRead() <150 && uS1.distanceRead() >10) ||
(uS2.distanceRead() <150 && uS2.distanceRead() >10) ||
(uS3.distanceRead() <150 && uS3.distanceRead() >10)) { // sensor trigger 10cm to 150cm
Serial.println("motion detected");
Time1 = millis();
while (Time1 < (Time0 + t)) {
RanREC = random(1, 7);
Serial.println();
Serial.println("SoundBulbs do its thing");
Serial.print("Time1 = ");
Serial.println(Time1);
Serial.print("Time0 + t = ");
Serial.println(Time0 + t);
Serial.println();
SoundBulb(RanREC);
Time1 = millis();
}
Serial.println("Going to Sleep");
GoToSleep();
}
delay(1000);
}
void SoundBulb(int x) {
/*
* The record module (R) is chosen at random and all other
* modules are set to play.
* There are 2 groups of 3 sound modules (A & B)
* This is done to ensure there is no gap in the the sound
* (eventually)
*/
nowPLAYA(x);
delay(2500);
nowREC(x);
stopPLAYB(x);
delay(2500);
nowPLAYB(x);
delay(5000);
stopPLAYA(x);
delay(2500);
nowPLAYA(x);
stopREC(x);
}
void nowPLAYA(int R) {
for (int i = 1 ; i <= 3; i += 1) {
if (i != R) {
digitalWrite(PLAY[i], HIGH);
}
}
}
void stopPLAYA(int R) {
for (int i = 1 ; i <= 3; i += 1) {
if (i != R) {
digitalWrite(PLAY[i], LOW);
}
}
}
void nowPLAYB(int R) {
for (int i = 4 ; i <= 6; i += 1) {
if (i != R) {
digitalWrite(PLAY[i], HIGH);
}
}
}
void stopPLAYB(int R) {
for (int i = 4 ; i <= 6; i += 1) {
if (i != R) {
digitalWrite(PLAY[i], LOW);
}
}
}
void nowREC(int R) {
digitalWrite(PLAY[R], LOW);
delay(PBut);
digitalWrite(REC[R], HIGH);
}
void stopREC(int R) {
digitalWrite(REC[R], LOW);
}
void GoToSleep(){
for (int i = 1 ; i <= 6; i += 1) {
digitalWrite(PLAY[i], HIGH);
Serial.print("now playing: ");
Serial.println(i);
}
delay(10000);
for (int i = 1 ; i <= 6; i += 1) {
digitalWrite(PLAY[i], LOW);
Serial.print("now shutting down: ");
Serial.println(i);
delay(10000);
}
reboot();
}
void reboot() {
wdt_disable();
wdt_enable(WDTO_15MS);
while (1) {}
}
