Skip to content

Add rotary encoder support.#887

Merged
dhalbert merged 5 commits intoadafruit:masterfrom
tannewt:rotaryio
Jun 1, 2018
Merged

Add rotary encoder support.#887
dhalbert merged 5 commits intoadafruit:masterfrom
tannewt:rotaryio

Conversation

@tannewt
Copy link
Member

@tannewt tannewt commented Jun 1, 2018

The peripheral helpers have been reorganized to separate them out. Over time hopefully they can grow into a more useful library that doesn't depend on ASF4 or MicroPython.

This also makes ticks more atomic which should reduce errors with DHT sensors. @jerryneedell you may want to confirm.

@ladyada
Copy link
Member

ladyada commented Jun 1, 2018

rad!

Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm working on a rework of the state machine in the rotary encoder interrupt handler, but I'll approve it as is and submit another PR or issue later.

The refactoring is great! Really like removing all the #ifdef stuff and regularizing the file names and locations.

self->eic_channel_b = pin_b->extint_channel;
self->pin_a = pin_a->pin;
self->pin_b = pin_b->pin;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set self->position = 0 somewhere in the constructor.

bool pin_b = gpio_get_pin_level(self->pin_b);

uint8_t this_state;
if (!pin_a && !pin_b) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the current algorithm can still jitter the position count due to bounces. For example, consider ab = 00 going to 01. If b bounces it will oscillate between this_state being 1 and 2, which will cause self->position to be incremented and decremented on each bounce.

There are actually 16 state transitions to consider: ab->a'b', so 2^4 different combinations or states. Some of these are "illegal" and represent going too fast, etc.

I'm writing up a reimplementation that considers all these states. The best implementations I've found online that seems to do the right thing are https://github.com/buxtronix/arduino/blob/master/libraries/Rotary/Rotary.cpp and https://github.com/Erriez/ErriezRotaryEncoderFullStep/blob/master/src/RotaryFullStep.cpp.

The product 377 in the store does a full set of transitions between detents (on each detent both A and B are open).

bool event_interrupt_overflow(uint8_t channel) {
bool overflow = false;
#ifdef SAMD21
if (channel > 7) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Off-by-1 error here for channels >= 8 (I had noticed this while debugging PDMIn. If, say, channel == 8, it will shift the channel number by 1 instead of by 0.
Change to:

    if (channel >= 8) {
        uint8_t value = 1 << (channel - 8);

Same issue at lines 156-157 and lines 171-172, but I can't leave comments there.


//| .. method:: deinit()
//|
//| Deinitialises the IncrementalEncoder and releases any hardware resources for reuse.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deinitialises -> Deinitializes

@dhalbert
Copy link
Collaborator

dhalbert commented Jun 1, 2018

I think it would be convenient if IncrementalEncoder.position was also settable, so you could reset it to zero or whatever.

@tannewt
Copy link
Member Author

tannewt commented Jun 1, 2018

Ok, updated as requested. I return early from busio.I2C to save space on pIRkey. Raising NotImplementedError should align with a more correct and expansive solution to this in the future.

dhalbert
dhalbert previously approved these changes Jun 1, 2018
Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great!

@dhalbert
Copy link
Collaborator

dhalbert commented Jun 1, 2018

Can't merge: Conflicting files:
ports/atmel-samd/samd51_clocks.c
ports/atmel-samd/supervisor/port.c

tannewt and others added 5 commits June 1, 2018 15:07
Ideally in the future they won't depend on ASF4 or MicroPython.
Always use current_tick when sub millisecond precision is required.
Otherwise getting the ms/us to correspond is tricky.
@tannewt
Copy link
Member Author

tannewt commented Jun 1, 2018

Rebased and will wait for Travis to verify all boards compile.

Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rebase worked

@dhalbert dhalbert merged commit de61bd0 into adafruit:master Jun 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants