Converted my Arduino foot pedal into a Teensy foot pedal!

Look at how neat my foot pedal looks now! It’s much better than my dangling-wires prototype with the Arduino. At just 0.7” by 1.2”, the Teensy USB board was small enough to tuck into the base of the foot pedal. Now it looks almost exactly like how it looked when I bought it from the store, except that the connector at the end of  the cable is USB instead of some funky plug.

Thanks to Teensyduino, I didn’t have to rewrite a lot of my code. The Teensy was much easier to turn into a keyboard, because I could use the standard bootloader instead of reflashing back and forth between the standard bootloader and a HID keyboard hex. The only wrinkle was that the Teensy library used keyboard scancodes instead of the USB keycodes I had used before. I couldn’t figure out how to send F13 using the Teensy library, so I changed it to send Shift+F1…Shift+F6, and I updated my AutoHotkey script to map the new keys.

If you happen to have the same foot pedal, you can solder brown and black to GND, orange to B0, blue to B1, tan to B2, and red to B3.

Here’s the new code:

const int redPin = 3;
const int tanPin = 2;
const int bluePin = 1;
const int orangePin = 0;
const int debounceDelay = 150;
const int longPressThreshold = 650;

int currentState;
int lastSwitch;
long lastDebounce;
long lastPressed;
int lastSwitchDebounced;
#define LED 11

uint8_t buf[8] = { 0 };	/* Keyboard report buffer */

#define SWITCH_NONE 0
#define SWITCH_LEFT 1
#define SWITCH_RIGHT 3


void setup() {
  pinMode(redPin, INPUT); digitalWrite(redPin, HIGH);
  pinMode(tanPin, INPUT); digitalWrite(tanPin, HIGH);
  pinMode(orangePin, INPUT); digitalWrite(orangePin, HIGH);
  pinMode(bluePin, INPUT); digitalWrite(bluePin, HIGH);
  pinMode(LED, OUTPUT); digitalWrite(LED, HIGH);
  lastSwitch = 0;
  lastDebounce = millis();
  currentState = 0;
  digitalWrite(LED, LOW);

int getCurrentSwitch() {
  if (!digitalRead(orangePin)) { return SWITCH_LEFT; }
  if (!digitalRead(tanPin)) { return SWITCH_CENTER; }
  if (!digitalRead(redPin)) { return SWITCH_RIGHT; }
  return SWITCH_NONE;

void sendKey(int currentSwitch, boolean isShort, boolean keyDown) {
  int debug = 0;
  digitalWrite(LED, keyDown ? HIGH : LOW);
  if (keyDown) {
    switch (currentSwitch) {
        case SWITCH_LEFT:   if (isShort) { Keyboard.set_key1(KEY_F1); } else { Keyboard.set_key1(KEY_F4); } break;
        case SWITCH_CENTER: if (isShort) { Keyboard.set_key1(KEY_F2); } else { Keyboard.set_key1(KEY_F5); } break;
        case SWITCH_RIGHT:  if (isShort) { Keyboard.set_key1(KEY_F3); } else { Keyboard.set_key1(KEY_F6); } break;
    if (debug) {
      Serial.println(isShort ? "Short" : "Long");
  } else {
    if (debug) { Serial.println("Up"); Serial.println(isShort ? "Short" : "Long"); }
  if (!debug) { Keyboard.send_now(); }

void loop() {
  int currentSwitch = getCurrentSwitch();
  if (currentSwitch != lastSwitch) {
    lastDebounce = millis();
//  Serial.println(currentSwitch);
  // Debounce it
  if (millis() - lastDebounce > debounceDelay) {
    switch (currentState) {
      case STATE_WAITING:
        // No keys pressed yet
        if (currentSwitch != SWITCH_NONE) {
          lastPressed = millis();
          currentState = STATE_SHORT_PRESSED;
        // Wait to see if this counts as a long press
        if (currentSwitch == SWITCH_NONE) {
          // Send the keystroke
          sendKey(lastSwitchDebounced, true, true);
          sendKey(lastSwitchDebounced, true, false);
          currentState = STATE_WAITING;
        } else if (currentSwitch != lastSwitch) {
          // Shouldn't happen, but just in case you're using a different footpedal...
          sendKey(lastSwitchDebounced, true, true);
          sendKey(lastSwitchDebounced, true, false);
          lastPressed = millis();
        } else if (millis() - lastPressed > longPressThreshold) {
          currentState = STATE_LONG_PRESSED;
          sendKey(lastSwitch, false, true);
        // Wait for the transition
        if (currentSwitch == SWITCH_NONE) {
          currentState = STATE_WAITING;
          sendKey(lastSwitch, false, false);
        } else if (currentSwitch != lastSwitch) {
          // Likewise, switching between inputs shouldn't happen with this footpedal,
          // but just in case...
          sendKey(lastSwitch, false, false);
          currentState = STATE_SHORT_PRESSED;
          lastPressed = millis();
    lastSwitchDebounced = currentSwitch;
  lastSwitch = currentSwitch;

Here is the relevant AutoHotkey snippet I’m working with:

+F1::Send, {PgUp}
+F2::Send, !{Tab}
+F3::Send, {PgDn}
+F4::Send, {PgUp}
+F5::Send, !{Tab}
+F6::Send, {PgDn}

Wheeee! It looks so neat now. I’ve still got some flakiness to work out, but it looks awesome!

—- Another foot pedal story —-

One Saturday, W- and I were at Active Surplus to buy some electronic components and to browse their ever-interesting collections. I overheard a woman looking for a footswitch. As she asked one of the Active Surplus employees about the switch characteristics so that she could turn it into a USB keyboard-type device, I couldn’t help but tell her the footswitch was totally awesome and that I’d done something similar recently. She was also interested in building a footswitch for transcription. I told her to look for "Sacha Chua Arduino USB footswitch" as a way to get to my notes on building a 6-way USB footswitch using the very same footswitch she was thinking of buying. We had a short but great conversation about hacking stuff. I hope she ends up making something awesome out of the footswitch!