Teensy 3 + Ableton, Analog CC causes midi crash.

Status
Not open for further replies.
Hi!

I'm trying to use my new Teensy 3.0 as a USB MIDI device. It seems to work great for digital inputs, such as the 'Buttons' example.

However I'm hoping to use it mostly for analog inputs, potentiometers and so on. I've tried a number of different approaches to the code, but the most basic is:

Code:
void setup() {
}
void loop() {
   usbMIDI.sendControlChange(1, analogRead(0)>>3, 1);
   delay(10); 
}

I have this set up with a standard potentiometer. When I use this code, or pretty much any other code that uses usbMIDI.sendControlChange(), this works perfectly in Max/MSP. It is stable and I get normal CC readings, all is well.

However, in Ableton Live this does not work properly. It will work for a few moments (maybe up to 30 seconds maximum) before the MIDI input starts to overload (visualised by the orange flashing box in the upper right hand corner of Live) and eventually the Teensy board stops responding and sending MIDI. Resetting the board gets it working again, with the same result.

It's very strange to me that the MIDI sending works perfectly in Max/MSP but not in Ableton!

I have tried a number of approaches - for example, I get the same result even if I use a very high value in the delay() function of the code.

It seems like someone else had a similar problem: http://forum.pjrc.com/threads/24012-Teensy-3-0-USB-MIDI-crashing

Any solutions or ideas?

using Mac OS 10.8.4, Teensy 3.0, Teensyduino 1.15, Arduino 1.0.5, Ableton 9.0.5
 
Last edited:
Maybe Ableton is sending MIDI messages to the Teensy?

This has been a problem for some Windows users with MIDI-OX, where certain common settings cause MIDI-OX to send stuff even though you intended it to only receive from Teensy. USB MIDI has true end-to-end flow control, which is distinctly different from serial MIDI. If the host sends stuff and you don't read it, eventually all the buffers fill up, and, well, the host can't send any more data. How it handles that situation is up to the software. Since you're getting an orange flashing box, maybe that's what Ableton is trying to warn you about?

Try running this:

Code:
void setup() {
}
void loop() {
   usbMIDI.sendControlChange(1, analogRead(0)>>3, 1);
   delay(10); 
   while (usbMIDI.read()) ; // read and discard any incoming MIDI messages
}

Of course, this is just a guess. Please let me know if this was it, or if I ought to try guessing something else?
 
Hi Paul, thanks for the quick response.

It looks like that has solved the MIDI crashing in Live, thanks so much!

Ableton still occasionally flashes the orange "midi overload" box, but it is no longer shutting down all the teensy midi activity. that's brilliant.

I'm pretty sure I can fix that midi overloading stuff with some clever coding.

Thanks again Paul, I'm excited to get this up and running.
 
Maybe I ought to update the Buttons example with that usbMIDI.read() line and a comment...

That would probably be useful!

It might also be useful to include a separate example dedicated to usbMIDI.sendControlChange(), just like the one you posted to help me. I think a lot of people want to make USB MIDI devices with potentiometers and other analog inputs, it might be helpful to them (as it was to me!).
 
It might also be useful to include a separate example dedicated to usbMIDI.sendControlChange(), just like the one you posted to help me. I think a lot of people want to make USB MIDI devices with potentiometers and other analog inputs, it might be helpful to them (as it was to me!).

How's this look? If you could give this a quick try with real MIDI equipment or software, I'd really appreciate a little feedback or just a confirmation it really works with real stuff?
 

Attachments

  • AnalogControlChange.ino
    1.7 KB · Views: 648
The way that the code samples at 50Hz rather than "as fast as possible" will be helpful guidance (and may solve the original poster's issue with "midi overload").
The code seems to assume that the analogRead resolution is 10. For Teensy 3.0 it might be better to set it explicitly (and explain how to get higher resolutions).
 
I disagree with the general approach.
Analogue signals are noisy and variable by nature, the solution to the problem of data flooding (with suspect data) is NOT to sample less often, but to filter more intelligently.
I suggest/recommend;
a) Filter for changes greater than 1 in the least significant bit (to ignore changes due to rounding and "noise").
According to how this is done it doesn't necessarily lead to loss of precision.
b) Filter for reasonable speed of change, in this case the human foot can move only so fast, i.e. it just can't move at inches per microsecond.
c) Filter for LARGE changes in recent averages.

This is basic data validation, i.e. don't process invalid input and expect valid output - - doing that less often is NOT a solution.

DECADES ago we heard of multi million dollar paychecks due to "computer bugs" - pay a thousand hours at a thousand dollars an hour will cause that.
10.00 per hour without the decimal multiplied by 40.00 hours without the decimal = $4,000,000
Credibility check; there are only 168 hours in a week, anyone making $1K per hour would not be in a weekly payroll group.
 
Last edited:
A smart filter example would be helpful for touchRead() as well.

They are almost certainly context sensitive, i.e. dependent on what can be expected in "bounce" and "settling' times, though I would use a similar approach.

I'm kinda new here in this forum, but I have been around A to D and the difficulties of processing their "data" for a very long time.
I would expect there to be existing code examples along the lines of what I outlined above.
If I find some I will post links.

Don't expect me to write code below the level of pseudo code (yet), I have very little Arduino specific knowledge/experience.
 
I've had great success with this approach. Rather than comparing an analog value to a previous analog value, it completely ignores all but every 8th analog value, calculates a MIDI value only for those analog values and compares it to the previously sent MIDI message. Also, it doesn't require any kind of timer or delay.
Code:
#include <MIDI.h>

const int channel = 1;
int analogValue = 0;
int previousMIDI = 0;
int newMIDI = 0;

void setup(){ 
  MIDI.begin();
}

void loop(){
  analogValue = analogRead(A0);
  if (analogValue % 8 == 0 && analogValue / 8 != previousMIDI){
    newMIDI = analogValue / 8;
    usbMIDI.sendControlChange(20, newMIDI, channel);
    previousMIDI = newMIDI;
  }
}
 
Last edited:
This has been a problem for some Windows users with MIDI-OX, where certain common settings cause MIDI-OX to send stuff even though you intended it to only receive from Teensy. USB MIDI has true end-to-end flow control, which is distinctly different from serial MIDI. If the host sends stuff and you don't read it, eventually all the buffers fill up, and, well, the host can't send any more data. How it handles that situation is up to the software.

Hi Paul,
Using teensy 3.2 on linux connecting my midi controller to pure data works very well, but I want to also send control out to teensy. When doing so (control out for example) teensy stop sending midi to pure data. I am controlling what I am sending to teensy (control change or note) I am not sending a lot of midi. Any idea on how to fix that?
 
Status
Not open for further replies.
Back
Top