Teensy 4.0 and host USB

Tombot7

Active member
Hi! I just bought a 4.0 and this is my first post.

I am trying to get usb host working.

What I did is split a USB cable and attached the green cable to D+ on the backside of the Teensy and the white calbe to D-. Because Teensy can't generate 5 volts, I took ANOTHER USB cable and grabbed the 5 volt and ground from there.

It really looks like crap. But here are pictures. (Hopefully they uploaded ok.)

It uploaded to the board fine and when I turn on the serial monitor it displays this:
"USB Host InputFunctions example"

but nothing else. I am connecting the hosted USB port to a Casio Privia PX-150 (an 88 key keyboard) which is independently powered. The idea of the program should be that any notes I hit are read and displayed on the serial monitor. Nothing is happening though.

I have tested the USB wire I made in the following ways:

I cut open ANOTHER USB wire and plugged it into the hosted-port. I verified that it is receiving 5 volt power and ground. I verified that the there are no closed circuits between the D+ and D- or any of the other wires. I verified that the the circuit does close between the backside of the Teensy at the solder points and the other end of the spliced cable (green and white).

I also plugged in another midi keyboard that is NOT independently powered and it does light up. So the 5 volt power is working. That other keyboard also was not read through the serial montior when I hit notes though.

I read that Teensy 4.0 does not have certain circuit protections for its D+ and D- pins but that that shouldn't matter for independently powered devices.

Maybe the easiest solution is to simply buy a Teensy 3.6 which is set up to have all 5 pin outs for the USB-host (and much easier to get to also as they are through-hole and not pads!). And I might just do that.

I also note that the D+ and D- soldering is VERY close to touching. However, it does NOT read as a closed circuit when I put the multimeter tips on the two solder blobs. Is it possible though that they are touching enough that it's causing a problem? I didn't have thinner solder or a thinner soldering tip so I just did the best I could...

THANK YOU ALL IN ADVANCE. NICE TO BE HERE!

This is the code I'm using:

Code:
/* Receive Incoming USB Host MIDI using functions.  As usbMIDI
   reads incoming messages, handler functions are run.
   See the InputRead example for the non-function alterative.
   This very long example demonstrates all possible handler
   functions.  Most applications need only some of these.
   This example is meant to allow easy copy-and-paste of the
   desired functions.
   Use the Arduino Serial Monitor to view the messages
   as Teensy receives them by USB MIDI
   You must select MIDI from the "Tools > USB Type" menu
   This example code is in the public domain.
*/

#include <USBHost_t36.h>

USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
MIDIDevice midi1(myusb);


void setup() {
  Serial.begin(115200);

  // Wait 1.5 seconds before turning on USB Host.  If connected USB devices
  // use too much power, Teensy at least completes USB enumeration, which
  // makes isolating the power issue easier.
  delay(1500);
  Serial.println("USB Host InputFunctions example");
  delay(10);
  myusb.begin();

  midi1.setHandleNoteOn(myNoteOn);
  midi1.setHandleNoteOff(myNoteOff);
  midi1.setHandleAfterTouchPoly(myAfterTouchPoly);
  midi1.setHandleControlChange(myControlChange);
  midi1.setHandleProgramChange(myProgramChange);
  midi1.setHandleAfterTouchChannel(myAfterTouchChannel);
  midi1.setHandlePitchChange(myPitchChange);
  // Only one of these System Exclusive handlers will actually be
  // used.  See the comments below for the difference between them.
  midi1.setHandleSystemExclusive(mySystemExclusiveChunk);
  midi1.setHandleSystemExclusive(mySystemExclusive); 
  midi1.setHandleTimeCodeQuarterFrame(myTimeCodeQuarterFrame);
  midi1.setHandleSongPosition(mySongPosition);
  midi1.setHandleSongSelect(mySongSelect);
  midi1.setHandleTuneRequest(myTuneRequest);
  midi1.setHandleClock(myClock);
  midi1.setHandleStart(myStart);
  midi1.setHandleContinue(myContinue);
  midi1.setHandleStop(myStop);
  midi1.setHandleActiveSensing(myActiveSensing);
  midi1.setHandleSystemReset(mySystemReset);
  // This generic System Real Time handler is only used if the
  // more specific ones are not set.
  midi1.setHandleRealTimeSystem(myRealTimeSystem);
}

