Teensy used as MIDI receiver

Status
Not open for further replies.

Filo96

New member
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);
  }
}

MIDI_TX_bb.jpg

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();
}*/

MIDI_RX_Teensy_bb.jpg

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?
 
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.
 
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.
 
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.
 
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.

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
 
Status
Not open for further replies.
Back
Top