Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

Reading variables from Tic T825

Hello, I am using a Tic T825 to control a stepper motor. The stepper accepts my write commands through the smbus and the I2C address for my device. The trouble I am having is getting any useful data returned when I want to read from a variable.
Here is a sample of my code with small GUI for user-control.

from tkinter import *
import tkinter
from smbus2 import SMBus, i2c_msg

# Reset
stepper_reset = 0xB0
# Set velocity
stepper_velocity = 0xE3
# Energize
energize = 0x85
# Denergize
de_energize = 0x86

# Class of variables
class Vars():
   position = 0
   control = 0

v = Vars()

# Establishes class for I2C commmunication
class TicI2C(object):
   def __init__(self, bus, address):
       self.bus = bus
       self.address = address

   # Sets the target position.
   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

# Declaration and intialization of smbus variable
bus = SMBus(1)
# Declaration of TicI2C instance
tic = TicI2C(bus, 0x11)

# Function to print position
def print_position():
   print(tic.get_variables(0x22,4))

# Function to reset stepper
def reset_stepper():
   tic.bus.write_byte(tic.address,stepper_reset)
   v.position=0

def exit_stepper():
   tic.bus.write_byte(tic.address,de_energize)
   v.control = 1

def increase_position():
   tic.set_target_position(v.position+100)
   v.position+=100

def decrease_position():
   tic.set_target_position(v.position-100)
   v.position-=100

# Initially energizes the motor
tic.bus.write_byte(tic.address,energize)

# Creates frame for GUI
root = Tk()
root.title('Stepper Motor Variable Retrival')
root.geometry('300x300')

btt_reset = Button(root,text='reset',command=reset_stepper)
btt_reset.place(x=200,y=20)

btt_exit = Button(root,text='exit',command=exit_stepper)
btt_exit.place(x=200,y=50)

lbl_position = Label(root,text=v.position)
lbl_position.place(x=20,y=50)

btt_inc_position = Button(root, text='+100',command=increase_position)
btt_inc_position.place(x=60,y=30)

btt_dec_position = Button(root, text='-100',command=decrease_position)
btt_dec_position.place(x=60,y=70)

# Button to print position
btt_print_position = Button(root,text='print position', command=print_position)
btt_print_position.place(x=60,y=100)

# Button to print current position returned from TicI2C function
btt_current_position = Button(root,text='Current Position from TicI2C',
                             command=lambda:print(tic.get_current_position()))
btt_current_position.place(x=60,y=130)

# Update loop dependant on v.control
while v.control == 0:
   root.update_idletasks()
   root.update()
   lbl_position.config(text=v.position)

# Destroys the frame of the gui
root.destroy()
   

Hello.

Can you elaborate on what return values you are seeing and what you expect? What are you using to control the Tic via I2C? Can you post pictures of your setup clearly showing how everything is connected in your setup?

- Amanda

The get_variables function of the TicI2C class returns a list of 255 values; I specifically have used offsets 0x22 and 0x26, the offset for current position variable and the offset for current velocity variable, with lengths 4. The value returned for either offset is a list of 255 for the specified length. If the get_current_position function is used, a -1 is returned. I expect the current position value to change when the target position is changed and reached, and I expect to see the current velocity value to change when I write values to the set velocity command and be zero when I set it to zero. The code for velocity is not included in the provided code, but it function properly besides the write. I am using a Raspberry Pi to control multiple Tic T825s, each with their own stepper motor. I can provide photos of how everything is connected in my setup. I hope that is sufficient information for you to assist me.

It looks like you are using the Raspberry Pi’s hardware I2C module, which has a known bug that prevents it from working reliably. Can you disconnect your Tic boards from your Raspberry Pi except for one and try running the example code in the “Example I2C code for Linux in Python” section in the Tic’s user’s guide? Please make sure to follow the instructions at the top of that section for setting up I2C on your Raspberry Pi and let us know the results.

- Amanda

Hello SamSmith,

Did you ever find a way to read variables from the Tic over I2C?

I have also struggled with reading from the tic using the example code for both i2c and serial wiring configurations.

Currently I am trying to use RPI3, python and i2c to control the Tic. I have the same result as you. I have no issue writing any command to the Tic and motors move as expected. But trying to read current position I get only -1 back. I have tried 0x0A, 0x22, 0x39 all with the same -1 return.

I dont think this is the hardware bug issue since I can write to the device so reliably.

an update on your attempts would be greatly appreciated.

thanks.

I was able to get proper reads by breaking the i2c_rdwr(write, read) command into two lines:

  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)
    self.bus.i2c_rdwr(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
1 Like