Teensy Midi Controller Project Advice/Journal

Status
Not open for further replies.
All the joints are soldered even if a bit of wire comes out either end of the joint. The terminals are connected to the wire and then the wire into the breadboard alongside the corresponding PIN number.
 
So actually I'm leaving the switches out of it and just doing jumper from pin to geound and can only get it to work intermittently for pin 0 and pin 1
 
So just one switch to pin for in midi monitor I get 63 127 on press 1 then 63 0 then 63 127 then 63 0. And then it hangs and it gets stuck until I unplug and replug the teensy
 
I'm not sure what's going on.... I'll retest my code but it won't be today.

The wire to ground test should have worked and the messages seem correct for one pin before if freezes up.

You could try the code from post 33 in case I added the problem in the five-modes version
 
I tested more and found the issue to reside in midiox. Once I switched to miditools to monitor it worked smoothly. So no issues with the code it is sending all the messages.

The hold time for toggling is a bit long if probably lower it to 1s. One touch is quite fast and not likely to be confused with a brief hold. Or else two quick taps instead of a long hold.

My question now lies in the bank switching. Is the bank switching dependent on which switch is the long press? Sometimes holding pin zero will result in switching from 60 to 80. Pin 0 should call only one definitive bank. Pin 1 the same. The switching does not seem absolute based on pin held down
 
Also can the array for CC contain D1 and D2 of the CC message? So instead of sending 60 127 and then 60 0 it will just always send 60 0? Or 60 1?

It seems the software I'm using accepts codes for CC this way. You declare which CC so say CC 0 and then it uses D2 to make the switching. So everything would be base CC 0 and unique codes would be set via D2 so it would be like this?

{0 1,0 2,0 3,0 4,0 5}
{0 6,0 7,0 8,0 9,0 10}
 
ok i think im starting to learn here.

we dont need any on or off constant because we are using D2 for the variance in switches. the constant is going to be d1 and we should set it to 0 for now.

i made some changes, replaced the on off with CCchan and switched the output message to send CCchan as D1 and CC[bank] as D2. what do you think?


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;
[COLOR="#0000CD"]const int CCchan = 0; // arbitrary 'on' value for D2 of CC message[/COLOR]
const int resetThreshold = 2000; /// mS hold to change bank

const byte CC[][DIGITAL_PINS] = {
  {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}
}; // 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(CCchan, CC[bank][i], channel); 
        }else{
          usbMIDI.sendControlChange(CCchan, CC[bank][i], channel);  
        }
        CCstate[i] = !CCstate[i] ; //toggle state memory
        timerOn = false ; //turn off timer (resets each cycle)
      }
    }
    if (timerOn && (toggleReset>resetThreshold)){
      toggleReset = 0;
      bank = i;
      //digitalWrite(LEDPIN, bank); // turn off for now...
    }
  }
}
 
oh i want to figure out how to not send CC code after toggling. Just complete the bank integer storage but not send a cc code. only send cc code if togglereset<resetThreshold
 
can it work like this?

Code:
if (btn[i].risingEdge()) {
      if(toggleReset>resetThreshold){
             toggleReset = 0;
             bank = i;
             //digitalWrite(LEDPIN, bank); // turn off for now...
          
      }
        else{
          usbMIDI.sendControlChange(CCchan, CC[bank][i], channel);  
          timerOn = false ; //turn off timer (resets each cycle)
        }
        
        
      }
   
      
    }
 
... Is the bank switching dependent on which switch is the long press? Sometimes holding pin zero will result in switching from 60 to 80. Pin 0 should call only one definitive bank. Pin 1 the same. The switching does not seem absolute based on pin held down
I don't recall how well I tested but the intended behavior is to change mode to whatever switch was down longer than the threshold time. The problem testing it is not having the feedback of the LED like you do in the two-mode version. Maybe the LED could flash i+1 times (1 to 5) to tell you what mode was selected (and the flashing would tell you the command took as well).

Also can the array for CC contain D1 and D2 of the CC message? So instead of sending 60 127 and then 60 0 it will just always send 60 0? Or 60 1?

It seems the software I'm using accepts codes for CC this way. You declare which CC so say CC 0 and then it uses D2 to make the switching. So everything would be base CC 0 and unique codes would be set via D2 so it would be like this?

