Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
jetrock
Published © GPL3+

USB Footswitch from Boss FS-5U, 6U and Similar

Build a small and robust device with minimal effort, turning any jack plug footswitch into a USB footswitch.

BeginnerFull instructions provided3,217
USB Footswitch from Boss FS-5U, 6U and Similar

Things used in this project

Story

Read more

Code

USB Foot switch

C/C++
#include <Keyboard.h>
//######################################################################################

//######################################################################################
//User Settings:
//Character(s) sent to USB when the "Tip" Button is pressed shortly
char Char_Tip[] ={' '};//start/stop command for many Apps. Hydrogen, Audacity, Transcibe!, YouTube, etc.
//Character(s) sent to USB when the "Tip" Button is pressed for at least LongPressTime ms 
char Char_Tip_Long[] = {KEY_LEFT_ALT, KEY_TAB};//Switching to previous App

//Character(s) sent to USB when the "Ring" Button is pressed shortly
const char Char_Ring[] ={','};//tapping the BPM for Hydrogen
//Character(s) sent to USB when the "Ring" Button is pressed for at least LongPressTime ms 
const char Char_Ring_Long[] ={KEY_LEFT_ALT, KEY_TAB};//Switching to previous App

int LongPressTime=700; //milliseconds 
int delayafterrelease=200;//milliseconds
int CMode=0; //Cable mode, Mono- or Stereo cable
//######################################################################################
//Cablemode 0: Autodetect
//    For Mono or Stereo cable Ring contact is always "connected" to ground (Boss FS-5U)
//    If AutoDetectStereo is 1: At Powerup for three seconds the signal of Ring_Tip
//    is evaluated. If it is LOW all the time (contact closed) a mono setup is assumed.
//    This is not hot-plugable. If cables are changed please reset by reconnecting usb.
//Cablemode 1: Mono or Stereo Cable, One Button, Tip contact only
//Cablemode 2: 2x mono to stereo, Two Buttons or Boss FS-6

//Button Commandes: KEY_RETURN, KEY_ESC, KEY_F1.., KEY_BACKSPACE, KEY_LEFT_CTRL...
//https://www.arduino.cc/en/Reference/KeyboardModifiers
//https://www.electronicsweekly.com/blogs/engineer-in-wonderland/arduino-micro-direct-access-board-leds-2017-08/
//----------------------------------------------------------------------------------------------------------
const int RXLED = 17; // The RX LED has a defined Arduino Micro pin
const int TXLED = 30; // The TX LED has a defined Arduino Micro pin
const int Pin_Ring = 2;
const int Pin_Tip = 7    ;
int Stat_Ring=0;
int Stat_Tip=0;
int RingPressedTime=0;
int TipPressedTime=0;
unsigned long int presstime;
int  lenRingCmd,lenRingLongCmd;
int  lenTipCmd,lenTipLongCmd;
//----------------------------------------------------------------------------------------------------------
void setup() {
  //turn off all LED
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(RXLED, OUTPUT); // Set RX LED as an output
  pinMode(TXLED, OUTPUT); // Set TX LED as an output
  digitalWrite(LED_BUILTIN, HIGH); // turn the LED off by making the voltage LOW
  digitalWrite(RXLED, HIGH); // set the LED off
  digitalWrite(TXLED, HIGH); // set the LED off
  // put your setup code here, to run once:
  pinMode(Pin_Ring, INPUT_PULLUP);
  pinMode(Pin_Tip, INPUT_PULLUP);
  digitalWrite(Pin_Ring, HIGH);
  digitalWrite(Pin_Tip, HIGH);

  lenRingCmd     =sizeof(Char_Ring)/sizeof(Char_Ring[0]); //number of keystrokes to be transmitted
  lenRingLongCmd =sizeof(Char_Ring_Long)/sizeof(Char_Ring_Long[0]);
  lenTipCmd      =sizeof(Char_Tip)/sizeof(Char_Tip[0]);
  lenTipLongCmd  =sizeof(Char_Tip_Long)/sizeof(Char_Tip_Long[0]);

  int locount=0; // number of events with Pin_Ring==low (contact closed)
  int hicount=1;// number of events with Pin_Ring==high (contact open), starts with 1 to avoid zero division
  if (CMode==0){
    for (int i=0; i<300; i++){ // testing for 3 seconds, counting open and close events
      if (LOW==digitalRead(Pin_Ring))
        locount+=1;
      else
        hicount+=1;
      delay(10);
    }
    if (locount/hicount < 0.01)//if highcount (open) is much higher than locount (closed) the Ring/Ground contact
                               //is not permamently closed. A stereo cable is used. Seems to be more stable than testing
                               //for a single open event.
      CMode=2;//stereo cable
    else 
      CMode=1;//mono cable
  }
  Keyboard.releaseAll();//you never know ;-)
}
//----------------------------------------------------------------------------------------------------------
void loop() {
  // put your main code here, to run repeatedly:
  int pressed=0;
  Stat_Ring=0;
  Stat_Tip=0;

//might be a good idea to use interrupts some day
  for (int i=0; i < 5; i++){
    delay(10);
    if (LOW==digitalRead(Pin_Ring)){
        Stat_Ring=1;  // This one is always 1 with a mono cable. With stereo cable 1 means button is pressed
    }
    if (LOW==digitalRead(Pin_Tip)){
        Stat_Tip=1;// 1 means button pressed with any cable
    }
  }

//Selecting and sending the keyboard commands:
  if (CMode==2){ //Ring contact is used. 2xmono->stereo or stereo->stereo configuration
    if (Stat_Ring==1){
      presstime=millis();//remember time of pressing event (ring contact)      
      while (LOW==digitalRead(Pin_Ring))
        delay(10); // wait for button being released. delay could be removed
      if (millis()-presstime > LongPressTime)//if button has been pressed longer than LongPressTime use long command
        for (int r=0; r<lenRingLongCmd; r++)//send all keyboard commands in the list
          Keyboard.press(Char_Ring_Long[r]);
      else
        for (int r=0;r<lenRingCmd;r++) //otherwise use short command
          Keyboard.press(Char_Ring[r]);
      pressed=1;//button has been pressed
    }
  }  
  
  if (Stat_Tip==1){//same as Ring Contact, for any CMode
    presstime=millis();
    while (LOW==digitalRead(Pin_Tip))
      delay(10); 
    if (millis()-presstime > LongPressTime)
      for (int t=0; t<lenTipLongCmd; t++)
        Keyboard.press(Char_Tip_Long[t]);
    else
     for (int t=0; t<lenTipCmd; t++)
        Keyboard.press(Char_Tip[t]);
    pressed=1;
    }
  
  if (pressed==1){
    Keyboard.releaseAll();
    delay(delayafterrelease);//make sure that no button press event is detectd during button release
    pressed=0;
  digitalWrite(LED_BUILTIN, HIGH); // turn the LED off by making the voltage LOW
//One could use these two LEDs for indicating CableMode
  digitalWrite(RXLED, HIGH); // set the LED off
  digitalWrite(TXLED, HIGH); // set the LED off
  }
  }
//----------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------  

 

Credits

jetrock
0 projects • 1 follower
Contact

Comments

Please log in or sign up to comment.