Bluetooth Build Button, Part 2: the proof-of-concept

Well it didn’t take much to get the core idea (Part 1: new project) working.



What you’re seeing here is the Adafruit Feather nrf52832 acting as a bluetooth keyboard, paired to my Macbook, and sending CTRL+ALT+F12 when I push the giant red button (mostly because it’s unlikely to be used by anything). It’s powered by a 500mAh lipo battery and not wired to the Macbook at all.

In the video, I have iTerm bound to run rake spec \n on CTRL+ALT+F12:

iterm binding

Functional, but only useful for Ruby projects. We’ll consider making this dynamic based on the current project directory a “stretch goal”.

Adafruit provides a library with examples for using the nrf52 as a bluetooth keyboard, which provided enough juice to get my own version up and running:

build-button.ino (GitHub)

Code Example

We initialize Bluefruit BLEDis, and BLEHidAdafruit:

// Radio level configuration
Bluefruit.begin();
Bluefruit.setTxPower(4);
Bluefruit.setName("Build Button");

// BLE device information service
bledis.setManufacturer("Gary Johnson");
bledis.setModel("Build Button");
bledis.begin();

// BLE HID service
blehid.begin();

And then start advertising as a HID keyboard:

// start advertising our HID service
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);
Bluefruit.Advertising.addService(blehid);
Bluefruit.Advertising.addName();
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds

When the button is pushed, we send our CTRL+ALT+F12:

if ( digitalRead(PIN_BUTTON) == 1 ) {
  blehid.keyboardReport(KEYBOARD_MODIFIER_LEFTCTRL|KEYBOARD_MODIFIER_LEFTALT, HID_KEY_F12);
}

And send the key up event when done:

blehid.keyRelease();

And that’s it! We have a bluetooth keyboard – check the GitHub page for the complete implementation.

Scope Creep

I really wanted to avoid the Arduino IDE as much as possible – I do a lot of my work in neovim from the command line. Building command line tooling also means that my build is automatable on a headless system, which I always see as a virtue when working remotely through SSH or deploying using a CI / CD pipeline.

I started with ino, but unfortunately the last commit was in 2014 and it no longer functions with the latest version of Arduino IDE.

Then I tried using the arduino-cli to build a Makefile (GitHub) but couldn’t quite get it functioning with the Adafruit nrf52.

Might come back and revisit this later, but for now I’m going to have to let this go.

Next Steps

It’s time to design an enclosure (Part 3: enclosure rough-ins)!