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 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); }
> 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. Das liegt an der verwendeten Tonerzeugung - hier wird ein MIDI-Musikinstrument angesteuert, das die Töne erzeugt. Das ist auch für den unsauberen Klang verantwortlich Und hiermit noteOn(0x90, note, out1); delay(100); noteOn(0x90, note, 0); delay(100); sagst Du Deinem Instrument, daß es einen Ton mit Laustärke out1 erzeugen soll, wartest eine fest vorgegebene Zeit und schaltest dann die Tonausgabe ab (mit Lautstärke 0). Das kann sich dann auch nur so anhören, wie das von Dir beschriebene Tut-Tut-Tut. Du solltest das Note-Off erst dann senden, wenn es eine Veränderung des Tones in Lautstärke oder Tonhöhe gibt. Eine fließende Tonhöhenveränderung, wie sie zum Theremin passt, ließe sich mit einem pitch bender erzeugen - wie der anzusteuern ist, ist dem MIDI-Programmierhandbuch Deines Musikinstrumentes zu entnehmen.
Kann das vielleicht auch an der Bautrate liegen? Ich will etwas ähnliches bauen und sende im Moment als Versuch immer nur eine Note im Intervall von 2000ms. Diese werden von TxD über eine Midi Buchse über ein Midikabel direkt zu meinen Midieingang in der Soundkarte übertragen. Dabei kommen auch nicht immer alle übertragenen Noten an. Manchmal nur jede 5te aber mnchmal auch die 2te nicht variiert sehr. Weiß jemand ob man mit einem Ardu in 31250 Baud senden kann? Weil in dem Seriellen Monitor in der Ardu Software kann man diese Baudrate auch nicht einstellen. Ist scheinbar keine Standardrate?! Oder wird nicht von der Seriellenschnittstelle unterstützt? (Vermutung nur!) Grüße Daniel
daniel d. wrote:
> Weiß jemand ob man mit einem Ardu in 31250 Baud senden kann?
Ja, das geht. Die Arduino Boards haben ein 16MHz oder 8MHz Quarz und
damit sind 31250 Baud ohne Fehler möglich.
Wie sieht denn deine genaue Beschaltung aus?
Hat sich erledigt. Es lag nicht an der Baudrate, sondern an den gesendeten Noten, denn die waren einfach zu kurz. Aber trotzdem danke! Die Midi-Schaltung, für die die es vielleicht interessiert, ist von midi.org. -> http://www.midi.org/techspecs/electrispec.php Grüße
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.