TRex controller motor controller lower speeds not working

Hi!

I require your help regarding a problem I’m encountering.

I have the TRex controller motor controller, I am able to drive the motor controller but, in the data command if I set the motor speed anything less than 255 the motor stops.

I am driving the robot from external supply [12v, 5 amps].
Any idea how to make motors speed lower .

my python code is below -

#!/usr/bin/python
from quick2wire import i2c
import sys
import time

startbyte = 0x0F
TREX_ADDRESS = 0x07

def getst():
with i2c.I2CMaster(1) as bus:
return bus.transaction(i2c.reading(0x07,24))

def setst(tmp):
with i2c.I2CMaster(1) as bus:
bus.transaction(i2c.writing(0x07,tmp))

class TrexDatacmd:
“”"
create a data package and send it
“”"

def __init__(self):
    '''
    Reset the trex controller data command
    '''

    self.sv = [0,0,0,0,0,0] #[1500, 1500, 1500, 1500, 0, 0]
    self.sd = [0,0,0,0,0,0] #[5, 10, -5, -15, 20, -20]
    self.lmspeed = 255
    self.rmspeed = 255
    self.ldir = 5
    self.rdir = 5
    self.lmbrake = 0
    self.rmbrake = 0
    self.devibrate = 50
    self.sensitivity = 50
    self.lowbat = 560
    self.i2caddr = 0x07
    self.i2cfreq = 0
    self.PWMfreq = 6

def sndDataCmd(self):
“”“Sends cmd to trx after sanity check”""

if not (self.PWMfreq > 0 and self.PWMfreq < 8):
    print ("PWM value not set correctly", self.PWMfreq)
    return
elif not(self.lmspeed > -256 and self.lmspeed < 256):
    print ("left motor speed not set correctly", self.lmspeed)
    return
elif not(self.lmbrake > -256 and self.lmbrake < 256):
    print ("left break calue not set correctly", self.lmbrake)
    return
elif not(self.rmspeed > -256 and self.rmspeed < 256):
    print ("Right motor speed not set correctly", self.rmspeed)
    return
elif not(self.rmbrake > -256 and self.rmbrake < 256):
    print ("Right motor speed not set correctly", self.rmbrake)
    return
elif (abs(self.sv[0])>2400):
    print ("Servo 0 value out of range")
    return
elif (abs(self.sv[1])>2400):
    print ("Servo 0 value out of range")
    return
elif (abs(self.sv[2])>2400):
    print ("Servo 0 value out of range")
    return
elif (abs(self.sv[3])>2400):
    print ("Servo 0 value out of range")
    return
elif (abs(self.sv[4]) > 2400):
    print ("Servo 0 value out of range")
    return
elif (abs(self.sv[5]) > 2400):
    print ("Servo 0 value out of range")
    return
elif not (self.sensitivity > -1 and self.sensitivity < 1024):
    print("Sensisity is outof range")
    return
elif not (self.lowbat > 549 and self.lowbat < 3001):
    print("Low Battary is out of range")
    return
elif not (self.i2caddr == 7):
    print("Do not udpate the i2c address",self.i2caddr)
    return
elif not (self.i2cfreq < 2):
    print("I2C frequency is out of range",self.i2cfreq)



tx = [startbyte, \
    self.PWMfreq, \
    __hight_byte(self.lmspeed), \
    __low_byte(self.lmspeed), \
    self.lmbrake, \
    __hight_byte(self.rmspeed), \
    __low_byte(self.rmspeed), \
    self.rmbrake, \
    __hight_byte(self.sv[0]), \
    __low_byte(self.sv[0]), \
    __hight_byte(self.sv[1]), \
    __low_byte(self.sv[1]), \
    __hight_byte(self.sv[2]), \
    __low_byte(self.sv[2]), \
    __hight_byte(self.sv[3]), \
    __low_byte(self.sv[3]), \
    __hight_byte(self.sv[4]), \
    __low_byte(self.sv[4]), \
    __hight_byte(self.sv[5]), \
    __low_byte(self.sv[5]), \
    self.devibrate, \
    __hight_byte(self.sensitivity), \
    __low_byte(self.sensitivity), \
    __hight_byte(self.lowbat), \
    __low_byte(self.lowbat), \
    self.i2caddr, \
    self.i2cfreq \
    ]

btx = bytes(tx)
print(btx)
setst(btx)
return

class TrexStatus:

def __init__(self):
    self.pr_cmd_st = 0
    self.bat_vlt = 0
    self.lft_mtr_cur = 0
    self.lft_mtr_cnt = 0
    self.rht_mtr_cur = 0
    self.rht_mtr_cnt = 0
    self.acc_x = 0
    self.acc_y = 0
    self.acc_z = 0
    self.imp_x = 0
    self.imp_y = 0
    self.imp_z = 0

def pntTrexSt(self):
    print("Previous data command status", end=" ")
    if (self.pr_cmd_st & 0x00):
        print("has update sucessfully.")
    else:
        print("has an Error -", end = " ")

    if (self.pr_cmd_st & 0x01):
        print("Start byte not received or incorrect data packet size")

    if (self.pr_cmd_st & 0x02):
        print("PWM frequency was not 1-7")

    if (self.pr_cmd_st & 0x04):
        print("Left or right motor speed was not -255 to +255")

    if (self.pr_cmd_st & 0x08):
        print("One or more servo positions was not -2400 to +2400")

    if (self.pr_cmd_st & 0x10):
        print("Impact sensitivity not 0-1023")

    if (self.pr_cmd_st & 0x20):
        print("Low battery was not 550 to 3000 i.e., 5.5V to 30V")

    if (self.pr_cmd_st & 0x40):
        print("I2C slave address was not 0-127")

    if (self.pr_cmd_st & 0x80):
        print("I2C speed not 0 which means 100kHz or 1 which means 400kHz")

    print("Battery voltage: " + str(self.bat_vlt))
    print("Left motor current: " + str(self.lft_mtr_cnt))
    print("Right motor current: " + str(self.rht_mtr_cnt))
    print("Accelerometer X-axis: " + str(self.acc_x))
    print("Accelerometer Y-axis : " + str(self.acc_y))
    print("Accelerometer Z-axis : " + str(self.acc_z))
    print("Impact X-axis: " + str(self.imp_x))
    print("Impact Y-axis: " + str(self.imp_y))
    print("Impact Z-axis: " + str(self.imp_z))

def getTrexSts(self):
‘’’
Get status from trex
- Battery voltage: An integer that is 100x the actual voltage
- Motor current: Current drawn by the motor in mA
- Accelerometer
- Impact
update the object with trex status
‘’’

b = getst()
self.pr_cmd_st = b[0][1]
self.bat_vlt = __hight_low_int(b[0][2], b[0][3])
self.lft_mtr_cur = __hight_low_int(b[0][4], b[0][5])
self.lft_mtr_cnt = __hight_low_int(b[0][6], b[0][7])
self.rht_mtr_cur = __hight_low_int(b[0][8], b[0][9])
self.rht_mtr_cnt = __hight_low_int(b[0][10], b[0][11])
self.acc_x = __hight_low_int(b[0][12], b[0][13])
self.acc_y = __hight_low_int(b[0][14], b[0][15])
self.acc_z = __hight_low_int(b[0][16], b[0][17])
self.imp_x = __hight_low_int(b[0][18], b[0][19])
self.imp_y = __hight_low_int(b[0][20], b[0][21])
self.imp_z = __hight_low_int(b[0][22], b[0][23])
return

trex_st = TrexStatus()
trexCmd = TrexDatacmd()

def __trex_reset(self):
‘’’
Reset the trex controller data command
‘’’
self.sv[0] = 1500
self.sv[1] = 1500
self.sv[2] = 1500
self.sv[3] = 1500
self.sv[4] = 0
self.sv[5] = 0

self.sd[0] = 5
self.sd[1] = 10
self.sd[2] = -5
self.sd[3] = -15
self.sd[4] = 20
self.sd[5] = -20

self.lmspeed = 0  # left motor speed from -255 to +255 (negative value = reverse)
self.rmspeed = 0  # right motor speed from -255 to +255 (negative value = reverse)
self.ldir = 5  # how much to change left  motor speed each loop (use for motor testing)
self.rdir = 5  # how much to change right motor speed each loop (use for motor testing)
self.lmbrake = 0  # left motor brake (non zero value = brake)
self.rmbrake = 0  # right motor brake (non zero value = brake)
self.devibrate = 50  # time delay after impact to prevent false re-triggering due to chassis vibration
self.sensitivity = 50  # threshold of acceleration / deceleration required to register as an impact
self.lowbat = 550  # adjust to suit your battery: 550 = 5.50V
self.i2caddr = 7  # default I2C address of T'REX is 7. If this is changed, the T'REX will automatically store new address in EEPROM
self.i2cfreq = 0  # I2C clock frequency. Default is 0=100kHz. Set to 1 for 400kHz

