A few months back I came across this video showing how to control a DSLR with a foot pedal. This re-ignited a long time project I've wanted to try: adding foot pedal control to emacs. How cool would it be to control emacs with not only 10 fingers, but your feet!
Looking more into this, I learned that such an idea was both totally doable and relatively inexpensive. Here's a recipe for exactly what I'd need to realize this dream: USB Foot Switch. The parts were easy enough to order off of Adafruit's website. I'd needed only a $7.00 foot switch and a $10.00 microcontroller.
The instructions promised a build time of less than an hour, however, I was skeptical. My area of expertise is in the software side of things, so clipping wires, soldering and such seems awfully intimidating.
To get around this, I decided to follow the instructions in reverse. First I'd program the chip. Then I'd see if I could get the keyboard behavior working. Then I'd plunge into the soldering side of things. It would take longer, but I'd get to start in my comfort zone.
I figured the best place to start was to get the hello world of programs running on the Trinket Pro chip, an LED blinker. To accomplish this, I followed the tutorial here.
Being an emacs snob, I completely skipped over the IDE instructions and jumped right into using AVRDude. Heck, a simple brew command line installed avrdude. I was on a roll. And then things came to a screeching halt when my attempts to use avrdude gave me various error messages. I googled for solutions, but it was beginning to look hopeless.
So, plan B: I returned to the IDE Instructions. While I had a couple of false starts, the instructions were really quite accurate. Everything seemed to work. I loaded up the blinker program:
int led = 1; // blink 'digital' pin 1 - AKA the built in red LED // the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. pinMode(led, OUTPUT); } // the loop routine runs over and over again forever: void loop() { digitalWrite(led, HIGH); delay(1000); digitalWrite(led, LOW); delay(1000); }
Hit the upload button, and poof, I successfully loaded the program into the chip. It was so effortless that I actually dug around and turned on verbose messages just to confirm that it was truly working.
There was only one problem: the program appeared to load, yet the LED on the board didn't blink. What the heck?!
On a whim, I brought up the pin-out of the Trinket Pro 5v:
Upon closer inspection I realized that the red LED I was after was labeled as #13. Aha! I updated my program to set 'led' to 13 and uploaded it to the device. And just like that, I had a blinking Trinket. Whoo!
OK, so I can get my code to run on the Trinket. Next up to was to do something with the keyboard library. I altered my blinking program to be like so:
#include <cmdline_defs.h> #include <ProTrinketKeyboard.h> #include <ProTrinketKeyboardC.h> #include <usbconfig.h> const int PIN_SWITCH = 0; // Trinket pin to connect to switch int led = 13; void setup() { pinMode(led, OUTPUT); TrinketKeyboard.begin(); // initialize keyboard library } void loop() { TrinketKeyboard.poll(); digitalWrite(led, HIGH); TrinketKeyboard.print("Hello World!"); // use for string instead of char delay(5000); digitalWrite(led, LOW); delay(3000); }
Along with toggling the LED, it spits out the text Hello World every 8 seconds.
I pushed the program the Trinket, and lo-and-behold, it worked! Now, it was a particularly useful program, but it did show that I was able to get the Trinket to simulate a keyboard action.
The final task I wanted to try was to have the board generate Hello World in response to a circuit being closed. After all, the switch is just a fancy way of grounding pin #1. At this point, any hardware geek would have busted out their soldering iron and gotten to work on finishing this project. But I wasn't quite ready to go there. I grabbed a few short lengths of wire and crudely attached them to the board by winding them into place:
I then installed the following program on the Trinket:
#include <cmdline_defs.h> #include <ProTrinketKeyboard.h> #include <ProTrinketKeyboardC.h> #include <usbconfig.h> const int PIN_SWITCH = 0; // Trinket pin to connect to switch const int LED = 13; void setup() { // Set button pin as input with an internal pullup resistor // The button is active-low, they read LOW when they are not pressed pinMode(PIN_SWITCH, INPUT_PULLUP); TrinketKeyboard.begin(); // initialize keyboard library } void loop() { TrinketKeyboard.poll(); if (digitalRead(PIN_SWITCH) == LOW) // If the foot switch grounds the pin { TrinketKeyboard.print("Hello World!"); // use for string instead of char digitalWrite(LED, HIGH); delay(3000); digitalWrite(LED, LOW); } }
With the Trinket plugged into my Mac via the USB cable, I ever so carefully touched the two exposed wires together. And to my amazement, Hello World blurted out on the screen. I tried again. And again. Success!
The end of the project is now in sight: I need to wire in the foot pedal switch and update the program to send a keystroke rather than a chunk of text. And then I need to figure out what bit of magic I want emacs to do when I hit the foot pedal. Hopefully that will be the hardest part.
Man, this Arduino hacking stuff is fun!
Update: While I had visions of using the pedal to power emacs, my first real use was a macOS hack.