EC11 Rotary Encoder with Sensor API

I have an EC11 rotary encoder wired to my nRF52840 and I am trying to get readings from it using the sensor API. However, I'm having issues with (seemingly) garbage data. When I rotate one "click" I get a variety of readings. Sometimes no readings whatsoever, sometimes multiple readings. I referenced the nrf_desktop wheel implementation for my configuration.

I should note that I am relying on software pullups for my configuration, hence the specific gpio definition for the encoder pins.

It is important to me that I do not poll the encoder in order to save power. Am I missing something obvious?

Here's my overlay file:

/ {
    aliases {
        sw0 = &button0;
        sw1 = &button1;
        sw2 = &button2;
        qdec0 = &qdec0;
        qenca = &encoder_a;
        qencb = &encoder_b;
    };
    
    encoder_a: encoder_a_pin {
        gpios = <&gpio1 13 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
        label = "Rotary interrupt A";
    };
    encoder_b: encoder_b_pin {
        gpios = <&gpio1 15 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
        label = "Rotary interrupt B";
    };
};


&pinctrl {
    qdec_pinctrl: qdec_pinctrl {
        group1 {
            psels = <NRF_PSEL(QDEC_A, 1, 13)>,
                    <NRF_PSEL(QDEC_B, 1, 15)>;
        };
    };
};

&qdec0 {
    status = "okay";
    pinctrl-0 = <&qdec_pinctrl>;
    pinctrl-names = "default";
    steps = <80>;
    led-pre = <0>;
};

My interface code:

const struct device *const encoder_device = DEVICE_DT_GET(DT_NODELABEL(qdec0));

static void sample_encoder()
{
    struct sensor_value val;
    int rc;
    rc = sensor_sample_fetch(encoder_device);
    if (rc != 0)
    {
        LOG_INF("Failed to fetch sample (%d)\n", rc);
        return 0;
    }

    rc = sensor_channel_get(encoder_device, SENSOR_CHAN_ROTATION, &val);
    if (rc != 0)
    {
        LOG_INF("Failed to get data (%d)\n", rc);
        return 0;
    }

    if (val.val1 != position)
    {
        position = val.val1;
        LOG_INF("Position = %d degrees\n", position);
    }
}

void init_encoder(){
    if (!device_is_ready(encoder_device))
    {
        LOG_ERR("Cannot get QDEC device");
        return -ENXIO;
    }

    static const struct sensor_trigger qdec_trig = {
        .type = SENSOR_TRIG_DATA_READY,
        .chan = SENSOR_CHAN_ROTATION,
    };

    err = sensor_trigger_set(encoder_device, (struct sensor_trigger *)&qdec_trig,
                             sample_encoder);
 }

Here is an example log of one "click" clockwise:

[00:11:40.740,112] <inf> main_logging: Position = 4 degrees

[00:11:40.822,021] <inf> main_logging: Position = 13 degrees

And here is the logs from three "clicks" counterclockwise:

[00:12:14.900,543] <inf> main_logging: Position = -9 degrees

[00:12:17.931,579] <inf> main_logging: Position = -18 degrees

[00:12:19.979,553] <inf> main_logging: Position = -4 degrees

[00:12:20.061,492] <inf> main_logging: Position = -13 degrees

Parents Reply Children
Related