MIDI Library- serielle Schnittstelle wählen

Hallo,

ich würde gerne diese MIDI Library nutzen, weiss aber nicht wie ich für die MIDI-Übertragung eine andere serielle Schnittstelle einstellen kann:

http://arduinomidilib.fortyseveneffects.com/index.html

Es geht mir lediglich um den Empfang von MIDI-Daten. Maybe someone can help.. :drooling_face:

Gruß Chris

PS: Mein bisheriger Code:

/******************************************************************************************************************/
/**************************************************  MIDI to Floppy  **********************************************/
/******************************************************************************************************************/

// Konvertiert eingehende MIDI-Befehle in Laufwerksgeräusche passender Tonhöhe um (mono).

#include <MIDI.h>

void setup()
{
  MIDI.begin(MIDI_CHANNEL_OMNI);       // MIDI_Empfang auf sämtlichen Kanälen starten
  
  MIDI.setHandleNoteOn(input_NoteOn);  // Dafür sorgen, dass bei eingehenden NoteOn_Befehlen etwas passiert
  MIDI.setHandleNoteOff(input_NoteOff);  // Dafür sorgen, dass bei eingehenden NoteOff_Befehlen etwas passiert
}

void loop()
{
    MIDI.read();  // Sobald ein MIDI_Befehl ankommt, wird dieser automatisch an die entspr. Funktion weitergeleitet
}

void input_NoteOn(byte channel, byte pitch, byte velocity)
{
  // channel  = MIDI_Kanal
  // pitch    = Tonhöhe
  // velocity = Anschlagstärke
  
  // Hier eintragen, was bei einem NoteOn_Befehl passieren soll
  
  if (velocity == 0)
  {
      // This acts like a NoteOff.
  }
}

void input_NoteOff(byte channel, byte pitch, byte velocity)
{
  // channel  = MIDI_Kanal
  // pitch    = Tonhöhe
  // velocity = Anschlagstärke
  
  // Hier eintragen, was bei einem NoteOff_Befehl passieren soll
}

Warum willst Du den Port ändern?

Weil ich befürchte unter Verwendung des ersten seriellen Anschlusses eines Arduino Megas nicht anständig debuggen zu können. Außerdem möchte ich beim Hochladen von Sketchen keine Leitungen abziehen müssen. Reicht das?

Gruß Chris

Hmm, nachvollziehbar, besonders das Debugging leuchtet mir ein. Upload sollte aber unkritisch sein.

So wie ich das sehe wird der serielle Port so gesetzt:
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, midiA); (Siehe Example MIDI_Dualmerger).

Daraus folgernd wird per Serial1 die zweite Schnittstelle verwendet.

Reicht das?

Ich bin mir nicht ganz sicher.

In diesem Beispiel werden serielle Schnittstellen verwendet, die auf Software Serial basieren. Ich jedoch möchte aber die am Arduino Mega physikalisch vorhandenen Schnittstellen verwenden. Leider gibt es hierfür jedoch kein Beispiel.

Gruß Chris

Das Beispiel verwendet Hardware- wie Softwareserial. Give it a try!

Ok.. dann habe ich mich wohl geirrt. Werde es mir noch einmal genauer anschauen.

Dank Dir für den Hinweis. :wink:

Gruß Chris

Wenn's funktioniert darfst Du mein 3. Karma sein :smiley:

Ich werde es nicht vergessen, muss jedoch jetzt erstmal einen Optokoppler und ne MIDI-Buchse kaufen gehen. XD

Gruß Chris

PS: Hier der geänderte Code (Arduino Mega 2560):

/******************************************************************************************************************/
/**************************************************  MIDI to Floppy  **********************************************/
/******************************************************************************************************************/

// Konvertiert eingehende MIDI-Befehle in Laufwerksgeräusche passender Tonhöhe um (mono).

#include <MIDI.h>

/**************************************************  Debugging  */

#define DEBUG  // Schaltet das Debugging ein oder aus (durch auskommentieren)

#ifdef DEBUG
#define debug_print(x) Serial.print(x)
#define debug_println(x) Serial.println(x)
#define debug_begin(x) Serial.begin(x)
#else
#define debug_print(x)
#define debug_println(x) 
#define debug_begin(x)
#endif

MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI_serial2);

const byte LED_13 =  13;

byte NoteON_count = 0;                    // Zählt die Anzahl der gleichzeitig gedrückten Tasten

void setup()
{
  debug_begin(9600);

  MIDI_serial2.begin(MIDI_CHANNEL_OMNI);  // MIDI_Empfang auf sämtlichen Kanälen starten (Serial 2)

  MIDI.setHandleNoteOn(rx_NoteOn);        // Dafür sorgen, dass bei eingehenden NoteOn_Befehlen etwas passiert
  MIDI.setHandleNoteOff(rx_NoteOff);      // Dafür sorgen, dass bei eingehenden NoteOff_Befehlen etwas passiert

  pinMode(LED_13, OUTPUT);
}

void loop()
{
  MIDI_serial2.read();  // Sobald ein MIDI_Befehl ankommt, wird dieser automatisch an die entspr. Funktion weitergeleitet
}

void rx_NoteOn(byte channel, byte pitch, byte velocity)  // NoteOn_Befehl erhalten
{
  debug_println("Note on");
  NoteON_count++;

  digitalWrite(LED_13, HIGH);  // Kontroll_LED
  PWM_output(1, pitch);        // Sorgt für die Erzeugung des PWM_Signals mit passender Tonhöhe
}

void rx_NoteOff(byte channel, byte pitch, byte velocity)  // NoteOff_Befehl erhalten
{
  debug_println("Note off");
  NoteON_count--;

  if(!NoteON_count)             // Ton nur dann ausschalten, wenn keine Taste mehr gedrückt gehalten wird
  {
    debug_println("Alle Tasten wurden losgelassen.");
    digitalWrite(LED_13, LOW);  // Kontroll_LED
    PWM_output(0, pitch);       // Stoppt die Ausgabe des PWM_Signals
  }
}

void PWM_output(boolean sound_on, byte pitch)  // PWM_Ausgabe
{
  
}

Na, funktioniert's mit der Schnittstellenauswahl?

Hallo,

hab bei mir tatsächlich noch einen Optokoppler gefunden. Leider bekomme ich den MIDI-Eingang trotzdem nicht an den Start.

Weiss nicht wirklich, wo ich da beim Eingrenzen des Fehlers ansetzen soll. Habe mich an diesem Schaltplan orientiert:

http://forum.arduino.cc/index.php?action=profile;u=47257;sa=showPosts

Bisher habe ich lediglich getestet, ob aus meinem MIDI-Keyboard tatsächlich MIDI-Befehle kommen. Dies ist der Fall.

Optokoppler: 4N35

Anbei zwei Bilder des Versuchsaufbaus.. vielleicht steh ich einfach nur mal wieder auf dem Schlauch. :~

Gruß Chris

Edit: Hab das Bild diode.jpg noch einmal hochgeladen, da ein Fehler drin war. Die beiden gelben Kabelenden zwischen denen nun ein schwarzes X ist, sind nicht miteinander verbunden. Sorry.

diode.jpg

So- mittlerweile kommen die MIDI-Daten am Arduino an und werden auch korrekt interpretiert.

Was nun aber nach wie vor nicht hinbekommen habe ist die Initialisierung der MIDI-Schnittstelle an einem anderen seriellen Anschluss als an dem, an dem dummerweise auch die USB-Schnittstelle hängt.

Anbei zwei Codes. Beide Codes funktionieren mit der Standardschnittstelle.

Meine Frage lautet nun folgendermaßen:

Wie muss ich im zweiten Code an der mit Ausrufezeichen markierten Stelle serial benennen, damit ich ausschließlich die zweite serielle Schnittstelle für die MIDI-Kommunikation verwenden kann?

#include <MIDI.h>

