0

I'm trying to read interrupts and detect direction of interrupts from an encoder using a raspberry pi , it is USdigital Brand "H6BM-1000-500-IE-S-H" , it has 1000 signals per revolution , the thing is that when I run my python program , I loose some steps (probably because of python speed) , I switched from RPi.GPIO to pigpio , because pigpio is written in C , and got all the interrupts right , the thing is that when I add python code on the callback function it looses steps , leaving me on the same spot as before , my next idea is to write the encoder interrupt value into a Register on the raspberry pi , so on my python program I only need to read the value , like a link between python and C , but I dont know how to detect interrupts on C and write them into a register , any help?

new ideas are also welcome

heres my code till now

#!/usr/bin/env python

import time
import math as m 
import pigpio # http://abyz.me.uk/rpi/pigpio/python.html


class Signal(object):
    """docstring for Interrupt"""
    def __init__(self, pinA , pinB):
        self.pinA      = pinA
        self.pinB      = pinB
        self.gpio      = pigpio.pi()
        self.perimetro = 40*m.pi
        self.cuenta    = 0
        self.estado    = 0
        self.tiempo_actual = 0 
        self.tiempo_anterior = time.time()
        self.velocidad = 0

        #Definicion de funciones que correran al interrumpirse en los pines
        self.interrupcionA  = self.gpio.callback(self.pinA, edge = pigpio.FALLING_EDGE ,func = self.guia)
        #self.interrupcionB = self.gpio.callback(self.pinB, edge = pigpio.EITHER_EDGE , func = self.referencia)


    def guia(self,a,b,c):
        self.tiempo_actual = time.time()
        if int(self.gpio.read(self.pinB)):
            self.cuenta += 1

        if not int(self.gpio.read(self.pinB)):
            self.cuenta -= 1

        tiempo = self.tiempo_actual-self.tiempo_anterior
        self.tiempo_anterior  = self.tiempo_actual
        self.velocidad = (self.perimetro/1000)/tiempo
        print "cuenta en %s" % self.cuenta    



def main():

    encoder = Signal(21,20)
    try:
        while 1:
            time.sleep(1)       
    except KeyboardInterrupt:
        pigpio.pi().clear_bank_1(bin(2**20+2**21))

if __name__ == '__main__':
    main()        
  • There are some pigpio encoder examples. Python at abyz.co.uk/rpi/pigpio/examples.html#Python_rotary_encoder_py and C but using the daemon at abyz.co.uk/rpi/pigpio/examples.html#pdif2_RED. The C code uses the same interface as Python but can handle far higher rotation rates. At least try the Python example to ensure your implementation performs at least as well. – joan Apr 23 '16 at 8:52
  • With pigpio you need to be using callbacks to monitor encoders. – joan Apr 23 '16 at 9:01
  • thanks for your solution joan , it seems it will work , but is there a way I can write the value of the C program into a register? , I mean low level programing , just as a PIC microcontroller , that way I could easily be just reading it when needed from python , thanks – Luis Borbolla Apr 25 '16 at 16:46
  • The best you could probably do is write the output to a pipe and have the Python read from the pipe. It would be a bit of a kludge though. – joan Apr 25 '16 at 16:57
  • Thank you very much for all your help , I've ran various tests on the rotary encoder you posted , and aparently python code of pigpio rotaryencoder solves my problem , should you answer it so I can mark your answer as best answer ? or should I answer it , I'm kind of new in this – Luis Borbolla Apr 26 '16 at 2:37
0

After making some tests , and thanks to joan's comments , I find the rotary encoder library for python enough to solve my problem , I modified it a little bit just to calculate velocity from interrupts and timestamps , that are suitable for what my application is (Programing and installing a PID{velocity , and position on cascade} for a stepper motor) this code captures all of my interrupts and rotation direction

here's the code I'm using

#!/usr/bin/env python
import pigpio

class decoder:

   """Clase para decodificar los pulsos de un encoder mecanico."""

   def __init__(self, pi, gpioA, gpioB, callback):

      self.pi = pi
      self.gpioA = gpioA
      self.gpioB = gpioB
      self.callback = callback



      self.levA = 0
      self.levB = 0

      self.lastGpio = None

      self.pi.set_mode(gpioA, pigpio.INPUT)
      self.pi.set_mode(gpioB, pigpio.INPUT)

      self.pi.set_pull_up_down(gpioA, pigpio.PUD_UP)
      self.pi.set_pull_up_down(gpioB, pigpio.PUD_UP)

      self.cbA = self.pi.callback(gpioA, pigpio.EITHER_EDGE, self._pulse)
      self.cbB = self.pi.callback(gpioB, pigpio.EITHER_EDGE, self._pulse)

   def _pulse(self, gpio, level, tick):

      """
      Decode the rotary encoder pulse.

                   +---------+         +---------+      0
                   |         |         |         |
         A         |         |         |         |
                   |         |         |         |
         +---------+         +---------+         +----- 1

             +---------+         +---------+            0
             |         |         |         |
         B   |         |         |         |
             |         |         |         |
         ----+         +---------+         +---------+  1
      """

      if gpio == self.gpioA:
         self.levA = level
      else:
         self.levB = level;

      if gpio != self.lastGpio: # debounce
         self.lastGpio = gpio

         if   gpio == self.gpioA and level == 1:
            if self.levB == 1:
               self.callback(1)
         elif gpio == self.gpioB and level == 1:
            if self.levA == 1:
               self.callback(-1)

   def cancel(self):

      """
      Cancel the rotary encoder decoder.
      """

      self.cbA.cancel()
      self.cbB.cancel()

if __name__ == "__main__":

   import time
   import pigpio

   import rotary_encoder

   pos = 0
   actual_time = 0
   past_time = time.time()
   velocidad = 0
   def callback(way):

      global pos
      global past_time
      global tiempo_actual
      global velocidad
      actual_time = time.time()
      pos -= way
      time = actual_time - past_time
      velocidad = 0.06283185307179587/time #linear movement of machine from each step of stepper motor
      past_time = actual_time





   pi = pigpio.pi()

   decoder = rotary_encoder.decoder(pi, 21, 20, callback)
   while 1:

      time.sleep(1)
      print("pos={0} vel={1}".format(pos,velocidad))


   decoder.cancel()

   pi.stop()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.