Teensy Midi Disconnect and Reconnect Problems on Windows

Status
Not open for further replies.

321lupo

Active member
hey everybody!
i have already received great help here many times so let me try it once more.
i have built five usb-midi controllers on teensy basis which I use to run a ableton live set on windows 10.
four instrument controllers are connected to a usb hub, which is 5volt external powered connected to one of the two usb ports of my laptop,
the remaining one, a us midi footpedal is connected to a second usb hub (also 5v powered) to which my external audio card is connected aswell, running into the second usb port of the laptop.

now, all the controllers function perfectly, however, every once in a while the midi footpedal disconnects (the others do too, but only rarely)
and since windows does not automatically reconnect i have to pull the usb cable out of the hub, stick it in again and windows recognizes the device once again. this is of course a problem in live shows since i cannot be running to the hub the whole time to reconnect the devices.

so, basically i need to make sure that the device reconnects or is reconnected automatically if it disconnects.

i havent found any teensy solutions that apply to me for this online or on this forum, but checked this windows based solution
(http://digital.ni.com/public.nsf/allkb/1D120A90884C25AF862573A700602459)
during which the whole usb port is disabled and reenabled. unfortunately, this is not a possible solution for me since that would disconnect all devices attached to that one port; in the case of the foot pedal the soundcard, too. so, a windows usb port solution wont work for me,
i need each teensy to make sure the connection is reestablished. (also the port isnt the problem, since other hub-connected devices continue to work even if one falls out.)

is there a way for teensy to automatically power down and power up again if it loses connection with ableton, or windows?
so far im only sending midi, and im able to read midi clock messages, so maybe something along the lines "if no midi clock is received disconnect and reconnect usb.." how would i do that in code?

as always, i appreciate any advice!
 
Try reducing the speed you're sending the midi data to the PC.
I find that if I seriously hammer the windows serial ports they jam and become unresponsive
 
Try reducing the speed you're sending the midi data to the PC.
I find that if I seriously hammer the windows serial ports they jam and become unresponsive

hey! thanks for the suggestion! i do not think this is really the problem though since all other devices continue to function perfectly (4 devices on one port, one device plus external soundcard on the other). additionally, the footpedal is the one device that sends the least data, i have the other devices running on a 20hz and no problem...
 
Code:
                                    //LCD & SHIELD Libraries
  #include <Wire.h>
  #include <Adafruit_MCP23017.h>
  #include <Adafruit_RGBLCDShield.h>
  Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
  #include <usb_keyboard.h>
                              // LCD backlight color
  #define RED 0x1
  #define YELLOW 0x3
  #define GREEN 0x2
  #define TEAL 0x6
  #define BLUE 0x4
  #define VIOLET 0x5
  #define WHITE 0x7
                              //Pushbuttons Debounce Library
  #include <Bounce.h>
                              //Midi Library
  #include <MIDI.h>
  const int MIDI_CHAN = 5;
  
  #define BUTTONBANK 6         //bankswitch button
  #define BUTTONSTOP 11        //stop button (not part of bank)
  #define BUTTONPLAY 23        //play (not part of bank)
  #define CTRLBUTTONS_N 12     //ctrl buttons used to trigger clips
  #define NUM_BANKS 2
  #define CTRL_DEL
  #define CTRL_STOP 72        //begin of control values available to footpedal (71-128)
  #define CTRL_PLAY 71
  #define CTRL_START 73       //start of ctrl values for buttons (number up in forloop)
  #define BOUNCE_T 50         //bounce time in ms
  int ctrlval[CTRLBUTTONS_N];  //control message bank, just to make sure that two buttons simultaneously clicked still get their momentary message sent
  int bank = 0;

  int buttonPins[] = {2,3,4,5,/*6,*/7,8,9,10,/*11,*/12,20,21,22,/*23*/};  //All button pins except bank, stop and play button
  // int buttons[CTRLBUTTONS_N];

  Bounce buttonBank = Bounce(BUTTONBANK, BOUNCE_T);                  
  Bounce buttonStop = Bounce(BUTTONSTOP, BOUNCE_T);
  Bounce buttonPlay = Bounce (BUTTONPLAY, BOUNCE_T);
  
  Bounce buttons[12] = {
    Bounce (buttonPins[0], BOUNCE_T), 
    Bounce (buttonPins[1], BOUNCE_T), 
    Bounce (buttonPins[2], BOUNCE_T), 
    Bounce (buttonPins[3], BOUNCE_T),
    Bounce (buttonPins[4], BOUNCE_T),
    Bounce (buttonPins[5], BOUNCE_T),
    Bounce (buttonPins[6], BOUNCE_T),
    Bounce (buttonPins[7], BOUNCE_T),
    Bounce (buttonPins[8], BOUNCE_T),
    Bounce (buttonPins[9], BOUNCE_T),
    Bounce (buttonPins[10], BOUNCE_T),
    Bounce (buttonPins[11], BOUNCE_T)
  };
  
  int bankadd = 0;

  unsigned long millisTime;                     //millis del-keystroke variables
  unsigned long delTime[CTRLBUTTONS_N];         //for now without arrays...         
  bool delBool[CTRLBUTTONS_N];
  int delHold = 2000;                           //time to hold down buttons to send del-msg
  unsigned long redoTime;
  bool redoBool;
  int redoHold = 2000;

  
void setup(){  
                             
  Serial.begin(9600);
  
  pinMode (BUTTONBANK, INPUT_PULLUP);
  pinMode (BUTTONSTOP, INPUT_PULLUP);
  pinMode (BUTTONPLAY, INPUT_PULLUP);
  
//  for(int i=0; i<CTRLBUTTONS_N; i++){                    //PULLUP FORLOOP
//    pinMode (buttonPins[i], INPUT_PULLUP);
//  }  
  
  pinMode(buttonPins[0], INPUT_PULLUP);
  pinMode(buttonPins[1], INPUT_PULLUP);
  pinMode(buttonPins[2], INPUT_PULLUP);
  pinMode(buttonPins[3], INPUT_PULLUP);
  pinMode(buttonPins[4], INPUT_PULLUP);
  pinMode(buttonPins[5], INPUT_PULLUP);
  pinMode(buttonPins[6], INPUT_PULLUP);
  pinMode(buttonPins[7], INPUT_PULLUP);
  pinMode(buttonPins[8], INPUT_PULLUP);
  pinMode(buttonPins[9], INPUT_PULLUP);
  pinMode(buttonPins[10], INPUT_PULLUP);
  pinMode(buttonPins[11], INPUT_PULLUP);
                          
  lcd.begin(16, 2);                         //LCD START
 
  lcd.clear();            
  lcd.setCursor(0, 0);
  lcd.print("START");
 
  Serial.println("serial start"); 

  for(int i=0; i<CTRLBUTTONS_N; i++){             //reset all del and redo Variables
    delTime[i]=0;
    delBool[i]=false;
  }
  redoTime=0;
  redoBool=false;
  
}

void loop(){

  millisTime = millis();                  //time var running WHATS THE MAX MILLIS VALUE?
  
  while (usbMIDI.read());   

  readButtons();

  if(buttonBank.fallingEdge()) {     //3 banks, Button+/-, Print LCD and Serial 
    bank++;
    bank %= NUM_BANKS;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Bank ");
    lcd.print(bank);
    Serial.print("Bank ");
    Serial.println(bank);
    redoTime=millisTime;
    redoBool=true;
  }
  if (buttonBank.risingEdge()) {
      redoBool=false;
    }
  if (millisTime-redoTime>=redoHold && redoBool==true) {
      redoBool=false;
      Serial.println ("Redo ");
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Redo ");
      Keyboard.set_modifier(MODIFIERKEY_CTRL);
      Keyboard.set_key1(KEY_Z);
      Keyboard.send_now();
      Keyboard.set_modifier(0);
      Keyboard.set_key1(0);
      Keyboard.send_now();
      bank=bank-1;
    }

  bankadd = bank * CTRLBUTTONS_N;     //ATTENTION THAT HE READS 12 HERE


  if (buttonStop.fallingEdge()) {
    usbMIDI.sendControlChange((CTRL_STOP), 127, MIDI_CHAN);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Stop ");
    Serial.println(String("ch=") + MIDI_CHAN + (", Control=") + (CTRL_STOP) + ("Velocity=127"));
  }
  if (buttonPlay.fallingEdge()) {
    usbMIDI.sendControlChange((CTRL_PLAY), 127, MIDI_CHAN);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Play ");
    Serial.println(String("ch=") + MIDI_CHAN + (", Control=") + (CTRL_PLAY) + ("Velocity=127"));
  }              
                     
  for(int i=0; i<CTRLBUTTONS_N; i++){   
    if (buttons[i].fallingEdge()) {
      usbMIDI.sendControlChange((CTRL_START+bankadd+i), 127, MIDI_CHAN);
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(" CTRL ");
      lcd.print (CTRL_START+bankadd+i);
      lcd.setCursor(0,1);
      lcd.print(" 127");
      Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_START+bankadd+i) + (" Velocity = 127 "));
      delTime[i]=millisTime;
      delBool[i]=true;
      ctrlval[i]=(CTRL_START+bankadd+i);
    }
    if (buttons[i].risingEdge()) {                                  //if the button gets released before delHold, delbool is false and the delete function cannot be sent
      
 //SEE IF THIS WORKS      
      //if (i==8||i==9||i==10||i==11 && (delBool[i]==true)){        //sends ctrl 0 (momentary midi msg) on the bottom four buttons
      if (ctrlval[i]==73 || ctrlval[i]==85 ||                          //sends ctrl 0 (momentary midi msg) on the top four buttons            
          ctrlval[i]==74 || ctrlval[i]==86 ||
          ctrlval[i]==75 || ctrlval[i]==87 ||
          ctrlval[i]==76 || ctrlval[i]==88 ||

          ctrlval[i]==77 || ctrlval[i]==89 ||                          //sends ctrl 0 (momentary midi msg) on the middle four buttons            
          ctrlval[i]==78 || ctrlval[i]==90 ||
          ctrlval[i]==79 || ctrlval[i]==91 ||
          ctrlval[i]==80 || ctrlval[i]==92 ||
          
          ctrlval[i]==81 || ctrlval[i]==93 ||                          //sends ctrl 0 (momentary midi msg) on the bottom four buttons            
          ctrlval[i]==82 || ctrlval[i]==94 ||
          ctrlval[i]==83 || ctrlval[i]==95 ||
          ctrlval[i]==84 || ctrlval[i]==96 &&  (delBool[i]==true)){
        usbMIDI.sendControlChange(ctrlval[i], 0, MIDI_CHAN);
        //usbMIDI.sendControlChange((CTRL_START+bankadd+i), 0, MIDI_CHAN);
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(" CTRL ");
        lcd.print (ctrlval[i]);
        lcd.setCursor(0,1);
        lcd.print(" 0");
        Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_START+bankadd+i) + (" Velocity = 0 MOMENTARY "));
      }

