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

Thread: Teensy used as MIDI receiver

  1. #1
    Junior Member
    Join Date
    Aug 2020
    Posts
    3

    Teensy used as MIDI receiver

    Hello, I'm a new user in this forum.
    Recently I bought a book called "Arduino for musicians. A complete guide to Arduino and Teensy microcontrollers".
    This book introduces the MIDI protocol and explains how to connect a input and output MIDI interface to MCUs.
    I didn't used Teensy 3.2 before (but I frequently use Arduino), however I'm not able to make Teensy work properly as MIDI receiver.

    Firstly I made a MIDI transmitter with an Arduino Uno. This is the code:
    Code:
    #include <MIDI.h>
    
    MIDI_CREATE_DEFAULT_INSTANCE();
    
    const int velocity = 100;
    const int channel = 1;
    
    void setup() {
      MIDI.begin(1); // channel 1 (default)
    }
    
    void loop() {
      for( int i = 50; i < 70; i+=2){
        MIDI.sendNoteOn(i, velocity, channel);
        MIDI.sendNoteOn(i + 4, velocity, channel);
        MIDI.sendNoteOn(i + 8, velocity, channel);
    
        delay(125);
    
        MIDI.sendNoteOff(i, 0, channel);
        MIDI.sendNoteOff(i + 4, 0, channel);
        MIDI.sendNoteOff(i + 8, 0, channel);
        
        delay(125);
      }
    }
    Click image for larger version. 

Name:	MIDI_TX_bb.jpg 
Views:	4 
Size:	89.6 KB 
ID:	21261

    Then I've created a receiver with Teensy 3.2 (in the schematic there is 3.1 because i didn't find 3.2). The code is the same of the book:
    Code:
    void setup() {
      Serial.begin(115200);
      usbMIDI.setHandleNoteOff(OnNoteOff);
      usbMIDI.setHandleNoteOn(OnNoteOn);
      usbMIDI.setHandleVelocityChange(OnVelocityChange);
      usbMIDI.setHandleControlChange(OnControlChange);
      usbMIDI.setHandleProgramChange(OnProgramChange);
      usbMIDI.setHandleAfterTouch(OnAfterTouch);
      /*usbMIDI.setHandlePitchChange(OnPitchChange);*/ //gives errors?
    }
    
    void loop() {
      usbMIDI.read();
    }
    
    void OnNoteOn(byte channel, byte note, byte velocity){
      Serial.print("Note On, ch=");
      Serial.print(channel, DEC);
      Serial.print(", note=");
      Serial.print(note, DEC);
      Serial.print(", velocity=");
      Serial.print(velocity, DEC);
      Serial.println();
    }
    
    void OnNoteOff(byte channel, byte note, byte velocity){
      Serial.print("Note Off, ch=");
      Serial.print(channel, DEC);
      Serial.print(", note=");
      Serial.print(note, DEC);
      Serial.print(", velocity=");
      Serial.print(velocity, DEC);
      Serial.println();
    }
    
    void OnVelocityChange(byte channel, byte note, byte velocity){
      Serial.print("Velocity Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", note=");
      Serial.print(note, DEC);
      Serial.print(", velocity=");
      Serial.print(velocity, DEC);
      Serial.println();
    }
    
    void OnControlChange(byte channel, byte control, byte value){
      Serial.print("Control Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", control=");
      Serial.print(control, DEC);
      Serial.print(", value=");
      Serial.print(value, DEC);
      Serial.println();
    }
    
    void OnProgramChange(byte channel, byte program){
      Serial.print("Program Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", program=");
      Serial.print(program, DEC);
      Serial.println();
    }
    
    void OnAfterTouch(byte channel, byte pressure){
      Serial.print("After Touch, ch=");
      Serial.print(channel, DEC);
      Serial.print(", pressure=");
      Serial.print(pressure, DEC);
      Serial.println();
    }
    // gives errors?
    /*void OnPitchChange(uint8_t channel, uint16_t pitch){
      Serial.print("Pitch Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", pitch=");
      Serial.print(pitch, DEC);
      Serial.println();
    }*/
    Click image for larger version. 

Name:	MIDI_RX_Teensy_bb.jpg 
Views:	3 
Size:	92.4 KB 
ID:	21263

    Here I use the 3.3V instead of 5V for the pin 8 of the 6N138 (maybe it's a problem?).

    When I connect Teensy to the USB port of the PC, I press the Teensy's program mode button, I select the board model from Arduino IDE and I select MIDI as USB Type.
    After that I select hid#vid_16C0&pid_0485 MIDI from Tools->Ports and I compile the code.
    There aren't errors so I open Serial Monitor in order to check what data is receiving but I see nothing..
    Any suggestion?

  2. #2
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    155
    Try:-
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
    Works here on a T3.2.

    void setup() and void() loop show that we are listening to usbMidi not MIDI.

    Hope this helps.

  3. #3
    Junior Member
    Join Date
    Aug 2020
    Posts
    3
    Thank you for your quick reply. If I'm not wrong you are using an instruction that come from this library: https://github.com/FortySevenEffects...o_midi_library
    However, what does (HardwareSerial, Serial1, MIDI) mean?
    Maybe about usbMidi you are right, I'll try to look better at the description of the book.

  4. #4
    Senior Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    155
    Teensyduino's MIDI library is the FortySevenEffects MIDI library with some enhancements. An Arduino UNO only has one serial port called TX RX so when using the MIDI library you instantiate it with:-

    Code:
    MIDI_CREATE_DEFAULT_INSTANCE();
    Which by default uses TX-RX so if you need to use some other serial port like in the pic of your Teensy setup using TX1-RX1.

    Code:
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
    Instantiates the Midi lib and connects it to TX1-RX1. At this point, Teensyduino's Midi lib behaves just like the FortySevenFX lib does on an UNO or whatever.

    In the IDE, File>Examples>Teensy>USB_MIDI>Interface 3x3 is worth a look at as it's using both Din Midi and usbMIDI.

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,470
    Teensy can communicate MIDI in 3 different ways.

    1: Serial MIDI, which uses 5 pin DIN connectors.

    2: USB device MIDI, where Teensy communicates MIDI with your PC in the manner a USB MIDI keyboard or other instrument would.

    3: USB host MIDI (only only Teensy 3.6, 4.0, 4.1), where Teensy communicates with USB MIDI instruments, as your computer would.

    For #1, you can use any of the serial ports on your Teensy. With Teensy 3.2, you have 3 of those ports. That MIDI_CREATE_INSTANCE stuff is the way you tell the MIDI library which of the serial ports you want it to use. You can even use MIDI_CREATE_INSTANCE 3 times to create an instance for each of the serial ports and have all 3 working simultaneously.

    The Tools > USB Type menu choices with MIDI are for case #2. There you use "usbMIDI". The instance name is pre-defined, because you only have 1 main USB port which communicates with your PC.

    In case #3, using the USBHost_t36 library you also create instances, but with a different syntax than #1. When a USB device is plugged into the USB host port on Teensy 3.6 or 4.1, or into any USB hubs you've connected, whatever USB MIDI instrument you connected becomes associated with the first unused instance you created.

    The good news is Teensy provides a lot more MIDI connectivity capability that most other Arduino compatible boards. But the flip side is with the ability to use several serial ports, USB device, and USB host which can connect many devices, specifying exactly which way you want to communicate is more complicated, especially compared to the very simple board which really can only do serial MIDI on a single port.

    Hopefully this lengthy explanation helps you to understand why these instance names are needed. If if you're just using 1 serial MIDI input, the system is designed to be able to support so much more.

  6. #6
    Junior Member
    Join Date
    Aug 2020
    Posts
    3

    Question

    Quote Originally Posted by MatrixRat View Post

    Code:
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
    Instantiates the Midi lib and connects it to TX1-RX1. At this point, Teensyduino's Midi lib behaves just like the FortySevenFX lib does on an UNO or whatever.
    Done! Now I have implemented the code and it works nicely! I want to post the result here at the end of my reply.

    Quote Originally Posted by PaulStoffregen View Post
    Teensy can communicate MIDI in 3 different ways.

    1: Serial MIDI, which uses 5 pin DIN connectors.

    2: USB device MIDI, where Teensy communicates MIDI with your PC in the manner a USB MIDI keyboard or other instrument would.

    3: USB host MIDI (only only Teensy 3.6, 4.0, 4.1), where Teensy communicates with USB MIDI instruments, as your computer would.
    Great explanation, thanks!
    This is giving me an idea. I don't have an audio card so I can't connect MIDI devices directly to my PC in order to use virtual instruments. By this way, if I combine the code for #1 (so Teensy receives MIDI data from the Serial1) and the code for #2 (so Teensy sends MIDI messages through USB to PC), I should be able to use a daw with a MIDI instrument.. Is it possible?


    The code I used to make Teensy receiving is the following:
    Code:
    #include <MIDI.h>
    
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
    
    const byte channel = 1;
    byte note = 0;
    byte velocity = 0;
    
    void setup() {
      MIDI.begin(channel);
      Serial.begin(57600);
      Serial.println("MIDI Input Test");
      pinMode(LED_BUILTIN, OUTPUT);
    }
    
    void loop() {
      if(MIDI.read()){ // look for a message
        switch(MIDI.getType()){ // get message type
          case midi::NoteOn:
            note = MIDI.getData1();
            velocity = MIDI.getData2();
            digitalWrite(LED_BUILTIN, HIGH);
            Serial.println(String("Note On:  ch=") + channel + ", note=" + note + ", velocity=" + velocity);
            break;
          case midi::NoteOff:
            note = MIDI.getData1();
            velocity = MIDI.getData2();
            digitalWrite(LED_BUILTIN, LOW);
            Serial.println(String("Note Off: ch=") + channel + ", note=" + note + ", velocity=" + velocity);
            break;
          default:
            break;
        }
      }
    }
    and the partial result shown in the Serial Monitor is:
    Code:
    Note On:  ch=1, note=50, velocity=100
    
    Note On:  ch=1, note=54, velocity=100
    
    Note On:  ch=1, note=58, velocity=100
    
    Note Off: ch=1, note=50, velocity=0
    
    Note Off: ch=1, note=54, velocity=0
    
    Note Off: ch=1, note=58, velocity=0
    
    Note On:  ch=1, note=52, velocity=100
    
    Note On:  ch=1, note=56, velocity=100
    
    Note On:  ch=1, note=60, velocity=100
    
    Note Off: ch=1, note=52, velocity=0
    
    Note Off: ch=1, note=56, velocity=0
    
    Note Off: ch=1, note=60, velocity=0
    
    Note On:  ch=1, note=54, velocity=100
    
    Note On:  ch=1, note=58, velocity=100
    
    Note On:  ch=1, note=62, velocity=100

Posting Permissions

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