Python中读取光学正交编码器的最有效算法

Python中读取光学正交编码器的最有效算法,python,raspberry-pi,raspberry-pi3,gpio,rospy,Python,Raspberry Pi,Raspberry Pi3,Gpio,Rospy,我在做一个项目,我用PD控制3个带光学正交编码器的电机,效率是必须的,因为我不想失去一些计数,破坏定位 首先,我创建了一个名为CMotor的类,我在其中定义了一些属性和方法。在这些方法中,我定义了RotaryDeal,它负责处理计数 一开始是这样的: class CMotor: def RotaryDeal(self): self.LastB = GPIO.input(self.PinB) self.LastA = GPIO.input(self.PinA

我在做一个项目,我用PD控制3个带光学正交编码器的电机,效率是必须的,因为我不想失去一些计数,破坏定位

首先,我创建了一个名为CMotor的类,我在其中定义了一些属性和方法。在这些方法中,我定义了RotaryDeal,它负责处理计数

一开始是这样的:

class CMotor:
    def RotaryDeal(self):
        self.LastB = GPIO.input(self.PinB)
        self.LastA = GPIO.input(self.PinA)

        while (self.LastA==GPIO.input(self.PinA) and self.LastB==GPIO.input(self.PinB) ):
                    flag = 1

        self.CurrentB = GPIO.input(self.PinB)
        self.CurrentA = GPIO.input(self.PinA)

        if self.CurrentA:
            if self.CurrentB:
                if self.LastA:
                    self.Cuentas-=1
                else:
                    self.Cuentas+=1

            else:
                if self.LastA:
                    self.Cuentas+=1
                else:
                    self.Cuentas-=1

        else:
            if self.CurrentB:
                if self.LastA:
                    self.Cuentas-=1
                else:
                    self.Cuentas+=1

            else:
                if self.LastA:
                    self.Cuentas+=1
                else:
                    self.Cuentas-=1
        print 'Cuentas %s = %d' % (self.Nombre, self.Cuentas)

#(Cuentas is Counts btw)
try:
    GPIO.add_event_detect(M3.PinA, GPIO.BOTH, callback=M3.RotaryDeal)
    GPIO.add_event_detect(M3.PinB, GPIO.BOTH, callback=M3.RotaryDeal)
        while 1:
            pass
except KeyBoardInterrupt:
    GPIO.cleanup()
为了使用它,我导入这个文件并创建一个名为M3的对象。然后:

try:
    while 1:
        M3.RotaryDeal()
except KeyboardInterrupt:
    GPIO.cleanup()
然而,我的代码效率不高,无法与多个电机一起工作,在使用rospy时也变得非常低效。这就是为什么我尝试按建议使用add_event_detect

我终于得到了这样的东西:

class CMotor:

    #Some other functions and the __init__

    def RotaryDeal(self, ev = None):
            self.CurrentB = GPIO.input(self.PinB)
            self.CurrentA = GPIO.input(self.PinA)

            if self.CurrentA:
                    if self.CurrentB:
                            if self.LastA:
                                    self.Cuentas-=1
                            else:
                                    self.Cuentas+=1

                    else:
                            if self.LastA:
                                    self.Cuentas+=1
                            else:
                                    self.Cuentas-=1

            else:
                    if self.CurrentB:
                            if self.LastA:
                                    self.Cuentas-=1
                            else:
                                    self.Cuentas+=1

                    else:
                            if self.LastA:
                                    self.Cuentas+=1
                            else:
                                    self.Cuentas-=1
            self.LastA = self.CurrentA
            self.LastB = self.CurrentB

            print 'Cuentas %s = %d' % (self.Nombre, self.Cuentas)

#sorry for the indentation, im copying it from the terminal (using ubuntu mate)
并这样称呼它:

class CMotor:
    def RotaryDeal(self):
        self.LastB = GPIO.input(self.PinB)
        self.LastA = GPIO.input(self.PinA)

        while (self.LastA==GPIO.input(self.PinA) and self.LastB==GPIO.input(self.PinB) ):
                    flag = 1

        self.CurrentB = GPIO.input(self.PinB)
        self.CurrentA = GPIO.input(self.PinA)

        if self.CurrentA:
            if self.CurrentB:
                if self.LastA:
                    self.Cuentas-=1
                else:
                    self.Cuentas+=1

            else:
                if self.LastA:
                    self.Cuentas+=1
                else:
                    self.Cuentas-=1

        else:
            if self.CurrentB:
                if self.LastA:
                    self.Cuentas-=1
                else:
                    self.Cuentas+=1

            else:
                if self.LastA:
                    self.Cuentas+=1
                else:
                    self.Cuentas-=1
        print 'Cuentas %s = %d' % (self.Nombre, self.Cuentas)

#(Cuentas is Counts btw)
try:
    GPIO.add_event_detect(M3.PinA, GPIO.BOTH, callback=M3.RotaryDeal)
    GPIO.add_event_detect(M3.PinB, GPIO.BOTH, callback=M3.RotaryDeal)
        while 1:
            pass
except KeyBoardInterrupt:
    GPIO.cleanup()
尽管它被认为效率更高,但事实恰恰相反。当我试图扭转它时,我得到了与原来完全不同的结果。如果你阅读全部4种情况,它应该每转读取3200个计数,但是“高效”算法丢失了我所有的计数。而且,我旋转转子的速度越快,它错过的计数就越多

请,如果有一种更有效的方法来读取编码器的所有四种情况下的计数,或者我自己犯了一个错误,我将非常感谢你发布它

PD:对于那些在4种情况下没有理解我意思的人:

 |PinA|PinB|
1| 0  | 0  |
2| 0  | 1  |
3| 1  | 0  |
4| 1  | 1  |
PD 2:我将使用rospy并将此计数发送到topic,发布过程需要花费一些时间,因此我需要尽可能高效的代码