Shop OBEX P1 Docs P2 Docs Learn Events
Absolute Binary Rotary Encoder (#27804) — Parallax Forums

Absolute Binary Rotary Encoder (#27804)

jmspaggijmspaggi Posts: 629
edited 2010-08-10 04:28 in Propeller 1
Hi all,

I'm trying to use the Absolute Binary Rotary Encoder (#27804) as a scroll input. Like the mouse middle-wheel.

The problem with this encoder is that they did not used the right way to do it.

It should have been something like:
0 = 000
1 = 001
2 = 011
3 = 010
4 = 110
5 = 111
6 = 101
7 = 100

(but with 4 digits)

That way, when you change from one position to another one, you just have to wait for one digit to change, then you know where you go.

With the 27804, 9 is 1001. To go to A, it needs to change the 2 last digits to be 1010. But as they said, all the digits are not going to move at the same time... So you can read 1000 before 1010, and think the user is going down instead of up.

I'm trying to translate that in SPIN, and I have some troubles.

Here is what I did.
PUB getStatus : result | scrollValue, oldScrollValue
  inputStatus := ina & (PIN_UP | PIN_DOWN | PIN_LEFT | PIN_RIGHT | PIN_SELECT | PIN_SCROLL_1 | PIN_SCROLL_2 | PIN_SCROLL_3 | PIN_SCROLL_4)
  scrollValue := (inputStatus & (PIN_SCROLL_1 | PIN_SCROLL_2 | PIN_SCROLL_3 | PIN_SCROLL_4)) >> 8
  if scrollValue <> lastMoveValue
    lastMoveTime := cnt
    lastMoveValue := scrollValue
    result := 0
  else
    if cnt > lastMoveTime + 100 * ms
      result := 0
      oldScrollValue := (inputPreviousStatus & (PIN_SCROLL_1 | PIN_SCROLL_2 | PIN_SCROLL_3 | PIN_SCROLL_4)) >> 8
      if (scrollValue == 15) AND (oldScrollValue == 0)
        result := 1
        inputPreviousStatus := inputStatus
      elseif (scrollValue == 0) AND (oldScrollValue == 15)
        result := -1
        inputPreviousStatus := inputStatus
      elseif scrollValue - oldScrollValue == 1
        result := -1
        inputPreviousStatus := inputStatus
      elseif oldScrollValue - scrollValue == 1
        result := 1
        inputPreviousStatus := inputStatus

The idea is to add a timeout. So if there is some changes on the bits, I wait them to stabilize for 100ms before taking any action. It's working prety fine, but even with that, when I scroll on the screen, sometime it's wrong and going back-way :( If I scroll to fast, then I miss the value because I'm waiting for the timeout, and I don't know anymore which direction the user is trying to go to.

Does anyone have already tried to use this "switch" with the prop? Any idea how I can simulate an infinit-scroll-wheel with it?

Thanks,

JM

Comments

  • tdlivingstdlivings Posts: 437
    edited 2010-08-08 18:24
    The encoder is working fine it puts out gray code, which is what you want.
    Only one bit position changes for any step the encoder makes as you turn it. No race conditions occur with gray code and confuse your code trying to decode it.

    A good article is in the nuts and volts section
    Column #6, May 2010: Spinning Up Fun with Encoders
  • kuronekokuroneko Posts: 3,623
    edited 2010-08-08 18:32
    tdlivings wrote: »
    The encoder is working fine it puts out gray code, which is what you want.
    Not according to the data sheet located here.
  • tdlivingstdlivings Posts: 437
    edited 2010-08-08 18:37
    Sorry, I was thinking of the incremental encoder 27805
  • TimmooreTimmoore Posts: 1,031
    edited 2010-08-08 18:40
    Why not use a standard debounce method something like
    wait until a change happens, read it, wait 100ms read again, repeat until you get 2 readings the same.
  • jmspaggijmspaggi Posts: 629
    edited 2010-08-09 04:11
    @Timmoore:

    That's what I did, but if the user scroll to fast, then you skip all the values :(

    Let's imagine the user scroll from 0 to 9 at 99ms per step...

    So you read 0, them you read 9. Was it asking to move forward? Or backward? You can't know.

    Same if he move from 0 to 5. Was it going from 0 to 15 to 14... to 5? Or from 0 to 1 to 2 ... to 5?

    So far, I removed this switch from my projet since I absolutly don't know how to handle it :( I have the 5 position switch, and will implement a hold/repeat feature to handle the scrolling.

    JM
  • Andrey DemenevAndrey Demenev Posts: 377
    edited 2010-08-09 05:31
    JM,

    First - such encoders are typically rated for 120 RPM max - so you should not expect it working properly at higher speeds

    Second - such encoders normally are designed to have short bounce time compared to regular switches. All I have seen stop bouncing in under 5 ms (though SMR8016 datasheet does not specify bounce time). So, for debouncing you read the position until you get stable reading for, say, 10 ms. To catch the situation when the bouncing has stoppped, but not all contacts have triggered yet (very unlikely) - you see how much the reading changed related to last known "good" reading. If that is +/-1 - you know the direction, otherwise - discard this new reading and go to debouncing again.
  • jmspaggijmspaggi Posts: 629
    edited 2010-08-09 06:52
    Hi Andrey,

    I tried by moving very slowly, and I still have some strange and unexpected behaviours :(

    Here is what I did:
    PUB getStatus : result | scrollValue, oldScrollValue
    
      scrollValue := (ina & (PIN_SCROLL_1 | PIN_SCROLL_2 | PIN_SCROLL_3 | PIN_SCROLL_4)) >> 8
        result := 0
    
      ' As long as the value is changing, read it and wait for it to stabilize
      if scrollValue <> lastScrollValue
        lastScrollTime := cnt
        lastScrollValue := scrollValue
      else
        ' Value did not changed. Is it stable since long enought to consider?
        if cnt > lastScrollTime + 50 * ms
          ' Value has not changed since at leat 50ms. So handle it.
          if (scrollValue == 15) AND (lastValidScrollValue == 0)
            result := 1
          elseif (scrollValue == 0) AND (lastValidScrollValue == 15)
            result := -1
          elseif scrollValue - lastValidScrollValue == 1
            result := -1
          elseif lastValidScrollValue - scrollValue == 1
            result := 1
          lastValidScrollValue := scrollValue
    

    Basicaly, I wait until I'm able to read the same value for more than 50ms, then I handle it. Even with that, I still see sometime my cursor jumping up instead of moving slowing down.

    I tried to increase the delay, but result is still the same.

    Is there something wrong into my code?

    Thanks,

    JM
  • Andrey DemenevAndrey Demenev Posts: 377
    edited 2010-08-09 07:41
    The only problem I see in your code is that you change lastValidScrollValue regardless of whether it is actually valid. It should be changed only in the branches where you set result to non-zero
  • jmspaggijmspaggi Posts: 629
    edited 2010-08-09 08:16
    That's what I did initially. I was updating lastValidScrollValue only when result was non-zero, but result was worst than this option.

    Also, I tried the oposite. Which is updating it only when result is zero. Not very nice result too :(

    JM
  • Brian RileyBrian Riley Posts: 626
    edited 2010-08-09 21:40
    From the #27804 Manual
    Absolute Binary Rotary Encoder (#27804)

    The Absolute Binary Rotary Encoder is a mechanical encoder capable of rotating a full 360° in both the clockwise and counterclockwise directions without limits. This device can also relate its current position relative to one of sixteen points on the encoder.

    This may be a bit harsh, but I have to ask if anyone bothered to ReadTheManual here? The 27804 is an ABSOLUTE POSITION encoder. Its says so in its name, it screams to you when you look at the chart on page 2 of the manual. The silence in the manual is deafening in its failure to mention anything about Grey Code. The code samples just simply read four bits and print the value (0-15).

    The 27804 is 'absolutely' the wrong encoder for what you want. The 27805 is what you want ... and it's half the price of the 27804!

    cheers ... BBR
  • Andrey DemenevAndrey Demenev Posts: 377
    edited 2010-08-09 23:11
    Brian, if read the thread and the code carefully, you'll see that topicstarter clearly understand what he is dealing with.

    Obviously, the correct one for the task is an incremental encoder. But I do not see reasons why absolute encoder cannot do the job with right software
  • jmspaggijmspaggi Posts: 629
    edited 2010-08-10 04:28
    And as Andrey said, that why I'm trying to do a small spin code to try to use this absolute position encoder that way.

    We refered many times to the manual, so we know exactly how it's working.

    We are just trying to see if there is a way to use it differently.

    JM
Sign In or Register to comment.