Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 1584

Python • Pigpio Wave playback changes speed.

$
0
0
Hello,
I have an application with several iterations in the field. There is a problem with motion suddenly becoming VERY fast (Pigpio pi.wave_send_once(self.plan)

The motion is calculated using the listed module once at program startup.

This is a rare problem, but has happened several times on several different fixtures.
Re-starting the main python program does not restore the playback speed for the waveform.
Reboot of Raspbian does restore the correct playback speed
It seems to happen after extended runtime of the Pi.

I unfortunately cannot reproduce the problem at will. I only know it takes a reboot to fix the problem

In the module:
Instantiating the class PiMoto and then calling instance.Start() is the correct procedure for startup of the motion part of this module.
Calling MakeProfile will create the waveform from the parameters coded into this line:

for each in self.Planner(50,20000,25000,1745):#Vstart,Vmax,Accel,Dist

and calling instance.Clamp() or instance.Unclamp() will play the motion

Any ideas of how to fix or avoid this problem?

Code:

class PiMoto():    def __init__(self):                #Input Numbers        self.rc = 16        self.ro = 17        self.lc = 6        self.lo = 19        self.lid = 20        #output numbers        self.d1dir = 4        self.d2dir = 18        self.d1pul = 12        self.d2pul = 13        self.enstp = 27        self.Homed = False        self.Active = False            def Start(self):        self.pi = pigpio.pi()        if not self.pi.connected:            exit(0)        self.pi.wave_clear()        self.MakeProfile()                self.pi.set_mode(self.d1pul,pigpio.OUTPUT)        self.pi.set_mode(self.d2pul,pigpio.OUTPUT)        self.pi.set_mode(self.enstp,pigpio.OUTPUT)        self.pi.set_mode(self.d1dir,pigpio.OUTPUT)        self.pi.set_mode(self.d2dir,pigpio.OUTPUT)        self.Active = True        def Stop(self):        if self.Active:            self.pi.stop()        def Home(self):        self.pi.write(self.d1dir,1)        self.pi.write(self.d2dir,0)        self.Homed = False        while self.Homed == False:            if self.pi.read(self.lo) == 1:                self.pi.gpio_trigger(self.d2pul, 5, 1)            if self.pi.read(self.ro) == 1:                self.pi.gpio_trigger(self.d1pul, 5, 1)            sleep(.005)            if self.pi.read(self.lo) == 0 and self.pi.read(self.ro) == 0:                self.Homed = True    def Clamp(self):        if self.Homed:            if self.pi.read(self.ro) == 0 and self.pi.read(self.lo) == 0:                self.pi.write(self.d1dir,0)                self.pi.write(self.d2dir,1)                self.pi.wave_send_once(self.plan)                print("Clamping")                while self.pi.wave_tx_busy():                    sleep(.02)                print("Clamped")            else:                print("Fixture cannot clamp")                def Unclamp(self):        if self.Homed:            if self.pi.read(self.rc) == 0 and self.pi.read(self.lc) == 0:                self.pi.write(self.d1dir,1)                self.pi.write(self.d2dir,0)                self.pi.wave_send_once(self.plan)                print("Unclamping")                while self.pi.wave_tx_busy():                    sleep(.02)                print("Unclamped")            else:                print("Fixture cannot unclamp")        def MakeProfile(self):            #Build the waveform for moving the stepper motors        open_close = []        #Fixture.Home()        bitmask = 1<<self.d1pul | 1<<self.d2pul #create bitmask so that playing the waveform runs both motors            #create the waveform for the entire motion        for each in self.Planner(50,20000,25000,1745):#Vstart,Vmax,Accel,Dist            ms = int(each[1]*500000)            open_close.append(pigpio.pulse(bitmask,0,ms))            open_close.append(pigpio.pulse(0,bitmask,ms))        self.pi.wave_add_generic(open_close)        self.plan = self.pi.wave_create()#This is the motion with ramp for travel        def Planner(self,Vstart,Vmax,A,D):        Vstart = float(Vstart)        Vmax = float(Vmax)        AccelTime = (Vmax - Vstart) / A#Get time for full acceleration        AccelDist = (Vstart * AccelTime) + (.5 * A * (AccelTime ** 2))                #Determine if we will reach max speed        if D/2 > AccelDist:            full_profile = True            full_speed_steps = int(D - (AccelDist * 2))        else:            full_profile = False            AccelDist = D / 2                    #Initialize first step        speed_time = [[Vstart, 1/Vstart]] #Speed in pulses per sec, time between pulses.        #Special case of 1 step        if D == 1:            return speed_time                #Build the profile, accel first        for idx in range(int(AccelDist -1)):#already made the first step            old_speed_time = speed_time[-1]            new_speed = old_speed_time[0] + (A * old_speed_time[1])            speed_time.append([new_speed, 1 / new_speed])                #Add steady speed if appropriate        if full_profile:            for idx in range(int(full_speed_steps)+1):                speed_time.append([Vmax,1/Vmax])                #reverse copy accel to make decel        for idx in range(int(AccelDist-1),0,-1):            speed_time.append(speed_time[idx])                    #Return to first step data        speed_time.append([Vstart, 1/Vstart])        #add steps to compensate odd number of steps when Vmax not reached        for idx in range(len(speed_time) , D):            speed_time.append([Vstart, 1/Vstart])        return speed_time

Statistics: Posted by rallenbaggett — Mon Jun 09, 2025 4:50 pm



Viewing all articles
Browse latest Browse all 1584

Trending Articles