//SEE IF THIS WORKS
      delBool[i]=false;
      
    }                                                             
    if (millisTime-delTime[i]>=delHold && delBool[i]==true) {        //for each button send a "delete" control value (mapped to delete looper button) if delbool is true and pressure time longer than delHold (3s)
      delBool[i]=false;
      usbMIDI.sendControlChange((CTRL_START+bankadd+i+(CTRLBUTTONS_N*NUM_BANKS)), 127, MIDI_CHAN); //send a ctrl change that adds on top of the ctrl values already send by the buttons (plus the buttons*times bank)
      Serial.println ("3s Ctrl");                                                              //so the value of every del ctrl button is the value of the ctrl plus 30
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(" CTRL ");
      lcd.print (CTRL_START+bankadd+i+(CTRLBUTTONS_N*NUM_BANKS));
      Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_START+bankadd+i+(CTRLBUTTONS_N*NUM_BANKS)) + (" Velocity = 127 "));
      delTime[i]=millisTime;
      delBool[i]=true;
      
 
    }
  }
}


void readButtons(){
  buttonBank.update();
  buttonStop.update();
  buttonPlay.update();
  for(int i=0; i<CTRLBUTTONS_N; i++){   
    buttons[i].update();
  }
}
 
whops, sorry that was an old version: here is the current one :)
apologies for dumb coding, but im only self-taught and an amateur at that.. the pedal works fine though, except for these occasional crashes

