joshnishikawa / MIDIcontroller

A library for creating Teensy MIDI controllers with support for hold or latch buttons, potentiometers, encoders, capacitive sensors, Piezo transducers and other velocity sensitive inputs with aftertouch.
223 stars 19 forks source link

Threshold Adjustment for MIDIswitch #27

Closed digitalelements closed 1 year ago

digitalelements commented 1 year ago

Is it possible to bring the setThreshold forward into my sketch ? I'm attempting to use one of my FSR pads as the switch. The behavior works great when I press my FSR but it will not respond to a strike from a drum stick.( my FSR is covered with a 6mm silicone layer) I'm using the FSR straight in to a digital pin ( 10 which is in the example sketch). I have not included a 10K resistor or 3.3v from the Teensy. I'm only guessing that it would take a threshold adjustment to make this work.

Thanks!

joshnishikawa commented 1 year ago

I assume that the other side of your FSR is attached to ground? setThreshold expects an analog value. Pin 10 is digital only so the Teensy has a minimum voltage that's considered HIGH. Anything below that is LOW. I'm not exactly sure what that voltage is but setThreshold wouldn't affect it.

Surprisingly, a naked FSR works fine for me as a MIDIswitch wired directly between ground and a digital pin. This is true whether I'm pressing the FSR with my finger or thumping it quickly with my fingernail. If I use INPUT_PULLUP in the bounce_button sketch from the Bounce2 library, it works just as well.

I don't think the silicone should make a difference. If it works when you press it, it should be fast enough to detect when you hit it too. I'd suggest using a MIDIdrum object on an analog pin and calling int myVar = myPad.read() in your loop. That will read what the MIDI output would be without actually sending it. Then do what you like with myVar.

By the way, what are you trying to do? toggle an effect? trigger a record button? scroll through options?

digitalelements commented 1 year ago

Yes .. my FSR is attached to ground. And, I was excited that the naked FSR was working so well when pressed using the MIDIswitch sketch. I was going to ask if I could combine a MIDIdrum, MIDIswitch and MIDIenc gracefully in a single sketch.

I'm building a device to navigate presets by sending MIDI program change ( instead of a MIDI CC ) which is another question.

I hope to have the MIDIenc send program changes as it does CC messages. The drum pad will send +1 to increment the program changes. There will also be a foot switch that also sends +1 to increment the program changes. The last function is that when the foot switch is pressed ( and held) that the drum pads function becomes -1 midi program change. this a bit of a "drummers" preset navigator. you don't have to put your sticks down to change presets.

digitalelements commented 1 year ago

Hey Josh,

I'me starting to experiment again with the the box that's loosely described above. I wanted to ask if it is even possible to have the encoder send MIDI program changes is a similar manner to the way it send CC messages ? You also mentioned it may be possible to use the int myVar = myPad.read() to send an incremental change in a CC value ? would you mind sharing what something like this might look like in a sketch. I'm having a tough time getting my head around it .... Sorry.

joshnishikawa commented 1 year ago

Program change is on the list of basic functionalities that this library doesn't handle yet. Update to version 2.6.6 and give this sketch a shot...

#include "MIDIcontroller.h"

byte MIDIchannel = 0;
const byte switchPin = 19;
const byte encoderPinA = 18;
const byte encoderPinB = 17; 
const byte padPin = 14;
int programNumber = 0;

MIDIdrum myPad(padPin, 37);
MIDIenc myEnc(encoderPinA, encoderPinB, 36, PER_DETENT);
MIDIswitch mySwitch(switchPin, 35, TRIGGER);

void setup() {
  pinMode(switchPin, INPUT_PULLUP);
  myPad.inputRange(12, 720);
  myPad.sensitivity(99); // This is still experimental!
}

void loop() {
  int encValue = myEnc.read();
  int switchValue = mySwitch.read();
  int padValue = myPad.read();

  if ( encValue >= 0 ){
    programNumber = encValue;
    usbMIDI.sendProgramChange(programNumber, MIDIchannel);
  }

  if ( switchValue > 0 ){
    programNumber = min(127, programNumber + 1);
    myEnc.write(programNumber); // keep the encoder up-to-date
    usbMIDI.sendProgramChange(programNumber, MIDIchannel);
  }

  // whether myPad increments or decrements
  // depents on the state of the footswitch
  if ( padValue > 0 ){ // only inc/dec on rising edge
    if ( digitalRead(switchPin) == LOW ){
      programNumber = max(0, programNumber - 1);
    } else {
      programNumber = min(127, programNumber + 1);
    }

    myEnc.write(programNumber); // keep the encoder up-to-date
    usbMIDI.sendProgramChange(programNumber, MIDIchannel);
  }
}

...and beware of bugs. I still need to go through this library with a fine-toothed comb (again).

digitalelements commented 1 year ago

Thank you Josh, This is very much appreciated ! .. I'm not afraid of bugs. I'm here for the long haul and ready and willing to chase and find bugs whenever you need. :)

digitalelements commented 1 year ago

Hey Josh,

The sketch is a super solid starting point. I do have some quirks to work out but it working pretty well. I'll keep you posted.

digitalelements commented 1 year ago

Hey Josh, Sure is fun working with this sketch. I did discover a few little quirks. first was pinMode(LEDpin, OUTPUT); was not declared in the scope. I did attempt to fix it but it was over my head. So, I just commented it out. The other thing was the encoder is not able to reach program 1 (0 in the data) However, I can press the foot switch and strike the pad to get to program 1. I am using encoders that have a push switch which makes me think I should add that to the sketch and use it to "reset" all to program zero. Thoughts ?

joshnishikawa commented 1 year ago

Ah, I was using the LED for testing and deleted the declaration but didn't delete the call to pinMode(LEDpin, OUTPUT). That line can just be deleted. As for not getting a 0, that line should read if ( encValue >= 0 ){ ( just an added = ). I edited the code above.

I also realize that continuing to turn the knob past 0 or 127 took you into a dead zone where you'd have to turn the knob back the opposite way to get out of. Unfortunately, you'll have to upgrade to 2.6.7 to fix that one.

digitalelements commented 1 year ago

Great stuff :) thank you. I've also updated to 2.6.7 as recommended. everything can reach both ends of the data values. and, it's nice that it stops at either end (0 or 127)

I'm chasing a bit of an issue with the pad. I'm not quite sure it has anything to do with the code. but I'm not totally sure. from time to time the pad will stop responding entirely. This is all on a breadboard at the moment. so, it could be my connections and I'm also try another FSR to rule that out. cheers!

joshnishikawa commented 1 year ago

I'm not getting any problems like that. Breadboards are notorious but it could be a number of things. Keep testing and, if you're pretty sure it's a problem with the library, go ahead and open another issue. I think the original issue here has been addressed. We got into Program Changes and I thought that was important enough to open a separate issue...so I did. Let's close this one.

digitalelements commented 1 year ago

understood and agreed .. thank you