Pages: 1 [2] 3 4 5   Go Down
Author Topic: Poti an analogen Pin als MIDI ausgeben  (Read 5580 times)
0 Members and 1 Guest are viewing this topic.
Germany
Offline Offline
Edison Member
*
Karma: 46
Posts: 2310
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Als Nichtmusiker knn ich dir nur empfehlen, dich strikt an das MIDI-Protokoll zu halten:
http://de.wikipedia.org/wiki/Musical_Instrument_Digital_Interface
Dort sollte alles erklärt sein, bei der Umsetzung auf dem Arduino hilft man dir natürlich weiterhin gern.
« Last Edit: March 20, 2012, 04:23:47 pm by sth77 » Logged

Mein Arduino-Blog: http://www.sth77.de/ - letzte Einträge: Teensy 3.0 - Teensyduino unter Window 7 - Teensyduino unter Windows 8

Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Also ich glaube mit dem Code funktioniert mein Vorhaben nicht so wie ich mir das dachte. Also ich weiss jetzt nicht ob ich mit dem was ich jetzt vorschlage richtig liege.

Also ich will den Poti benutzen um im Abelton Fader regeln zu können z.B. von Lautstärke 0 - 100. Oder einen Effektpegel regulieren. Diesen Poti will ich i Abelton frei zuweisen können.

Müsste ich dazu nicht den Wert des Potis auslesen und diesen Wert sozusagen wieder al Midi Signal über USB ans Abelton senden?

Im Grunde sind die Codes von dir mim schon der richtige Ansatz aber wenn ich den Code richtig verstehe schickt er "nur" einen Ton ans Abelton, diesen Ton kann ich dann mittels Poti verändern. Oder?

Jedoch sollte ich doch mit dem vom Analogen Pin ausgelesenen Wert (vom Poti) nehmen und als Midi Signal so weiter geben?

Ist dieser Ansatz / Gedanke richtig?
Logged

WW
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Also ich glaube mit dem Code funktioniert mein Vorhaben nicht so wie ich mir das dachte.
Das sind auch nur zwei Beispiele wie man ein Poti abfragt und eine MIDI-Nachricht senden kann.

Müsste ich dazu nicht den Wert des Potis auslesen und diesen Wert sozusagen wieder al Midi Signal über USB ans Abelton senden?
Richtig
Im Grunde sind die Codes von dir mim schon der richtige Ansatz aber wenn ich den Code richtig verstehe schickt er "nur" einen Ton ans Abelton, diesen Ton kann ich dann mittels Poti verändern. Oder?
Richtig
Jedoch sollte ich doch mit dem vom Analogen Pin ausgelesenen Wert (vom Poti) nehmen und als Midi Signal so weiter geben?
Ist dieser Ansatz / Gedanke richtig?
Ja, ist er.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich werd das mal soooooo zusammenbasteln wie ich meine das es hinhauen könnte. :-) IIch würde mich freuen wenn du da dann drüber schauen könntest.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
const int analogInPin = A0; 

int sensorValue = 0;       
int outputValue = 0;

void setup() {
  Serial.begin(38400);
}

void loop() {
  // auslesen des Wertes aus de Analogen Eingan
  sensorValue = analogRead(INPUT);
  outputValue = map(sensorValue, 0, 1023, 0, 255);
  analogWrite(analogInPin, outputValue);
 
  Serial.write(outputValue);
 
  delay(10);
 
}

Habe mich jetzt an den vorgegebenen Examples aus der Arduino Software und den Beispielen hier etwas zusammengeschustert. Bin mir noch nicht im klaren darüber was ich gemacht habe, aber kann man den Ansatz als "geht in die richtige Richtung" bezeichnen oder eher als "total daneben" ?

Viele Grüße
Logged

WW
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Habe mich jetzt an den vorgegebenen Examples aus der Arduino Software und den Beispielen hier etwas zusammengeschustert.
Zusammengeschustert ist das richtige Wort dafür.
Bin mir noch nicht im klaren darüber was ich gemacht habe,
Das sieht man, wenn Du Dir nicht die Mühe machst die Sprache zu lernen und die Funktion der einzelnen Befehle zu lernen, wirst Du nicht weit kommen. Du hast ein Beispiel mit einer LED benutzt, dessen Helligkeit über einen Sensor (Poti) geregelt wird, richtig?
Die Helligkeit einer LED hat aber nun so gar nichts mit dem MIDI-Protokoll zu tun.

Du kannst nicht irgend etwas senden und erwarten das Ableton Live das als MIDI versteht, wenn Du Dich nicht an das MIDI-Protokoll hältst. Das habe ich Dir weiter oben schon verlinkt.
Im Grunde ist es recht einfach:
Eine MIDI-Nachricht besteht aus ein bis drei Bytes.
Beispiele für ein Byte lange Kommandos sind z.B.
clock = 248
start = 250
stop = 252
Beispiele für drei Byte lange Kommandos hatten wir ja schon, z.B. 'note on' und 'note off'.
Nehmen wir als Beispiel 'note on':
Im ersten Byte wird der Befehl 'note on' und der Kanal, für den dies gilt, gesendet:
'note on' ist als 1001 definiert (diese vier Bit heissen im MIDI-Jargon 'first nibble' oder 'most-significant nibble'), jetzt hängen wir noch vier Bit für den Kanal dran ('least-significant  nibble'). Nehmen wir Kanal 11, da wir bei Null mit dem Zählen beginnen, müssen wir tatsächlich 10 und nicht 11 verwenden. 10 in binärer Schreibweise ist 1010. Damit erhalten wir (binär) für das Kommando 'note on' auf Kanal 11: 10011010 (dezimal 154).

Das zweite Byte in diesem Kommando ist die Note. MIDI kennt 128 Noten (0 - 127); das der Kammerton A die MIDI Notennummer 69 hat wissen wir ja schon.

Das dritte Byte ist 'velocity', der Anschlag. Dieser kann Werte von 0-127 annehmen. Da wir richtig in die (eine) Taste hauen wollen, nehmen wir 127.

Somit haben wir jetzt die drei Bytes für das komplette Kommando "Note A3 auf Kanal 11 mit vollem Anschlag AN":
154 69 127
In Arduino wäre das dann:
Code:
Serial.write(154);
Serial.write(69);
Serial.write(127);

Und genauso wird für alle anderen Befehle, wie 'polyphonic aftertouch', 'control change', 'pitch wheel change', und wie sie alle heissen, verfahren.
Die Lautstärke z.B. versteckt sich hinter 'control change' ('first nibble' 1011). "Ändere etwas auf Kanal 11" wäre also 1011 + 1010 = 10111010 (dezimal 186) [Achtung, das ist natürlich keine Addition.]
Was ändere ich? Da schaue ich wieder bei midi.org und sehe: 'channel volume' ist definiert als 00000111 (dezimal 7). Worauf ändere ich die Lautstärke? Auf das, was der Arduino vom Poti einliest (mögliche Werte wieder 0-127).
Code:
Serial.write(186);              // control change auf Kanal 11
Serial.write(7);                // Ändere die Lautstärke...
Serial.write(meinWertVomPoti);  // ... auf meinWertVomPoti

Auf midi.org steht das alles in Binär, Hexadezimal und Dezimal; damit brauchst Du Dich also noch nicht einmal groß rumschlagen, nachlesen reicht. Ich wollte es, wegen dem grundsätzlichen Verständnis, aber einmal erklären.
Eigentlich ist das MIDI-Protokoll total simpel. Wenn Dir das, auf diese Art, zu kompliziert ist, würde ich Dir die Verwendung der MIDI-Bibliothek empfehlen, diese hat mkl0815 freundlicherweise bereits verlinkt.
Da vereinfacht sich die Sache zu 'sendControlChange (byte ControlNumber, byte ControlValue, byte Channel)'.
Für obiges Beispiel also
Code:
sendControlChange(7, meinWertVomPoti, 11);
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In Deinem Programm stecken, unabhängig von der MIDI-Kommunikation noch diverse Fehler. Ich bezweifle das Du das Programm überhaupt ohne Fehler compilieren kannst.
Hast Du das mal probiert? Am besten lernt man immer noch, wenn man versucht die Fehler selbst zu finden und zu beheben. Erst wenn man damit nicht weiter kommt, sollte man fragen.
Zu Deinem Programm:
Code:
  // auslesen des Wertes aus de Analogen Eingang
  sensorValue = analogRead(INPUT);
Was ist INPUT, das ist nirgendwo definiert. Hier sollte sicher "analogInPin" stehen.
Code:
 
analogWrite(analogInPin, outputValue);
Warum willst Du nochmal einen Wert auf dem Eingangspin ausgeben?  Das macht keinen Sinn. Abgesehen davon ist "analogWrite()" eine Funktion die nur für PWM-Pins Sinn macht, da Du damit das Tast-Verhältnis des PWM-Signals setzen kannst.
 
Der Rest ist erstmal syntaktisch korrekt, an der Semantik musst Du aber definitiv noch arbeiten.
Wenn Du es geschafft hast, die korrekten MIDI-Daten an Deinen Rechner zu senden, solltest Du das sicher nicht alle 10ms machen, sondern nur dann, wenn sich der Wert auch geändert hat. Ziel sollte es immer sein nur so viele Daten zu übertragen, wie nötig, nicht so viele wie möglich.
Logged

Germany
Offline Offline
Edison Member
*
Karma: 46
Posts: 2310
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Wie gesagt, du musst dir überlegen, wie die MIDI-Kommunikation eigentlich funktioniert, zumindest den groben Rahmen. Wenn die Erläuterungen von mime (zumindest halbwegs) verstanden hast, du aber eine leichtere, eingängige Lösung suchst, dann kannst du die bereits verlinkte MIDI-Bibliothek verwenden. Soweit ich das beurteilen kann, lässt diese vom Funktionsumfang keine Wünsche übrig.
Logged

Mein Arduino-Blog: http://www.sth77.de/ - letzte Einträge: Teensy 3.0 - Teensyduino unter Window 7 - Teensyduino unter Windows 8

WW
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In Deinem Programm stecken, unabhängig von der MIDI-Kommunikation noch diverse Fehler. Ich bezweifle das Du das Programm überhaupt ohne Fehler compilieren kannst.

Doch es läßt sich compilieren und es sendet auch Daten an den Computer. Da er sich aber offenbar überhaupt nicht mit dem MIDI-Protokoll beschäftigt hat, sendet sein Programm quer durch allerlei MIDI-Kommandos und Kanäle irgendetwas, manchmal auch für MIDI-Geräte/Programme unverständlichen Kram. Das hat mich auch erstaunt.

14:31:31.105   To MIDI Monitor (Untitled)   Active Sense      
14:31:31.115   To MIDI Monitor (Untitled)   Active Sense      
14:31:31.125   To MIDI Monitor (Untitled)   Stop      
14:31:31.136   To MIDI Monitor (Untitled)   Continue      
14:31:31.145   To MIDI Monitor (Untitled)   Start      
14:31:31.156   To MIDI Monitor (Untitled)   Invalid      1 bytes
14:31:31.167   To MIDI Monitor (Untitled)   Invalid      1 bytes
14:31:31.177   To MIDI Monitor (Untitled)   Clock      
14:31:31.187   To MIDI Monitor (Untitled)   Clock      
14:31:31.197   To MIDI Monitor (Untitled)   Invalid      1 bytes
14:31:31.208   To MIDI Monitor (Untitled)   Clock      
14:31:31.217   To MIDI Monitor (Untitled)   Invalid      1 bytes
14:31:31.228   To MIDI Monitor (Untitled)   Tune Request      
14:31:31.248   To MIDI Monitor (Untitled)   Invalid      1 bytes
14:31:31.270   To MIDI Monitor (Untitled)   Invalid      2 bytes
14:31:31.290   To MIDI Monitor (Untitled)   Invalid      1 bytes
14:31:31.352   To MIDI Monitor (Untitled)   SysEx      1 bytes
14:31:31.659   To MIDI Monitor (Untitled)   Note Off   13   122   0


Soweit ich das beurteilen kann, lässt diese vom Funktionsumfang keine Wünsche übrig.
Man kann Omni wohl nur empfangen, was ihm nicht viel nützen wird, da er ja senden will.
(Omni heisst nichts anderes als "auf allen 16 Kanälen", statt nur auf einem Kanal)
Aber diese kleine Restriktion ließe sich leicht mit einer For-Schleife, die einmal durch alle 16 Kanäle rattert, umgehen.
Mir persönlich ist die "mach es selbst"-Methode lieber, da weiss man was das Programm tatsächlich macht (und was man selbst macht). Aber das ist vielleicht Geschmackssache. So oder so muß man sich mit dem MIDI-Protokoll beschäftigen, wenn ich nicht weiss, was ich tue, hilft mir auch keine library weiter.
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Es Funktioniert durch Zufall, weil INPUT in der Arduino.h der IDE definiert wird. Ansonsten würde es Fehler geben beim Compilieren.
Allerdings mit 0x0, also dem Wert 0.
Es wird also ein analogRead(0) aufgerufen. Das bringt aber nix, denn "A0" ist mit 14 definiert.
Damit wird also nicht das Poti ausgelesen.
Logged

WW
Offline Offline
Jr. Member
**
Karma: 0
Posts: 59
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Frag mich nicht warum es überhaupt geht, wundert mich auch sehr. Aber ich habe es ja ausprobiert, siehe oben, es sendet halt irgendetwas und das Ergebnis ändert sich auch, wenn ich am Poti drehe. Nur halt völlig wahl- und sinnlos. Schon erstaunlich.
Logged

Offline Offline
Edison Member
*
Karma: 21
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

*rofl*  smiley-eek
Code:
int analogRead(uint8_t pin)
{
        uint8_t low, high;

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
        if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#elif defined(__AVR_ATmega32U4__)
        if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#else
        if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif
Das ist aus /hardware/arduino/cores/arduino/wiring_analog.c (IDE Libs)
Es funktioniert, weil für den Arduino der A0 Eingang auf Pin 14 gemappt wird. Da wir einen ATmega328 (bzw.168) haben, gibt es nur digitale 13 Pins und die IDE verwendet Pin14 als ersten Analogen. Daher funktioniert das Programm auch, denn da das INPUT als 0x0 definiert ist und das als Parameter übergeben wird, wird tatsächlich der erste analoge Eingang ausgewertet.
Würde man korrekterweise die 14 (oder A0) übergeben, würde aus dann genau der folgende Code ausgeführt:
Code:
if (pin >= 14) pin -= 14; // allow for channel or pin numbers
Und es würde auch wieder "0" heraus kommen.
Wir haben es also mit einem "falschen Fehler" zu tun.  smiley
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ich seh schon ich will mit dem Kopf durch die Wand.  smiley Doch der Beton ist härter als ich dachte. Das ist halt absolutes Neuland für mich. Hauptberuflich bin ich Konstrukteur i Sondermaschinenbau und das hier soll der ausgleich zu täglichen Mechanik sein.

Ich will euch auf keinen Fall verrückt machen, ich probiere jetzt einfach ma weiter und lass euch meine Ergebnisse hier auf dem Board, wäre nett wenn ihr sie weiter ausdiskutiert.   smiley-eek-blue
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

...scheiße ich muss passen, ich krieg das irgendwie nicht hin. weiss gar net wo ich anfangen soll...! *arghhh*
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Also wieder ein wenig geschuster und es tut auf jedenfall das was es tun sollte im abelton.

Code:
void setup()
{               
Serial.begin(38400);
}

int THRESHOLD=2;
int maxPin;
int knobFunction(const int pin, int divisor)
{
  static int prevRead[6] = {0, 0, 0, 0, 0, 0};   
  int output = analogRead(pin)/4;    
  if (abs(output - prevRead[0])  >= THRESHOLD)
    {prevRead[pin] = output;}
  else
    {output = prevRead[pin];}
  return output/2;
}

void loop () {
  static int lastmaxVal = 0;
  int maxVal = knobFunction(0, 4);
  if(maxVal != lastmaxVal)
  {
    Serial.println(maxVal);
    lastmaxVal = maxVal;
   
Serial.write(186);              // control change auf Kanal 11
Serial.write(7);                // Ändere die Lautstärke...
Serial.write(maxVal);       // ... auf meinWertVomPoti
  }


Jetzt habe ich aber noch 3 Dinge die ich nicht ganz kapiere oder nicht nachvollziehen kann:

1. Senden tut er das Signal nur wenn ich am Poti drehe, das ist so in Ordnung. Im Abelton zeigt er aber ständig ein Empfangs-Signal an. Ich gehe davon aus das liegt daran das das Tool Serial_MIDI_Converter dafür verantwortlich ist. Oder?

2. Im Serialmonitor zeigte vor meiner "schusterei" einen Wert von 0-127 an, so hat er es aber nicht im Abelton erkannt, dann habe ich die Serial.write Befehle eingefügt. Dann hat er im Serialmonitor beim drehen des potis einen "Mischwert" angzeigt z.B.: 87 und eine Zeile darunter ºW (so was ähnliches). Ich gehe davon aus das im Code die Zeile Serial.println(maxVal); dafür verantwortlich ist das er beide Werte anzeigt?

3. Um das Signal ans Abelton zu übergeben benutze ich das Tool Serial_MIDI_Converter, gibt es eine Möglichkeit das ganze auch ohne dieses Tool benutzen zu müssen?

Viele Grüße.
Logged

Pages: 1 [2] 3 4 5   Go Up
Jump to: