AndiHub

Code-Outlet von Andreas Bahr, Zürich

Blinksy

Eine Beatbox für die Guggenheim Box by The Sporthorses

Erste Tests von Blinksy

Blinksy ist eine Beatbox-Erweiterung für die von Jonas Guggenheim & den Sporthorses geschaffene "Guggenheim Box", eine Telefonkabinen-artige Installation mit Lichtschranken. Vereinfacht formuliert erlaubt die Box und ihre Erweiterungen, einen Modul-Synthsizer zu "spielen".

ARE YOU QUA(RA)NTIZED? 2020

The Sporthoses sind eine Live-Performance-Band deren Auftritte nicht nur die Ohren, sondern auch die Augen erfreuen.

Blinksy Hardware

Kern ist ein Arduino Nano. Über einen Drehschalter mit 4 Positionen können 4 verschiedene Pattern ausgewählt werden, die maximal 4 LED-Lampen direkt ansteuern. Diese triggern die Lichtschranken anstelle eines Sporthorse-Musikers.

In der ersten Version der Hardware nach meinem Entwurf waren 2 kräftige LEDs pro Kanal vorgesehen, meine Idee war, mehr LED = mehr Licht = weniger Anfällig auf Streulicht. Die Musiker haben aber Dank ihrer Erfahrung im Instrumentenbau eine bessere Lösung gefunden: der Einsatz von einfachen Optiken. So konnten mit einzelnen LEDs perfekte Resultate erzielt werden.

Schema

Erste Version Blinksy Hardware - Klick für Zoom

Blinksy Software

In der Arduino-Welt muss mit C/C++ programmiert werden. Ich mag C nicht, muss aber zugeben, es ist wesentlich effizienter damit zu arbeiten, als mit Maschinensprache/Assembler...

Die aktuelle Version erlaubt das Task-Synchrone umschalten der Pattern während der Live-Performance. Die Pattern selbst sind im Header des Scripts definiert.

Aktuelle Version: Download

Die hier angebotene Ino-Datei können Sie mit der Arduino-IDE verwenden. Sie lässt sich aber auch mit einem normalen Text-Editor lesen.

2-Kanal "Labor-Version" für die Software-Entwicklung

Erste Version

Die etwas einfachere erste Version eignet sich sehr gut um die Funktionsweise der Software zu erkennen: Der HW-Timer des Prozessors wird verwendet für das korrekte Timing, er meldet via einen Interupt das vergehen der Zeit zurück an die Software...

 
/* blinksy v0.4
 * music sequencer with lights
 * for the Guggenheim-Box
 * copyleft 2017 button3 & the sporthorses
 * -----------------------------------------
 * sequencer plays a note by switching 
 * a light off for some milliseconds.
 * in the musical setup, write any character 
 * for a note, leave blank otherwise.
 * -----------------------------------------
 * 4 sets with 4 tracks on 4 led-lamps
 * BPM values from 20 to 180
 */


// MUSIC SETUP ==========================================
// SET 1 ------------------------------------------------
int set1bpm = 40;
// TICK RULER         "1...2...3...4...5...6...7...8..."
char set1track1[33] = "x       x       x       x       ";
char set1track2[33] = "    x       x       x       x   ";
char set1track3[33] = "                                ";
char set1track4[33] = "                                ";
// SET 2 ------------------------------------------------
int set2bpm = 80;
// TICK RULER         "1...2...3...4...5...6...7...8..."
char set2track1[33] = "x       x       x       x       ";
char set2track2[33] = "x   x   x   x   x   x   x   x   ";
char set2track3[33] = "    x       x       x       x   ";
char set2track4[33] = "                                ";
// SET 3 ------------------------------------------------
int set3bpm = 60;
// TICK RULER         "1...2...3...4...5...6...7...8..."
char set3track1[33] = "                                ";
char set3track2[33] = "                                ";
char set3track3[33] = "                                ";
char set3track4[33] = "                                ";
// SET 4 ------------------------------------------------
int set4bpm = 60;
// TICK RULER         "1...2...3...4...5...6...7...8..."
char set4track1[33] = "                                ";
char set4track2[33] = "                                ";
char set4track3[33] = "                                ";
char set4track4[33] = "                                ";
// ======================================================


// internal setup
volatile int loopCount = 0;
const unsigned long CLOCK_FREQ = 250000;
unsigned int impulseMiliSec = 10;
unsigned int compareON = 20000;
unsigned int compareOFF = 10000;
int bpm = 60;
char track1[33];
char track2[33];
char track3[33];
char track4[33];

// system initialisation
void setup() {
  Serial.begin(9600);
  noInterrupts();

  // BPM flash
  pinMode(LED_BUILTIN, OUTPUT); // on-board led
  // 4 lights
  pinMode(12, OUTPUT); // light 1
  pinMode(11, OUTPUT); // light 2
  pinMode(10, OUTPUT); // light 3
  pinMode(9, OUTPUT); // light 4
  digitalWrite(12, HIGH); // switch them OFF
  digitalWrite(11, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(9, HIGH);
  // set-switch
  pinMode(5, INPUT_PULLUP); // prg 1
  pinMode(6, INPUT_PULLUP); // prg 2
  pinMode(7, INPUT_PULLUP); // prg 3
  pinMode(8, INPUT_PULLUP); // prg 4

  // load music data
  if(digitalRead(8) == LOW) {
    bpm = set4bpm;
    strcpy(track1, set4track1);
    strcpy(track2, set4track2);
    strcpy(track3, set4track3);
    strcpy(track4, set4track4);
  } else {
    if(digitalRead(7) == LOW) {
      bpm = set3bpm;
      strcpy(track1, set3track1);
      strcpy(track2, set3track2);
      strcpy(track3, set3track3);
      strcpy(track4, set3track4);
    } else {
      if(digitalRead(6) == LOW) {
        bpm = set2bpm;
        strcpy(track1, set2track1);
        strcpy(track2, set2track2);
        strcpy(track3, set2track3);
        strcpy(track4, set2track4);
      } else {
        bpm = set1bpm;
        strcpy(track1, set1track1);
        strcpy(track2, set1track2);
        strcpy(track3, set1track3);
        strcpy(track4, set1track4);
      }
    }
  }

  // calculate timer-compare-values
  compareON = (CLOCK_FREQ / (bpm * 32 / 60)) - 1;
  compareOFF = (int)(((float)impulseMiliSec / 1000) / (1 / (float)CLOCK_FREQ) - 1);
  
  // timer 1 setup
  TCCR1A = 0;
  TCCR1B = 0;
  OCR1A = compareON;
  OCR1B = compareOFF;
  TCCR1B |= _BV(CS10); // clock ON
  TCCR1B |= _BV(CS11); // prescale 64
  TCCR1B |= _BV(WGM12); // mode: ctc
  TIMSK1 |= _BV(OCIE1A); // enable interrupt
  TIMSK1 |= _BV(OCIE1B); // enable interrupt
  interrupts();
}


// impulse ON
ISR(TIMER1_COMPA_vect) {
  // metronome BPM flash
  if(loopCount == 0) digitalWrite(LED_BUILTIN, HIGH);
  else digitalWrite(LED_BUILTIN, LOW);

  // play sequence
  if(track1[loopCount] != ' ') digitalWrite(12, HIGH);
  if(track2[loopCount] != ' ') digitalWrite(11, HIGH);
  if(track3[loopCount] != ' ') digitalWrite(10, HIGH);
  if(track4[loopCount] != ' ') digitalWrite(9, HIGH);

  // ticks gear
  if(loopCount == 31) loopCount = 0;
  else loopCount++;
}

// impulse OFF
ISR(TIMER1_COMPB_vect) {
  digitalWrite(12, LOW);
  digitalWrite(11, LOW);
  digitalWrite(10, LOW);
  digitalWrite(9, LOW);
}


// status infos
void loop() {
  Serial.println(bpm);
  Serial.println(compareON);
  Serial.println(compareOFF);
  Serial.println("---------");
  delay(1000);
}