{0 1,0 2,0 3,0 4,0 5}
{0 6,0 7,0 8,0 9,0 10}
D1 is the CC message and D2 is it's parameter value. For on/off functions the convention is that D2<64 = OFF and >=64 is ON. I had assumed a common OFF and ON value would be enough but if you want these can be replaced by arrays. But now I'm not even sure you want toggling behaviour.

But I don't think you want to make D1 a single value as that will limit your code to only sending one CC message type. Even if you want that for now I'd say leave the CC array in place with all the same values in it.

oh i want to figure out how to not send CC code after toggling. Just complete the bank integer storage but not send a cc code. only send cc code if togglereset<resetThreshold
I thought it already works this way. That very test (togglereset<resetThreshold) is around the code that sends the CC.

I'll have to review your posts a little more carefully, in particular your code fragment.
 
I see the problem with the mode select... working on it but likely don't have time this morning.
 
Ok i think it is about time to discuss the more detailed purpose of the project.

It is to be used for live guitar. The input signal is routed through the DAW software Reaper.

In Reaper there are Tracks that the signal can be processed through. Each track has a configuration of FX that process the input signal.

Two things are desired. Capability of switching tracks and capability of turning FX on and off inside the individual track.

Switching tracks is handled by using diffreent values of one control code. So 0 60, 0 61, 0 62 etc. where the second value is the switch.

Switching FX internal to the track is handled by CC D1. so 0 is just the Control Code series for changing tracks. All other CC are to switch FX>

so there needs to be a toggle between mode. I was thinking that eventually I can have one row of buttons to send CC 0 codes. and then all the other switches can use CC 1-127





for the five switch method i am thinking of a toggle integer. say FxMode

The toggle integer can be set when the first switch is pressed.

