0

Is pigpio wave generator suitable for PID applications (constantly changing its value , on PID update) It is a position PID for a stepper motor with a pulse train driver , it works , however the motor vibrates a little when working , and does not when I run Nema42.avance(ts), not even if I change its values on a for loop, am I doing something wrong? or is there a better alternative for this problem?

this is my stepper motor class

class Nema42(object):
    """docstring for Nema42"""
    def __init__(self, pin_direccion , pin_pulse):
        self.pin_direccion = pin_direccion
        self.pin_pulse     = pin_pulse
        self.pi = pigpio.pi()
        self.pi.set_mode(self.pin_direccion, pigpio.OUTPUT)
        self.pi.set_mode(self.pin_pulse, pigpio.OUTPUT)

    def avance(self , tus ):
        if tus == 0:
            self.stop()
        else:

            if tus < 0: direccion = 1
            else : direccion = 0
            self.pi.write(self.pin_direccion , direccion)
            if tus < 1000 : tus = 1000 #Maximum defined motor speed
            if tus > 2500 : tus = 2500 #minimum defined motor speed
            self.pi.wave_clear()
            self.pi.wave_add_generic([
                pigpio.pulse(0,1<<self.pin_pulse,tus),
                pigpio.pulse(1<<self.pin_pulse,0,tus),])
            wid = self.pi.wave_create()
            self.pi.wave_send_repeat(wid)

    def stop(self):
        print "PARADA"
        self.pi.wave_tx_stop()

this is the callback I'm running every encoder interrupt

def callback(self,way):


      self.pos += way*0.12566370614359174 #linear movement each encoder pulse
      error = self.pid_posicion.pid.update(self.pos)
      if abs(self.pos - self.pid_posicion.pid.set_point) > 0.15:

         if error > 0 : direccion = -1   #define direction 
         elif error < 0 : direccion = 1

         sp = 2500 - abs(error) #de-aceleration sort of ramp based on pid error 
         if sp <0: sp = 1 #saturation for avoiding rotation to the wrong direction
         sp = sp * direccion
         self.pid_posicion.motor.avance(sp) #Nema42 class

      else: 
         self.pid_posicion.motor.avance(0)
         self.cancel()

the encoder is being controlled by the rotary_encoder class provided on the examples of pigpio

any better alternative?

I'm open to suggestions

thanks in advance

EDIT :

The stepper motor I'm using is a Nema42 , running 400steps per revolution @150 rpm , the for loop I used as a test is the following code

import time
from stepper import Nema42

motor = Nema42(12,7)
for i in range(1500):
    motor.avance(2500-i)
    time.sleep(0.001)

When I change the Ts of the wave , I get a little overshoot , this doesnt happen con the avobe for loop , probably because of smooth change , however it does happen on the PID update

  • What sort of data rates are you talking about? In particular how many pulses per second. Could you clarify the comment about it vibrates but doesn't when you use a for loop. Are you talking about the same software? – joan May 22 '16 at 7:06
1

I suggest you don't use wave_clear in the loop. Use it once at the start of the script.

I would use http://abyz.me.uk/rpi/pigpio/python.html#wave_send_using_mode with sync to ensure there is no discontinuity in the pulses, then wait until you are sure the previous wave has completed and use wave_delete to remove it.

  • Hi Joan thanks for your answer , I've searched on pigpio.pi() funcitions , and I couldn't find the wave_send_using_mode() function , is it on a newer version of pigpio? my current version is 1.26 and I'm using python 2.7 – Luis Borbolla May 23 '16 at 15:02
  • 26 is fairly old. The current version is 52 on github or abyz.co.uk/rpi/pigpio/download.html. It is also bundled with the Raspberry Pi Org image at version 50 (sudo apt-get install pigpio python-pigpio python3-pigpio). – joan May 23 '16 at 15:30
  • @LuisBorbolla See abyz.co.uk/rpi/pigpio/examples.html#Python_wave_PWM_py for an example, – joan May 23 '16 at 16:00
1

Analizing Joan's answer , I modified my code on Nema42 class above , the stepper motor now works really nice :) the code was modified to this

class Nema42(object):
    """docstring for Nema42"""
    def __init__(self, pin_direccion , pin_pulse):
        self.pin_direccion = pin_direccion
        self.pin_pulse     = pin_pulse
        self.pi = pigpio.pi()
        self.pi.wave_clear()
        self.pi.set_mode(self.pin_direccion, pigpio.OUTPUT)
        self.pi.set_mode(self.pin_pulse, pigpio.OUTPUT)
        self.wid_vieja = None #define variable for past wave

    def avance(self , tus ):
        if tus == 0:
            self.stop()
        else:

            if tus < 0: direccion = 0
            else : direccion = 1
            self.pi.write(self.pin_direccion , direccion)
            if abs(tus) < 1500 : tus = 1500
            if abs(tus) > 2500 : tus = 2500
            tus = abs(int(tus))
            self.pi.wave_add_generic([
                pigpio.pulse(0,1<<self.pin_pulse,tus),
                pigpio.pulse(1<<self.pin_pulse,0,tus),])
            wid = self.pi.wave_create()
            if self.wid_vieja is not None: #vieja = old
                self.pi.wave_send_using_mode(wid , pigpio.WAVE_MODE_REPEAT_SYNC)
                while self.pi.wave_tx_at() !=wid:
                    pass
                self.pi.wave_delete(self.wid_vieja)
            else : 
                self.pi.wave_send_repeat(wid)
            self.wid_vieja = wid

    def stop(self):
        print "PARADA"
        self.pi.wave_tx_stop().

Please excuse my code written half spanish , and half English

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.