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

Das ständige Senden liegt einfach daran, das Du innerhalb von loop() ein
Code:
  static int lastmaxVal = 0;
stehen hast. Damit wird bei jedem Durchlauf von loop die Variable neu erzeugt und auf 0 gesetzt.
Damit ist das "  if(maxVal != lastmaxVal)" aber immer erfüllt und es wird jedesmal gesendet.
Wenn Du das noch aus der Loop rausnimmst, sollte es passen.
Mario.
Logged

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

Er sendet nicht ständig, sondern nur, wenn sich das Signal um THRESHOLD verändernd hat smiley-wink
Logged

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

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?
mit Serial.println(maxVal); schickst Du ja auch nur irgendwas über die Leitung, was nicht dem MIDI-Protokoll entspricht.
Bei mir sieht das dann so aus:
+10.037 - Error: got nonsense MIDI data: 35300d0a
+10.047 - Error: got nonsense MIDI data: 35310d0a
+10.057 - Error: got nonsense MIDI data: 35320d0a
+10.067 - Error: got nonsense MIDI data: 35330d
+10.069 - Error: got nonsense MIDI data: 0a
usw. Also das musst Du rauskommentieren, das kannst Du zum debuggen in der IDE nehmen, aber für Live musst Du es löschen/auskommentieren.
Die °A °B und sonstige seltsame Symbole kommen von den drei Zeilen in denen Du die MIDI-Nachricht schickst.

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?
Nur wenn Du Hardware hast, die dir MIDI zu USB umsetzt und Du z.B. ein MIDI-Shield für den Arduino hast.


Die Variable 'divisor', welche Du mit der Funktion 'knobFunction' übergibst, wird überhaupt nicht verwendet, dann kannst Du sie auch komplett rauswerfen. (kostet nur unnötig Speicher)

Code:
int output = analogRead(pin)/4;
hier wird durch 4 und
Code:
return output/2;
hier noch mal durch 2 dividiert - eine Division reicht smiley-wink
Code:
int output = analogRead(pin)/8;
...
return output;
Multiplikationen und Divisionen sind für Mikrokontroller sehr aufwendig, deshalb solltest Du eine entfernen, dann wird der Code flotter (und 10 Bytes kürzer).
Logged

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

Er sendet nicht ständig, sondern nur, wenn sich das Signal um THRESHOLD verändernd hat smiley-wink
Stimmt, das liegt aber daran, das die Funktion knobFunction den gleichen Fehler macht und das Array "prefRead" immer wieder neu definiert und damit wenn der Wert sich nicht ändert eine "0" zurückliefert. Damit ist aber im loop die Bedingung wieder erfüllt. Wieder ein falscher Fehler :-)
Der Code ist alles andere als optimal, das macht es unheimlich schwierig Bugs von echten Fehlern zu unterscheiden ...
Logged

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

Stimmt, das liegt aber daran, das die Funktion knobFunction den gleichen Fehler macht und das Array "prefRead" immer wieder neu definiert und damit wenn der Wert sich nicht ändert eine "0" zurückliefert. Damit ist aber im loop die Bedingung wieder erfüllt. Wieder ein falscher Fehler :-)
Der Code ist alles andere als optimal, das macht es unheimlich schwierig Bugs von echten Fehlern zu unterscheiden ...
Nein, die Variablen sind ja als "static" definiert:
Variables declared as static will only be created and initialized the first time a function is called.

edit: Ich finde den Code aber auch verwirrend.
« Last Edit: March 22, 2012, 07:59:14 am by mime » Logged

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

Okay danke für die Verbesserungen und Tips. Habe das jetzt auch verändert mit der division und dem Serial.print.

Wenn ich jetzt mehrere Potis anschießen will also im Eingang 0, 1, 2, 3 usw. wie muss ich das im code einbinden bzw. ansteuern?

Grüße
Ak-Nak47
Logged

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

Als erstes möchte ich Dir vorschlagen vernünftige Namen zu vergeben, also nicht so etwas wie poti1, poti2 .... in ein paar Wochen weisst Du sonst u.U. selbst nicht mehr was was ist. Also vielleicht so etwas wie lautPoti...oder was immer Dir einleuchtend erscheint.

Du kannst den Pin jedesmal in die Befehle schreiben:
meinWert = analogRead(A0);

Oder, was bei größeren Programmen besser ist, auf eine Variable legen. Das hat den großen Vorteil, daß Du, wenn Du die Hardware änderst, nicht den ganzen Code abklappern musst um A0 in Irgendetwas zu ändern, sondern nur diese eine Variable ändern musst.

Beispiel:
Code:
/* Variablen */
int volume, int balance;

/* Pinbelegung */
const int volumePot = A0;
const int balancePot = A1;
// u.s.w.
void setup() {
  ....
}
void loop(){
....
}

Oder meintest Du, wie die Funktion 'knobFunction' mit mehreren Potis funktioniert?
Logged

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

ja ich meinte wie ich diese funktion die ich jetzt auf den einen poti habe auch für mehrere angeschlossene potis benutze kann, wo genau binde ich die potis im code ein?
Logged

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

Das ist in der Funktion schon eingebaut. Du übergibst ihr den Pin an dem das Poti hängt.

static int prevRead[6] = {0, 0, 0, 0, 0, 0};
In dieser Zeile wird ein Array 'prevRead' erzeugt, darin speichert die Funktion sechs Werte für die sechs analogen Eingänge. Also 'prevRead[0]' ist dann der Wert von A0 u.s.w..
int output = analogRead(pin)/8;
Hier wird der Eingang 'pin' ausgelesen, 'pin' ist die Variable, die Du der Funktion übergeben musst. Das sieht man auch an der Zeile:
int knobFunction(const int pin)
In der Klammer steht der Parameter der übergeben wird.

Code:
/* Variablen */
int volume, lastVolume, balance, lastBalance;
int threshold = 2;

/* Pinbelegung */
int volumePot = A0;
int balancePot = A1;

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

void loop(){
/* Read and send volume */
  volume = knobFunction(volumePot);
  if(volume != lastVolume) {
    lastVolume = volume;
    //Serial.print("volume: ");
    //Serial.println(volume);
    Serial.write(186);
    Serial.write(7);
    Serial.write(volume);
  }
/* Read and send balance */
  balance = knobFunction(balancePot);
  if(balance != lastBalance) {
    lastBalance = balance;
    //Serial.print("balance: ");
    //Serial.println(balance);
    // irgend etwas tun
  }
}

int knobFunction(const int pin)
{
  static int prevRead[6] = {0, 0, 0, 0, 0, 0};   
  int output = analogRead(pin)/8;    
  if (abs(output - prevRead[0])  >= threshold)
    {prevRead[pin] = output;}
  else
    {output = prevRead[pin];}
  return output;
}
Logged

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

Balance fällt auch wieder unter 'control change'.
Kanal ist nun auch eine Variable (die habe ich wieder auf Byte gesetzt um RAM zu sparen), somit kannst Du den Kanal einfach ändern. Wenn Du einen Taster hast, dann z.B. mit dem.

Code:
/* Variablen */
byte volume, lastVolume, balance, lastBalance;
byte channel = 1;     // Hier Kanal festlegen (1 bis 16)
int threshold = 2;

/* Pinbelegung */
const int volumePot = A0;   // Poti für die Lautstärke
const int balancePot = A1;  // Poti für die Balance

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

void loop(){
/* Lies und sende Lautstärke */
  volume = knobFunction(volumePot);
  if(volume != lastVolume) {
    lastVolume = volume;
    //Serial.print("volume: ");
    //Serial.println(volume);
    Serial.write(175 + channel);  // Sende 'control change' auf Kanal 'channel'
    Serial.write(7);              // ändere Lautstärke auf...
    Serial.write(volume);         // den Wert der Variablen 'volume'
  }
/* Lies und sende Balance */
  balance = knobFunction(balancePot);
  if(balance != lastBalance) {
    lastBalance = balance;
    //Serial.print("balance: ");
    //Serial.println(balance);     
    Serial.write(175 + channel);  // Sende 'control change' auf Kanal 'channel'
    Serial.write(8);              // ändere Balance auf...
    Serial.write(balance);        // den Wert der Variablen 'balance'
   }
}

/* Funktionen */
int knobFunction(const int pin)
{
  static int prevRead[6] = {0, 0, 0, 0, 0, 0};   
  int output = analogRead(pin)/8;    
  if (abs(output - prevRead[0])  >= threshold)
    {prevRead[pin] = output;}
  else
    {output = prevRead[pin];}
  return output;
}

Das ist ein bißchen schizophren, Variablen & Co englisch und Kommentare deutsch  smiley-roll
Logged

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

Okay also verstehen tu ich das was du gepostet hast auf jeden Fall. Komisch irgendwie leuchtet das jetzt besser ein als vorher. Klasse. Danke.

Jetzt habe ich auf dem Arduino ja nur 6 analoge Eingänge, jetzt habe ich die Möglichkeit des "Multiplexen" i wie fern muss ich hier jetzt verfahren. Angenommen ich würde gerne 16 Potis verwenden? Muss ich dazu im Code das Multiplexen berücksichtigen? Ich gehe mal davon aus das ich das muss.

Logged

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

Angenommen ich würde gerne 16 Potis verwenden? Muss ich dazu im Code das Multiplexen berücksichtigen? Ich gehe mal davon aus das ich das muss.

Ja sicher, Du kannst nicht erwarten das die Hardware wie von Zauberhand von alleine funktioniert.
Hier ist ein Beispiel wie man 16 Potis demultiplexen kann, also genau das, was Du machen willst:
http://bildr.org/2011/02/cd74hc4067-arduino/

Der Chip kostet 84 Cent, ist also nicht wirklich teuer.
Logged

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

Ja eigentlich das was ich will, muss nur gucken wie viele digitale ich noch frei habe. das könnte sehr sehr eng werden. :-) Nicht schlecht.

Woher kannst du diesen ganzen Stuff? Hast du das gelernt oder hast du beruflich damit zu tun?
Logged

Germany
Online Online
Edison Member
*
Karma: 47
Posts: 2320
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ja eigentlich das was ich will, muss nur gucken wie viele digitale ich noch frei habe. das könnte sehr sehr eng werden. :-) Nicht schlecht.

Naja, 4 digitale Ausgänge sind ja auch nicht die Welt. Was soll denn noch aufgebaut werden, dass du solch einen Verschleiß an Pins hast? smiley-wink
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

Das will ich noch nicht verraten, es ist noch ein langer weg bis dorthin. vieles haben wir testen können aber wir sind noch a m entwicken, aber ich werde es hier natürlich posten, keine frage. Im CAD System habe ich alles designt jetzt sollte ich mich langsam ans doing machen aber mir fehlt da ausreichend zeit (leider).
Logged

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