#define LED 13   		    // LED pin on Arduino Uno
unsigned long ontime;
// This function will be automatically called when a NoteOn is received.
// It must be a void-returning function with the correct parameters,
// see documentation here: 
// http://arduinomidilib.sourceforge.net/class_m_i_d_i___class.html

MIDI_CREATE_INSTANCE(HardwareSerial, Serial, midiA); 

void HandleNoteOn(byte channel, byte pitch, byte velocity)
{
    // Do whatever you want when you receive a Note On.
    digitalWrite(LED,HIGH);
    ontime = millis();
    if (velocity == 0)
    {
        // This acts like a NoteOff.
    }
    
    // Try to keep your callbacks short (no delays ect) 
    // otherwise it would slow down the loop() and have a bad impact 
    // on real-time performance.
}

// -----------------------------------------------------------------------------

void setup()
{
    // Initiate MIDI communications, listen to all channels
    midiA.begin(MIDI_CHANNEL_OMNI);    
  
    // Connect the HandleNoteOn function to the library, 
    // so it is called upon reception of a NoteOn.
    midiA.setHandleNoteOn(HandleNoteOn);  // Put only the name of the function

    pinMode(LED, OUTPUT);
}


void loop()
{
    // Call MIDI.read the fastest you can for real-time performance.
    midiA.read();
  
    // There is no need to check if there are messages incoming 
    // if they are bound to a Callback function.
    // The attached method will be called automatically 
    // when the corresponding message has been received.
    if(millis() >= ontime + 100) digitalWrite(LED,LOW);
}
#include <MIDI.h>

#define LED 13   		    // LED pin on Arduino Uno
unsigned long ontime;
// This function will be automatically called when a NoteOn is received.
// It must be a void-returning function with the correct parameters,
// see documentation here: 
// http://arduinomidilib.sourceforge.net/class_m_i_d_i___class.html




                                                     //  !!!!!!
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, midiA); //  !!!!!!
                                                     //  !!!!!!



void HandleNoteOn(byte channel, byte pitch, byte velocity)
{
    // Do whatever you want when you receive a Note On.
    digitalWrite(LED,HIGH);
    ontime = millis();
    if (velocity == 0)
    {
        // This acts like a NoteOff.
    }
    
    // Try to keep your callbacks short (no delays ect) 
    // otherwise it would slow down the loop() and have a bad impact 
    // on real-time performance.
}

// -----------------------------------------------------------------------------

void setup()
{
    // Initiate MIDI communications, listen to all channels
    midiA.begin(MIDI_CHANNEL_OMNI);    
  
    // Connect the HandleNoteOn function to the library, 
    // so it is called upon reception of a NoteOn.
    midiA.setHandleNoteOn(HandleNoteOn);  // Put only the name of the function

    pinMode(LED, OUTPUT);
}


void loop()
{
    // Call MIDI.read the fastest you can for real-time performance.
    midiA.read();
  
    // There is no need to check if there are messages incoming 
    // if they are bound to a Callback function.
    // The attached method will be called automatically 
    // when the corresponding message has been received.
    if(millis() >= ontime + 100) digitalWrite(LED,LOW);
}

Gruß Chris

Ich probier das am WE mal mit meinem Mega.

Cool, danke.

Wie soll man da anständig debuggen, wenn ständig was dazwischenfunkt?

Gruß Chris

Hallo,

ich hatte gerade erst dasselbe Problem. Habe dann die serielle Schnittstelle in MIDI.h von "Serial" zu "Serial1" geändert:

#define USE_SERIAL_PORT         Serial1      // Change the number (to Serial1 for example) if you want

Ich bin allerdings absoluter Arduino Anfänger, daher habe ich keine Ahnung, ob der von Klaus vorgeschlagene Weg auch funktionieren müsste.

Grüße
Peter

Hey, danke.

Hast Du das wirklich innerhalb von MIDI.h geändert (kann die Stelle nicht finden), oder hast Du diese Zeile in Deinen Sketch geschrieben?

Gruß Chris

Chris72622:
Hey, danke.

