
Today’s progress is a bit misplaced in the “Pi Project” folder. I wound up
using my Adafruit Feather 32u4 Bluefruit
LE to emulate a keyboard. Since this is
exactly what it was designed to do, it really wasn’t that hard. Which means it
took me a long time. My goal was to use a Bluefruit LE UART
Friend connected to my Raspberry Pi.
That was beyond my current skills so I decided to take smaller steps. The
Feather has lots of samples doing exactly what I want to do, so I went that
route.
The plan is still to go back to the Pi though since my end goal is to make a
keyboard that gets updates from the computer it’s connected to and I assume
it’d be easiest to do that with a restful API. But that’s for Future Josh to
work through.
Working with
several
tutorials
and code
samples
I was able to create a simple app that sends custom strings of keyboard codes
to whatever device is paired.
Code
Below are the highlights of the application. First it declares the commands to
send as constants, and then polls for button state and sends corresponding
messages.
BLE Commands
Two types of BLE commands are supported, keyboard codes, and control commands.
Keyboard codes are sequences of key downs (key ups are inferred by sending
either the next code, or by sending a message with no codes). Keyboard codes
are sent in a message that is up to 8 bytes long.
- The first byte is a bit mask of any modifiers (shift, alt, etc)
- The second byte is always
00
- Bytes 3 through 8 are the keys to send
For example 08-00-07 is the command for pressing the Windows Key + D. 08
is the left Windows key, and 07 is the letter D (it’s case insensitive, if
you want to have an upper case D, then also send shift).
As stated above, up to 6 keys can be sent at once. So to send abc, that
would be 00-00-04-05-06. But then this would continue to send c repeatedly
since we never sent the key up signal. To do that, just send an empty message
with 00-00.
A complete listing of the keys can be found in section 12 here.
The other type of message that I’m sending is a control command. This is used
to emulate media buttons like play, stop, and volume control. In my example I
use it just for play (which will also pause). Adafruit’s sample code has a
listing of some available
commands.
Code Logic
Each loop of the main method polls the state of the buttons to determine which
messages to send. It also records its state so the next iteration can either
send the key up signal in the case of the keyboard codes, or to simply not
resend the play command a second time (thereby pausing the music if the button
is held down for more than a fraction of a second).
It’s all pretty hard coded now, but the idea is to have it evolve to be more
configurable over time.
char CMD_MISSION_CONTROL[] = "01-00-52"; // (Left) Control + Arrow Up
char CMD_APP_WINDOWS[] = "01-00-51"; // (Left) Control + Arrow Down
char CMD_SHOW_DESKTOP[] = "08-00-07"; // (Left) Window + D
char CMD_VOLUME_UP[] = "00-00-80"; // Volume Up
char CMD_VOLUME_DOWN[] = "00-00-81"; // Volume Down
char CMD_VOLUME_MUTE[] = "00-00-7F"; // Volume Mute
char CMD_F14[] = "00-00-69"; // F14
char CMD_KEYS_UP[] = "00-00"; // No keys held
void loop(void)
{
int pressed = 0;
int playPressed = false;
if ( digitalRead(5) == LOW )
{
pressed++;
printKeyboardCode(CMD_MISSION_CONTROL);
}
if ( digitalRead(6) == LOW )
{
pressed++;
printKeyboardCode(CMD_APP_WINDOWS);
}
if ( digitalRead(9) == LOW )
{
pressed++;
printKeyboardCode(CMD_SHOW_DESKTOP);
}
if ( digitalRead(10) == LOW )
{
playPressed = true;
if (!playButtonPressedLastTime)
{
printControlKey("PLAY");
}
}
if ( digitalRead(11) == LOW )
{
pressed++;
printKeyboardCode(CMD_VOLUME_UP);
}
if ( digitalRead(12) == LOW )
{
pressed++;
printKeyboardCode(CMD_VOLUME_DOWN);
}
if (pressed < 1 && buttonsPressedLastTime > 0){
// send the key-up command
printKeyboardCode(CMD_KEYS_UP);
}
buttonsPressedLastTime = pressed;
playButtonPressedLastTime = playPressed;
}
void printKeyboardCode(char keys[])
{
ble.print("AT+BleKeyboardCode=");
ble.println(keys);
}
void printControlKey(char keys[])
{
ble.print("AT+BleHidControlKey=");
ble.println(keys);
}
Wiring

Wiring is pretty simple for this device since it’s essentially made for this
use case. I strung together 5 buttons with a common ground, and plugged each of
the buttons into the pins 5, 6, 9, 10, 11, and 12. I have a Battery on order,
and will wire up that and a power switch once they arrive.