Pages: [1]   Go Down
Author Topic: Arduino Theremin  (Read 1404 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
ich bin Julia und suche Leute, die mir bei meiner Programmierung behilflich sein können.
Ich möchte mit dem Arduino ein Theremin bauen und habe dazu zwei Infrarotabstand-Sensoren benutzt.
Der eine Sensor, soll für die Tonhöhe verantwortlich sein, der andere soll die Lautsärke variieren.
Ich habe versucht die Signale im Programm in Midisignale zu verarbeiten. Diese, gehen über einen Midikonverter an meinen Computer, wo sie in ein Synthesizerprogramm geladen werden, wo man alle möglichen Instrumente einstellen kann.
Ich habe mich bei der Programmierung an folgendes Programm gehalten, dass ich auf der Arduino-homepage gefunden habe:

Allow a Person to Play Notes

The previous example will just play notes, no interactivity. The example below uses an analog input to set the pitch, and a digital input (a switch) to start and stop the note:

// The switch is on Arduino pin 10:
#define switchPin 10
// Middle C (MIDI note value 60) is the lowest note we'll play:
#define middleC 60
//  Indicator LED:
#define LEDpin 13

// Variables:
char note = 0;            // The MIDI note value to be played
int AnalogValue = 0;           // value from the analog input
int lastNotePlayed = 0;   // note turned on when you press the switch
int lastSwitchState = 0;  // state of the switch during previous time through the main loop
int currentSwitchState = 0;

void setup() {
  //  set the states of the I/O pins:
  pinMode(switchPin, INPUT);
  pinMode(LEDpin, OUTPUT);
  //  Set MIDI baud rate:
  Serial.begin(31250);
  blink(3);
}

void loop() {
  //  My potentiometer gave a range from 0 to 1023:
  AnalogValue = analogRead(0);
  //  convert to a range from 0 to 127:
  note = AnalogValue/8;
  currentSwitchState = digitalRead(switchPin);
  // Check to see that the switch is pressed:
  if (currentSwitchState == 1) {
    //  check to see that the switch wasn't pressed last time
    //  through the main loop:
    if (lastSwitchState == 0) {
      // set the note value based on the analog value, plus a couple octaves:
     // note = note + 60;
      // start a note playing:
      noteOn(0x90, note, 0x40);
      // save the note we played, so we can turn it off:
      lastNotePlayed = note;
      digitalWrite(LEDpin, HIGH);
    }
  }
    else {   // if the switch is not pressed:
    //  but the switch was pressed last time through the main loop:
    if (lastSwitchState == 1) {
      //  stop the last note played:
      noteOn(0x90, lastNotePlayed, 0x00);
      digitalWrite(LEDpin, LOW);
    }
}

  //  save the state of the switch for next time
  //  through the main loop:
  lastSwitchState = currentSwitchState;
}

//  plays a MIDI note.  Doesn't check to see that
//  cmd is greater than 127, or that data values are  less than 127:
void noteOn(char cmd, char data1, char data2) {
  Serial.print(cmd, BYTE);
  Serial.print(data1, BYTE);
  Serial.print(data2, BYTE);
}

// Blinks an LED 3 times
void blink(int howManyTimes) {
  int i;
  for (i=0; i< howManyTimes; i++) {
    digitalWrite(LEDpin, HIGH);
    delay(100);
    digitalWrite(LEDpin, LOW);
    delay(100);
  }
}

Play Notes

Once you're connected, sending MIDI is just a matter of sending the appropriate bytes. The bytes have to be sent as binary values, but you can format them in your code as decimal or hexadecimal values. The example below uses hexadecimal format for any fixed values, and a variable for changing values. All values are sent serially as raw binary values, using the BYTE modifier to Serial.print() (Many MIDI tables give the command values in hex, so this was done in hex for the sake of convenience):

// Variables:
char note = 0;            // The MIDI note value to be played

void setup() {
  //  Set MIDI baud rate:
  Serial.begin(31250);
}

void loop() {
  // play notes from F#-0 (30) to F#-5 (90):
  for (note = 30; note < 90; note ++) {
    //Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
    noteOn(0x90, note, 0x45);
    delay(100);
    //Note on channel 1 (0x90), some note value (note), silent velocity (0x00):
    noteOn(0x90, note, 0x00);  
    delay(100);
  }
}

//  plays a MIDI note.  Doesn't check to see that
//  cmd is greater than 127, or that data values are  less than 127:
void noteOn(char cmd, char data1, char data2) {
  Serial.print(cmd, BYTE);
  Serial.print(data1, BYTE);
  Serial.print(data2, BYTE);
}


Leider habe ich nicht das gewünschte Ergebnis erzielt. Es lassen sich nur fünf Töne spielen, die auch nicht besonders sauber klingen; außerdem hätte ich gerne einen durchgehenden Ton, habe aber stattdessen ein sich ständig wiederholendes Tuten. Quasi ein Tut tut tut anstatt eines Tuuuuuuut.
Ich habe schon viele Varianten ausprobiert und an dem Programm rum gefummelt, da ich aber blutige Anfängerin bin, bin ich bereits an meine Grenzen gestoßen und hoffe, dass sich jemand die Zeit nimmt und schaut, was ich vielleicht falsch gemacht habe.
Ich danke euch von Herzen im Voraus.
Liebe Grüße
Julia


// The switch is on Arduino pin 10:
int note = 0;           //Tonhöhe
int sensorPin2 = 2; //Tonsensor auf Pin2
int digiData2 = 2;
int sensorPin3 = 1; //Lautstaerkesensor auf Pin1
int digiData3 = 3;
int out1 = 0;          //Lautstärke
int x = 0;              //zählvariable
int count = 0;
int digiZ = 20; //Zähler, wie wiele Werte aufsummieren
int digiT = 0; // Index für Anzahl der Werte
int digiAll = 0;  //Summe der Werte
int digiAll2 = 0;
int digiT1 = 0;
int values[] = {0,1,2,3,4,5,6,7};
int lou[]= {0x00,0x20,0x30,0x40,0x50,0x70,0x80,0x90};
int notes[] = {0,20,30,40,50,70,80,90};
  
void setup() {
Serial.begin(31250);
//Serial.begin(9600);
}

void loop() {
  for(x = 0 ; x <= 5; x+=1)
  {
    do
    {
      digiData2 = analogRead(sensorPin2);
      digiAll= digiAll + digiData2;
      digiT++;
    } while(digiT<digiZ);
    digiData2 = digiAll/digiZ/80;
    digiT = 0;
    digiAll = 0;
    for(count=0; count<=5; count++) {
      if (values[count] == digiData2) {
        note = notes[count];
      }
    }      
    
    }
 
  for(x = 0 ; x <= 10; x+=1)
  {
    do
    {
      digiData3 = analogRead(sensorPin3); // Werte vom Sensor einlesen
      digiAll2= digiAll2 + digiData3; //Aufsummieren der Sensorwerte in der variablen digiAll2
      digiT1++; // Zähler hochsetzen, wie viele werte aufsummiert wurden
    } while(digiT1<digiZ); //Schauen ob Anzahl der AUfsummierten Werte schon die geplante Anzahl digiZ ist
    digiData3 = digiAll2/digiZ/80;
    digiT1 = 0; //Nullsetzen der Zählervariablen
    digiAll2 = 0; //Nullsetzen der Summenvariablen
    //digiData3 = digiData3/150;
    for(count=0; count<=5; count ++) {
      if (values[count] == digiData3) { // Auslesen des Lautstärkewertes aus der Liste lou passend zum ermittelten digiData3-Wert
        out1 = lou[count];
      }
    }
 }

  noteOn(0x90, note, out1);
  delay(100);
  noteOn(0x90, note, 0);
  delay(100);
}
 
void noteOn(char cmd, int data1, int data2) {
 Serial.print(cmd, BYTE);  
 Serial.print(data1, BYTE);
 Serial.print(data2, BYTE);
  
//Serial.print(digiData2);
//Serial.println("  ");
// Serial.println(digiData21);
 //Serial.println( "        ");
//Serial.print(digiData3);
 //Serial.print("  ");
 //Serial.println(out1);
}
Logged

"The old Europe"
Offline Offline
Edison Member
*
Karma: 1
Posts: 2005
Bootloaders suck!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,

ich bin mein MIDI experte, aber mir scheint, dass du hier

Code:
  noteOn(0x90, note, 0x45);
   delay(100);
   //Note on channel 1 (0x90), some note value (note), silent velocity (0x00):
   noteOn(0x90, note, 0x00);  
   delay(100);

in der tonleiter den ton nach 100ms wieder abschaltest. Das wuerde das tut,tut,tut erklaeren. Vielleicht unterstuetzt MIDI auch so etwas wie decay bei noten ?

Edit:

Auf wikipedia gibts info ueber die MIDI befehle. Unter anderem auch so etwas wie key-release.

http://de.wikipedia.org/wiki/Musical_Instrument_Digital_Interface#MIDI-Protokoll
« Last Edit: February 04, 2009, 11:26:46 am by madworm » Logged

• Upload doesn't work? Do a loop-back test.
• There's absolutely NO excuse for not having an ISP!
• Your AVR needs a brain surgery? Use the online FUSE calculator.
My projects: RGB LED matrix, RGB LED ring, various ATtiny gadgets...
• Microsoft is not the answer. It is the question, and the answer is NO!

Pages: [1]   Go Up
Jump to: