TD hanging with Arduino running MIDIUSB library

Hi! I’m experiencing a strange freeze I can’t seem to wrap my head around:

TouchDesigner is controlling an image’s lighting with input from an Arduino Leonardo emulating a MIDI device with three sliders on a Windows 11 PC with a NVIDIA Quadro RTX 3000 with updated drivers. The Arduino code wass sending MIDI values for the sliders and a heartbeat every 30 seconds to confirm that the Arduino is connected. If that heartbeat isn’t heard for 5 minutes, a TimerCHOP will hit done and the program will show an error message for staff to check the connection. I’ve removed that heartbeat function and we’re still seeing the same issue. All of these MIDI events are happening on channel 16 as Control Change Events.

What tends to happen is the program starts up in perform mode, the sliders will be responsive for the first ~10 seconds, but afterwards, they stop working and the whole application hangs/crashes. We’ve had limited success with re-enabling the USB port on startup but haven’t found that to be a consistent fix.

One strange thing we’ve noticed is that if you unplug the Arduino from the PC during this freeze, TouchDesigner will recover and start working again. Then, if you plug the Arduino back in, it’ll re-freeze. Even if the USB port the Arduino is plugged into is disabled, the program is freezing.

To test, we simplified the program to just the input nodes and are still seeing the freeze on startup. What’s especially odd, is that we’re not seeing this freeze happen in a setup on Windows 10, which makes me think there may be some strange Windows 11 config we need to hunt down and change. I’ve attached the Arduino code if that’s helpful at all.

#include "MIDIUSB.h"
#define NUM_SLIDES 3
#define CHANNEL 191 //sends bf = control changed to 16

int controllers[NUM_SLIDES] = {0x0, 0x1, 0x2};  
int channels[NUM_SLIDES] = {0, 1, 2};
int minSlide[NUM_SLIDES] = {25, 25, 25}; //initialized min to account for physical jitter at slider start
int maxSlide[NUM_SLIDES] = {900, 900, 900}; //initialized max to account for physical jitter at slider end

const int slideA = 0;
const int slideB = 1;
const int slideC = 2;

const uint8_t sliders[NUM_SLIDES] = {slideA, slideB, slideC};
uint8_t notesTime[NUM_SLIDES];

int mappedVal;
int analogVal[NUM_SLIDES];
int analogOld[NUM_SLIDES];

int slop = 2;
const int timeoutLength = 30000; //30 second intervals
unsigned long nextTrigger = millis();

void setup() {
   controlChange(CHANNEL, 0x3, 127);
}

void loop() {

  //if(millis() > nextTrigger) {
    //controlChange(CHANNEL, 0x3, 127);
    //nextTrigger = millis() + timeoutLength;
    //MidiUSB.flush(); 
 // }
  readSlides();
  delay(3);
}

void readSlides() {
  
  for (int i = 0; i < NUM_SLIDES; i++) {

    if (minSlide[i] > analogRead(i)) {
      minSlide[i] = analogRead(i);
    }

    if (maxSlide[i] < analogRead(i)) {
      maxSlide[i] = analogRead(i);
    }

    mappedVal = map(analogRead(i), minSlide[i], maxSlide[i], 127, 0);
    analogVal[i] = mappedVal; //flipped due to on-site sliders' orientation
    
    if (abs(analogVal[i] - analogOld[i]) >= slop) {

      controlChange(CHANNEL, controllers[i], analogVal[i]);
      MidiUSB.flush();

      analogOld[i] = analogVal[i];
    }
  }
}

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

I’m having trouble uploading the DMP and simplified .toe to this post so I’ll try in the comments

Here’s the test file Test.4.toe (4.3 KB)

And here’s the DMP Dropbox - TouchDesigner (3).DMP - Simplify your life