Shop OBEX P1 Docs P2 Docs Learn Events
Jonny Mac's Smartpin Quadrature Encoder from 2020 — Parallax Forums

Jonny Mac's Smartpin Quadrature Encoder from 2020

@JonnyMac I have been fighting with both the examples for quadrature encoder from the Parallax Website and your example in the zip in the OBEX. FYI: Your example in the zip in OBEX uses "field" in the serial code. Apparently the problem I had was my encoder uses 4 detents per count. I didn't know that was a thing until I saw your other code from 2020.

I needed an example that didn't require a dedicated cog. You provided one from 2020 in the OBEX outside the zip named jm_quadrature.spin2. It's perfect. I have a little loop that runs and pauses 20ms for debounce that runs inside a larger loop that executes once a second.

No example was provided as a top file for this, so I am attaching one here. Just needs debug enabled to see the result.

Thanks for all the code you provide!

Comments

  • I do about the same thing with the P2, in a larger but manageable REPEAT loop.
    There about a dozen things I want to keep up to date with in my application _RTC, 4x4 Keypad, (mechanical) encoder. to name a few. It is always a balance between the different functions I need/want, and good response time with the end user /operator.
    My main REPEAT loop is about 3000 loops per second, with the Encoder being about 2 mS long - I take a Encoder reading called "then", wait (only) 2 mS and take another reading called "now" make a comparison and update as required. It works perfectly and with good response time.

  • JonnyMacJonnyMac Posts: 9,064
    edited 2024-09-23 17:46

    Sorry you were having troubles, Terry. I have updated the object with a version #, and the one you have may not include the filtering option suggested by Evan (way back when this all first started). I used the object during one of the gov't lockdown classes, and provided a demo back then. I found it and have freshened it for those that are interested.

    This is what the freshened version of the old demo looks like. It works on Propeller Tool, Spin Tools IDE, and FlexProp. As it's PST-centric, you have to press a key after the terminal window opens.

    I like to do demos that show how to do real things with my objects. To that end I knocked together a demo that mimics the radio in my car. The volume knob is, of course, an encoder and when I press it I can change the treble, bass, and balance. I reproduced that as a little terminal demo. This shows how you can have single encoder that controls multiple values.

    I'll get these into ObEx so others don't have to go looking for them.

    @macca, @ersmith Is there a way to turn off the flashing cursor in your standard terminal windows?

    EDIT (23 SEP) Added Schmitt Trigger mode to encoder input pins per suggestion from Evan H.

  • ersmithersmith Posts: 6,025

    @JonnyMac said:

    @macca, @ersmith Is there a way to turn off the flashing cursor in your standard terminal windows?

    No, not at the moment. How is that done in the PST? I didn't see any command for it in the docs, but I may have an old version.

  • JonnyMacJonnyMac Posts: 9,064

    In PST the flashing cursor does not exist -- it's always invisible.

  • maccamacca Posts: 765

    @JonnyMac said:

    @macca, @ersmith Is there a way to turn off the flashing cursor in your standard terminal windows?

    Not with PST, with the ANSI terminal, there is the code to hide the cursor, <ESC>[?25l (and <ESC>[?25h to show again), but no setting to hide completely.

  • evanhevanh Posts: 15,620
    edited 2024-09-23 11:11

    @JonnyMac said:
    ... and the one you have may not include the filtering option suggested by Evan (way back when this all first started).

    Note those debounce circuits can be reconfigured. Each pin can hold up to eight samples for debouncing alone. The power-up default for "filt0" is just two samples at sysclock/1 frequency. That's barely any effect. The power-up default for "filt1" is three samples at sysclock/32, or sysclock/96. Which is quite reasonable for an encoder when above 100 MHz sysclock.

    However, I would want to use all eight samples given the choice. Configuring is somewhat cryptic and I don't think Chip ever did any examples ...

    PS: I'd enable the P_SCHMITT_A Schmitt Trigger input circuit. I've seen it alone make a difference. In fact I'd choose it before trying to wrangle the debounce hardware.

  • evanhevanh Posts: 15,620
    edited 2024-09-23 14:16

    Jon,
    Here's an example insert into your code (replacing the CASE statement) of configuring FILT1 to use eight samples for its "length".

    ...
        mode := P_QUADRATURE | dif.[2..0] << 24                       ' configure for quadrature
    
        if filter >= 0
            mode |= P_FILT1_AB
            hubset( SETFILT | FILT1 | FLEN8 | filter )
    
        pinclear(bpin)                                                ' clear old mode from B pin
        pinstart(apin, mode, 0, 0)                                    ' start a/b quadrature mode
    ...
    

    where the filter parameter variable selects the power-of-two tap (sampling interval). 0 = sysclock/1, 1 = sysclock/2, 2 = sysclock/4, 3 = sysclock/8, 4 = sysclock/16, and so on up to 31 = sysclock/2G.

    filter = 4 would be suitable choice: 8 len x 16 tap = sysclock/128 total debounce window.

    I've made a list of constants for the rest of the HUBSET mode word:

    CON
    
        SETFILT = (1<<30)
    
        FILT0 = (0<<7)
        FILT1 = (1<<7)
        FILT2 = (2<<7)
        FILT3 = (3<<7)
    
        FLEN2 = (0<<5)
        FLEN3 = (1<<5)
        FLEN5 = (2<<5)
        FLEN8 = (3<<5)
    
  • JonnyMacJonnyMac Posts: 9,064
    edited 2024-09-23 15:25

    For the time-being I have left the filter selection as-is until I can fully understand pin filtering implementation. Thanks for the feedback.

  • evanhevanh Posts: 15,620
    edited 2024-09-23 22:13

    Schmitt Trigger is still the right thing regardless.

    ...
        pinstart(bpin, P_SCHMITT_A, 0, 0)                             ' clear old mode from B pin
        pinstart(apin, P_SCHMITT_A | mode, 0, 0)                      ' start a/b quadrature mode
    ...
    
  • JonnyMacJonnyMac Posts: 9,064
    edited 2024-09-24 13:55

    Agreed. I did add that.

    I had a thought... since there are four possible filter settings that are global to the chip (or is it to a cog?), I thought it better to have a separate object that would allow the user to redefine any of the filter configurations. It's an object with one method:

    pub configure(fn, len, tap) : status
    
    '' Configure filter # fn (0..3)
    '' -- len is 0..3 (2, 3, 5, or 8 flipflops)
    '' -- tap is 0..31 (sysclock divisor, 1..2,147,483,648)
    
      if (fn < 0) || (fn > 3)
        return false
    
      if (len < 0) || (len > 3)
        return false
    
      if (tap < 0) || (tap > 31)
        return false
    
      hubset($4000_0000 + ($80 * fn) + (len << 5) + tap)  
    
      return true
    

    I used a PWM smart pin to create signal into a pin and ran a small assembly method that could copy the state of the filtered pin to the output of another to test different filter settings. The behavior seemed to work as expected.

  • evanhevanh Posts: 15,620

    Looks right. Yes, whole chip wide. They're basically four timers shared between all smartpins.

    They are exposed as a ring bus of twelve signals, four sampling signals and eight selector signals, that do the smartpin rounds. I'm not convinced it saved any real-estate though. Having one dedicated timer per smartpin might have been better. The smartpin's already contain the sample shifters and state change logic. Once the bus routing space is accounted for, then the saving from less overall timers can't be much.

    That's a general problem during HDL IC design. The space for routing resources is only ever estimated as a percentage of the gate count I think. Not until the synthesis is done does anyone know if it fits or not.

    Here's a diagram I made that I think represents the F-block frontend of each smartpin:

  • evanhevanh Posts: 15,620
    edited 2024-09-24 04:21

    F-Block (called Logic Input) location as per this - https://forums.parallax.com/discussion/171420/smartpin-diagram/p1

  • evanhevanh Posts: 15,620

    I'm thinking the "length" selectors aren't really needed. Just make it fixed at eight samples. That'd save a bunch on routing.

Sign In or Register to comment.