Teensy Midi Controller Project Advice/Journal

Status
Not open for further replies.
Yes that sounds right. There are many extraeneous pieces in the initial code that I think would make sense to be removed. I am still re reading everything and making sense of what is happening. It is starting to piece together in my mind.

What we really need is for the timer to load the bank with 5 unique CCs. And have 5 sets of unique CC codes. So in result I could Have 25 presets.

I could use this very well I think.
 
So button 0 is help for 2 seconds or even for one second it loads the bank with CC 1,2,3,4 and 5.
hold button 1 and it loads the bank with 6,7,8,9,and 10 and so on right?
 
Oh... and they don't have to toggle OFF and ON. It's easier if they don't

We can send the same CC message every time if the DAW is treating CC messages more like program changes.

Or we can toggle the accompanying value between OFF (0) and ON (127).
 
So button 0 is help for 2 seconds or even for one second it loads the bank with CC 1,2,3,4 and 5.
hold button 1 and it loads the bank with 6,7,8,9,and 10 and so on right?

Yeah something like that. The numbers are in arrays and can be whatever you like but there would be five sets of them.

No clue if that's anything that would be beneficial.

At that point LEDs or a 7-segment display to say which set is active might be in order.
 
Ok so that is good for the bank system.
the thought to add onto this would be individual controls per preset. so another bank of 5-10 switches.

The array for these switches and the LED text for printout is loaded when the specific bank number is selected.

So example if we are in bank 3 and select switch 2 that will be CC 12 andwhen pressed can load switches 6-10 with led printouts and codes in an array.
 
I just meant five banks of five might get confusing if you can't tell which bank you've selected.

An LED above the switch could tell the user which bank is active.
Another (of a different color) could do the same for which switches are active assuming you have toggled behaviour and switches can be 'off' or 'on' independently.



Let's leave off on displaying the info back to the user for now...
 
yeah leds would be nice. i can see this controller being set up very specifically for what I would need it for.

Can you program multiple events for when a switch is pressed? i.e. send a CC code and also load the array?
 
I suggest we take the A/B bank example from my first post here and change it as follows:

Note on/off becomes CC 127/0
Send CC only on releasing the witch (risingEdge) and only if timer is below 2000 mS
Reset timer on fallingEdge - start counting the timer only when a switch is down
If timer > 2000 mS when risingEdge is detected then toggle mode/bank and do not send CC for the button pressed

FYI - with this scheme we could make it so it changes mode if ANY button is held for >2000ms.

If this sounds OK to you let me know and I'll make a version with these changes later tonight.

Sorry I guess I forgot about your project the other day.

Here's a version that changes mode if any button is held for more than two seconds.
Code:
#include <Bounce.h>

//**********CONSTANTS**********
const int BOUNCE_TIME = 25; // fine tune if the buttons need more/less time
const int LEDPIN = 13; // Upper BANK indicator LED 
const int DIGITAL_PINS = 5; // size of the PINS array (no longer includes toggle button!)
const int PINS[DIGITAL_PINS] = {0,1,2,3,4}; // set pin numbers of swtiches
const int channel = 1;
const int ONvalue = 127; // arbitrary 'on' value for D2 of CC message
const int OFFvalue = 0; // arbitrary 'off' value for D2 of CC message
const int resetThreshold = 2000; /// mS hold to change bank

const byte CC[][DIGITAL_PINS] = {
  {60,61,62,63,64},
  {80,81,82,83,84},
}; // this is the banks by switches matrix of CC values for the bank system

//**********VARIABLES/LIBRARY OBJECTS**********
int bank = 0; // this is the bank variable to be toggled
boolean CCstate[DIGITAL_PINS]; // array of current CC on/off toggle state
boolean timerOn; // timer toggle memory tracks whether a new fallingEdge was heard since the last rising; used in bank switching

Bounce btn[] = {
  Bounce(PINS[0], BOUNCE_TIME),
  Bounce(PINS[1], BOUNCE_TIME),
  Bounce(PINS[2], BOUNCE_TIME),
  Bounce(PINS[3], BOUNCE_TIME),
  Bounce(PINS[4], BOUNCE_TIME),
  };
elapsedMillis toggleReset; // mS clock counter to reset on contact/risgingEdge()

//**********SETUP**********
void setup() {
  //Serial.begin(9600);
  for (int i = 0;i<DIGITAL_PINS;i++){
    pinMode(PINS[i], INPUT_PULLUP);
  }
  pinMode(LEDPIN, OUTPUT);
}

