Page 1 of 1

Trying to control linear actuator - won't move unless it's in a while loop

Posted: Sun Apr 28, 2019 11:45 am
by johnsayeau
I've beee trying to get a linear actuator to rach out and poke something and then go back. I can only get it to move if I put the setTargetPosition and setEngaged in a while loop but then I can't break out of the while loop using the on target position reached handler. Here's my code:

Code: Select all

import sys
import time
from Phidget22.Devices.RCServo import *
from Phidget22.PhidgetException import *
from Phidget22.Phidget import *

class PokeyMtr:
    def __init__(self, channelId, target_position, serial_number):
        self.mtr = RCServo()
        self.mtr.setDeviceSerialNumber(serial_number)
        self.mtr.setChannel(channelId)
        self.mtr.openWaitForAttachment(1000)
        self.mtr.setOnTargetPositionReachedHandler(self.targetReachedHandler())
        self.targetPosition = target_position
        self.isDone = False


    def go_mtr_go(self):
        while True:
            try:
                self.mtr.setTargetPosition(self.targetPosition)
            except PhidgetException as e:
                print(e.details)
            self.mtr.setEngaged(True)


    def targetReachedHandler(self):
        print("yo")
       

pokey = PokeyMtr(0, 44.0, 305396)
pokey.go_mtr_go()
If I just have the the stuff in the go_mtr_go function outside a while loop the targetreachedhandler prints "yo" but the motor never moves. Not sure what I'm doing wrong. I'm a noob.

Re: Trying to control linear actuator - won't move unless it's in a while loop

Posted: Sun Apr 28, 2019 5:10 pm
by hlaps1990
In "go_mtr_go(self)" it looks like you're setting the target position before engaging the device? Perhaps try setting the target after engaging? I've never used this Phidget but I think the stepper Phidgets have to be engaged first. I'm a noob too.

Re: Trying to control linear actuator - won't move unless it's in a while loop

Posted: Mon Apr 29, 2019 9:41 am
by mparadis
setTargetPosition will work regardless of whether it's called before or after setEngaged.

The problem with this code is that, without the loop, the program terminates immediately after the "yo" is printed. This does not allow enough time for the servo to reach the desired position. If you add

Code: Select all

time.sleep(2)
at the very bottom of this program, it will wait long enough for the motor to reach position before the program terminates.

Re: Trying to control linear actuator - won't move unless it's in a while loop

Posted: Mon Apr 29, 2019 2:05 pm
by johnsayeau
mparadis not sure I understand what adding the 2 second sleep does but it works. the position reached handler doesn't work like I thought it would. it gets triggered almost as soon as the motor starts moving even though the motor may move for several seconds after that. Also when I add the 2 second sleep the motor will keep moving after the program ends if it takes the motor longer than 2 seconds to move. If I move the motor form position 44.0 to 144.0 it can take more that 9 seconds. I'll have to try to find some info a bout pulse width etc. here's what I have now and it does what I want it to. I added in the currentinput device because I might going to monitor the current an use that as an indicator that I've reached desired position. ie current = 0.0

Code: Select all

import sys
import time
from Phidget22.Devices.RCServo import *
from Phidget22.Devices.CurrentInput import *
from Phidget22.PhidgetException import *
from Phidget22.Phidget import *
from Phidget22.Net import *
from time import sleep


class PokeyMtr:
    def __init__(self, channelId, serial_number):
        self.mtr = RCServo()
        self.driver_board = CurrentInput()
        self.driver_board.setDeviceSerialNumber(serial_number)
        self.driver_board.setChannel(0)
        self.driver_board.openWaitForAttachment(1000)
        self.mtr.setDeviceSerialNumber(serial_number)
        self.mtr.setChannel(channelId)
        self.mtr.openWaitForAttachment(1000)
        self.mtr.setMinPosition(0)
        self.mtr.setOnTargetPositionReachedHandler(self.targetReachedHandler())
        self.isDone = False


    def go_mtr_go(self, target_position):
        try:
            self.mtr.setTargetPosition(target_position)
        except PhidgetException as e:
            print(e.details)
        self.mtr.setEngaged(True)
        sleep(1)



    def close_mtr(self):
        self.mtr.close()


pokey = PokeyMtr(0, 305396)
pokey.go_mtr_go(44)
pokey.close_mtr()

I did this to prevent the go_mtr_go() from returning before the mtr is done moving:

Code: Select all

    def go_mtr_go(self, target_position):
        try:
            self.mtr.setTargetPosition(target_position)
        except PhidgetException as e:
            print(e.details)
        self.mtr.setEngaged(True)
        sleep(2)
        while True:
            current = self.driver_board.getCurrent()
            print(current)
            if current == 0:
                print("motor off")
                return

Re: Trying to control linear actuator - won't move unless it's in a while loop

Posted: Fri May 03, 2019 9:16 am
by jdecoux
Without the 2 second sleep, your program gets to the end of the code and exits immediately, as it has no more code to run.

With the 2 second sleep, the program stays alive for long enough for the Target Position Reached handler to be called before exiting.

If you don't close your Phidget properly at the end of your program, the servo controller will continue to send the motor to its last target position, as it has never been told to stop.

RC Servo controllers don't actually know the position of the servo they are controlling, they only know where they are telling the motor to go. The acceleration and velocity limits set in software adjust the trajectory of a series of positions being sent to the RC servo over time, to try to track a given motion profile.

If the motor is too slow to keep up with the set acceleration and velocity limits, the motor controller will say it has reached the target position (i.e. it is sending the signal for the final target position) long before the RC servo actually gets there.

You can adjust the velocity limit of the servo controller to something closer to the speed of your linear actuator to have the Target Position Reached event line up with the time the motor actually gets there.