Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 16 of 16

Thread: Footsy - Teensy 2 based MIDI foot pedal controller

  1. #1
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Vancouver Canada
    Posts
    551

    Footsy - Teensy 2 based MIDI foot pedal controller

    Teensy-based MIDI foot-controller system -- just add sustain and expression pedals.
    Name:  footsy.jpg
Views: 5312
Size:  29.3 KB
    Physical build consists of nothing but a Teensy 2, some 1/4" sockets, a USB cable and a polystyrene enclosure.

    Here's a screenshot of the SysEx CC assign system (built with FlowStone [forum])
    Click image for larger version. 

Name:	sreeny.png 
Views:	924 
Size:	40.4 KB 
ID:	1115
    It sends a small (16 byte) sysex message to configure the box -- only nine bytes are program data, the rest is to make sure it's the intended message.
    (I used the private-use (non-commercial) sysex ID '7D' with an added four bytes as a 'key'.)
    The code also sends back three bytes as an acknowledge message.



    Code - fragments and ideas stolen liberally from all over but especially Knobber
    Code:
    #include <Bounce.h> 
    #include <EEPROM.h>
    const int thrshld = 7; // threshold for when change in voltage updates CC on analog pins
    const int delayL = 5; // > delay can reduce number of MIDI msgs - can be good or bad??
    // higher delay likely advantage if using lower threshold to limit repeats at same CC
    
    int chnl; // MIDI channel 
    int v0,v1;// analog values for volage from dividers
    int v0L, v1L;// lagged voltage values - last time cc was recalc'd
    int v0D = 10,v1D = 10; // delta values - current - lag; force cc to calc on init
    int toggled[3] = {false,false,false}; // toggle indicates when toggle behavior in effect
    int mem[14]={1,4,7,64,0,65,0,66,0};// an array of sysEx bytes, + defaults until EEPROM is loaded
    Bounce button[3] = {Bounce(0, 5),Bounce(1, 5),Bounce(2, 5)}; // init 'bounce' for 3 buttons
    
    void setup() {
      Serial.begin(31250);
      pinMode(0, INPUT_PULLUP); // set up three digital pins
      pinMode(1, INPUT_PULLUP); // with PULLUPs
      pinMode(2, INPUT_PULLUP); //
      if (EEPROM.read(0)>0 && EEPROM.read(0)<17){ // EEPROM @ 0 is non-zer0 or not a viable MIDI channel
        for (int i = 0; i <= 8; i++) { // read EEPROM for sysEx data
          mem[i] = EEPROM.read(i);
          delay(5); // give time for EEPROM read??
        }
        int chnl = mem[0];
      }
    }
    
    
    // *************THE MAIN LOOP************
    void loop() { 
      if(usbMIDI.read() && usbMIDI.getType() == 7) { //if MIDI is sysEx
        doSysEx(); // look for CC change msg
      }
      getAnalogData(); // get/process analog pins
      getDigitalData(); // get/process digital pins
     delay(delayL);
    }
    
    //************ANALOG SECTION**************
    void getAnalogData(){
      v0 = analogRead(0);
      v1 = analogRead(1);
      if (v0D > thrshld) // if delta variable shows change past threshold - recalulate
      {
        usbMIDI.sendControlChange(mem[1], v0/8, chnl); // calculate CC for analog 1 and send
        v0L = v0; // lag only on update
      }
      v0D = abs(v0L-v0);
      if (v1D > thrshld)
      {
        usbMIDI.sendControlChange(mem[2], v1/8, chnl); // calculate CC for analog 2 and send
        v1L = v1; // lag only on update
      }
      v1D = abs(v1L-v1);
    }
    
    //************DIGITAL SECTION**************
    void getDigitalData(){
      for (int i = 0; i < 3; i++){
        button[i].update(); //update bounce object for each button
        if (button[i].fallingEdge()) { // button press to ground
          if (toggled[i] && mem[i * 2 + 4]==1){ // if toggled state and toggle behavoiour both true...
            usbMIDI.sendControlChange(mem[i * 2 + 3], 0, chnl);  // unlatch to OFF
            toggled[i] = false      ;  // toggled to false for next time
          }
          else { // either latched and toggled==false or non-latched... 
            usbMIDI.sendControlChange(mem[i * 2 + 3],127, chnl); //...either way to to ON state
            if(mem[i * 2 + 4]==1){
              toggled[i] = true      ;  // but only change toggled state if in latched mode
            }
          }
        }
        if (button[i].risingEdge()) { // button release - pullup to HIGH
          if (not(mem[i * 2 + 4]==1)){ // if non-latched 
              usbMIDI.sendControlChange(mem[i * 2 + 3], 0, chnl);  // to to OFF
          }
        }
      }
    }
    
    //************SYSEX SECTION**************
    void doSysEx(){
      byte *sysExBytes = usbMIDI.getSysExArray();
      if (sysExBytes[0] == 0xf0 
      && sysExBytes[15] == 0xf7 
      && sysExBytes[1] == 0x7D // 7D is private use (non-commercial)
      && sysExBytes[2] == 0x4C // 4-byte 'key' - not really needed if via USB but why not!
      && sysExBytes[3] == 0x65
      && sysExBytes[4] == 0x69
      && sysExBytes[5] == 0x66){ // read and compare static bytes to ensure valid msg
          for (int i = 0; i < 10; i++) {
          EEPROM.write(i, sysExBytes[i+6]);
          mem[i] = sysExBytes[i+6];
        }  
        byte data[] = { 0xF0, 0x7D, 0xF7 }; // ACK msg - should be safe for any device even if listening for 7D
        usbMIDI.sendSysEx(3, data);         // SEND
        for (int i = 0; i < 3; i++) {
          toggled[i] = false; // for consistant behaviour, start in OFF position
        }
      }
    }
    Last edited by oddson; 11-23-2013 at 08:55 PM. Reason: updated code

  2. #2
    Senior Member MickMad's Avatar
    Join Date
    Feb 2013
    Location
    Essonne, France
    Posts
    141
    Nice stuff! I always wanted to make my very own MIDI foot controller w/ a Teensy. I also love the idea of using sysex messages to configure the thing

    I don't know what do you use this for, but I'd love to have something like 10 heavy-duty footswitches on mine, I don't like the idea of plugging things together to actually use something. You know, you could easily hack a few footswitches and expression pedal inside a bigger box and you'll have a ready-to-use all-in-one foot controller Keep up the good work

  3. #3
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Vancouver Canada
    Posts
    551
    Quote Originally Posted by MickMad View Post
    I don't know what do you use this for, but I'd love to have something like 10 heavy-duty footswitches on mine, I don't like the idea of plugging things together to actually use something. You know, you could easily hack a few footswitches and expression pedal inside a bigger box and you'll have a ready-to-use all-in-one foot controller Keep up the good work
    The plan is to make one with many momentary switches built in and with proper MIDI in/out/through. But it would still have external expression connections and at least two external switches as sustain pedals are so nice to 'play' -- rather than when you want to latch on an effect.

    This one was to get a build done quickly and cheaply. I love Teensy!

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,405
    Nice looking build.

    I'd like to show this on the Teensy Projects page. But an image at least 300 pixels wide is needed. Any chance you could post a higher res image?

  5. #5
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Vancouver Canada
    Posts
    551
    Quote Originally Posted by PaulStoffregen View Post
    Nice looking build.

    I'd like to show this on the Teensy Projects page. But an image at least 300 pixels wide is needed. Any chance you could post a higher res image?
    Thanks... Would look better if I could get three holes to line up!

    I'll post better photos shortly (took that one after midnight last night as I wanted to post something here in a hurry)...

    Can you hold off for a week or so with adding it to your projects page until I can polish things a bit and to show the FlowStone part on their site?

    And would you update with a link to my site (oddsonic.com) once I have something on it there? (It's just a placeholder site for the domain name with some of my music on in right now.)

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,405
    Sure, not a problem. Just post when you're ready.

  7. #7
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Vancouver Canada
    Posts
    551

    photos

    here are the photos for the project page and a link to a thread on the CC software on the FlowStone site.
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	footsy.JPG 
Views:	270 
Size:	54.7 KB 
ID:	1124   Click image for larger version. 

Name:	footsy_w_pedals.JPG 
Views:	379 
Size:	70.5 KB 
ID:	1123  

    Click image for larger version. 

Name:	footsy_wire.jpg 
Views:	410 
Size:	41.6 KB 
ID:	1130  
    Last edited by oddson; 11-23-2013 at 07:31 AM.

  8. #8
    Junior Member
    Join Date
    Oct 2014
    Posts
    3
    Hi!
    I am going to build one of theese. I have a Teensy 3.1 on its way but I have never programmed. So is it possible to get some help?
    How do I start?
    Can I download the program/ code?
    What program do I need?
    Is it possible to do this with a Mac? (I have both)

    Best Regards/
    Mårten

  9. #9
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,405
    Quote Originally Posted by pianomarten View Post
    How do I start?
    This tutorial is a pretty good starting point.

    http://www.pjrc.com/teensy/tutorial.html

    After you get Arduino + Teensyduino set up and you're able to upload the LED blink, perhaps open some of the examples, from File > Examples > Teensy > USB_MIDI. Even if those examples aren't exactly what you need, I'd highly recommend at least connecting a pushbutton and get it to send note-on & note-off messages to software on your Mac. It's always easier to begin a new project when you've got a solid working example as starting point.

  10. #10
    Senior Member
    Join Date
    Jan 2013
    Posts
    964
    The enclosure in the images posted earlier in this thread look like the small enclosures from Hammond MfG.
    Just in case they are not, Hammond makes these nice aluminum Die Cast boxes spcifically for Stomp Boxes.
    Avaiable from Digikey and other sources. The smaller boxes cost about $10.

  11. #11
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Vancouver Canada
    Posts
    551
    Quote Originally Posted by pianomarten View Post
    Hi!
    I am going to build one of these...
    The physical build is very simple. (@Headroom - It is a Hammond 1590B project box but --as mentioned in the initial post-- it's just Polystyrene as die-cast aluminum for EM shielding isn't needed for and non-audio project like this.)

    I have a Teensy 3.1 on its way...
    I don't know if any changes to my code above are required for a teensy 3.x as I built mine with a 2.x.
    ...but I have never programmed.
    Hopefully you have the left-brain skills that makes programming make sense for you. Arduino programming is fairly straightforward but it's still programming. Take the time with Paul's tutorials before trying to move on.

    So is it possible to get some help?
    There's a lot of help available here if you put in some effort. If there's something about my code you need help with I'd be happy to assist.

    Is it possible to do this with a Mac?
    The Teensyduino software is available for the Mac but the Flowstone 'CC Assign Tool' applet referenced above works only on Windows. But you can skip it altogether and just use hard-coded CC parameters into your device or find another program to send MIDI Sysex to the device. It's just 16 bytes of Sysex data and there are lots of Mac programs that could do this part, although likely without a graphical user-interface for picking the parameters.

  12. #12
    Junior Member
    Join Date
    Oct 2014
    Posts
    3
    Thanks for your answers. I have done the blink programming so I know it is working. I think I'll skip the sysex for now. I want to have only 2 foot pedals. One for changing patch in MainStage (cc04 or 03) and one for sustain pedal on cc64 can I do a program like these?

    Is this totally wrong?

    #include <Bounce.h>

    const int channel = 1;

    Bounce button0 = Bounce(0, 5);
    Bounce button1 = Bounce(1, 5);


    void setup() {

    pinMode(0, INPUT_PULLUP);
    pinMode(1, INPUT_PULLUP);

    }

    void loop() {

    button0.update();
    button1.update();



    if (button0.fallingEdge()) {
    usbMIDI.setHandleControlChange(03, 127, channel); //cc03
    }
    if (button1.fallingEdge()) {
    usbMIDI.setHandleControlChange(64, 127, channel); //cc64
    }


    while (usbMIDI.read()) {
    // ignore incoming messages
    }
    }
    Last edited by pianomarten; 11-04-2014 at 10:02 PM.

  13. #13
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Vancouver Canada
    Posts
    551
    Your going 'on' when switch goes off and you're not dealing with the rising edge... but you're not too far off from what I can see.

  14. #14
    Junior Member
    Join Date
    Oct 2014
    Posts
    3
    I don't understand. Do I need the rising edge too? Like this:

    if (button0.risingEdge()) {
    usbMIDI.setHandleControlChange(03, 0, channel); //cc03
    }
    if (button1.risingEdge()) {
    usbMIDI.setHandleControlChange(64, 0, channel); //cc64
    }

    ...Or should i just change falling to rising?


    Sorry for hi-jacking your thread.
    Last edited by pianomarten; 11-04-2014 at 10:03 PM.

  15. #15
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Vancouver Canada
    Posts
    551
    Honestly I'm not too sure... I was barely competent at this when I made it a year or more ago but (unless I'm badly mistaken) you need something to send back an 'off' state when you let up on the pedal. That's assuming you're making momentary switch like a sustain pedal and not a toggle switch. If a toggle switch then you can ignore the falling state and have it change on the rising but you have to keep track of what state it was in last.

    But assuming you do want a sustain-type momentary switch then you need to send a zero value when the switch is 'off'. And if so I think the what you have above is correct but possibly backward...

    Because the next complicating factor is that some switches are normally open and some normally closed. If it's normally closed then you want the falling state to represent the 'on' state (MIDI=127) and the rising 'off' (MIDI=0) which is what you appear to have above.

    Anyone else care to help with this... I'd hate to be mis-remembering how this works.
    Last edited by oddson; 11-05-2014 at 02:04 AM.

  16. #16
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Vancouver Canada
    Posts
    551

    You were close

    You were really close... although you did change the MIDI function name (setHandleControlChange?) which I didn't notice and caused me a bit of confusion when I got a compiler error with your code...

    This worked for me:
    Code:
    #include <Bounce.h>
    
     const int channel = 1;
    
     Bounce button0 = Bounce(0, 5);
     Bounce button1 = Bounce(1, 5); 
    
      
     void setup() {
       Serial.begin(31250);
       pinMode(0, INPUT_PULLUP);
       pinMode(1, INPUT_PULLUP);
     }
    
     void loop() {
    
     button0.update();
     button1.update();
    
    
    
     if (button0.fallingEdge()) {
     usbMIDI.sendControlChange(3, 127, channel); //cc03
     }
     if (button1.fallingEdge()) {
     usbMIDI.sendControlChange(64, 127, channel); //cc64
     }
     if (button0.risingEdge()) {
     usbMIDI.sendControlChange(3, 0, channel); //cc03
     }
     if (button1.risingEdge()) {
     usbMIDI.sendControlChange(64, 0, channel); //cc64
     }
    
     while (usbMIDI.read()) {
     // ignore incoming messages
     }
     }
    If your switches are normally closed just swap the zero and the 127 values.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •