Rotary Encoder Bluetooth HID

Posted on
  • This project was driven by the inconvenience of using SDR (Software Defined Radio) programs without having an explicit physical tuning knob to adjust frequency. Subsequently, I have found it also useful for scrolling with tablets.

    The implementation uses an Espruino Puck.js and a rotary encoder as shown below in the breadboard prototype and the final device.

    Connections are (Encoder -> Puck): GND -> GND, SW -> D28, ENCODER -> D29,D30.

    The program below presents the Rotary Encoder as the middle wheel and button of a bluetooth mouse.

    function createEncoder(pinA,pinB){
      var,, incr0 =0, second=false;
      var OBJ = {};
      function handler () {
        var a =;
        var b =;
        if (a != a0) {              // A changed
          a0 = a;
          if (b != c0) {
            c0 = b;
            var incr = (a == b)?1:-1;
            if (incr!=incr0 || !second) OBJ.emit("change",incr);
            incr0=incr; second = !second;
      return OBJ;
    function createSwitch(pinA){
      var OBJ = {};
      function handler(ns){
      return OBJ;
    //HID report for Mouse device
    var report = new Uint8Array([
      0x05, 0x01, 0x09, 0x02, 0xA1, 0x01,
      0x09, 0x01, 0xA1, 0x00, 0x05, 0x09,
      0x19, 0x01, 0x29, 0x03, 0x15, 0x00,
      0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
      0x81, 0x02, 0x95, 0x01, 0x75, 0x05,
      0x81, 0x01, 0x05, 0x01, 0x09, 0x30,
      0x09, 0x31, 0x09, 0x38, 0x15, 0x81, 
      0x25, 0x7F, 0x75, 0x08, 0x95, 0x03,   
      0x81, 0x06, 0xC0, 0x09, 0x3c, 0x05,
      0xff, 0x09, 0x01, 0x15, 0x00, 0x25,
      0x01, 0x75, 0x01, 0x95, 0x02, 0xb1,
      0x22, 0x75, 0x06, 0x95, 0x01, 0xb1,
      0x01,   0xc0 ]
    NRF.setServices(undefined, { hid :report });
    var ROT = createEncoder(D29,D30);
    var SW = createSwitch(D28);

    The encoder handler is adapted from here and I found it worked much more reliably than the Espruino encoder module. In addition the following code allows the device to switch from HID to normal Espruino mode for connection to the WebIDE i.e. hold down the encoder switch until the Puck flashes GREEN. On reboot or reset, it will go into HID mode by default and flash BLUE. On connection, there is a BlUE flash and a RED flash on disconnection.

      if( E.kickWatchdog();
    E.enableWatchdog(10, false);
    function flash(pin){
    function delayms(d) {
        var t = getTime()+d/1000; 
    var STOR = require("Storage");
    if ({
      if ("main.js")) eval("main.js"));
    } else {
  • This looks great - thanks!

    Would there be any problem with me copying this into an example to put on itself?

  • Very happy for you to put it on as an example - I would be honoured!

  • Very cool! Could you share the source of your GPIO connectors ? I have similar project and hd to solder, which I am not very good at, especially in small, close pins.. Thank you

  • The sockets are actually for IC pins and the last place I bought something similar was from Mechboards .

    The usual breadboard jumper wires are too thick for these sockets and I am afraid I have no idea where the ones in the picture came from.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Rotary Encoder Bluetooth HID

Posted by Avatar for jeffmer @jeffmer