About a year ago I finished building the new photo booth for my photography small business. I wanted to use push button arcade buttons to begin the photo booths automation. I found some tutorials using a Teensy to act as a usb controller. In my first attempt at soldering I connected the arcade buttons to the Teensy.
https://twitter.com/ajskelton/status/513395793118887936
The Teensy works great and really adds a lot to the photo booth.
From two buttons to twelve, connecting the usb keypad
We’re busy planning for a big Harry Potter Halloween Party and we wanted to use our photo booth. With Breeze Softwear’s DSLR Remote Pro I found the ability use keyboard shortcuts to change profiles. I also found that you can use the same print overlay in your live view so users can position themselves to match whatever overlay you’re using. Their example was a headless sumo wrestler so users could put their head on top of the wrestler. I thought of using cutouts of different characters from the Harry Potter movies so people could pose with their favorites.
The idea is great but I needed a way to allow people to quickly switch between the profiles. We don’t use a touch screen for our booth so I started looking for programable mini keyboards. I came across this tutorial on SparkFun for making your own usb keypad. The ProMicro is like the Teensy so I felt confidant I could make this work. After getting the ProMicro and Usb Keypad it was time to put them together.
My work has a nice soldering station with a lighted magnifying glass making it easier to solder.
Having not soldered anything in a year my skills clearly did not improve. They may not be clean but they did work. I did miss a little and got some solder on the keypad, so it’s a good thing this project is just for me.
I followed the tutorials suggested pins to use.
Almost done!
All connected and the wire lengths were perfect to fold the Pro Micro up against the usb keypad.
Next step, coding
After getting all my wires connected I ran into a little bit of a problem. Using Arduino I pushed my code to the ProMicro but nothing worked. I realized I hadn’t tested the ProMicro when it first arrived so I tried the basic Blink program and that didn’t work either.
Now I needed to figure out if my ProMicro even worked. I found in the troubleshooting section a way to fix a “bricked” board by manually connecting the GRD and RST pins. This would load the Arduino Leonardo bootloader. If you tap the reset pin twice it will pause eight seconds before starting. This is just enough time to upload a new sketch. For more instructions on bricked boards read the full faq.
Doing so I was able to upload the Blink program so I knew my board wasn’t broken. Yea!
I’m not sure if it’s just my board, but any time I want to upload a new sketch I have to go through this procedure. I have the correct board selected in Arduino so I’m not sure why it keeps happening.
Back on track
Now that I could load new sketches onto my ProMicro I had to re-solder my connections. I had removed them to do my troubleshooting of the ProMicro. On the second time around I used different pins so my code below wont match the pictures above.
I began using the code from the tutorial but only a few of the buttons were working, and half that did were printing the wrong number. I looked at the datasheet for the usb keypad and found that the pins were updated since the writing of the tutorial.
All I had to do was rewrite a small part of the code to change the watched pins.
int getKeypadStatus()
{
int rowPins[4] = {keypadPins[1], keypadPins[6], keypadPins[5], keypadPins[3]}; // row pins are 2, 7, 6, and 4 of the keypad
int columnPins[3] = {keypadPins[2], keypadPins[0], keypadPins[4]}; // column pins are pins 3, 1, and 5 of the keypad
After all the buttons were functioning correctly on the usb keypad I changed the switch cases. The shortcuts for profiles are CTRL + SHIFT + #. Originally this wouldn’t have been possible but version 1.0.1 of Arduino allowed for non-ASCII characters. Sending this updated sketch to my ProMicro and loading up DSLR Remote Pro it was a success. Switching between profiles was instantaneous though the bottom row of buttons wouldn’t work. These pointed at F1, F2, and F3 respectively but only triggered the keys 1,2, and 3. I’ll continue to work on this but nine profiles will be plenty for our party so I’ll probably just leave it there.
Here is my final code, or check it out on github for the latest version.
/* keyPadHiduino Example Code
by: Jim Lindblom
date: January 5, 2012
license: MIT license. If you find this code useful, please
feel free to use this code however you'd like, commercially
or otherwise. Just keep this license on there whatever you do.
*/
// Pins 1-7 of the keypad connected to the Arduino respectively:
int keypadPins[7] = {2, 3, 6, 7, 10, 16, 14};
int keypadStatus; // Used to monitor which buttons are pressed.
int timeout; // timeout variable used in loop
void setup()
{
for (int i=0; i<7; i++)
{
pinMode(keypadPins[i], INPUT); // Set all keypad pins as inputs
digitalWrite(keypadPins[i], HIGH); // pull all keypad pins high
}
}
void loop()
{
keypadStatus = getKeypadStatus(); // read which buttons are pressed
if (keypadStatus != 0) // If a button is pressed go into here
{
sendKeyPress(keypadStatus); // send the button over USB
timeout = 2000; // top of the repeat delay
while ((getKeypadStatus() == keypadStatus) && (--timeout)) // Decrement timeout and check if key is being held down
delayMicroseconds(1);
while (getKeypadStatus() == keypadStatus) // while the same button is held down
{
sendKeyPress(keypadStatus); // continue to send the button over USB
delay(50); // 50ms repeat rate
}
}
}
/* sendKeyPress(int key): This function sends a single key over USB
It requires an int, of which the 12 LSbs are used. Each bit in
key represents a single button on the keypad.
This function will only send a key press if a single button
is being pressed */
void sendKeyPress(int key)
{
switch(key)
{
case 1: // 0x001
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('1');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
case 2: // 0x002
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('2');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
case 4: // 0x004
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('3');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
case 8: // 0x008
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('4');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
case 16: // 0x010
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('5');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
case 32: // 0x020
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('6');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
case 64: // 0x040
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('7');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
case 128: // 0x080
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('8');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
case 256: // 0x100
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('9');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
case 512: // 0x200
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('KEY_F1');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
case 1024: // 0x400
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('KEY_F2');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
case 2048: // 0x800
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.write('KEY_F3');
Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release(KEY_LEFT_SHIFT);
break;
}
}
/* getKeypadStatus(): This function returns an int that represents
the status of the 12-button keypad. Only the 12 LSb's of the return
value hold any significange. Each bit represents the status of a single
key on the button pad. '1' is bit 0, '2' is bit 1, '3' is bit 2, ...,
'#' is bit 11.
This function doesn't work for multitouch.
*/
int getKeypadStatus()
{
int rowPins[4] = {keypadPins[1], keypadPins[6], keypadPins[5], keypadPins[3]}; // row pins are 2, 7, 6, and 4 of the keypad
int columnPins[3] = {keypadPins[2], keypadPins[0], keypadPins[4]}; // column pins are pins 3, 1, and 5 of the keypad
int keypadStatus = 0; // this will be what's returned
/* initialize all pins, inputs w/ pull-ups */
for (int i=0; i<7; i++)
{
pinMode(keypadPins[i], INPUT);
digitalWrite(keypadPins[i], HIGH);
}
for (int row=0; row<4; row++)
{ // initial for loop to check all 4 rows
pinMode(rowPins[row], OUTPUT); // set the row pin as an output
digitalWrite(rowPins[row], LOW); // pull the row pins low
for (int col=0; col<3; col++)
{ // embedded for loop to check all 3 columns of each row
if (!digitalRead(columnPins[col]))
{
keypadStatus |= 1 << ((row+1)*3 + (col+1) - 4); // set the status bit of the keypad return value
}
}
pinMode(rowPins[row], INPUT); // reset the row pin as an input
digitalWrite(rowPins[row], HIGH); // pull the row pin high
}
return keypadStatus;
}
Leave a Reply