I did a small interactive slackline project for KulturSYDHavn. A festival on the quay of Teglholmen and around the Illutron barge in conjunction with the annual KulturHavn festival on Islands Brygge on the 6, 7 and 8th of August. We created an interactive playground around the barge and together with Illutron I put up the slackline with RGB color feedback on the quay. I owe a great thanks to the Illutron crew who put a lot of energy into this festival, especially Troels Just Christoffersen who helped put the last pieces of the slackline installation up while I was gone in the week preceeding the festival. And I owe a thanks to the sponsors who made it possible, Slackline.dk and Rullegræsset.dk who sponsored a free feet slacklight15 kit and 1 metric ton of roll out grass respectively.

Documentation
The slackline is hooked up to a strain gauge that measures the weight on the slackline. An Op-Amp amplifies the signal for the arduino and two pieces of flexible high intensity RGB led strip are controlled with PWM via a ULN2003 Darlington transistor array.
Schematics
Code
// KulturSYDHavn Illutron Interactive slackline code by Johan Bichel Lindegaard
float h;
int h_int;
int r=0, g=0, b=0, intensity=100;
void h2rgb(float h, int &R, int &G, int &B);
// Select which analog input the strain gauge is connected to.
const int mPin = 0;
int m = 0;
int state = 0; // 0: inactive, 1: active, 3: pending inactive
int deactivationThreshold = 8;
int deactivationTime = 1000;
unsigned long stateTimeStamp;
unsigned long stateTime = 0;
// Select which PWM-capable pins are to be used.
const int redPin = 10;
const int greenPin = 11;
const int bluePin = 9;
long brbgPreviousMillis = 0;
long fadePreviousMillis = 0;
boolean blinkState = 0;
boolean fadeUp = 0;
// range calibration variables.
int lowPoint;
int highPoint;
void setup()
{
// start serial port at 9600 bps:
// Serial.begin(9600);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
// calibrate
lowPoint = analogRead(mPin);
highPoint = lowPoint + 124;
if(highPoint > 1024) {
highPoint = 1024;
}
// test pins
rgb(255,0 ,0 ); delay(500);
rgb(0 ,255,0 ); delay(500);
rgb(0 ,0 ,255); delay(500);
}
void loop()
{
int m = analogRead(mPin);
// Check calibration, and expand range if needed.
if(m < lowPoint) {
lowPoint = m;
} else if(m > highPoint) {
highPoint = m;
}
// Serial.println(m);
// keep track of how long the line has been active and inactive
if(m > lowPoint + deactivationThreshold) {
if(state == 0) {
state = 1;
stateTimeStamp = millis();
}
stateTime = millis() - stateTimeStamp;
} else if(state == 1){
state = 3;
stateTimeStamp = millis();
} else {
stateTime = millis() - stateTimeStamp;
if(stateTime > deactivationTime) {
state = 0;
}
}
if(state != 0){
// Convert input to RGB through hue then output.
h = ((float)map(m, lowPoint, highPoint, 1024, 0))/1024;
h_int = (int) 360*h;
h2rgb(h,r,g,b);
// if active for a short while enter fancy blink mode then return to normal
if(stateTime > 15000 && stateTime < 60000) {
int btime = map(stateTime,15000,60000,1000,50);
brgb(r,g,b,btime);
} else {
rgb(r,g,b);
}
} else {
unsigned long currentMillis = millis();
if(currentMillis - fadePreviousMillis > 100) {
fadePreviousMillis = currentMillis;
if(intensity > 99) { fadeUp = false;
} else if (intensity < 1) {
fadeUp = true; }
if(fadeUp) { ++intensity;
} else { --intensity; }
rgb(255,0,0,intensity);
}
}
}
void rgb(int r, int g, int b) {
analogWrite(redPin,r);
analogWrite(greenPin,g);
analogWrite(bluePin,b);
}
void rgb(int r, int g, int b, float intensity) {
if(intensity > 100) {
intensity = 100;
} else if(intensity < 0){
intensity = 0;
}
rgb(r/100*intensity, g/100*intensity, b/100*intensity);
}
void brgb(int r, int g, int b, int interval) {
unsigned long currentMillis = millis();
if(currentMillis - brbgPreviousMillis > interval) {
brbgPreviousMillis = currentMillis;
if (!blinkState) {
blinkState = 1;
rgb(r,g,b);
} else {
blinkState = 0;
rgb(0,0,0);
}
}
}
void h2rgb(float H, int& R, int& G, int& B) {
int var_i;
float S=1, V=1, var_1, var_2, var_3, var_h, var_r, var_g, var_b;
if ( S == 0 ) //HSV values = 0 √∑ 1
{
R = V * 255;
G = V * 255;
B = V * 255;
}
else
{
var_h = H * 6;
if ( var_h == 6 ) var_h = 0; //H must be < 1
var_i = int( var_h ) ; //Or ... var_i = floor( var_h )
var_1 = V * ( 1 - S );
var_2 = V * ( 1 - S * ( var_h - var_i ) );
var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) );
if ( var_i == 0 ) {
var_r = V ;
var_g = var_3 ;
var_b = var_1 ;
}
else if ( var_i == 1 ) {
var_r = var_2 ;
var_g = V ;
var_b = var_1 ;
}
else if ( var_i == 2 ) {
var_r = var_1 ;
var_g = V ;
var_b = var_3 ;
}
else if ( var_i == 3 ) {
var_r = var_1 ;
var_g = var_2 ;
var_b = V ;
}
else if ( var_i == 4 ) {
var_r = var_3 ;
var_g = var_1 ;
var_b = V ;
}
else {
var_r = V ;
var_g = var_1 ;
var_b = var_2 ;
}
R = (1-var_r) * 255; //RGB results = 0 √∑ 255
G = (1-var_g) * 255;
B = (1-var_b) * 255;
}
}