I am attempting to control & monitor two stepper motors using two tic T500 drivers set up for I2C communication in Python with a Raspberry Pi. Controlling the motors works flawlessly, I can energize, set position, home, de-energize, etc… with no issues. However, I cannot seem to use any of the read-type I2C commands.
Specifically, the get_variables
command will always return a list of [255, 255, …] depending on the specified length. This is in reference to the example program in section 12.9 of the tic handbook, shown below.
I heeded the warnings about using I2C on Raspberry Pi and followed the instructions in 12.8 to provide stable access to the i2c-gpio overlay. For my device, /dev/i2c-1
shows the connected tics with proper device numbers, not the usual /dev/i2c-3
mentioned in the user guide.
Running the demo program below doesn’t throw any errors, and indeed drives the motor with tic device number 14, but the printed position is always -1
. After some investigating with get_variables
, it appears to always return a list of 255
s, which the get_current_position
function translates to a position of -1
.
I’m not an expert in I2C communications or linux here, so any help or insight is appreciated.
# Uses the smbus2 library to send and receive data from a Tic.
# Works on Linux with either Python 2 or Python 3.
#
# NOTE: The Tic's control mode must be "Serial / I2C / USB".
# NOTE: For reliable operation on a Raspberry Pi, enable the i2c-gpio
# overlay and use the I2C device it provides (usually /dev/i2c-3).
# NOTE: You might nee to change the 'SMBus(3)' line below to specify the
# correct I2C device.
# NOTE: You might need to change the 'address = 11' line below to match
# the device number of your Tic.
from smbus2 import SMBus, i2c_msg
class TicI2C(object):
def __init__(self, bus, address):
self.bus = bus
self.address = address
# Sends the "Exit safe start" command.
def exit_safe_start(self):
command = [0x83]
write = i2c_msg.write(self.address, command)
self.bus.i2c_rdwr(write)
# Sets the target position.
#
# For more information about what this command does, see the
# "Set target position" command in the "Command reference" section of the
# Tic user's guide.
def set_target_position(self, target):
command = [0xE0,
target >> 0 & 0xFF,
target >> 8 & 0xFF,
target >> 16 & 0xFF,
target >> 24 & 0xFF]
write = i2c_msg.write(self.address, command)
self.bus.i2c_rdwr(write)
# Gets one or more variables from the Tic.
def get_variables(self, offset, length):
write = i2c_msg.write(self.address, [0xA1, offset])
read = i2c_msg.read(self.address, length)
self.bus.i2c_rdwr(write, read)
return list(read)
# Gets the "Current position" variable from the Tic.
def get_current_position(self):
b = self.get_variables(0x22, 4)
position = b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24)
if position >= (1 << 31):
position -= (1 << 32)
return position
# Open a handle to "/dev/i2c-3", representing the I2C bus.
bus = SMBus(1)
# Select the I2C address of the Tic (the device number).
address = 14
tic = TicI2C(bus, address)
position = tic.get_current_position()
print("Current position is {}.".format(position))
new_target = -200 if position > 0 else 200
print("Setting target position to {}.".format(new_target));
tic.exit_safe_start()
tic.set_target_position(new_target)