Code:
                                    //LCD & SHIELD Libraries
  #include <Wire.h>
  #include <Adafruit_MCP23017.h>
  #include <Adafruit_RGBLCDShield.h>
  Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
  //#include <usb_keyboard.h>
                                    // LCD backlight color
  #define RED 0x1
  #define YELLOW 0x3
  #define GREEN 0x2
  #define TEAL 0x6
  #define BLUE 0x4
  #define VIOLET 0x5
  #define WHITE 0x7
                                    //Pushbuttons Debounce Library
  #include <Bounce.h>
                                    //Midi Library
  #include <MIDI.h>
  const int MIDI_CHAN = 5;

                                    //buttons on following pins, left to right, top to bottom: {2,3,4,5,/*6,*/7,8,9,10,/*11,*/12,20,21,22,/*23*/}
  #define BUTTONBANK 6              //bankswitch button
  #define BUTTONSTOP 11             //stop button (not part of bank)
  #define BUTTONPLAY 23             //play (not part of bank)
  int buttonaPins[] =   {2,  4,  7,  9,   12,   21};  //button group a, responsible for sending start go and stop ctrl msgs
  int buttonbPins[] =   {  3,  5,  8,  10,   20,   22};  //button group b, responsible for sending clear and del msgs
  #define BOUNCE_T 50               //bounce time in ms

  #define CTRLBUTTONSA_N 6          //ctrl A buttons used to trigger loopers
  #define CTRLBUTTONSB_N 6          //ctrl B buttons used to redo/clear
  #define CTRL_PLAY 65              //begin of control values available to footpedal (71-128)
  #define CTRL_STOP 66              
  #define CTRL_RACK 67              //CTRL value for instrument rack changes
  #define CTRL_RECSTART 68          //start of ctrl values for rec buttons (number up in forloop)
  #define CTRL_STOPSTART 80         //start of ctrl values for stop buttons (number up in forloop)
  #define CTRL_CLEARSTART 92        //start of ctrl values for clear buttons (number up in forloop)
  #define CTRL_TRACKSTART 104       //start of ctrl values for track on/off buttons (number up in forloop)
  #define CTRL_UNDOSTART 116        //start of ctrl values for undo buttons (number up in forloop)


  
  #define NUM_CTRLBANKS 2               //bank variables
  #define NUM_RACKBANKS 2   
  int ctrlbank = 0;                     //two banks, 0 and 1
  int rackbank = 0;
  int ctrlbankadd = 0;                  //add variable, bankadd = bank * CTRLBUTTONS_N
  int rackbankadd = 0;
  bool bankBool = false;
  int holdTime = 1500;
  int doubleTime = 300;
  int rackvar = 0;
  bool racktimeBool = false;
   
  unsigned long millisTime=0;         //time counter
  unsigned long bankTime=0;  
  unsigned long clearallTime=0;
  bool stoppressBool=false; 
  bool clearallBool=false;   
         
  bool recaBool[CTRLBUTTONSA_N] = {true, true, true, true, true, true};
  bool recbBool[CTRLBUTTONSA_N] = {true, true, true, true, true, true};
  bool recapressBool[CTRLBUTTONSA_N] = {false, false, false, false, false, false};
  bool recbpressBool[CTRLBUTTONSA_N] = {false, false, false, false, false, false};
  
  bool doubleaBool[CTRLBUTTONSA_N] = {false, false, false, false, false, false};
  bool doublebBool[CTRLBUTTONSB_N] = {false, false, false, false, false, false};
  bool doubleapressBool[CTRLBUTTONSA_N] = {false, false, false, false, false, false};
  bool doublebpressBool[CTRLBUTTONSB_N] = {false, false, false, false, false, false};
  bool doubleacountBool[CTRLBUTTONSA_N] = {false, false, false, false, false, false};
  bool doublebcountBool[CTRLBUTTONSB_N] = {false, false, false, false, false, false};
  unsigned long doubleaTime[CTRLBUTTONSA_N]={0,0,0,0,0,0};
  unsigned long doublebTime[CTRLBUTTONSB_N]={0,0,0,0,0,0};   
  int x=0;
  
  bool holdaBool[CTRLBUTTONSA_N] = {false, false, false, false, false, false};
  bool holdbBool[CTRLBUTTONSB_N] = {false, false, false, false, false, false};
  bool holdapressBool[CTRLBUTTONSA_N] = {false, false, false, false, false, false};
  bool holdbpressBool[CTRLBUTTONSB_N] = {false, false, false, false, false, false};
  unsigned long holdaTime[CTRLBUTTONSA_N]={0,0,0,0,0,0};
  unsigned long holdbTime[CTRLBUTTONSB_N]={0,0,0,0,0,0};    

  Bounce buttonBank = Bounce(BUTTONBANK, BOUNCE_T);                  
  Bounce buttonStop = Bounce(BUTTONSTOP, BOUNCE_T);
  Bounce buttonPlay = Bounce (BUTTONPLAY, BOUNCE_T);
  
  Bounce buttonsA[6] = {
    Bounce (buttonaPins[0], BOUNCE_T), 
    Bounce (buttonaPins[1], BOUNCE_T), 
    Bounce (buttonaPins[2], BOUNCE_T), 
    Bounce (buttonaPins[3], BOUNCE_T),
    Bounce (buttonaPins[4], BOUNCE_T),
    Bounce (buttonaPins[5], BOUNCE_T),
  };

  Bounce buttonsB[6] = {
    Bounce (buttonbPins[0], BOUNCE_T), 
    Bounce (buttonbPins[1], BOUNCE_T), 
    Bounce (buttonbPins[2], BOUNCE_T), 
    Bounce (buttonbPins[3], BOUNCE_T),
    Bounce (buttonbPins[4], BOUNCE_T),
    Bounce (buttonbPins[5], BOUNCE_T),
  };
  