def printb(string):
‘’’
Print bold text to screen
‘’’
print(’\033[1m’ + string + ‘\033[0m’)

def __trex_status():
‘’’
Read status from trex
Return as a byte array
‘’’
#answer = i2c.read_i2c_block_data(TREX_ADDRESS, 240, 24)

return b'\x0f\x01\x04\xb6\x9f\xad\xff\xff\xff\xd0\xff\xff\x02\x86\x02\x86\x02\x86\x00\x00\x00\x00\x00\x00'
#return answer
#return [b'\x0f\x00\x04\xb6\x9f\xad\xff\xff\xff\xd0\xff\xff\x02\x88\x02\x88\x02\x88\x00\x00\x00\x00\x00\x00']

def __hight_byte(integer):
‘’’
Get the hight byte from a int
‘’’
return integer >> 8

def __low_byte(integer):
‘’’
Get the low byte from a int
‘’’
return integer & 0xFF

def __hight_low_int(hight_byte, low_byte):
‘’’
Convert low and low and hight byte to int
‘’’
return (int(hight_byte) << 8) + int(low_byte)

if name == ‘main’:
#print("-------------------")
getTrexSts(trex_st)
#trex_st.pntTrexSt()
sndDataCmd(trexCmd) # initial

#todo: Create a thread to read the status periodically
#todo: ROS message to update the Trex status continously
#todo: ROS service to set the trex speeds/break and direction or \
# drive it using differential steering [http://wiki.ros.org/diff_drive_controller]
#todo: GUI to view the trex status and plot it

getTrexSts(trex_st)
if trex_st.pr_cmd_st == 0:
    sndDataCmd(trexCmd)  # initial
    time.sleep(5)
    # motor stops here
    trexCmd.rmspeed = 254
    trexCmd.lmspeed = 254
    
else:
    while (1):
        print(".", end = " ")
        getTrexSts(trex_st)
        trexCmd.rmspeed += 20
        trexCmd.lmspeed -= 20
        sndDataCmd(trexCmd)  # initial
        time.sleep(1)

        #print(__hight_byte(trexCmd.lmspeed),__low_byte(trexCmd.lmspeed))

        if trexCmd.lmspeed > 20:
            break
trexCmd.rmspeed = 0
trexCmd.lmspeed = 0
sndDataCmd(trexCmd)

Thank you so much in advance for your help in adavance!

Hi @SSH,

In the future, I recommend you instead link to a code repository (such as GitHub, BitBucket, etc.) or attach a file (or files in and an archive, such as .rar or .zip) for simplicity. Pasting code in the post is fine for a few lines but for complex examples it is not quite readable (and lacks proper highlighting/color coding of most IDEs/editors).

I assume you are referring to one of the two Pololu TReX controller?

Have you tried using the configuration utility (and check jumpers) to ensure everything is set/configured properly for your use case? With more complex controllers it often happens that the issue is not with the code itself but with the settings in the motor controller!

You may also want to look at this short article. It seems to have some useful info including mentioning controlling speed.

I hope this helps.

Sincerely,

Thanks Scharette,

The link you have shared is for the jrTREX, I am using the Trex controller the commands for both are different i believe.

I have been using the Wild Thumper chassis and motor controller for easy interface -
https://robosavvy.com/store/dagu-wild-thumper-arduino-robot-pack-configurable.html

I have attached the code file.trex_control.txt (9.2 KB)

Hey,

Good to mention which one you are using. For that controller, I found this topic on the manufacturer’s forum. I highly recommend reading through it. The customer goes through the process of making their code work and understand how to control the speed/current step by step (and also mentioning it is not very clear / easy to figure out).

You may also want to look at this one, too.

The code for both links are for Arduino, but it shouldn’t be too much of a challenge to translate to Python for your RPi since the control is through a serial port.

Sincerely,

The link shared is for the jrTrex controller, I am using https://robosavvy.com/store/dagu-t-39-rex-robot-motor-controller.html.

Both of these have different interface, I was debugging the arduino code, I am not able to reduce speed in the embedded code also.