Using --position via TICCMD doesn't seem to stop the stepper at that position - and other questions

Hello - I have the TIC 36v4 stepper drivers. I really like the interface, but I’m having some issues:

  1. The stepper seems to default moving in the NEGATIVE direction, see below… why?
  2. How do I get the stepper to move to a position, and stop?
  3. When I explicitly set a negative/positive velocity, does this instigate the “Invert Motor Direction” in the EEPROM, or no? (If the latter, that is excellent, since I can move the motor back and forth without burning out the EEPROM with write/rewrite cycles!)

First, my code, I’m using Python


import time
from datetime import datetime
import subprocess
import yaml #needed for tic
from pprint import pprint #for pretty printing of dictionaries 

#NOTE: The following addresses can be found using the Tic software
#from Pololu
periPumpAddress = "00413599"

def interpreter(command):

	total_command = "ticcmd -d " + periPumpAddress + " " + command	
 	
	proc = subprocess.Popen(total_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
	out, err = proc.communicate()

	return out, err #might need to just "return" with nothing here 


def resetTIC(): 
	
	currCommand = "--reset"

	returnedVal = interpreter(currCommand)
 
	print("resetTIC Returned val is: {}".format(returnedVal))
	print("resetTIC Type of returned Val is: {}".format(type(returnedVal)))
		
	return 


def getCurrTICPosition(): 
	
	#status = yaml.safe_load(ticcmd('-s', '--full'))
	
	currCommand = "-s --full"

	returnedVal = interpreter(currCommand)

	status = yaml.safe_load(returnedVal[0])

	currentPosition = status['Current position']
 
	return currentPosition

def moveTICToPreDefinedPosition(targetPosition = 2000): 
	
	#reset to position = 0
	resetTIC()    
	
	currPosition = getCurrTICPosition()
	print("After reset, position is: {}".format(currPosition))

	targetPositionAsStr = str(targetPosition)

	currCommand = "--resume --position" + " " + targetPositionAsStr
	
	dummy = input("current position desired is: {} ... hit enter to proceed".format(targetPositionAsStr))

	interpreter("--energize")
	
	currPos = int(getCurrTICPosition())
	
	time.sleep(0.1)
	interpreter(currCommand)

	while currPosition < targetPosition: 
		time.sleep(0.5) #just to avoid spamming the USB port
		currPosition = getCurrTICPosition()
		print("Current position is now: {}".format(currPosition))
  
	interpreter("--deenergize")
  
	return 

############################################################################################
#
#	Testing code
#
#
############################################################################################

moveTICToPreDefinedPosition()

The output I get here is:


resetTIC Returned val is: (b’', None)
resetTIC Type of returned Val is: <class ‘tuple’>
After reset, position is: 0
current position desired is: 2000 … hit enter to proceed
Current position is now: -63
Current position is now: -131
Current position is now: -200
Current position is now: -267
Current position is now: -332
Current position is now: -398
Current position is now: -465
Current position is now: -534
Current position is now: -601
Current position is now: -671
Current position is now: -738
Current position is now: -804
Current position is now: -873


So question 1) Why is it going in the negative direction, by default?

I can, of course, enforce the direction - let’s say I modify the above code changing this:

currCommand = "--resume --position" + " " + targetPositionAsStr

To this:

currCommand = "--resume --velocity 3000000 --position" + " " + targetPositionAsStr

Now I get the output:


resetTIC Type of returned Val is: <class ‘tuple’>
After reset, position is: 0
current position desired is: 2000 … hit enter to proceed
Current position is now: 188
Current position is now: 396
Current position is now: 598
Current position is now: 820
Current position is now: 1032
Current position is now: 1238
Current position is now: 1440
Current position is now: 1648
Current position is now: 1856
Current position is now: 2056


As you can see, I go past the setpoint! Only because of my Python code (while loop) does the pump stop - otherwise it keeps running! For example, if I set the sleep time to like 2 seconds, I will go wildly past the position setpoint. So, question 2 - why?

[I’ll note - while this *works* it’s not good for my application, where I can’t necessarily rely on my Python code to precisely move a stepper to a setpoint - I want to set it and let the TIC software go to where it needs to go.]

One more note - I can use the TIC Control Center software to set a position, but again, it will not stop once it reaches this position.


Finally, question 3), as we saw above, I can set a negative or positive velocity. Is this doing the “invert motor direction” in the EEPROM, or does it avoid the write/rewrite?

I think I got the “–position” to work as desired!

I have some other steppers set up. These were looking like they were working as expected - i.e. they were going to a set position, and stopping.

It seems like the difference was the “Enable automatic homing” radio button on the Advanced Settings page. Once I removed this from the “faulty” driver, things seemed to work as normal.

And, it seems like I have an answer to my first two questions:

  1. In code, I have to purposefully set the “–velocity” variable for my TICs prior to use
  2. See above - disabling the “enable automatic homing” seems to have solved this problem. I suppose I can do an EEPROM write of this value in code in order to ensure it doesn’t happen again, but it should be set now.

My third question still stands!

In case it helps others, here’s the relevant bit of code that does what I need:

def moveTICToPreDefinedPosition(targetPosition = 2000, targetSpeed = 4000000, targetAccelDecel = 20000): 
	
	#reset to position = 0
	resetTIC()    
	
	currPosition = getCurrTICPosition()
	print("After reset, position is: {}".format(currPosition))

	targetPositionAsStr = str(targetPosition)
	targetSpeedAsStr = str(targetSpeed)
	targetAccelDecelAsStr = str(targetAccelDecel)
 
	#set speed
	currCommand = "--max-speed " + targetSpeedAsStr
	interpreter(currCommand)
	time.sleep(0.05) #short delay
 
	#set accel/decl
	currCommand = "--max-accel " + targetAccelDecelAsStr
	interpreter(currCommand)
	time.sleep(0.05) #short delay
	currCommand = "--max-decel " + targetAccelDecelAsStr
	interpreter(currCommand)
	time.sleep(0.05) #short delay
 
	#this works without velocity being set, otherwise velocity overrides position! 
	currCommand = "--resume --position" + " " + targetPositionAsStr
 
	dummy = input("current position desired is: {} ... hit enter to proceed".format(targetPositionAsStr))

	interpreter("--energize")
	
	currPos = int(getCurrTICPosition())
	
	time.sleep(0.1)
	interpreter(currCommand)

	while currPosition < targetPosition: 
		time.sleep(2) #just to avoid spamming the USB port
		currPosition = getCurrTICPosition()
		print("Current position is now: {}".format(currPosition))
  
	interpreter("--deenergize")
  
	return 

Hello.

To answer your third (and last remaining) question, no, switching from commanding a positive velocity to commanding a negative velocity does not change anything stored in the EEPROM. “Invert Motor Direction” just swaps which direction corresponds to a positive or negative velocity.

To clarify the answers to your first two questions (especially for others who might come across this post), here are some specifics:

  1. It sounds like you had the automatic homing option enabled, which will cause the motor to home before responding to the target position command whenever it does not already have a known position (e.g. when it first starts up or after anytime it de-energizes). If you are not using a homing switch, then you should not be using the automatic homing feature. If you want to use a homing switch, please make sure you have configured and tested it as described in the “Setting up limit switches and homing” section of the Tic user’s guide.

  2. It sounds like this was related to the automatic homing option being enabled, but it is also important to note that the “set target velocity” command does not work the way you were trying to use it; this command is independent to setting the target position (i.e. it does not control the velocity of the motor while it is going to a target position), so they will override each other. When commanding a target position, the speed profile is determined by the max acceleration, max deceleration, and max speed variables, so you can adjust those as needed, like you are doing in your updated code.

Brandon

Thanks for the response!

Yes, I mis-spoke - I cannot move “forward/backward” by setting the velocity - rather by setting the position.

The fact that changing position does not need EEPROM writing to change motor direction is excellent! I was worried, for my application, that I was going to burn out the motor driver('s EEPROM) earlier than I would have wanted.

Thanks also for the information about homing, specifically: “…will cause the motor to home before responding to the target position command whenever it does not already have a known position (e.g. when it first starts up or after anytime it de-energizes)”. This was precisely my use case, de-energizing the motor.

Finally, yes, I can set a velocity, then set a position and tell the motor to start, which does precisely what I want: move to a position, at a velocity.

Thanks again!

2 Likes