//**********LOOP**********
void loop() {
  for (int i = 0;i<DIGITAL_PINS;i++){ // loop through each object in the BOUNCE arrray for the note switches (no longer includes TOGGLE)
    btn[i].update();
    if (btn[i].fallingEdge()) {
      timerOn = true ;
      toggleReset = 0;
    }
    if (btn[i].risingEdge()) {
      if(toggleReset<resetThreshold){
        if (CCstate[i]){ 
          usbMIDI.sendControlChange(CC[bank][i], ONvalue, channel); 
        }else{
          usbMIDI.sendControlChange(CC[bank][i], OFFvalue, channel);  
        }
        CCstate[i] = !CCstate[i] ; //toggle state memory
        timerOn = false ; //turn off timer (resets each cycle)
      }
    }
    if (timerOn && (toggleReset>resetThreshold)){
      toggleReset = 0;
      bank = !bank;
      digitalWrite(LEDPIN, bank); // visual feedback for ALT bank selection
    }
  }
}
It toggles the LED as well as the state (currently set to the internal pin but you can power an external LED on your front-panel to indicate you are in alternate mode).

If you keep holding it keeps toggling -- which is good I think since if you accidentally hold too long you just keep holding to correct and release when the LED is in the correct state.

As indicated this one only sends the CC messages after you release and then toggles the second byte of data to OFF and ON (0 and 127 as the code is now).
 
Sorry I guess I forgot about your project the other day.

Here's a version that changes mode if any button is held for more than two seconds.
Code:
#include <Bounce.h>

//**********CONSTANTS**********
const int BOUNCE_TIME = 25; // fine tune if the buttons need more/less time
const int LEDPIN = 13; // Upper BANK indicator LED 
const int DIGITAL_PINS = 5; // size of the PINS array (no longer includes toggle button!)
const int PINS[DIGITAL_PINS] = {0,1,2,3,4}; // set pin numbers of swtiches
const int channel = 1;
const int ONvalue = 127; // arbitrary 'on' value for D2 of CC message
const int OFFvalue = 0; // arbitrary 'off' value for D2 of CC message
const int resetThreshold = 2000; /// mS hold to change bank

const byte CC[][DIGITAL_PINS] = {
  {60,61,62,63,64},
  {80,81,82,83,84},
}; // this is the banks by switches matrix of CC values for the bank system

//**********VARIABLES/LIBRARY OBJECTS**********
int bank = 0; // this is the bank variable to be toggled
boolean CCstate[DIGITAL_PINS]; // array of current CC on/off toggle state
boolean timerOn; // timer toggle memory tracks whether a new fallingEdge was heard since the last rising; used in bank switching

Bounce btn[] = {
  Bounce(PINS[0], BOUNCE_TIME),
  Bounce(PINS[1], BOUNCE_TIME),
  Bounce(PINS[2], BOUNCE_TIME),
  Bounce(PINS[3], BOUNCE_TIME),
  Bounce(PINS[4], BOUNCE_TIME),
  };
elapsedMillis toggleReset; // mS clock counter to reset on contact/risgingEdge()

//**********SETUP**********
void setup() {
  //Serial.begin(9600);
  for (int i = 0;i<DIGITAL_PINS;i++){
    pinMode(PINS[i], INPUT_PULLUP);
  }
  pinMode(LEDPIN, OUTPUT);
}

//**********LOOP**********
void loop() {
  for (int i = 0;i<DIGITAL_PINS;i++){ // loop through each object in the BOUNCE arrray for the note switches (no longer includes TOGGLE)
    btn[i].update();
    if (btn[i].fallingEdge()) {
      timerOn = true ;
      toggleReset = 0;
    }
    if (btn[i].risingEdge()) {
      if(toggleReset<resetThreshold){
        if (CCstate[i]){ 
          usbMIDI.sendControlChange(CC[bank][i], ONvalue, channel); 
        }else{
          usbMIDI.sendControlChange(CC[bank][i], OFFvalue, channel);  
        }
        CCstate[i] = !CCstate[i] ; //toggle state memory
        timerOn = false ; //turn off timer (resets each cycle)
      }
    }
    if (timerOn && (toggleReset>resetThreshold)){
      toggleReset = 0;
      bank = !bank;
      digitalWrite(LEDPIN, bank); // visual feedback for ALT bank selection
    }
  }
}
It toggles the LED as well as the state (currently set to the internal pin but you can power an external LED on your front-panel to indicate you are in alternate mode).

