Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

Thread: Addressing multiple serial midi outputs through a variable or array?

  1. #1
    Junior Member
    Join Date
    Mar 2019
    Posts
    18

    Addressing multiple serial midi outputs through a variable or array?

    The midi controller that I am building has 5 serial midi outputs on it and will not be using usbmidi. I am having a difficult time finding good examples that show how other people have handled multiple serial midi outputs with regards to assigning them to variables that I can cycle between.

    Currently, my outputs are established as:
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI1);
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI2);
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial3, MIDI3);
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial4, MIDI4);
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial5, MIDI5);

    This works fine for establishing my outputs and I can send commands to them individually but the problem I am trying to figure out is how to address them programmatically through a variable that i could change through an interface control such as a button.

    Ideally assigning them to an array seems like the best option but for the life of me I can not decipher what the proper syntax is to do this with the MIDI.h library. Is there a better way to do it or is anyone familiar with how to handle this?

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,804
    Maybe this is along the needed lines ?

    I posted this on the T4_Beta thread - using the 7 Serial# ports it has - you can see the array I made and then cycle through - courtesy of a further refines sample from KurtE:
    Code:
    #define SPD 2000000
    #define BUFFER_SIZE  320
    char buffer_out[BUFFER_SIZE];
    char buffer[80];
    
    HardwareSerial *psAll[7] = { &Serial1, &Serial2, &Serial3, &Serial4, &Serial5, &Serial6, &Serial7 };
    void setup() {
      pinMode(13, OUTPUT);
      for ( int ii = 0; ii < 7; ii++ ) {
        psAll[ii]->begin(SPD);
      }
      digitalWrite( LED_BUILTIN, 1 );
      while (!Serial && millis() < 2200) digitalWrite( LED_BUILTIN, !digitalRead( LED_BUILTIN) );
      Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
      digitalWrite( LED_BUILTIN, 1 );
      delay(100);
      Serial.print("Test all Serials - Serial @ms=");
      digitalWrite( LED_BUILTIN, !digitalRead( LED_BUILTIN));
      delay(100);
      Serial.println(millis());
      digitalWrite( LED_BUILTIN, !digitalRead( LED_BUILTIN));
      delay(10);
      Serial.printf("Baud rate: %d\n", SPD);
      digitalWrite( LED_BUILTIN, !digitalRead( LED_BUILTIN));
      Serial1.println( "Hello World! #1" );
    }
    
    void serialXfer(HardwareSerial * psIn, HardwareSerial * psOut, bool bWrite, uint32_t ii)
    {
      uint32_t cb = psIn->available();
      if (cb) {
        if (cb > sizeof(buffer)) cb = sizeof(buffer);
        if (cb >  psOut->availableForWrite()) cb = psOut->availableForWrite();
        psIn->readBytes(buffer, cb);
        if ( bWrite ) {
          psOut->print((char)('A' + ii));
          psOut->write(buffer, cb);
        }
      }
    }
    
    uint32_t iiCnt = 0;
    void loop() {
      for ( int ii = 0; ii < 7; ii++ ) {
        serialXfer( psAll[ii], psAll[ii], true, ii );
        Serial.print( buffer );
        delay(10);
      }
      Serial.println( "==============================" );
      delay(2000);
      iiCnt++;
      if ( !(iiCnt % 10) ) {
        for ( int jj = 0; jj < 4; jj++ ) {
          for ( int ii = 0; ii < 7; ii++ ) {
            serialXfer( psAll[ii], psAll[ii], false, ii );
            delay(5);
          }
        }
        Serial1.print( "Hello World!" );
        Serial1.println( iiCnt );
        buffer[0] = 0;
      }
    }

  3. #3
    Junior Member
    Join Date
    Mar 2019
    Posts
    18
    Thank you! This definitely looks promising and solves the problem of how to properly address each output in an array. Iíll have to check out the T4 page and see what thatís all about, it looks a lot more complicated than what Iím probably going to accomplish!

  4. #4
    Senior Member
    Join Date
    Feb 2017
    Posts
    299
    I know nothing of MIDI. But, using standard C++ techniques, you can define your array of MIDI object pointers like this:
    Code:
    #include "Arduino.h"
    #include "Audio.h"
    #include "MIDI.h"
    
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI1);
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI2);
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial3, MIDI3);
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial4, MIDI4);
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial5, MIDI5);
    
    midi::MidiInterface<HardwareSerial> *interfaceArray[] = { &MIDI1, &MIDI1, &MIDI3, &MIDI4, &MIDI5 };
    
    const uint8_t numMidi = sizeof(interfaceArray) / sizeof(interfaceArray[0]);
    
    void setup() {
    	for (uint8_t i = 0; i < numMidi; i++) {
    		interfaceArray[i]->begin();
    	}
    }
    
    void loop() {
    }

  5. #5
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,804
    … the mechanics work - the Array, passing and using the pointers .. - just a trivial and incomplete sample that runs each of 7 serial ports cross wired between two Teensys to send and receive the message across all the ports.

  6. #6
    Senior Member
    Join Date
    Feb 2017
    Posts
    299
    You can also instantiate an array of objects directly:
    Code:
    #include "Arduino.h"
    #include "MIDI.h"
    
    midi::MidiInterface<HardwareSerial> interfaceArray[] = {
    		{ Serial1 }, { Serial2 }, { Serial3 }, { Serial4 }, { Serial5 }
    };
    
    const uint8_t numMidi = sizeof(interfaceArray) / sizeof(interfaceArray[0]);
    
    void setup() {
    	for (uint8_t i = 0; i < numMidi; i++) {
    		interfaceArray[i].begin();
    	}
    }
    
    void loop() {
    }

  7. #7
    Junior Member
    Join Date
    Mar 2019
    Posts
    18
    I owe all you guys a beer! Thank you so much for the suggestions. gfvalvo I had about gave up on trying to figure out how to do exactly that! I've been close to this a couple times but never got it right, I think because I was not understanding what the "::" does.

  8. #8
    Senior Member
    Join Date
    Jan 2013
    Posts
    181
    Quote Originally Posted by massahwahl View Post
    ... I was not understanding what the "::" does.
    That's the scope resolution operator. It is used for Qualified name lookup.

    In this case, the #include of "MIDI.h" declares the namespace named midi. midi::MidiInterface refers to the MidiInterface member of the midi namespace, which happens to be a class template.

  9. #9
    Junior Member
    Join Date
    Mar 2019
    Posts
    18
    Thank you for the explanation, i do coding with VB for my day job and C++ is way different but its coming together the further i get into these more complex topics like this. Much appreciated!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •