SuperCollider

SuperCollider + Arduino #1

In this page we will learn the basics of serial communication between SuperCollider and Arduino. To start off we’re going to control the brightness of LED from SuperCollider! First, our circuit:

Now, in Arduino upload:

unsigned char val = 0;

void setup() { 
  Serial.begin(9600);
  pinMode(13, OUTPUT); // use one of the ~ pwm pin
} 

void loop() {
  if (Serial.available()) {
    val = Serial.read();
    analogWrite(13, val);
  }
}

Finally in SuperCollider:

// evaluate to find the name of your arduino
SerialPort.listDevices;
// see post window

// make sure serial monitor is not open in arduino IDE
// then open port
(
~port = SerialPort(
	"/dev/cu.usbmodem141101", // your arduino's name
	baudrate: 9600, // must match arduino rate
	crtscts: true
);
)

// send to arduino
// maximum brightness
~port.put(255);

// minimum
~port.put(0);

// random flicker
r = Routine { loop { ~port.put(1.exprand(255)); 0.3.wait } }.play;

// stop
r.stop;

// close before quitting
~port.close;

More than 1 LED?

When controlling more than 1 LED, we need to identify them. In Arduino:

unsigned char val = 0;
unsigned char id = 0;
  
void setup() { 
  Serial.begin(9600);
  // use 2 of ~ pwm pins
  pinMode(11, OUTPUT);
  pinMode(9, OUTPUT);
} 

void loop() {
  // need to wait till you get
  // more than 1 data
  if (Serial.available() > 1) {
    id = Serial.read();
    val = Serial.read();
    analogWrite(id, val);
  }
}

and in SuperCollider:

// evaluate to find the name of your arduino
SerialPort.listDevices;
// see post window

// make sure serial monitor is not open in arduino IDE
// then open port
(
~port = SerialPort(
	"/dev/cu.usbmodem141101", // your arduino's name
	baudrate: 9600, // must match arduino rate
	crtscts: true
);
)

// send id & brightness to arduino
// pin 11 maximum brightness
~port.putAll([11, 255]);

// pin 11 minimum
~port.putAll([11, 0]);

// or 2 in 1
// both pins max brightness
~port.putAll([11, 255, 9, 255]);

// both pins off
~port.putAll([11, 0, 9, 0]);

// close before quitting
~port.close;

SuperCollider + Arduino #2

In the examples above we controlled LEDs from SuperCollider. Here, however, we are going to do the opposite: using a push button and potentiometer on Arduino to control sounds in SuperCollider.

In Arduino:

int push = 0;
int pot0 = 0;
int pot1 = 0;

void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT); // our push button
  waitForSuperCollider();
}

// a monitor function waiting to 'handshake' with supercollider
void waitForSuperCollider() {
  while (Serial.available() <= 0) {
    // send an initial string. must match the number of values you want to send
    Serial.println("0,0,0");
    delay(300);
  }
}

void loop() {
  if (Serial.available() > 0) {

    // read from supercollider
    Serial.read();

    // our readings in arduino
    push = digitalRead(2);
    pot0 = analogRead(A1);
    delay(10); // delay in between analog reads for stability
    pot1 = analogRead(A2);

    // below will serial print an array of values
    Serial.print(push);
    Serial.print(","); // adding comma!
    Serial.print(pot0);
    Serial.print(","); // adding comma!
    Serial.println(pot1); // finally, break line!
  }
}

In SuperCollider:

// evaluate to find the name of your arduino
SerialPort.listDevices;
// see post window

// make sure serial monitor is not open in arduino IDE
// then open port
(
~port = SerialPort(
	"/dev/cu.usbmodem141101", // your arduino's name
	baudrate: 9600, // must match arduino rate
	crtscts: true
);
)

// a loop for reading from arduino
(
~routine = Routine {
	var byte, str, val;
	inf.do { |i|
		if(~port.read == Char.nl.asInteger, {
			str = "";
			while(
				{ byte = ~port.read; byte != Char.ret.asInteger },
				{ str = str ++ byte.asAscii }
			);
			val = str.split(Char.comma).asInteger;
			
			// our sound 
			// triggered and controlled form arduino
			
			// push button = on/off sound
			// pot0 = freq
			// pot1 = amp
			
			if(val[0] == 1, { 
			{ SinOsc.ar(
				val[1].linexp(0, 1023, 400, 1600), 0, 
				val[2].linlin(0, 1023, -30, -16).dbamp
			) * Env.perc(0.01, 0.1).kr(2) }.play;
			});
		});
	};
}.play;
)

// this will kick off reading (handshaking with arduino)
~port.put(0);

// stop
~routine.stop; ~port.close;