If you keep holding it keeps toggling -- which is good I think since if you accidentally hold too long you just keep holding to correct and release when the LED is in the correct state.

As indicated this one only sends the CC messages after you release and then toggles the second byte of data to OFF and ON (0 and 127 as the code is now).


Ok so understanding the way you wrote it in mode when when I hit and release switch 0 it will send CC 60 and then in mode 2 when i hit switch 0 it will send code 80.

Upon toggling mode with long press an LED will show the alternate mode.

Questions:

1) which switch is the long press to activate the toggled mode?
2) can there be more than one alternate bank? i.e. array loaded depending on which switch is the long hold toggle activator?
 
1) Right now they all work as mode switch. If any fallingEdge() (contact) is detected the timer variable is set and the counter starts incrementing (technically the reset that would otherwise happen every cycle is bypassed and so the elapsedMillis variable is allowed to increment). If there is no risingEdge() (release) detected after 2000 mS (the value in resetThreshold) then the mode is toggled and the counter reset. If a risingEdge() is detected prior to that amount of time elapsing then the CC message for that switch in the current mode is sent.

2) Yes... it would be fairly simple to make bank an integer and to set it's value based on which switch triggered the fallingEdge that started the counter. And if you want feedback the simplest would be to make LEDPIN into an array and use the bank value as an index to track which should be on.
 
1) Right now they all work as mode switch. If any fallingEdge() (contact) is detected the timer variable is set and the counter starts incrementing (technically the reset that would otherwise happen every cycle is bypassed and so the elapsedMillis variable is allowed to increment). If there is no risingEdge() (release) detected after 2000 mS (the value in resetThreshold) then the mode is toggled and the counter reset. If a risingEdge() is detected prior to that amount of time elapsing then the CC message for that switch in the current mode is sent.

2) Yes... it would be fairly simple to make bank an integer and to set it's value based on which switch triggered the fallingEdge that started the counter. And if you want feedback the simplest would be to make LEDPIN into an array and use the bank value as an index to track which should be on.

ok this actually sounds amazingly flexible because it would give me very quick access to 25 different codes
 
It will be Wednesday next week before I'll have time at my Teensy setup so until then coding will be guesswork on a text editor.

But I believe the five-mode option is as simple as expanding the CC array to be five by five and to set bank to 'i' instead of toggling it between 1 and 0 with bank = !bank;

Now it will pick the mode based on the index of the switch you are holding down instead of just toggling; with very little coding change.

Code:
#include <Bounce.h>

//**********CONSTANTS**********
const int BOUNCE_TIME = 25; // fine tune if the buttons need more/less time
const int LEDPIN = 13; // Upper BANK indicator LED 
const int DIGITAL_PINS = 5; // size of the PINS array (no longer includes toggle button!)
const int PINS[DIGITAL_PINS] = {0,1,2,3,4}; // set pin numbers of swtiches
const int channel = 1;
const int ONvalue = 127; // arbitrary 'on' value for D2 of CC message
const int OFFvalue = 0; // arbitrary 'off' value for D2 of CC message
const int resetThreshold = 2000; /// mS hold to change bank

const byte CC[][DIGITAL_PINS] = {
[COLOR="#FF0000"]  {60,61,62,63,64},
  {65,66,67,68,69},
  {70,71,72,73,74},
  {75,76,77,78,79},
  {80,81,82,83,84},
  {85,86,87,88,89}[/COLOR]
}; // this is the banks by switches matrix of CC values for the bank system

//**********VARIABLES/LIBRARY OBJECTS**********
int bank = 0; // this is the bank variable to be toggled
boolean CCstate[DIGITAL_PINS]; // array of current CC on/off toggle state
boolean timerOn; // timer toggle memory tracks whether a new fallingEdge was heard since the last rising; used in bank switching

Bounce btn[] = {
  Bounce(PINS[0], BOUNCE_TIME),
  Bounce(PINS[1], BOUNCE_TIME),
  Bounce(PINS[2], BOUNCE_TIME),
  Bounce(PINS[3], BOUNCE_TIME),
  Bounce(PINS[4], BOUNCE_TIME),
  };
elapsedMillis toggleReset; // mS clock counter to reset on contact/risgingEdge()

//**********SETUP**********
void setup() {
  //Serial.begin(9600);
  for (int i = 0;i<DIGITAL_PINS;i++){
    pinMode(PINS[i], INPUT_PULLUP);
  }
  pinMode(LEDPIN, OUTPUT);
}

//**********LOOP**********
void loop() {
  for (int i = 0;i<DIGITAL_PINS;i++){ // loop through each object in the BOUNCE arrray for the note switches (no longer includes TOGGLE)
    btn[i].update();
    if (btn[i].fallingEdge()) {
      timerOn = true ;
      toggleReset = 0;
    }
    if (btn[i].risingEdge()) {
      if(toggleReset<resetThreshold){
        if (CCstate[i]){ 
          usbMIDI.sendControlChange(CC[bank][i], ONvalue, channel); 
        }else{
          usbMIDI.sendControlChange(CC[bank][i], OFFvalue, channel);  
        }
        CCstate[i] = !CCstate[i] ; //toggle state memory
        timerOn = false ; //turn off timer (resets each cycle)
      }
    }
    if (timerOn && (toggleReset>resetThreshold)){
      toggleReset = 0;
      bank =[COLOR="#FF0000"] i;[/COLOR]
[COLOR="#FF0000"]      //digitalWrite(LEDPIN, bank); // turn off for now...[/COLOR]
    }
  }
}

So then you have the display issue. The LED is disabled for now.
 
... it would be fairly simple to make bank an integer and to set it's value based on which switch triggered the fallingEdge that started the counter. And if you want feedback the simplest would be to make LEDPIN into an array and use the bank value as an index to track which should be on.

It is the risingEdge which selects the bank. The fallingEdge of any button starts the counter.

There is only one counter so it will be reset if a second button is pressed while one is already down and (I think) the first to rise (be released) after passing the the threshold that will select the mode.

In normal operation it won't matter but just in case you were trying to follow the logic.

You might want to reduce the timing threshold to 1500 or even 1000 as holding two seconds seems very long.
 
It is the risingEdge which selects the bank. The fallingEdge of any button starts the counter.

There is only one counter so it will be reset if a second button is pressed while one is already down and (I think) the first to rise (be released) after passing the the threshold that will select the mode.

In normal operation it won't matter but just in case you were trying to follow the logic.

You might want to reduce the timing threshold to 1500 or even 1000 as holding two seconds seems very long.

Ok so I can reduce the timing. Can the code be setup so that the bank selected after the timer is based on which pin is the rising edge? so if rising edge is pin 0 load Array A and is risingedge is pin 1 load array B and if risingedge is pin 2 load Array C?


As far as constructing the components. For LEDs do I need resistors in the signal chain?

I have just the board with pins in it. How would you recommend connecting the switches and leds to the pins on the board? Are there some specific kinds of connectors? Or should I just use breadboard or something like that?
 
...Can the code be setup so that the bank selected after the timer is based on which pin is the rising edge? so if rising edge is pin 0 load Array A and is risingedge is pin 1 load array B and if risingedge is pin 2 load Array C?
Not sure what you're getting at. I think your asking for what the code already does but I'm not sure.

As far as constructing the components. For LEDs do I need resistors in the signal chain?
Always

I have just the board with pins in it. How would you recommend connecting the switches and leds to the pins on the board? Are there some specific kinds of connectors? Or should I just use breadboard or something like that?
Breadboard to get it working. If all you have is switches and LEDS you can use female jumper wires when you move off the breadboard (if you are OK soldering the resisters in line with the LED leads and shielding the leads).

See this thread https://forum.pjrc.com/threads/4719...dboarding-jumper-wires-outside-of-prototyping
 
You can get LEDS with resistors inline but you can make the same thing with heat shrink tubing and solder.

mc6Jl8L5P9VgQ27fl7XS1ww.jpg
 
Do you have a midi monitor program to listen?

i used midi ox and midi tools to try to monitor the input from the teensy and it was intermittent. It picked up some things some times but it was not anything that I could understand as CC codes. It certainly did not show anything in my DAW.
 
i have the switches going to ground and then also to the input of the pins and then a jumper from teensy ground pin to ground line on breadboard.,

midi.jpg
 
I was testing with a wire from ground to pull each pin LOW as needed. Was working for me.

I don't know how this code could produce anything other than CC.
 
Like I said... the code seemed to do what I expected when pulling pins to ground with a wire. I'm pretty confident it works.
 
Do you think that I have the footswitch pole pieces wrong? I didn't think the orientation of the switch poles really made a difference
 
Status
Not open for further replies.
Back
Top