risingedge if togglereset<resetThreshold { usbMIDI send.ControlCode(CCChan, CC[bank], channel; timer=0;FxMode=1;)


that way we can do

if togglereset<resetThreshold && FxMode=1 { usbMIDI send.ControlCode(CC[bank], CCChan, channel)}



Long Hold enters CC0 mode by setting the toggle integer to CC0 mode and selecting the bank for that pin.

if timeron && togglereset > resetThreshold {
timer=0;
bank=i;
FxMode=0;
}
 
So for the Reaper track select you don't want toggle off and on behaviour at all... you want 'send this CC message the same every time'?

It's easy to add arrays for the ON and OFF D2 values, so if you do want that behaviour you would just configure that row to have the same OFF and ON values so that it's toggle state doesn't matter.

I really don't know what's wrong with my bank select logic but I definitely saw some buggy behaviour so I'll have to have a look into that later. I think I'm not setting the timer ON/OFF variable correctly and the timer is running at times other than intended.

In the meantime the changes to my existing code to add individually configurable ON/OFF values are very minimal and I've entered values that should demo the 'specialty' CC messages you're looking for (assuming I'm reading you correctly).

Just define ONvalue and OFFvalue as two dimensional arrays the same as CC[][] and then feed them the same index values inside the MIDI send:

Code:
[COLOR="#FF0000"]const byte ONvalue[][DIGITAL_PINS][/COLOR] = {
  {65,66,67,68,69},
  {127,127,127,127,127},
  {127,127,127,127,127},  
  {127,127,127,127,127},  
  {127,127,127,127,127}
};
[COLOR="#FF0000"]const byte OFFvalue[][DIGITAL_PINS][/COLOR] = {
  {65,66,67,68,69},
  {0,0,0,0,0},
  {0,0,0,0,0},
  {0,0,0,0,0},
  {0,0,0,0,0},
  {0,0,0,0,0}
};
 ...
const byte CC[][DIGITAL_PINS] = {
  {0,0,0,0,0},
  {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}
};
...

      if(toggleReset<resetThreshold){
        if (CCstate[i]){ 
          usbMIDI.sendControlChange(CC[bank][i], ONvalue[COLOR="#FF0000"][bank][i][/COLOR], channel); 
        }else{
          usbMIDI.sendControlChange(CC[bank][i], OFFvalue[COLOR="#FF0000"][bank][i][/COLOR], channel);  
        }
        CCstate[i] = !CCstate[i] ; //toggle state memory
        timerOn = false ; //turn off timer (resets each cycle)
      }

Assuming the bug in my mode logic is just some boneheaded mistake I haven't noticed yet I should be able to sort it out tonight.
 
No there is no need for on or off values.

The track switching uses Control Code 0 as a channel.

Track switching performs various muting and unmuting tasks based upon which CC 0 value is sent.


Inside the individual tracks the fx are switched on and off using CC. They don't look at the value just the control code. That's why the track switching is limited to CC 0 so that the rest of CC 1-127 is available for different fx switching
 
BONE HEAD! I'm a BONE HEAD

I found the error in logic... I the timing thing only works as a toggle (bank = !bank) because the i indicator is in a randomish position when the timing threashold happens to cross after you start up the timer with a button press. For toggle that doesn't matter as there is only one other state but for a mode select it won't work.


I think the solution is to test the state of the pin as a regular digital read (rather than the BOUNCE edge detection) and if LOW and the time is over the threashold then that is the pin's index becomes the bank value.

Since the pin has ages to settle we don't need to use BOUNCE to see if the pin is being pulled to ground.

I'll give that a go when I'm at the compiler tonight.
 
So if btn rising edge && togglereset>resetThreshold. ?
Nearly...

if (digitalRead[PINS]=LOW && togglereset>resetThreshold){...}

or something like that... I'm saying don't worry about the BOUNCE edges as they are long ago by the time the code gets here but the pin reading itself will be stable and so BOUNCE is not needed either.

I need a compiler to stop me from including nonsense so if you can you may want to wait until I can give you working code.

(EDIT - reading the pin may be something we shouldn't do every pass of the code since we don't have to and so it might be better to test the threshold first and only read the pin if we're in the long-hold already).
 
Nearly...

if (digitalRead[PINS]=LOW && togglereset>resetThreshold){...}

or something like that... I'm saying don't worry about the BOUNCE edges as they are long ago by the time the code gets here but the pin reading itself will be stable and so BOUNCE is not needed either.

I need a compiler to stop me from including nonsense so if you can you may want to wait until I can give you working code.

(EDIT - reading the pin may be something we shouldn't do every pass of the code since we don't have to and so it might be better to test the threshold first and only read the pin if we're in the long-hold already).


ok ill wait for you before proceeding to think of any changes or testing.

Thanks for this experience by the way. It is giving me an organic learning experience. I already am starting to learn how it works.
 
Nearly...

if (digitalRead[PINS]=LOW && togglereset>resetThreshold){...}

or something like that... I'm saying don't worry about the BOUNCE edges as they are long ago by the time the code gets here but the pin reading itself will be stable and so BOUNCE is not needed either.

I need a compiler to stop me from including nonsense so if you can you may want to wait until I can give you working code.

(EDIT - reading the pin may be something we shouldn't do every pass of the code since we don't have to and so it might be better to test the threshold first and only read the pin if we're in the long-hold already).


so in theory you could also set that time to be the switching time for int FxMode

that way if FxMode=1 send CC if FxMode = 0 send CC 0 Value. the array can stay the same even for the banks. Its simply switching the order of the code for constant vs bank variable
 
you can try this line in the existing code structure and it might work... I think the timer variable needs to be reset in there too.

But if it won't compile I have some syntax issue that you may or may not want to get bogged down with it right now.
 
so in theory you could also set that time to be the switching time for int FxMode

that way if FxMode=1 send CC if FxMode = 0 send CC 0 Value. the array can stay the same even for the banks. Its simply switching the order of the code for constant vs bank variable

My proposed code already does this for bank 1 if I'm understanding exactly what you want from this!

Bank 1 (bank=0 as index) is set up with CC values all zero.

And the ONvalue and OFFvalue entries are the same in each column.

If you release the first switch (before the threshold) then the MIDI message will be a CC with D1=0 and D2=65

It will be remembering that it is 'ON' (even though it doesn't matter) and then when you release the same button again it will use the OFFvalue for D2 but it's the same (on the assumption I mentioned in the threads above that this is what you want!!!).

The other banks are set up conventionally as OFF/ON toggles with 0 and 127 as the corresponding D2 values.
 
Status
Not open for further replies.
Back
Top