void loop() {
  // The handler functions are called when midi1 reads data.  They
  // will not be called automatically.  You must call midi1.read()
  // regularly from loop() for midi1 to actually read incoming
  // data and run the handler functions as messages arrive.
  myusb.Task();
  midi1.read();
}


void myNoteOn(byte channel, byte note, byte velocity) {
  // When a USB device with multiple virtual cables is used,
  // midi1.getCable() can be used to read which of the virtual
  // MIDI cables received this message.
  Serial.print("Note On, ch=");
  Serial.print(channel, DEC);
  Serial.print(", note=");
  Serial.print(note, DEC);
  Serial.print(", velocity=");
  Serial.println(velocity, DEC);
}

void myNoteOff(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.println(velocity, DEC);
}

void myAfterTouchPoly(byte channel, byte note, byte velocity) {
  Serial.print("AfterTouch Change, ch=");
  Serial.print(channel, DEC);
  Serial.print(", note=");
  Serial.print(note, DEC);
  Serial.print(", velocity=");
  Serial.println(velocity, DEC);
}

void myControlChange(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.println(value, DEC);
}

void myProgramChange(byte channel, byte program) {
  Serial.print("Program Change, ch=");
  Serial.print(channel, DEC);
  Serial.print(", program=");
  Serial.println(program, DEC);
}

void myAfterTouchChannel(byte channel, byte pressure) {
  Serial.print("After Touch, ch=");
  Serial.print(channel, DEC);
  Serial.print(", pressure=");
  Serial.println(pressure, DEC);
}

void myPitchChange(byte channel, int pitch) {
  Serial.print("Pitch Change, ch=");
  Serial.print(channel, DEC);
  Serial.print(", pitch=");
  Serial.println(pitch, DEC);
}


// This 3-input System Exclusive function is more complex, but allows you to
// process very large messages which do not fully fit within the midi1's
// internal buffer.  Large messages are given to you in chunks, with the
// 3rd parameter to tell you which is the last chunk.  This function is
// a Teensy extension, not available in the Arduino MIDI library.
//
void mySystemExclusiveChunk(const byte *data, uint16_t length, bool last) {
  Serial.print("SysEx Message: ");
  printBytes(data, length);
  if (last) {
    Serial.println(" (end)");
  } else {
    Serial.println(" (to be continued)");
  }
}

// This simpler 2-input System Exclusive function can only receive messages
// up to the size of the internal buffer.  Larger messages are truncated, with
// no way to receive the data which did not fit in the buffer.  If both types
// of SysEx functions are set, the 3-input version will be called by midi1.
//
void mySystemExclusive(byte *data, unsigned int length) {
  Serial.print("SysEx Message: ");
  printBytes(data, length);
  Serial.println();
}

void myTimeCodeQuarterFrame(byte data) {
  static char SMPTE[8]={'0','0','0','0','0','0','0','0'};
  static byte fps=0;
  byte index = data >> 4;
  byte number = data & 15;
  if (index == 7) {
    fps = (number >> 1) & 3;
    number = number & 1;
  }
  if (index < 8 || number < 10) {
    SMPTE[index] = number + '0';
    Serial.print("TimeCode: ");  // perhaps only print when index == 7
    Serial.print(SMPTE[7]);
    Serial.print(SMPTE[6]);
    Serial.print(':');
    Serial.print(SMPTE[5]);
    Serial.print(SMPTE[4]);
    Serial.print(':');
    Serial.print(SMPTE[3]);
    Serial.print(SMPTE[2]);
    Serial.print('.');
    Serial.print(SMPTE[1]);  // perhaps add 2 to compensate for MIDI latency?
    Serial.print(SMPTE[0]);
    switch (fps) {
      case 0: Serial.println(" 24 fps"); break;
      case 1: Serial.println(" 25 fps"); break;
      case 2: Serial.println(" 29.97 fps"); break;
      case 3: Serial.println(" 30 fps"); break;
    }
  } else {
    Serial.print("TimeCode: invalid data = ");
    Serial.println(data, HEX);
  }
}

void mySongPosition(uint16_t beats) {
  Serial.print("Song Position, beat=");
  Serial.println(beats);
}

void mySongSelect(byte songNumber) {
  Serial.print("Song Select, song=");
  Serial.println(songNumber, DEC);
}