Hast Du das wirklich innerhalb von MIDI.h geändert (kann die Stelle nicht finden), oder hast Du diese Zeile in Deinen Sketch geschrieben?

Gruß Chris

Innerhalb von MIDI.h. Das steht ziemlich am Anfang.

Grüße
Peter

Ich kann das bei mir nicht finden! :astonished:

/*!
 *  @file       MIDI.h
 *  Project     Arduino MIDI Library
 *  @brief      MIDI Library for the Arduino
 *  @version    4.0
 *  @author     Francois Best
 *  @date       24/02/11
 *  license     GPL Forty Seven Effects - 2011
 */

#pragma once

#include "midi_Settings.h"
#include "midi_Defs.h"

#ifdef FSE_AVR
#include <ak47.h>
#endif

// -----------------------------------------------------------------------------

BEGIN_MIDI_NAMESPACE

/*! \brief The main class for MIDI handling.
It is templated over the type of serial port to provide abstraction from
the hardware interface, meaning you can use HardwareSerial, SoftwareSerial
or ak47's Uart classes. The only requirement is that the class implements
the begin, read, write and available methods.
 */
template<class SerialPort>
class MidiInterface
{
public:
    MidiInterface(SerialPort& inSerial);
    ~MidiInterface();

public:
    void begin(Channel inChannel = 1);

    // -------------------------------------------------------------------------
    // MIDI Output

#if MIDI_BUILD_OUTPUT

public:
    inline void sendNoteOn(DataByte inNoteNumber,
                           DataByte inVelocity,
                           Channel inChannel);

    inline void sendNoteOff(DataByte inNoteNumber,
                            DataByte inVelocity,
                            Channel inChannel);

    inline void sendProgramChange(DataByte inProgramNumber,
                                  Channel inChannel);

    inline void sendControlChange(DataByte inControlNumber,
                                  DataByte inControlValue,
                                  Channel inChannel);

    inline void sendPitchBend(int inPitchValue,    Channel inChannel);
    inline void sendPitchBend(double inPitchValue, Channel inChannel);

    inline void sendPolyPressure(DataByte inNoteNumber,
                                 DataByte inPressure,
                                 Channel inChannel);

    inline void sendAfterTouch(DataByte inPressure,
                               Channel inChannel);

    inline void sendSysEx(unsigned inLength,
                          const byte* inArray,
                          bool inArrayContainsBoundaries = false);

    inline void sendTimeCodeQuarterFrame(DataByte inTypeNibble,
                                         DataByte inValuesNibble);
    inline void sendTimeCodeQuarterFrame(DataByte inData);

    inline void sendSongPosition(unsigned inBeats);
    inline void sendSongSelect(DataByte inSongNumber);
    inline void sendTuneRequest();
    inline void sendRealTime(MidiType inType);

public:
    void send(MidiType inType,
              DataByte inData1,
              DataByte inData2,
              Channel inChannel);

private:
    inline StatusByte getStatus(MidiType inType,
                                Channel inChannel) const;

#endif // MIDI_BUILD_OUTPUT

    // -------------------------------------------------------------------------
    // MIDI Input

#if MIDI_BUILD_INPUT

public:
    bool read();
    bool read(Channel inChannel);

public:
    inline MidiType getType() const;
    inline Channel  getChannel() const;
    inline DataByte getData1() const;
    inline DataByte getData2() const;
    inline const byte* getSysExArray() const;
    inline unsigned getSysExArrayLength() const;
    inline bool check() const;

public:
    inline Channel getInputChannel() const;
    inline void setInputChannel(Channel inChannel);

public:
    static inline MidiType getTypeFromStatusByte(byte inStatus);
	static inline bool isChannelMessage(MidiType inType);

private:
    bool inputFilter(Channel inChannel);
    bool parse();
    void resetInput();

private:
    StatusByte  mRunningStatus_RX;
    Channel     mInputChannel;
    byte        mPendingMessage[3];
    unsigned    mPendingMessageExpectedLenght;
    unsigned    mPendingMessageIndex;
    Message     mMessage;

    // -------------------------------------------------------------------------
    // Input Callbacks

#if MIDI_USE_CALLBACKS

public:
    inline void setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity));
    inline void setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity));
    inline void setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure));
    inline void setHandleControlChange(void (*fptr)(byte channel, byte number, byte value));
    inline void setHandleProgramChange(void (*fptr)(byte channel, byte number));
    inline void setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure));
    inline void setHandlePitchBend(void (*fptr)(byte channel, int bend));
    inline void setHandleSystemExclusive(void (*fptr)(byte * array, byte size));
    inline void setHandleTimeCodeQuarterFrame(void (*fptr)(byte data));
    inline void setHandleSongPosition(void (*fptr)(unsigned beats));
    inline void setHandleSongSelect(void (*fptr)(byte songnumber));
    inline void setHandleTuneRequest(void (*fptr)(void));
    inline void setHandleClock(void (*fptr)(void));
    inline void setHandleStart(void (*fptr)(void));
    inline void setHandleContinue(void (*fptr)(void));
    inline void setHandleStop(void (*fptr)(void));
    inline void setHandleActiveSensing(void (*fptr)(void));
    inline void setHandleSystemReset(void (*fptr)(void));

    inline void disconnectCallbackFromType(MidiType inType);

private:
    void launchCallback();

    void (*mNoteOffCallback)(byte channel, byte note, byte velocity);
    void (*mNoteOnCallback)(byte channel, byte note, byte velocity);
    void (*mAfterTouchPolyCallback)(byte channel, byte note, byte velocity);
    void (*mControlChangeCallback)(byte channel, byte, byte);
    void (*mProgramChangeCallback)(byte channel, byte);
    void (*mAfterTouchChannelCallback)(byte channel, byte);
    void (*mPitchBendCallback)(byte channel, int);
    void (*mSystemExclusiveCallback)(byte * array, byte size);
    void (*mTimeCodeQuarterFrameCallback)(byte data);
    void (*mSongPositionCallback)(unsigned beats);
    void (*mSongSelectCallback)(byte songnumber);
    void (*mTuneRequestCallback)(void);
    void (*mClockCallback)(void);
    void (*mStartCallback)(void);
    void (*mContinueCallback)(void);
    void (*mStopCallback)(void);
    void (*mActiveSensingCallback)(void);
    void (*mSystemResetCallback)(void);

#endif // MIDI_USE_CALLBACKS
#endif // MIDI_BUILD_INPUT

    // -------------------------------------------------------------------------
    // MIDI Soft Thru

#if MIDI_BUILD_THRU

public:
    inline MidiFilterMode getFilterMode() const;
    inline bool getThruState() const;

    inline void turnThruOn(MidiFilterMode inThruFilterMode = Full);
    inline void turnThruOff();
    inline void setThruFilterMode(MidiFilterMode inThruFilterMode);


private:
    void thruFilter(byte inChannel);

private:
    bool            mThruActivated  : 1;
    MidiFilterMode  mThruFilterMode : 7;

#endif // MIDI_BUILD_THRU


#if MIDI_USE_RUNNING_STATUS
private:
    StatusByte mRunningStatus_TX;
#endif

private:
    SerialPort& mSerial;
};

// -----------------------------------------------------------------------------

unsigned encodeSysEx(const byte* inData,  byte* outSysEx, unsigned inLenght);
unsigned decodeSysEx(const byte* inSysEx, byte* outData,  unsigned inLenght);

END_MIDI_NAMESPACE

// -----------------------------------------------------------------------------

#if MIDI_AUTO_INSTANCIATE && defined(ARDUINO)
    extern MIDI_NAMESPACE::MidiInterface<MIDI_DEFAULT_SERIAL_CLASS> MIDI;
#endif

// -----------------------------------------------------------------------------

#include "MIDI.hpp"

Sorry, ich sehe gerade, dass ich Version 3.2 habe, du aber 4.0.