Encoder in Hardware with Timer Peripheral

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
MartinManzinger
Posts: 4
Joined: Sat Jun 13, 2020 10:49 am

Encoder in Hardware with Timer Peripheral

Post by MartinManzinger » Sat Jun 13, 2020 11:03 am

Hello,

I connected an encoder to the ports Y1 and Y2. I checked the signals with the oscilloscope and it looks fine. These two pins have an alternate function for Ch1/Ch2 of the timer 8 (af=3). I want to use the timer 8 as a counter, so that the peripheral evaluates the encoder signals without interrupting the CPU. I followed the documentation on the wiki page, but I cant get it running. I also tried different timers and I also used the latest (threading) firmware: v1.12-535-g509359754

My code looks like this:

Code: Select all

from pyb import Pin, Timer

class QEncoder:
    def __init__(self):
        # setup input pins, alternate function: encoder
        ENCP_A = Pin('Y1', Pin.AF_PP, pull=Pin.PULL_NONE, af=3)
        ENCP_B = Pin('Y2', Pin.AF_PP, pull=Pin.PULL_NONE, af=3)
        # setup timer peripheral
        self.Timer_Peripheral = Timer(8)
        temp = self.Timer_Peripheral.channel(1, mode=Timer.ENC_AB, pin=None)
        #self.Timer_Peripheral.counter(50)
    def get_value(self):
        return self.Timer_Peripheral.counter() 

e = QEncoder()
for i in range(10):
    print(e.get_value())
    sleep(0.1)
One thing that isn't clear for me is the pin mode. Should it be Pin.IN since it is an input? But I tried this too and it didn't work. Any ideas?

MartinManzinger
Posts: 4
Joined: Sat Jun 13, 2020 10:49 am

Re: Encoder in Hardware with Timer Peripheral

Post by MartinManzinger » Sat Jun 13, 2020 12:04 pm

I just checked the STM reference manual. There is only timer 2, 3, 4, and 5 mentioned, regarding the encoder interface. I assume that only these timers are capable of what I need. But that is fine, since C6 and C7 are also connected to timer 3 as channel 1 and channel 2. I changed my encoder class like following:

Code: Select all

class QEncoder:
    def __init__(self):
        # setup input pins, alternate function: encoder
        self.ENCP_A = Pin('C6', Pin.AF_PP, pull=Pin.PULL_NONE, af=2) 
        self.ENCP_B = Pin('C7', Pin.AF_PP, pull=Pin.PULL_NONE, af=2)
        # setup timer peripheral
        self.Timer_Peripheral = Timer(3)
        temp = self.Timer_Peripheral.channel(1, mode=Timer.ENC_AB, pin=None)
    def get_value(self):
        return self.Timer_Peripheral.counter() 