void myTuneRequest() {
  Serial.println("Tune Request");
}

void myClock() {
  Serial.println("Clock");
}

void myStart() {
  Serial.println("Start");
}

void myContinue() {
  Serial.println("Continue");
}

void myStop() {
  Serial.println("Stop");
}

void myActiveSensing() {
  Serial.println("Actvice Sensing");
}

void mySystemReset() {
  Serial.println("System Reset");
}

void myRealTimeSystem(uint8_t realtimebyte) {
  Serial.print("Real Time Message, code=");
  Serial.println(realtimebyte, HEX);
}



void printBytes(const byte *data, unsigned int size) {
  while (size > 0) {
    byte b = *data++;
    if (b < 16) Serial.print('0');
    Serial.print(b, HEX);
    if (size > 1) Serial.print(' ');
    size = size - 1;
  }
}
 

Attachments

  • unnamed 3.jpg
    unnamed 3.jpg
    77.6 KB · Views: 37
  • unnamed 2.jpg
    unnamed 2.jpg
    133.8 KB · Views: 39
  • unnamed.jpg
    unnamed.jpg
    86.3 KB · Views: 53
Hi all -- immediately after posting this I had the thought that I could test whether D+ and D- where interfering with each other by seeing if there was a resistance reading while touching the two solder globs on the pads.

They are indeed reading as 1.6 million ohms or so -- meaning the solder on the two pads is making a slight electrical contact.

I've got to figure out how to get clean solder on these pads & then I'll report back.

Sorry if I wasted anybody's time!
 
The USB ground wire needs to be connected to Teensy 4.0, close to where the D+ and D- wires connect.

The 1.6M ohms measurement is probably a false alarm. Your multimeter transmits a small test current and measures the resulting voltage to compute ohms. But if the circuit is diode or transistor, the test current pass through it and creates a voltage due to the semiconductor P-N junctions, which your meter falsely interprets as resistance. Your meter can't know whether you have connected a resistor or something else. It just shows a number of what resistor would respond to the test current with the observed voltage.

But even if you did have a 1.6M resistor connected between D+ and D-, that would be very unlikely to have any effect. USB uses much lower impedance, approx 90 ohms during normal use, and approx 1.5K during device detection, and about 15K when unused.
 
Hi Paul -

Before I saw your reply I resoldered the two pad wires and got lucky. They are clearly separate from each other. There is no way they are touching. Now the reading in Ohms between them is 2.6 million ohms. So I appreciate your insight or I might have thought I blew out the board.

As far as grounding the 5 volts to the teensy rather than back to the power-source USB, I'm not sure I understand. I don't have a great understanding of grounding in general (or really the basics of electronics), but wouldn't this mean there isn't a complete circuit with the 5 volts from the USB? Don't they need to go back to ground to compete a circuit - or will any ground do? Also, will grounding those 5 volts to my teensy hurt it? I thought the teensy couldn't handle 5 volts? Or is that not true of its ground?

Thanks for the help!
 
I went ahead and did it anyway despite my not understanding (that is, connected the USB ground to the ground on the teensy. The one near the D+ and D-). It did not work. Previously, data was not working but the host-usb port was supplying 5 volt power.

Now it is no longer supplying 5 volt power and still not working.

:(
 
I went ahead and ordered a Teensy 4.1. I think it's worth the $26 for the extra support for host USB: 1) through pins rather than pads 2) on board 5 volt and 2 grounds (one for shielding) 3) protection circuits for non-powered devices and hot swapping.

It might be a little more board than what I need for this project, but then again maybe not. I'm building a one-octave bass foot pedal that will output 5 pin midi, USB midi to a computer (and be seen as a MIDI device automatically), and also host-midi to synths and things.

Since it's got all this power as a board, I might be able to expand it later if I come up with more ideas I guess...

Anyway - thanks!
 
I figured I'd update this for completion sake -- Teensy 4.1 host worked perfectly. The 1 Oct MIDI foot controller works perfectly. It's hooked up to a Boog and sounds frickin great. It was much easier than I thought it would be and now I'm on to making a Teensy poly synth. I am absolutely blown away by how great the Audio Library is for Teensy. It's handling 16 VERY complicated voices with no problems -- about 20% CPU and no memory wall yet.
 
Back
Top