Hi there,
I am pretty new to Python and controlling stepper motors.
I am currently working on a project where I need to control six stepper motors and reading six encoder values.
So my basic setup consists of a RPi4, six Pololu Tic T825 and six stepper motors (1.9V, 1.8A) with attached encoders (5V operating current).
I connected the Tics via I2C to the PI (physical GPIO Pins 3 and 5). The Tics are powered with a 15V 20A powersupply.
The encoders are attached to the Tics RX/TX pins and are getting their 5V and GND from them aswell.
Controlling the motors from the TicGUI software isn’t a problem at all. Also if I check the connection to the I2C devices with “i2cdetect -y 1” all attached devices are listed with the adresses configured.
As I was having issues I have played around with baudrates a little (changing vom 9600 to 16000 to 32000 in the PI and the Tics). That didn’t help.
So basically the problem is, if I start my code (based on the example in the documentation) there is an error message prompted after a few seconds.
Traceback (most recent call last):
File "/home/pi/Desktop/testMH.py", line 79, in <module>
tic.set_target_position(300)
File "/home/pi/Desktop/testMH.py", line 38, in set_target_position
self.bus.i2c_rdwr(write)
File "/home/pi/.local/lib/python3.7/site-packages/smbus2/smbus2.py", line 637, in i2c_rdwr
ioctl(self.fd, I2C_RDWR, ioctl_data)
OSError: [Errno 121] Remote I/O error
My code is the following:
from smbus2 import SMBus, i2c_msg
from time import sleep
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)
print(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)
print(address, offset)
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(0x39, 4)
position = b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24)
if position >= (1 << 31):
position -= (1 << 32)
return position
def energize(self):
command = [0x85]
write = i2c_msg.write(self.address, command)
self.bus.i2c_rdwr(write)
# 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 = 7
tic = TicI2C(bus, address)
tic.exit_safe_start()
while True:
tic.energize()
tic.set_target_position(-300)
posi = tic.get_current_position()
print("Current position is {}.".format(posi))
sleep(1)
tic.energize()
tic.set_target_position(300)
print("Current position is {}.".format(posi))
sleep(1)
Any help would be much appreciated.
Best