我正在开展一个项目,我对带有光学正交编码器的 3 个电机使用 PD 控制,并且效率是必须的,因为我不想丢失一些计数并破坏定位。
首先,我创建了一个名为 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)
为了使用它,我导入该文件并创建一个名为 M3 的对象。然后:
try:
while 1:
M3.RotaryDeal()
except KeyboardInterrupt:
GPIO.cleanup()
尽管如此,我的代码效率不高,无法与多个电机一起工作,并且在使用 rospy 时也变得非常低效。这就是为什么我尝试按照建议使用 add_event_detect here
我终于得到了这样的东西:
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)
并这样称呼它:
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 并将此计数发送到主题,发布过程会消耗一些时间,所以我需要代码尽可能高效
这是每次执行 RotaryDeal() 时都会生成一条打印语句吗?打印到终端是一个非常慢的操作,最好将编码器值简单地存储在本地变量中,并每隔几千次迭代左右打印它。