void setup(){  
                             
  Serial.begin(9600);
  
  pinMode (BUTTONBANK, INPUT_PULLUP);
  pinMode (BUTTONSTOP, INPUT_PULLUP);
  pinMode (BUTTONPLAY, INPUT_PULLUP);
  
  pinMode(buttonaPins[0], INPUT_PULLUP);
  pinMode(buttonaPins[1], INPUT_PULLUP);
  pinMode(buttonaPins[2], INPUT_PULLUP);
  pinMode(buttonaPins[3], INPUT_PULLUP);
  pinMode(buttonaPins[4], INPUT_PULLUP);
  pinMode(buttonaPins[5], INPUT_PULLUP);
  
  pinMode(buttonbPins[0], INPUT_PULLUP);
  pinMode(buttonbPins[1], INPUT_PULLUP);
  pinMode(buttonbPins[2], INPUT_PULLUP);
  pinMode(buttonbPins[3], INPUT_PULLUP);
  pinMode(buttonbPins[4], INPUT_PULLUP);
  pinMode(buttonbPins[5], INPUT_PULLUP);
                          
  lcd.begin(16, 2);                           //LCD START
 
  lcd.clear();            
  lcd.setCursor(0, 0);
  lcd.print("START");
 
  Serial.println("serial start"); 
}

void loop(){

  millisTime = millis();                      //time var running WHATS THE MAX MILLIS VALUE?
  
  while (usbMIDI.read());   

  readButtons();

  if(buttonBank.fallingEdge() && racktimeBool==false) {     //bank button
    ctrlbank++;
    ctrlbank %= NUM_CTRLBANKS;
    ctrlbankadd = ctrlbank * CTRLBUTTONSA_N;
    bankTime=millisTime;
    bankBool=true;
    Serial.print("CTRL Bank ");
    Serial.println(ctrlbank);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("CTRL Bank ");
    lcd.print(ctrlbank);
  }
  if (buttonBank.risingEdge()) {
      bankBool=false;
    }
  if (millisTime-bankTime>=holdTime && bankBool==true && racktimeBool==false) {
      bankBool=false;
      ctrlbank=ctrlbank-1;
      racktimeBool = true;
      Serial.println ("Rack Time");
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("RACKTIME BABY");
      rackbank=0;
    }
    
  if (racktimeBool==true){                          //RACKTTIME BABY time to choose your rack
    if(buttonBank.fallingEdge()) {    
      rackbank++;
      rackbank %= NUM_RACKBANKS;
      Serial.print("Rack Bank ");
      Serial.println(rackbank);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Rack Bank ");
      lcd.print(rackbank);
      rackbankadd = rackbank * (CTRLBUTTONSA_N+CTRLBUTTONSB_N);
      bankTime=millisTime;
      bankBool=true;
    }
    if (buttonBank.risingEdge()) {
        bankBool=false;
      }
    if (millisTime-bankTime>=holdTime && bankBool==true && racktimeBool==true) {
        bankBool=false;
        racktimeBool = false;
        rackbank=rackbank-1;
        Serial.println ("Control Time");
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("YOU GOT CONTROL!");
    }
    if (buttonStop.fallingEdge()) {
      rackvar = rackvar+1;
      if (rackvar>23) rackvar=0;
      sendrackVar();
    }
    if (buttonPlay.fallingEdge()) {
      rackvar = rackvar-1;
      if (rackvar<0) rackvar=23;
      sendrackVar();
    }
    for(int i=0; i<CTRLBUTTONSA_N; i++){   
      if (buttonsA[i].fallingEdge()) {
      rackvar=(i*2)+rackbankadd;   
      sendrackVar();  
      }
    }
    for(int i=0; i<CTRLBUTTONSB_N; i++){ 
      if (buttonsB[i].fallingEdge()) {
      rackvar=(i*2)+rackbankadd+1;
      sendrackVar();
      }
    }  
  }

  else if (racktimeBool==false){                    //CONTROL TIME time to send looper controls 
  
    if (buttonStop.fallingEdge() && stoppressBool==false) {     //if press is registered and button is not pressed
      clearallTime=millisTime;                                  //start clear all counter
      stoppressBool=true;                                       //button is pressed
      clearallBool=true;                                        //expect clear all
    }
    if (buttonStop.risingEdge() && stoppressBool==true && clearallBool==true) {       //if button is raised and it was pressed before and clearall was expected
      usbMIDI.sendControlChange((CTRL_STOP), 127, MIDI_CHAN);                         //send a stop message
      usbMIDI.sendControlChange((CTRL_STOP), 0, MIDI_CHAN);
      
      for(int i=0; i<12; i++){   
        usbMIDI.sendControlChange(CTRL_STOPSTART+i, 127, MIDI_CHAN);                  //we send stop messages
      }
      
      stoppressBool=false;                                                            //but is not pressed anymore
      clearallBool=false;                                                             //we do not exect a clearall
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("Stop ");
                          Serial.println(String("ch=") + MIDI_CHAN + (", Control=") + (CTRL_STOP) + ("Velocity=127"));
                          Serial.println(String("ch=") + MIDI_CHAN + (", Control=") + (CTRL_STOP) + ("Velocity=0")); 
    }
    if (millisTime-clearallTime>=holdTime && clearallBool==true && stoppressBool==true) {  //if time has run out and we still expect a clearall and the button is pressed
      for(int i=0; i<12; i++){   
        usbMIDI.sendControlChange(CTRL_CLEARSTART+i, 127, MIDI_CHAN);                  //we send clearall messages
      }
            clearallBool=false;                                                        //we do not expect a clearall
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Loopers cleared");
    }
    if (buttonStop.risingEdge() && stoppressBool==true && clearallBool==false) {       //if button is released and was pressed and we do not expect a clearall
      stoppressBool=false;                                                             //button is not pressed anymore
      for(int i=0; i<12; i++){   
      usbMIDI.sendControlChange(CTRL_CLEARSTART+i, 0, MIDI_CHAN);
      delay(3);               
      }
    }
      
    
    if (buttonPlay.fallingEdge()) {
      usbMIDI.sendControlChange((CTRL_PLAY), 127, MIDI_CHAN);
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Play ");
      Serial.println(String("ch=") + MIDI_CHAN + (", Control=") + (CTRL_PLAY) + ("Velocity=127"));
    }    
    if (buttonPlay.risingEdge()) {
      usbMIDI.sendControlChange((CTRL_PLAY), 0, MIDI_CHAN);  
      Serial.println(String("ch=") + MIDI_CHAN + (", Control=") + (CTRL_PLAY) + ("Velocity=0"));
    }
    
    for(int i=0; i<CTRLBUTTONSA_N; i++){                          //BUTTON GROUP A
      if (buttonsA[i].fallingEdge() && recaBool[i]==true) {                           //if ctrlabutton is pressed and if we are waiting for a rec 127
        usbMIDI.sendControlChange((CTRL_RECSTART+ctrlbankadd+i), 127, MIDI_CHAN);     //we send a rec ctrl message
        recaBool[i]=false;                                                            //we are not waiting for a rec 127
        recapressBool[i]=true;                                                        //we are ready to send the 0 value for rec
        holdaTime[i]=millisTime;                                                      //hold time is starting
        holdaBool[i]=true;                                                            //we are waiting for a hold

                          Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_RECSTART+ctrlbankadd+i) + (" Velocity = 127 "));
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("REC CTRL ");
                          lcd.print(CTRL_RECSTART+ctrlbankadd+i);
                          lcd.setCursor(0,1);
                          lcd.print("127");
      }
      if (buttonsA[i].risingEdge() && recapressBool[i]==true) {                      //if the button gets released and if we were ready for a 0 rec value
        usbMIDI.sendControlChange(CTRL_RECSTART+ctrlbankadd+i, 0, MIDI_CHAN);        //we send the 0 rec value
        recapressBool[i]=false;                                                      //we are not ready for a rec 0
        doubleaBool[i]=true;                                                         //we are ready for a double 127
        doubleaTime[i]=millisTime;                                                   //double press time is starting
        doubleacountBool[i]=true;
        holdaBool[i]=false;                                                          //we are not ready for a hold 127
                          Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_RECSTART+ctrlbankadd+i) + (" Velocity = 0 MOMENTARY "));
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("REC CTRL ");
                          lcd.print (CTRL_RECSTART+ctrlbankadd+i);
                          lcd.setCursor(0,1);
                          lcd.print("0");
      }
      if (millisTime-doubleaTime[i]>doubleTime && doubleacountBool[i]==true){                                        //if double press time has run out  
        recaBool[i]=true;                                                               //we are ready for a rec 127  
        doubleaBool[i]=false;                                                           //we are not ready for a double 127
        doubleacountBool[i]=false;
      }
      else if (buttonsA[i].fallingEdge() && millisTime-doubleaTime[i]<=doubleTime && doubleaBool[i]==true){     //if double press has not run out and we are waiting for a double 127
        usbMIDI.sendControlChange(CTRL_STOPSTART+ctrlbankadd+i, 127, MIDI_CHAN);                                //we send a double press stop ctrl value
        doubleaBool[i]=false;                                                                                   //we are not ready for a double 127
        doubleapressBool[i]=true;                                                                               //we are ready for a double 0 value
        holdaTime[i]=millisTime;                                                                                //we are again starting the hold clock
        holdaBool[i]=true;                                                                                      //we are waiting for a hold 127
                          Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_STOPSTART+ctrlbankadd+i) + (" Velocity = 127 "));
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("STOP CTRL ");
                          lcd.print(CTRL_STOPSTART+ctrlbankadd+i);
                          lcd.setCursor(0,1);
                          lcd.print("127");
      }
      if (buttonsA[i].risingEdge()&& doubleapressBool[i]==true){                                                //if we are ready for a double0 and it happens
        usbMIDI.sendControlChange(CTRL_STOPSTART+ctrlbankadd+i, 0, MIDI_CHAN);                                    //we send a 0 stop value
        recaBool[i]=true;                                                                                         //we are ready for a rec 127  
        doubleapressBool[i]=false;                                                                                //we are not ready for a double 0
        holdaBool[i]=false;                                                                                       //we are not anymore waiting for a hold  
                          Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_STOPSTART+ctrlbankadd+i) + (" Velocity = 0 "));
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("STOP CTRL ");
                          lcd.print(CTRL_STOPSTART+ctrlbankadd+i);
                          lcd.setCursor(0,1);
                          lcd.print("0");          
      }                                                        
      if (millisTime-holdaTime[i]>=holdTime && holdaBool[i]==true) {                                             //if we are ready for a hold 127 and it happens
        usbMIDI.sendControlChange(CTRL_STOPSTART+ctrlbankadd+i, 0, MIDI_CHAN);                                   //we send a 0 stop value 
        delay (4);
        usbMIDI.sendControlChange(CTRL_RECSTART+ctrlbankadd+i, 0, MIDI_CHAN);                                    //we send the 0 rec value
        delay (4);
        usbMIDI.sendControlChange(CTRL_CLEARSTART+ctrlbankadd+i, 127, MIDI_CHAN);                                //we send the clear message
        holdaBool[i]=false;                                                                                      //we are not anymore waiting for a hold127
        holdapressBool[i]=true;                                                                                  //we are ready for a hold0
                          Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_CLEARSTART+ctrlbankadd+i) + (" Velocity = 127"));
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("CLEAR CTRL ");
                          lcd.print(CTRL_CLEARSTART+ctrlbankadd+i);
                          lcd.setCursor(0,1);
                          lcd.print("127");  
     }
      if (buttonsA[i].risingEdge()&& holdapressBool[i]==true) {                                                   //if we are ready for a hold0 and the buttons rises
         usbMIDI.sendControlChange(CTRL_CLEARSTART+ctrlbankadd+i, 0, MIDI_CHAN);                                  //we send the 0 clear message
         recaBool[i]=true;
         doubleaBool[i]=false;
         holdapressBool[i]=false;
                          Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_CLEARSTART+ctrlbankadd+i) + (" Velocity = 0 "));
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("CLEAR CTRL ");
                          lcd.print(CTRL_CLEARSTART+ctrlbankadd+i);
                          lcd.setCursor(0,1);
                          lcd.print("0");  
      }         
    }

    
    for(int i=0; i<CTRLBUTTONSB_N; i++){                          //BUTTON GROUP B  TRACK ON/OFF and UNDO
      if (buttonsB[i].fallingEdge() && recbBool[i]==true) {                           //if ctrlbbutton is pressed and if we are waiting for a rec 127
        recbBool[i]=false;                                                            //we are not waiting for a rec 127
        recbpressBool[i]=true;                                                        //we are ready to send the 0 value for rec
        holdbTime[i]=millisTime;                                                      //hold time is starting
        holdbBool[i]=true;                                                            //we are waiting for a hold
        
      }
      if (buttonsB[i].risingEdge() && recbpressBool[i]==true) {                      //if the button gets release        
        recapressBool[i]=false;                                                      //we are not ready for a rec 0
        doublebBool[i]=true;                                                         //we are ready for a double 127
        doublebTime[i]=millisTime;                                                   //double press time is starting
        doublebcountBool[i]=true;
        holdbBool[i]=false;                                                          //we are not ready for a hold 127
      }
      if (millisTime-doublebTime[i]>doubleTime && doublebcountBool[i]==true){        //if double press time has run out  
        recbBool[i]=true;                                                            //we are ready for a rec 127  
        doublebBool[i]=false;                                                        //we are not ready for a double 127
        doublebcountBool[i]=false;
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("HAA, TOO SLOW!!!");
      }
      else if (buttonsB[i].fallingEdge() && millisTime-doublebTime[i]<=doubleTime && doublebBool[i]==true){     //STOP if double press has not run out and we are waiting for a double 127
        //usbMIDI.sendControlChange(CTRL_TRACKSTART+ctrlbankadd+i, 127, MIDI_CHAN);                               //we send a double press stop ctrl value
        doublebBool[i]=false;                                                                                   //we are not ready for a double 127
        doublebpressBool[i]=true;                                                                               //we are ready for a double 0 value
        holdbTime[i]=millisTime;                                                                                //we are again starting the hold clock
        holdbBool[i]=true;                                                                                      //we are waiting for a hold 127
        doublebcountBool[i]=false;
                          /*Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_TRACKSTART+ctrlbankadd+i) + (" Velocity = 127 "));
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("TRACK CTRL ");
                          lcd.print(CTRL_TRACKSTART+ctrlbankadd+i);
                          lcd.setCursor(0,1);
                          lcd.print("127");*/
      }
      if (buttonsB[i].risingEdge()&& doublebpressBool[i]==true){                                                  //if we are ready for a double0 and it happens
        x++;
        if (x>1) x=0;
        if (x==0){
          usbMIDI.sendControlChange(CTRL_TRACKSTART+ctrlbankadd+i, 0, MIDI_CHAN);                                   //we send a 0 track value
                          Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_TRACKSTART+ctrlbankadd+i) + (" Velocity = 0 "));
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("TRACK CTRL ");
                          lcd.print(CTRL_TRACKSTART+ctrlbankadd+i);
                          lcd.setCursor(0,1);
                          lcd.print("0");      
        }
        if (x==1){
          usbMIDI.sendControlChange(CTRL_TRACKSTART+ctrlbankadd+i, 127, MIDI_CHAN);                                   //we send a 127 track value
                          Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_TRACKSTART+ctrlbankadd+i) + (" Velocity = 0 "));
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("TRACK CTRL ");
                          lcd.print(CTRL_TRACKSTART+ctrlbankadd+i);
                          lcd.setCursor(0,1);
                          lcd.print("127");   
        }
        recbBool[i]=true;                                                                                         //we are ready for a rec 127  
        doublebpressBool[i]=false;                                                                                //we are not ready for a double 0
        holdbBool[i]=false;                                                                                       //we are not anymore waiting for a hold 
        doublebcountBool[i]=false;     
      }                                                        
      if (millisTime-holdbTime[i]>=holdTime && holdbBool[i]==true) {                                             //if we are ready for a hold 127 and it happens
        
        usbMIDI.sendControlChange(CTRL_UNDOSTART+ctrlbankadd+i, 127, MIDI_CHAN);                                 //we send the undo message
        holdbBool[i]=false;                                                                                      //we are not anymore waiting for a hold127
        holdbpressBool[i]=true;                                                                                  //we are ready for a hold0
        doublebcountBool[i]=false;
                          Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_UNDOSTART+ctrlbankadd+i) + (" Velocity = 127"));
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("UNDO CTRL ");
                          lcd.print(CTRL_UNDOSTART+ctrlbankadd+i);
                          lcd.setCursor(0,1);
                          lcd.print("127");  
     }
      if (buttonsB[i].risingEdge()&& holdbpressBool[i]==true) {                                                   //if we are ready for a hold0 and the buttons rises
         usbMIDI.sendControlChange(CTRL_UNDOSTART+ctrlbankadd+i, 0, MIDI_CHAN);                                   //we send the 0 clear message
         recbBool[i]=true;
         doublebBool[i]=false;
         holdbpressBool[i]=false;
         doublebcountBool[i]=false;
                          Serial.println(String(" ch= ") + MIDI_CHAN + (", Control = ") + (CTRL_UNDOSTART+ctrlbankadd+i) + (" Velocity = 0 "));
                          lcd.clear();
                          lcd.setCursor(0,0);
                          lcd.print("UNDO CTRL ");
                          lcd.print(CTRL_STOPSTART+ctrlbankadd+i);
                          lcd.setCursor(0,1);
                          lcd.print("0");  
      }         
    }    
  }
}