But it still doesnt work :-(

MartinManzinger
Posts: 4
Joined: Sat Jun 13, 2020 10:49 am

Re: Encoder in Hardware with Timer Peripheral

Post by MartinManzinger » Sat Jun 13, 2020 12:20 pm

Niiiiice, I got it working! :D :D

The problem was the prescaler: I had to turn far to much to even get a single count. This is working:

Code: Select all

class QEncoder:
    def __init__(self):
        # setup input pins, alternate function: encoder
        self.ENCP_A = Pin('C6', Pin.AF_OD, pull=Pin.PULL_NONE, af=2) 
        self.ENCP_B = Pin('C7', Pin.AF_OD, pull=Pin.PULL_NONE, af=2)
        # setup timer peripheral
        self.Timer_Peripheral = Timer(3, prescaler=1, period=1000, mode=Timer.UP, div=1)
        temp = self.Timer_Peripheral.channel(2, mode=Timer.ENC_AB, pin=None)
    def get_value(self):
        return self.Timer_Peripheral.counter() 

SpotlightKid
Posts: 459
Joined: Wed Apr 08, 2015 5:19 am

Re: Encoder in Hardware with Timer Peripheral

Post by SpotlightKid » Sat Jun 13, 2020 8:16 pm

Do you get reliable monotonic increments/decrements of the counter with this? In my experience the internal decoding does not handle encoders with switch bouncing (which is most of them) very well. I get the best experience, when handling the pins myself in a pin interrupt handler and keeping the preceding state to filter out invalid state transitions:

https://github.com/SpotlightKid/micropy ... der.py#L72

OutoftheBOTS_
Posts: 799
Joined: Mon Nov 20, 2017 10:18 am

Re: Encoder in Hardware with Timer Peripheral

Post by OutoftheBOTS_ » Sat Jun 13, 2020 10:05 pm

SpotlightKid wrote:
Sat Jun 13, 2020 8:16 pm
Do you get reliable monotonic increments/decrements of the counter with this? In my experience the internal decoding does not handle encoders with switch bouncing (which is most of them) very well. I get the best experience, when handling the pins myself in a pin interrupt handler and keeping the preceding state to filter out invalid state transitions:

https://github.com/SpotlightKid/micropy ... der.py#L72
I have used the STM32 hardware encoder counters on their timers for a lot for my robotic projects (programmed in C not MP). I have never used an encoder counter that as bounce. When ever I put the encoders on the scope it gets clean switching of all the cheap encoder counters that I have used including both optical and magnetic. I have experimented with most of these motors with encoders here and some other as well https://www.aliexpress.com/wholesale?ca ... or+encoder

According to the docs fro STM32 it is suppose to handle jitter well.

I have never personally had a problem with encoder bounce but before I started to use the hardware encoder counters I regularly had the problem that software encoder counters couldn't keep up with counting multiple encoders at once. Most of the cheap magnetic encoder I use have 11 poles and of course you need to count 4 signals per pole, most of the motors then have a gear boxes of about 35:1 and if a motor is spinning at up to 200 RPM, doing the math 11 * 4 * 35 * 200 = 308,000 signals per second to count (308KHz) then if you have several motors it very quickly gets outside what the CPU can count without running any other code. The optical encoders tend to have much more poles so end up with even higher signals this little motor that I used on 1 project https://www.aliexpress.com/item/3281519 ... hweb201603_ has an optical encoder then with the gear box has 10,000 signals per revolution and the project had 3 of these motors.

SpotlightKid
Posts: 459
Joined: Wed Apr 08, 2015 5:19 am

Re: Encoder in Hardware with Timer Peripheral

Post by SpotlightKid » Sun Jun 14, 2020 5:19 pm

Ok, we're talking about different encoders and different uses here. My experience is with using encoders for controlling user interfaces, e.g. in place of a potentiometer. These are encoders that come for 5-8 bucks for 10 pieces.

OutoftheBOTS_
Posts: 799
Joined: Mon Nov 20, 2017 10:18 am

Re: Encoder in Hardware with Timer Peripheral

Post by OutoftheBOTS_ » Sun Jun 14, 2020 9:35 pm

SpotlightKid wrote:
Sun Jun 14, 2020 5:19 pm
Ok, we're talking about different encoders and different uses here. My experience is with using encoders for controlling user interfaces, e.g. in place of a potentiometer. These are encoders that come for 5-8 bucks for 10 pieces.
Ahh yes those use mechanical switches that bounce a lot but only turn slowly.

BTW you can now buy these mechanical rotary encoder switches with hardware bounce filters on them very cheap see https://www.aliexpress.com/item/3291542 ... hweb201603_

SpotlightKid
Posts: 459
Joined: Wed Apr 08, 2015 5:19 am

Re: Encoder in Hardware with Timer Peripheral

Post by SpotlightKid » Sun Jun 14, 2020 10:11 pm

Oh, these look also handy for breadboarding and DIY projects, yes. But ordering from China is such nuisance. Still waiting on three orders from >4 weeks ago.

MartinManzinger
Posts: 4
Joined: Sat Jun 13, 2020 10:49 am

Re: Encoder in Hardware with Timer Peripheral

Post by MartinManzinger » Mon Jun 15, 2020 9:55 am

I put a schmitt trigger in front of every button and encoder signal I have. So for me it's the perfect solution now. It's maybe a good idea to put a example code into the wiki?


Post Reply