void readButtons(){
  buttonBank.update();
  buttonStop.update();
  buttonPlay.update();
  for(int i=0; i<CTRLBUTTONSA_N; i++){   
    buttonsA[i].update();
  }
  for(int i=0; i<CTRLBUTTONSB_N; i++){   
    buttonsB[i].update();
  }
}

void sendrackVar(){
  usbMIDI.sendControlChange(CTRL_RACK, rackvar, MIDI_CHAN);
  Serial.print(" Rack Nr ");
  Serial.println(rackvar);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Rack Nr: ");
  lcd.print(rackvar);
}
 
I'm having a skim through now, there's a lot to it and without investing serious time it's not going to jump out at me.

Can you monitor the device with a serial monitor and find out the last thing it sends before it crashes? Either that or make an interrupt firing every 10 seconds which transmits a string "ping" down the serial.

This will help to check if the program is freezing or locking up if it is actually the windows usb side
 
Ok, I will try checking what it sends right before in a few hours.
I would also like to do the interrupt you are suggesting, however, i am not sure exactly how to do that (even after checking the arduino page).
is it enough to just send the string every 10 seconds on a millis function in the main code (ie, right after loop) or do you mean something else?
ie:
Code:
 interruptTime = 0;
void loop {
 millisTime =millis();
 if (millisTime-interruptTIme>10){
   Serial.println("Ping");
  interruptTime=millisTime;
something like that?
thanks for your help!
 
Code:
void setup(void) {
  Serial.begin(9600);
  myTimer.begin(heartbeat, 10000000);  // Time in microseconds (10s)
}

// functions called by IntervalTimer should be short, run as quickly as
// possible, and should avoid calling other functions if possible.
void heartbeat() {
  Serial.println("still alive");
}

You seem to be unaware of what interrupts are.
When an interrupt occurs, in this case after 10 seconds (but it can be a variety of things, such as on a pin change), the program stops doing whatever it is doing and jumps to a predefined area. In this case this is the function heartbeat(). It then executes this function and returns back to where it was.
This is useful as no matter what it's doing it will stop to print "Still alive". This is useful as if your program is stuck in a loop it will still transmit this. Allowing us to determine if the serial communication is actually dropping or if your program is getting stuck
 
Last edited:
hey! yeah, as i said i'm not much of a programmer.. :)
anyways, i did as you said and let an interrupt run. i used it yesterday for 4 hours and today for 3 and it didn't crash... ?
not sure what happened here, but thanks i guess, ill check it again during the next day to see if that solved the problem.

for the other devices, would you tell me ow you reduce the speed midi data is sent? on the other devices im using a delay, but there is probably a better way, correct?
in any case, thanks you!
 
Sounds like a Heisenbug!
I'm glad it's working though.

The common practice for removing delays is either. Setup an intervalTimer to trigger a regular interrupt. Orrrr when you transmit save the value of millis(); to a variable. Then when you want to check if you've waited long enough from the last transmission check to see if (millis() - lastMillis) > (delayInMilliseconds)
 
ha, yeah, i guess that must be it. i inserted the interrupt in another controller and it seems to work more stable now, too... weird, but well, im gonna put interrupts everywhere now! teensys, mobile phone, fridge, oven ;)
anyways, if the same problems should show up again, ill post here, but for now: thank you very much!
 
hey again! so, unfortunately the problems haven't disappeared. the footpedal continues to work without problems, however, the usb hub on the second usb-in on my laptop with four teensy based midi controllers connected to it continues to fall out and not recognized the devices after manual un plugging and re-plugging. the hub is powered by an external 5 volt battery, so the teensys work independently of the laptop one is a drumpad with a lot of leds, so it needs extrapower), often everything works, then for an extended period of time without problem, then it falls out, if i unplug and replug the hub does usually not get recognized, however, if i plug another usb device in (like a mouse) it works. if i restart the laptop the setup usually works again.
i reduced the speed that midi is send to the pc teensys, each instrument midi send is 20 hz or more, for the ctrl sends 50ms between sends, and i took out most of the serial.print too, in case that is hard to handle. tried different usb hubs, too, same problem. the hub is connected over a 2m meter cable to the laptop, teensys are connected to the hub via 1m usb cables. thank you for any tipps!
did anybody experience similar problems? any other suggestions on how to proceed? ill run an interrupt again and see what that says..
ps: merry xmas ;)
 
Last edited:
Maybe try monitoring the VUSB voltage that's actually arriving at each Teensy after the hub? Perhaps it's dropping too low when those LEDs turn on?

Posting a photo might help. Well maybe.... but really, I'm mostly just curious to see the whole project. Sounds pretty awesome!
 
hey,
how would i monitor the voltage, simply with a voltage meter or is there a code to do it?

i just had the gauntlet connected yesterday running an interrupt, too (i do feel this seems to keep the connection going)
and ableton kept on reloading the midi towards the end of the session (maybe cpu was getting full or ram...?) (well, i think it was the midi reloading, the little blue "sandclock circle" showed up and it usually only does that when a midi device is being connected.
at the same time, the serial kept running smooth. for the whole time.

ill try another run with all the instrument today, if somebody would be willing to take a look at my amateur code, maybe just one of the things, maybe just a quick look to make sure i didnt program any major mistakes, i would be very grateful. just let me know and i post it. so far, i am sending midi when midi is played, im sending reset scales during mode switches but with a delay of five between each message (this is to make sure any midis that might escape without a note off are turned off during switches) and im sending control messages, but only when control changes occur and a 50 ms millis delay between messages. i turned off most serial messages. i also deactived the turn usb of to save energy mode on windows. i am running this setup on a lenovo x250 with ssd card, so ram being full shouldnt be a problem. i am using "balanced" on the battery, so the cpu isnt running full power. i want to use the full-power setting durings gigs only, but have the system run stable on balanced during practise sessions to have it impeccable during actual performances

here is a photo of the setup (im wearing the chest piece under a shirt, but yes, it still looks pretty ridiculous altogether...). except for the chest thingy its ony two rgb leds per device, and the amp running out of the battery should be plenty. the chest rarely has all leds activated. i dont think the usb hub has an ampere limiter, so the devices should be able to draw as much as they want to..

im wearing all this stuff, the hub and battery in a fanny pack, so there is movement involved and theoretically a usb cable could disconnect at a certain point. however, ableton 9 automatically reconnects during a set if a new midi instrument shows up, so that shouldnt be a problem. what weirds me out is that occasionally it stops wanting to recognize the whole hub. the gauntlet sometimes stops being responsive, as if the teensy crashed, and the footpedal occasionally send messages without buttons having been pressed. (that said, the stomps buttons are the cheap ones from china...so it might be a hardware bug).

so, i basically need to make sure that the main setup runs stable on all the devices, that the gauntlet does not get stuck, that the laptop does not have problems reading all the incoming midi (one channel per device). guitar runs fine, the glove runs fine, except that the vibration motor every once in a while turns crazy, then i just unplug and replug it (i did put the motor on the standard circuit https://www.google.com/imgres?imgrefurl=http://learningaboutelectronics.com/Articles/Vibration-motor-circuit.php&tbnid=1g725ifQUZFXqM:&docid=X5zQgHLosJpMbM&h=391&w=716), chest runs fine, except of course when the whole hub disconnects.. each instrument has a teensy, chest, glove and guitar have an accel, and there is a bunch of fsr sensors, usually cobined with position sensors which send, according to mode, either midi note on off messages or control changes. for me it is crucial that the setup runs stable since im planning on using it for gigs pretty soon, so any help is very much appreciated!

rsz_20151228_135803.jpgrsz_20151228_141214[1].jpg
 
Last edited:
hey, so i checked again and it seems it is a two-stage problem. windows does not always recognize the midi device(s) when connected over the externally powered hub. and ableton crashes at certain point when windows is trying to recognize the devices.

1st, at time windows doesnt seem to recognize the devices when connected through the hub, they do show up in the device manager, but all four are declared:
"Unknown usb device device descriptor test failed" and
" Windows has stopped this device because it has reported problems. (Code 43)
A request for the USB device descriptor failed."
as i mentioned, the hub is powered by a five volt battery power supply (to charge ipods, etc) and connects to the laptop usb in over a 2 meter cable. if i go straight hub to laptop in that scenario the problem remains. If only two devices are connected to the hub, same problem, in this case the serial doesnt work either.
If I unplug the hub and connect one device directly it works. At times they work perfectly together. I just now switched on one device after the other, and they all worked, disconnected and reconnected the hub, not working.
connected one directly: working.
connected one over hub: failed to be recognized.
conneceted same one directly: works fine.
connecting same on over hub without external power: not working.
connecting again without ext power: working.
connecting one again with ext power: working.
connecting again with power working.
connecting all four devices with ext power: working
disabling all but one: working.
enabling all four: working
pulling out hub, putting hub back in: working.
disconnecting hub, reconnecting all four: not working.
enabling only one: not working.
connecting one directly: working.
connecting one over the hub: not working.
.. and so forth
so, direct connection of the midi device works always, but using the hub (or other hubs, i have several) does not always work. they do show up in the device manager, but
with that message" Windows has stopped this device because it has reported problems. (Code 43) A request for the USB device descriptor failed."

mhm, it seems that when i connect the hub without the external power then every device gets recognized without problems

anyone any suggestions? or any alternatives how to reliably connected 5 teensy midi devices and one external soundcard to a two usb port laptop?
 
Last edited:
ok, so i tried it out several times without the external power for the usb hub and the teensies connect with much greater reliability. might this be because the start up with port connection and are not already powered beforehand?
anyways, since the port is usb 3.0 that means i have 900mA to spread over the four devices. since the chest alone has 9 rgbs (each of the other ones have two) i am already at a possible of (9+6)*3*25mA for the Leds so 1125 mA just for that. I will make sure to only use one color at a time, but in general, does anybody have any tipps on how to either connect the hub with external power, or maybe some other workaround? in the long-run i will have to use external power for my teensys, that is pretty certain..
cheers!
 
Status
Not open for further replies.
Back
Top