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

Pololu Forum

TReX - Arduino read joy - remap - write to serial

Hi, as per subject of post.

I am trying to get my Arduino Nano V3.0 to

  • read some analog values
  • remap the values to maintain a positive integer ie
    (forward - map(mainVal, 512, 1023, 0, 127)
    (reverse - map(mainVal, 0, 511, 0, 127)
    contained with in functions for forward and reverse respectively

-then convert that number to HEX
String myString = (mainVal, HEX)

Write to software serial
-softwareSerial.write(forward)
-softwareSerial.write(remapped and converted to HEX value)

Am i heading in the right direction with this code ?
Only the M1 ‘mainSheet’ bit is done so far till i know if i am barking up the wrong tree or not
– updated code with acclerate HEX to make use of current limiting settings.

Sections of code specifically i am referring to are
Void mainIn() / Void mainOut()

//Software serial settings
#include <SoftwareSerial.h>
const int tRexout = 7; // rx pin of Arduino, SO(serial out)of TRex.
const int tRexin = 8; // tx pin of Arduino, SI(serial in)of TRex.

SoftwareSerial tRexSerial (tRexout, tRexin); // RX to SO of Trex, TX to SI of Trex

// Pot inputs
// Main sheet M1
int mainPin = A0;  //input A0 for mainsheet
int mainVal = analogRead(mainPin);  // int to hold mainInput value, 128 is neutral
int mainValmapin;
int mainValmapout;

// Jib sheet M2
int jibPin = A1;
int jibVal = 0;


void setup()
{
  tRexSerial.begin(19200);
  pinMode(tRexout, INPUT);  // probably not needed as SoftWare serial already handles this.
  pinMode(tRexin, OUTPUT);  // probably not needed as SoftWare serial already handles this.

delay (200) ;    // wait for Software serial to start, probably to long edit this line.


}

void loop () {
  // Main Sheet deadbands
  mainVal = analogRead(mainPin);
  Serial.print("Main Val = ");
  Serial.print(mainVal);
  if (mainVal >= 900)
  {
    mainOut();
  }
  else if (mainVal <= 100 )
  {
    mainIn();
  }
  else
  {
    mainStop();
  }

  // Jib control dead bands
  jibVal = analogRead(jibPin);
  Serial.print("Jib Val = ");
  Serial.print(jibVal);
  Serial.println();
  if (jibVal >= 900)
  {
    jibOut();
  }
  else if (jibVal <= 100 )
  {
    jibIn();
  }
  else
  {
    jibStop();
  }


}

void mainOut() {
  // this function will let the main sheet out
  // turn on motor 1 'forward'
    // use accleration HEX so that the current limiting is enabled.
  mainValmapout = map(mainVal, 512, 1023, 0, 127); // map speed
  String mainString = (mainValmapout, HEX);    // convert main value int to HEX for TReX
  tRexSerial.write(0xC6); // accelerate motor1 forward
  tRexSerial.write(mainString); // Analog read val,mapped, converted to HEX write to software serial.
}

void mainIn() {
  // this function will pull the main sheet in
  // turn on motor A 'reverse'
  mainValmapin = map(mainVal, 0, 511, 0 , 127); // map reverse speed to return positive int 0-127
  String mainString = (mainValmapin, HEX);    // convert int to HEX for TReX
  tRexSerial.write(0xC5); //reverse accelerate motor 2
  tRexSerial.write(mainString); // Analog read val,mapped, converted to HEX write to software serial.

}

void mainStop () {

}


void jibOut() {
  // this function will let jib sheet out
  // turn on motor B 'forward'

}

void jibIn() {
  // this function will bring jib sheet in
  // turn on motor B 'reverse'

}

void jibStop () {

}

Hello.

I took a quick look at your code, and did not notice anything obviously wrong with the general approach you are using. However, converting your target speed, which was an integer, to a string before trying to send it as a data byte using the SoftwareSerial.write() function will not work. Basically: tRexSerial.write(127) is different than tRexSerial.write("127"). You do not need to convert the integer value into hex for SoftwareSerial.write() to work. So, to fix this, you can just use the integer values of mainValmapout and mainValmapin directly as the data byte for tRexSerial.write().

If you end up having problems, could you post the simplest version of your code that shows the issue? It might also help if you give more context for what you controlling with the TReX and what behavior you want from it.

-Jon

Thank you so much, Ive made those changes and the code actually compiles now :confused:
no response from TReX as yet, i may have some jumpers set wrong, ill go thru the documentation again.

…for the documentation…would it be possible for it to be a bit clearer ?

A look-up table with headings would clear things up a lot

-Table for Serial commands
/ Function / Motor 1&2 / Motor 1 / Motor 2 / Motor 3 /
Get data
Full forward
Acc forward
Fwd Stop
Full back
Acc back
Fwd Back

You kinda have it at the start of the commands documents but
these lines are not clear 0xC0 – 0xC3: Set Motor 1
where there is a range what is the range for ? its deep at the bottom of the document still could be more readable.
00 = brake low (command 0xC0/0xC8) this line is grouped under Motor Two…but apparently refers to both motors ?
…there is two brake lows for each motor, is there any difference in either of them ?
11 = brake low (command 0xC3/0xCB)

A look up table would be much easier to read, i could not find anywhere in the documentation that says i can directly write integers to set the speed (tho if i was any good at programming i would / should of known that hey…)

As to what i need the motor controller to do. (it was longer but condensed it for readability)
Drive winches in disabled sailing boats at my local sailability club - i have a vested interest, have a severe brain injury myself, sailabilitygc.org
(link to more detail sailabilitygc.org/liberty-propor … ch-assist/)

  • TReX to drive both bidirectional winch motors and bilge pump.
  • TReX to use accelerate so to be more gentle on the winch workings.
    - TReX to use current control to ‘switch off’ to prevent over driving a locked up winch (fully wound in/out)

Its sort of working

Trouble i am having is.
Forward = Green LED, works great
Reverse = RED led, is inverted…ie its fast near the neutral position going to a stop at the end point…

Don’t forward and reverse take a positive acceleration integer ? 0-127 ?

my code

void mainOut() {
  // this function will let the main sheet out
  // turn on motor 1 'forward'
  // use accleration HEX so that the current limiting is enabled.
  mainValmapout = map(mainVal, 512, 1023, 0, 127); // map speed
  tRexSerial.write(0xC6); // accelerate function motor1 forward
  tRexSerial.write(mainValmapout); // Analog read val,mapped write to software serial.
}

void mainIn() {
  // this function will pull the main sheet in
  // turn on motor A 'reverse'
  mainValmapin = map(mainVal, 0, 511, 0 , 127); // map reverse speed to return positive int 0-127
  tRexSerial.write(0xC5); //reverse accelerate motor 1
  tRexSerial.write(mainValmapin); // Analog read val ,mapped, write to software serial.

}

do i just reverse the map ?
mainValmapin = map(mainVal, 0, 511, 127, 0);
or does it need to be (mainVal, 0 ,511, 0, -127);

Nearly got it working,

Answer to above question
-please check the code below.

Still a bit of cross over where both LED’s light up going from forward to reverse.
Full volts only on RED led, Green only lighting up faintly.

i must be putting in the wrong HEX code but i cant figure it out, trying to fix by trial and error…



//Software serial settings
#include <SoftwareSerial.h>
const int rx = 7; // rx pin of Arduino, SO(serial out)of TRex.
const int tx = 8; // tx pin of Arduino, SI(serial in)of TRex.

SoftwareSerial tRexSerial (rx, tx); // RX to SO of Trex, TX to SI of Trex

// Pot inputs
// Main sheet M1
int mainPin = A0;  //input A0 for mainsheet
int mainVal = 507;  // int to hold mainInput value, startup in neutral 511
int mainValmapin;
int mainValmapout;


// Jib sheet M2
int jibPin = A1;
int jibVal = 507;
int jibValmapin;
int jibValmapout;

// dead band settings
int deadVal = 200;    // will change to pot values , one for eaxh axis
int midVal = 507;
int fwdVal = (midVal + deadVal);
int revVal = (midVal - deadVal);


void setup()
{
  Serial.begin(19200);
  tRexSerial.begin(19200);
  delay (100) ;    // wait for Software serial to start, probably to long edit this line.
}

void loop () {
  // Main sheet control

  mainVal = analogRead(mainPin);
  Serial.print("main = ");
  Serial.print(mainVal);
  if (mainVal > fwdVal)
  {
    // Forward motor A
    mainValmapout = map(mainVal, fwdVal, 1023, 0 , 127); // map reverse speed to return positive int 0-127
    tRexSerial.write(0xC6); // accelerate motor 1
    tRexSerial.write(mainValmapout); // Analog read val ,mapped, write to software serial.
  }
  else (mainVal < revVal );
  {
    // Reverse motor A
    mainValmapin = map(mainVal, 0, revVal, 127 , 0); // map reverse speed to return positive int 0-127
    tRexSerial.write(0xC5); //reverse accelerate motor 1
    tRexSerial.write(mainValmapin); // Analog read val ,mapped, write to software serial.
  }

  // Jib control
  jibVal = analogRead(jibPin);
  Serial.print(" , jib = ");
  Serial.print(jibVal);
  Serial.println();
  if (jibVal > fwdVal)
  {
    // turn on motor B 'forward'
    jibValmapout = map(jibVal, fwdVal, 1023, 0, 127); // map speed to return positive int 0-127
    tRexSerial.write(0xCE); // accelerate motor 2 forward
    tRexSerial.write(jibValmapout); // Analog read val,mapped write to software serial.
  }
  else (jibVal < revVal );
  {
    // turn on motor B 'reverse'
    jibValmapin = map(jibVal, 0, revVal, 127 , 0); // map reverse speed to return positive int 0-127
    tRexSerial.write(0xCD); //reverse accelerate motor 2
    tRexSerial.write(jibValmapin); // Analog read val ,mapped, write to software serial.
  }

}




Hi, can anyone tell me where to find the instructions on setting the speed ?

I see lots of references to setting speed in the configuration settings but nowhere the command values

I have tried 0-127 but not sure if that’s working.

I really want to set proportional speed.

Finally got it sorted,

Needed
if
else if
…and else statment, i was missing this instruction on what to do when there was no valid joy input.

This code is working for proportional control of M1 & M2

Joystick input to Arduino, Software Serial to TReX
Now to work out how to pull the Amp’s info and modify/limit the speed/stop motors.

[code]//Software serial settings
#include <SoftwareSerial.h>
const int rx = 7; // rx pin of Arduino, SO(serial out)of TRex.
const int tx = 8; // tx pin of Arduino, SI(serial in)of TRex.

SoftwareSerial tRexSerial (rx, tx); // RX to SO of Trex, TX to SI of Trex

// Pot inputs
// Main sheet M1
int mainPin = A0; //input A0 for mainsheet
int mainVal = 507; // int to hold mainInput value, startup in neutral 511
int mainValmapin;
int mainValmapout;

// Jib sheet M2
int jibPin = A1;
int jibVal = 507;
int jibValmapin;
int jibValmapout;

// dead band settings
int deadVal = 200; // will change to pot values , one for eaxh axis
int midVal = 507;
int fwdVal = (midVal + deadVal);
int revVal = (midVal - deadVal);

void setup()
{
Serial.begin(19200);
tRexSerial.begin(19200);
delay (100) ; // wait for Software serial to start, probably to long edit this line.
}

void loop () {
// Main sheet control

mainVal = analogRead(mainPin);
Serial.print("main = ");
Serial.print(mainVal);
if (mainVal > fwdVal)
{
// Forward motor A
mainValmapout = map(mainVal, fwdVal, 1023, 0 , 127); // map reverse speed to return positive int 0-127
tRexSerial.write(0xC6); // accelerate motor 1
tRexSerial.write(mainValmapout); // Analog read val ,mapped, write to software serial.
}
else if(mainVal < revVal )
{
// Reverse motor A
mainValmapin = map(mainVal, 0, revVal, 127 , 0); // map reverse speed to return positive int 0-127
tRexSerial.write(0xC5); //reverse accelerate motor 1
tRexSerial.write(mainValmapin); // Analog read val ,mapped, write to software serial.
}
else
tRexSerial.write(0XC4);

// Jib control
jibVal = analogRead(jibPin);
Serial.print(" , jib = ");
Serial.print(jibVal);
Serial.println();
if (jibVal > fwdVal)
{
// turn on motor B 'forward’
jibValmapout = map(jibVal, fwdVal, 1023, 0, 127); // map speed to return positive int 0-127
tRexSerial.write(0xCE); // accelerate motor 2 forward
tRexSerial.write(jibValmapout); // Analog read val,mapped write to software serial.
}
else if(jibVal < revVal )
{
// turn on motor B 'reverse’
jibValmapin = map(jibVal, 0, revVal, 127 , 0); // map reverse speed to return positive int 0-127
tRexSerial.write(0xCD); //reverse accelerate motor 2
tRexSerial.write(jibValmapin); // Analog read val ,mapped, write to software serial.
}
else
tRexSerial.write(0xCC);
}

[/code]

Hi Jonathan

I am seeking direction on how to set the current limits.

From one of the documents i see this in the first paragraph.

[quote]Parameters in Detail:
0x00: device number (default value: 0x07)
The device number can be used in conjunction with the extended serial command protocol to
communicate with one of many devices connected to the same serial line. The command
protocol would be:
0x80, device #, command byte with MSB cleared, any necessary data bytes
[/quote]

So for my application should i be doing the following ?
As requested i have cut the code down to just the bits i am referring to.

int m1currentlimit = 2 //  m1 / m2 current limit is 2amps
int m2currentlimit = 2 // Parameter for current limit M1 = 0x13 , M2= 0x14 ? 
int m1pccl = 0   // Value 0 proportionally constant current limit (pccl) turns motors off ? 
int m2pccl = 0   // (proportionally constant parameter for M1 is 0x15, M2 is 0x16) 

Void Setup(){
// tRexSerial.write(0x80, 0x07, Parameter to set, value to set parameter to);  ?
//tRexSerial.write(0x80, 0x07, 0x13 , 2); // set M1 current limit
// Arduino needs data packet to be built 
    data[0] = (0x80);   // set parameter bit instruction
    data[1] = (0x07);   // TReX id number (if i had more than one, still necessary with only one)
    data[2] = (0x13);   // Parameter id, 0x13 for M1 Current Limit
    data[3] = (2);      // Value for Current limit
    
    for (unsigned char i = 0; i < 4; i++)
      tRexSerial.write(data[i]);


//tRexSerial.write(0x80, 0x07, 0x15, 0);  // set M1  Proportionally constant 0 (turn motors off if over current)
//Arduino needs data packet to be built
    data[0] = (0x80);   // set parameter bit instruction
    data[1] = (0x07);   // TReX id number (if i had more than one, still necessary with only one)
    data[2] = (0x15);   // Parameter id, 0x15 for M1 Proportionally constant current Limit
    data[3] = (0);      // Value for Current limit
    
    for (unsigned char i = 0; i < 4; i++)
      tRexSerial.write(data[i]);
delay (10) // give tRex time to apply settings.

In this way, i am hoping the TReX overrides the serial data joystick commands if over / near current limit ?

Ive done it line by line (instead of setting both motors the same) as each motor will require different current limits.
eg jib is direct drive, main is via block and tackle gear reduction but both use the same model winch motors.

Should i also be setting the dead band this way v’s the way i have done it in the Arduino analog read if/else statements ?

Code i had working last night now not working after trying to add parameter settings info to
void setup ()

Its quite frustrating to work this out with the non existent examples / Libraries.
I hope by sticking all my failures up someone can benefit, its a great product.

This is like trying to walk thru a forest blind folded and deaf in the dark with gloves on ! :frowning:

Q: Do i need to tell the TReX after i have made the settings that it may now operate in normal mode ?

/* Written by Tony Matthews for the purpose of Disabled assist sail winch control
in 303 and liberty Class Access dinghy's

Code here in is written by Tony Matthews, whom has TBI. Use at your own risk.

Notes from Pololu's documentation.
--Motor Current codes --
0x13: motor 1 current limit
 (default: 0 – no motor 1 current limit)
0x14: motor 2 current limit
 (default: 0 – no motor 2 current limit)
0x15: motor 1 current limit proportionality constant P
 (default: 0x0A)
0x16: motor 2 current limit proportionality constant P
 (default: 0x0A)

 --Acceleration Codes--


*/



//Software serial settings
#include <SoftwareSerial.h>
const int rx = 7; // rx pin of Arduino, SO(serial out)of TRex.
const int tx = 8; // tx pin of Arduino, SI(serial in)of TRex.

SoftwareSerial tRexSerial (rx, tx); // RX to SO of Trex, TX to SI of Trex

// Pot inputs
// Main sheet M1
int mainPin = A0;  //input A0 for mainsheet
int mainVal = 507;  // int to hold mainInput value, startup in neutral 511
int mainValmapin;
int mainValmapout;


// Jib sheet M2
int jibPin = A1;
int jibVal = 507;
int jibValmapin;
int jibValmapout;

// dead band settings
int deadVal = 200;    // will change to pot values , one for eaxh axis
int midVal = 507;
int fwdVal = (midVal + deadVal);
int revVal = (midVal - deadVal);

// TReX parameter settings and notes
//int mOnecl = 2;  //  m1 / m2 current limit is 2amps
//int mTwocl = 2;  // Parameter for current limit M1 = 0x13 , M2= 0x14 ?
//int mOnepccl = 0;   // Value 0 proportionally constant current limit (pccl) turns motors off ?
//int mTwopccl = 0;   // (proportionally constant parameter for M1 is 0x15, M2 is 0x16)
unsigned char data[4];
unsigned long timer = 0;

void setup()
{
  Serial.begin(19200);
  tRexSerial.begin(19200);
  delay (100) ;    // wait for Software serial to start, probably to long edit this line.
  
  // Write TReX parameters.
  // syntax - tRexSerial.write(0x80, 0x07, Parameter to set, value to set parameter to);  ?
  
  //tRexSerial.write(0x80, 0x07, 0x13 , 2); // set M1 current limit
  //tRexSerial.write(0x80, 0x07, 0x15, 0);  // set M1  Proportionally constant 0 (turn motors off if over current)

  // build m1 data packet for current limit and proportionally constant
  // build M1 current limit packet
  data[0] = (0x80);   // set parameter bit instruction
  data[1] = (0x07);   // TReX id number (if i had more than one, still necessary with only one)
  data[2] = (0x13);   // Parameter id, 0x13 for M1 Current Limit
  data[3] = (2);      // Value for Current limit

  for (unsigned char i = 0; i < 4; i++)
    tRexSerial.write(data[i]);

  // build M1 Proportionally constant settings packet
  //tRexSerial.write(0x80, 0x07, 0x15, 0);  // set M1  Proportionally constant 0 (turn motors off if over current)
  data[0] = (0x80);   // set parameter bit instruction
  data[1] = (0x07);   // TReX id number (if i had more than one, still necessary with only one)
  data[2] = (0x15);   // Parameter id, 0x15 for M1 Proportionally constant current Limit
  data[3] = (0);      // Value for Current limit

  for (unsigned char i = 0; i < 4; i++)
    tRexSerial.write(data[i]);
    
    //Build M2 Parameter settings packets
    
    //M2 data packet for current limit
  data[0] = (0x80);   // set parameter bit instruction
  data[1] = (0x07);   // TReX id number (if i had more than one, still necessary with only one)
  data[2] = (0x14);   // Parameter id, 0x14 for M2 Current Limit
  data[3] = (2);      // Value for Current limit

  for (unsigned char i = 0; i < 4; i++)
    tRexSerial.write(data[i]);

  // Build M2 Proportionally constant settings packet
  // set M1  Proportionally constant 0 (turn motors off if over current)
  data[0] = (0x80);   // set parameter bit instruction
  data[1] = (0x07);   // TReX id number (if i had more than one, still necessary with only one)
  data[2] = (0x16);   // Parameter id, 0x15 for M1 Proportionally constant current Limit
  data[3] = (0);      // Value for Current limit

  for (unsigned char i = 0; i < 4; i++)
    tRexSerial.write(data[i]);
  
  delay (10); // give tRex time to apply settings.

}

void loop () {
  // Main sheet control

  mainVal = analogRead(mainPin);
  Serial.print("main = ");
  Serial.print(mainVal);
  if (mainVal > fwdVal)
  {
    // Forward motor A
    mainValmapout = map(mainVal, fwdVal, 1023, 0 , 127); // map reverse speed to return positive int 0-127
    tRexSerial.write(0xC6); // accelerate motor 1
    tRexSerial.write(mainValmapout); // Analog read val ,mapped, write to software serial.
  }
  else if (mainVal < revVal )
  {
    // Reverse motor A
    mainValmapin = map(mainVal, 0, revVal, 127 , 0); // map reverse speed to return positive int 0-127
    tRexSerial.write(0xC5); //reverse accelerate motor 1
    tRexSerial.write(mainValmapin); // Analog read val ,mapped, write to software serial.
  }
  else
    tRexSerial.write(0XC4);

  // Jib control
  jibVal = analogRead(jibPin);
  Serial.print(" , jib = ");
  Serial.print(jibVal);
  Serial.println();
  if (jibVal > fwdVal)
  {
    // turn on motor B 'forward'
    jibValmapout = map(jibVal, fwdVal, 1023, 0, 127); // map speed to return positive int 0-127
    tRexSerial.write(0xCE); // accelerate motor 2 forward
    tRexSerial.write(jibValmapout); // Analog read val,mapped write to software serial.
  }
  else if (jibVal < revVal )
  {
    // turn on motor B 'reverse'
    jibValmapin = map(jibVal, 0, revVal, 127 , 0); // map reverse speed to return positive int 0-127
    tRexSerial.write(0xCD); //reverse accelerate motor 2
    tRexSerial.write(jibValmapin); // Analog read val ,mapped, write to software serial.
  }
  else
    tRexSerial.write(0xCC);
}


Increasing the delay after

tRexSerial.begin

fixed the problem.

Ive since read conflicting information (or the information previously read was misleading, as there was only an example for the expanded protocol, i thought i had to use expanded protocol for the Configuration set parameters), i dont know if i can use the compact protocol, would make the code a bit smaller.

Working code with spelling errors
Reads Joystick, limits current to 2amps (hopefully might have that bit written wrong), drives to motors for servo assist disabled sailing boats.

Please remember the brain function of the guy doing all this…ME, is horribly low following being crushed like a pancake stack in a car accident…i was the maple syrup dribbling out the sides…

The whole lot could be horribly wrong.

/* Written by Tony Matthews for the purpose of Disabled assist sail winch contol
in 303 and liberty Class Access dinghy's

Code here in is written by Tony Matthews, whom has TBI. Use at your own risk.

Notes from Pololu's documentation.
--Motor Current codes --
0x13: motor 1 current limit
 (default: 0 – no motor 1 current limit)
0x14: motor 2 current limit
 (default: 0 – no motor 2 current limit)
0x15: motor 1 current limit proportionality constant P
 (default: 0x0A)
0x16: motor 2 current limit proportionality constant P
 (default: 0x0A)

 --Accelleration Codes--


*/



//Software serial settings
#include <SoftwareSerial.h>
const int rx = 7; // rx pin of Arduino, SO(serial out)of TRex.
const int tx = 8; // tx pin of Arduino, SI(serial in)of TRex.

SoftwareSerial tRexSerial (rx, tx); // RX to SO of Trex, TX to SI of Trex

// Pot inputs
// Main sheet M1
int mainPin = A0;  //input A0 for mainsheet
int mainVal = 507;  // int to hold mainInput value, startup in neutral 511
int mainValmapin;
int mainValmapout;


// Jib sheet M2
int jibPin = A1;
int jibVal = 507;
int jibValmapin;
int jibValmapout;

// dead band settings
int deadVal = 200;    // will change to pot values , one for eaxh axis
int midVal = 507;
int fwdVal = (midVal + deadVal);
int revVal = (midVal - deadVal);

// TReX parameter settings and notes
//int mOnecl = 2;  //  m1 / m2 current limit is 2amps
//int mTwocl = 2;  // Parameter for current limit M1 = 0x13 , M2= 0x14 ?
//int mOnepccl = 0;   // Value 0 proportionally constant current limit (pccl) turns motors off ?
//int mTwopccl = 0;   // (proportionally constant parameter for M1 is 0x15, M2 is 0x16)
unsigned char data[4];
unsigned long timer = 0;

void setup()
{
  Serial.begin(19200);
  tRexSerial.begin(19200);
  delay (400) ;    // wait for Software serial to start, probably to long edit this line.
  
  // Write TReX parameters.
  // syntax - tRexSerial.write(0x80, 0x07, Parameter to set, value to set parameter to);  ?
  
  //tRexSerial.write(0x80, 0x07, 0x13 , 2); // set M1 current limit
  //tRexSerial.write(0x80, 0x07, 0x15, 0);  // set M1  Proportionally constant 0 (turn motors off if over current)

  // build m1 data packet for current limit and proportionally constant
  // build M1 current limit packet
  data[0] = (0x80);   // set parameter bit instruction
  data[1] = (0x07);   // TReX id number (if i had more than one, still necessary with only one)
  data[2] = (0x13);   // Parameter id, 0x13 for M1 Current Limit
  data[3] = (2);      // Value for Current limit

  for (unsigned char i = 0; i < 4; i++)
    tRexSerial.write(data[i]);

  // build M1 Porportionally constant settings packet
  //tRexSerial.write(0x80, 0x07, 0x15, 0);  // set M1  Proportionally constant 0 (turn motors off if over current)
  data[0] = (0x80);   // set parameter bit instruction
  data[1] = (0x07);   // TReX id number (if i had more than one, still necessary with only one)
  data[2] = (0x15);   // Parameter id, 0x15 for M1 Proportionally constant current Limit
  data[3] = (0);      // Value for Current limit

  for (unsigned char i = 0; i < 4; i++)
    tRexSerial.write(data[i]);
    
    //Build M2 Parameter settings packets
    
    //M2 data packet for current limit
  data[0] = (0x80);   // set parameter bit instruction
  data[1] = (0x07);   // TReX id number (if i had more than one, still necessary with only one)
  data[2] = (0x14);   // Parameter id, 0x14 for M2 Current Limit
  data[3] = (2);      // Value for Current limit

  for (unsigned char i = 0; i < 4; i++)
    tRexSerial.write(data[i]);

  // Build M2 Porportionally constant settings packet
  // set M1  Proportionally constant 0 (turn motors off if over current)
  data[0] = (0x80);   // set parameter bit instruction
  data[1] = (0x07);   // TReX id number (if i had more than one, still necessary with only one)
  data[2] = (0x16);   // Parameter id, 0x15 for M1 Proportionally constant current Limit
  data[3] = (0);      // Value for Current limit

  for (unsigned char i = 0; i < 4; i++)
    tRexSerial.write(data[i]);
  
  delay (10); // give tRex time to apply settings.

}

void loop () {
  // Main sheet control

  mainVal = analogRead(mainPin);
  Serial.print("main = ");
  Serial.print(mainVal);
  if (mainVal > fwdVal)
  {
    // Forward motor A
    mainValmapout = map(mainVal, fwdVal, 1023, 0 , 127); // map reverse speed to return positive int 0-127
    tRexSerial.write(0xC6); // accelerate motor 1
    tRexSerial.write(mainValmapout); // Analog read val ,mapped, write to software serial.
  }
  else if (mainVal < revVal )
  {
    // Reverse motor A
    mainValmapin = map(mainVal, 0, revVal, 127 , 0); // map reverse speed to return positive int 0-127
    tRexSerial.write(0xC5); //reverse accelerate motor 1
    tRexSerial.write(mainValmapin); // Analog read val ,mapped, write to software serial.
  }
  else
    tRexSerial.write(0XC4);

  // Jib control
  jibVal = analogRead(jibPin);
  Serial.print(" , jib = ");
  Serial.print(jibVal);
  Serial.println();
  if (jibVal > fwdVal)
  {
    // turn on motor B 'forward'
    jibValmapout = map(jibVal, fwdVal, 1023, 0, 127); // map speed to return positive int 0-127
    tRexSerial.write(0xCE); // accelerate motor 2 forward
    tRexSerial.write(jibValmapout); // Analog read val,mapped write to software serial.
  }
  else if (jibVal < revVal )
  {
    // turn on motor B 'reverse'
    jibValmapin = map(jibVal, 0, revVal, 127 , 0); // map reverse speed to return positive int 0-127
    tRexSerial.write(0xCD); //reverse accelerate motor 2
    tRexSerial.write(jibValmapin); // Analog read val ,mapped, write to software serial.
  }
  else
    tRexSerial.write(0xCC);
}


We can help you understand how to use the TReX and get your system working, but please note that we do not recommend our products for applications where their failure can lead to injury or property damage.

With all of the recent posts you have made, and the various changes to your code and system, it is difficult to tell exactly what could still be a relevant issue. However, your latest post makes it seem like you figured out any problems that came up before that post and that most everything is working, so I’ll just answer your newest questions from that post. (Please let me know if there are any other outstanding questions you have.)

Like it says in the TReX configuration parameter documentation, the motor 1 and motor 2 current limit parameters are 7-bit values (0 to 127) used to represent an 8-bit value (0 to 255). This 8-bit value can be multiplied by 150mA to get the approximate current it represents. (It is not very obvious, but we mention this under the “get motor x current” section of the TReX command documentation.) So, to figure out what the current limit values should be for a 2A current limit, you could make a simple calculation like 2A / (150mA) / 2, which rounds up to about 7. Accordingly, your value of 2 would have set 2 * 2 *150mA, which is about 600mA.

It should not matter whether you use the compact or expanded (Pololu) protocol to set the configuration parameters. Like you mentioned, using the compact protocol does use fewer command bytes, so the code to use it will not be as large.

By the way, thank you for your feedback about the usability of the TReX documentation; I passed it on to the rest of the engineers here.

-Jon

Hi Jonathan, thank you for the direction.

  • filled in the gaps in my previous notes at top of sketch.
  • minor additions to notes inside sketch (eg current limit equation)
  • left the expanded protocol, left the serial monitor stuff.

Please add this example to your resources tab, if it is appropriate, with that sketch for pulling data from a TReX

[code]/* written by Tony Matthews for the purpose of
Disabled assist sail winch control
in 303 and liberty Class Access dinghy’s

One brushed bidirectional motor drives a main sheet winch,
One brushed bidirectional motor drives a jib sheet (liberty) or rudder (303’s, 2.3’s)
One brushed motor is a bilge pump, to empty any water that splashes in
Or operate signalling device, horn/light.

Code here in is written by Tony Matthews, whom has TBI.
TBI – Traumatic Brain Injury …Use at your own risk.
For the benefit of Sailability Gold Coast, Queensland, Australia.

Serial.print is for testing.
tRexSerial.write is the software serial UART to communicate with the TReX.

Notes from Pololu’s documentation.
–Motor Current codes –
Code needs one of each ie, current and current limit
0x13: motor 1 current limit (default: 0 – no motor 1 current limit)
0x14: motor 2 current limit (default: 0 – no motor 2 current limit)
0x15: motor 1 current limit proportionality constant P (default: 0x0A)
0x16: motor 2 current limit proportionality constant P (default: 0x0A)

–Acceleration Codes–
Acceleration used over ‘set direction’ as TReX has in built soft start/stop
Less wear on the winches to have soft starts.
Motor 1 - BiDirectional
0xC4 - Brake Low M1
0xC5 - Reverse M1
0xC6 - Forward M1
0xC7 - Brake low M1

Motor 2 - BiDirectional
0xCC - Brake Low M2
0xCD - Reverse M2
0xCE - Forward M2
0xCF - Brake Low M2

Motor 3 - Single direction only
0xF1 - Accelerate Motor M3

– Motor speed settings –
May be represented as an integer as the Arduino converts it to HEX automatically (TReX reads HEX)
Must be positive number between 0-127
0 being stopped, 127 full speed
(Actual speed depends on acceleration logic and current draw V current limit)
eg M3 to full speed would be
tRexSerial.write(0xF1); //M3
tRexSerial.write(127); // full speed
*/

//Software serial settings
#include <SoftwareSerial.h>
const int rx = 7; // rx pin of Arduino, SO(serial out)of TRex.
const int tx = 8; // tx pin of Arduino, SI(serial in)of TRex.

SoftwareSerial tRexSerial (rx, tx); // RX to SO of Trex, TX to SI of Trex

// Pot inputs
// Main sheet M1
int mainPin = A0; //input A0 for mainsheet
int mainVal = 507; // int to hold mainInput value, start up in neutral 511
int mainValmapin;
int mainValmapout;

// Jib sheet M2
int jibPin = A1;
int jibVal = 507;
int jibValmapin;
int jibValmapout;

// dead band settings
int deadVal = 200; // will change to pot values , one for each axis
int midVal = 507;
int fwdVal = (midVal + deadVal);
int revVal = (midVal - deadVal);

// data packet settings
unsigned char data[4];
unsigned long timer = 0;

void setup()
{
Serial.begin(19200);
tRexSerial.begin(19200);
delay (400) ; // wait for serial to start.

// Write TReX Motor Settings/Behaviour.

// build M1 data packet for current limit and proportionally constant
// build M1 current limit packet
data[0] = (0x80); // set parameter bit instruction
data[1] = (0x07); // TReX id number (if i had more than one, still necessary with only one)
data[2] = (0x13); // Parameter id, 0x13 for M1 Current Limit
data[3] = (7); // Current limit (desired current limit in milliamps / 150ma / 2 = ( )value)
// eg, desired current limit 2amps, ergo 2000/150/2=6.66, rounded up to 7
for (unsigned char i = 0; i < 4; i++)
tRexSerial.write(data[i]);

// build M1 Proportionally constant settings packet
data[0] = (0x80); // set parameter bit instruction
data[1] = (0x07); // TReX id number (if i had more than one, still necessary with only one)
data[2] = (0x15); // Parameter id, 0x15 for M1 Proportionally constant current Limit (pccl)
data[3] = (0); // Behaviour of PCCL current limit // Proportionally constant 0 (turn motors off if over current)

for (unsigned char i = 0; i < 4; i++)
tRexSerial.write(data[i]);

//Build M2 Parameter settings packets

//M2 data packet for current limit
data[0] = (0x80); // set parameter bit instruction
data[1] = (0x07); // TReX id number (if i had more than one, still necessary with only one)
data[2] = (0x14); // Parameter id, 0x14 for M2 Current Limit
data[3] = (7); // Current limit (desired current limit in milliamps / 150ma / 2 = ( )value)
// eg, desired current limit 2amps, ergo 2000/150/2=6.66, rounded up to 7
for (unsigned char i = 0; i < 4; i++)
tRexSerial.write(data[i]);

// Build M2 Proportionally constant settings packet

data[0] = (0x80); // set parameter bit instruction
data[1] = (0x07); // TReX id number (if i had more than one, still necessary with only one)
data[2] = (0x16); // Parameter id, 0x15 for M1 Proportionally constant current Limit
data[3] = (0); // Behaviour of PCCL Proportionally constant 0 (turn motors off if over current)

for (unsigned char i = 0; i < 4; i++)
tRexSerial.write(data[i]);

delay (10); // give tRex time to apply settings.

}

void loop () {

// Main sheet control
mainVal = analogRead(mainPin);
Serial.print("main = ");
Serial.print(mainVal);
if (mainVal > fwdVal)
{
// Forward motor A
mainValmapout = map(mainVal, fwdVal, 1023, 0 , 127); // map reverse speed to return int 0-127
tRexSerial.write(0xC6); // accelerate motor 1
tRexSerial.write(mainValmapout); // Analog read val ,mapped, write to software serial.
}
else if (mainVal < revVal )
{
// Reverse motor A
mainValmapin = map(mainVal, 0, revVal, 127 , 0); // map reverse speed to return int 0-127
tRexSerial.write(0xC5); //reverse accelerate motor 1
tRexSerial.write(mainValmapin); // Analog read val ,mapped, write to software serial.
}
else
tRexSerial.write(0XC4);

// Jib control
jibVal = analogRead(jibPin);
Serial.print(" , jib = ");
Serial.print(jibVal);
Serial.println();
if (jibVal > fwdVal)
{
// turn on motor B 'forward’
jibValmapout = map(jibVal, fwdVal, 1023, 0, 127); // map speed to return positive int 0-127
tRexSerial.write(0xCE); // accelerate motor 2 forward
tRexSerial.write(jibValmapout); // Analog read val, mapped write to software serial.
}
else if (jibVal < revVal )
{
// turn on motor B 'reverse’
jibValmapin = map(jibVal, 0, revVal, 127 , 0); // map reverse speed to return positive int 0-127
tRexSerial.write(0xCD); //reverse accelerate motor 2
tRexSerial.write(jibValmapin); // Analog read val ,mapped, write to software serial.
}
else
tRexSerial.write(0xCC);
}

[/code]

I am glad you got everything working; thanks for sharing your code. We’ll consider adding it as a resource for the TReX.

-Jon

Hi Jon, can i pick your brains again please…or anyone.

The TReX is not responding to the joystick deflections correctly from the above sketch.

5k Pot on Arduino (works i connected it to TReX in analog mode and perfect)
Pot Volts read good with DMM,

But the TReX, only goes into ‘full speed’ when the joystick is off center (ie giving readings on both channels)

I have tried,
Constrain()
Different pots, spark fun thumb joystick with circuit board 10k, Big analog joystick from Servo City 5k
Different analog pins,
checked battery voltages,
different int values for each motor (instead of same dead band for both)
Different Arduino Nano V3.0 board
Different Arduino Eleven (same as UNO)
vRef for joystick power.
5v for joystick power
3.3v for Joystick power/ground
TReX for joystick power/ground
Supply power for the lot from Lipo via Trex
Supply power via battery TRex and USB Arduino (yeah i know i risk burning out my usb power but willing to try anything at this juncture)
Supply power to Arduino with 12v wall plug, TRex on Battery.
analogRead, delay, read same analog again. quora.com/Why-is-a-little-d … in-Arduino
delays between If statements(sorta helps but outputs ‘hang’ )

combinations of all above…that a lot of combinations !

Only thing that has worked to get one motor working as it should is to /* */ comment out one of the analog inputs in void setup() and outputs inside the void loop ()

After testing the joystick on the Analog mode(on the TReX), i had a question.
Do i even need a micro controller to do what i want do i ?

In reading the Parameters and Commands document it is clear that to utilize the current limiting you need serial control…

[quote]If you intend to use the current-limiting feature of the TReX, you should use acceleration
commands to control your motor speed.[/quote]

So i thought i had to Learn how to code up an Arduino …

But that is also available via the Windows Configure app too ?

I also wanted to make use of one input and have an override via RC PPM for if a sailor needed assistance.
So ultimately i need to use this with Serial
This is driving me nuts.

I am powering the Arduino via the 5v rail of the TReX, which is powered from a four Cell LiPo 5000mah 20-30c discharge so there should be enough juice ?

I am now trying to connect to my Saleae Logic4 Analyser, to see what is going on.
Single CH never a problem, Dual…it all goes pear shaped, maybe the Arduino needs the write data[i] for i=i +ii type data writes not the line by line as it has in the manual…maybe , need to read the data stream.

Ok , commenting out the second section - altered code only reads A0 and should write Cx05, 127 to Serial…and in the Saleae Logic analyser i can see that it does do exactly that.

Code running as expected when not commented out, i can see that i might be missing the motor identifier …well the code is the motor identifier to stop but does it also need the stop speed ? Its not mentioned in the manual…or in the non existent example code… /hint/hint boys…throw us a bone, gifted individuals you are.

45deg on joystick, both motors should be in full reverse and you can see they are…so that bits working.

Ok so i tried comment out the ‘else’ which was the ‘Brake Low’ if no valid joystick inputs, that did not help . TReX still indicating that it wants to drive in last known direction but motors not turning.

So it needs some signal to say ‘ok now do nothing’ ?
Does brake low need a value, and what would that value be ?

Is there no command for just to stop outputting power to M1/M2 ? no brake , no forward, just shut the output off ?
Or does the back EMF mean there has to be a ‘brake low’ to handle the power incoming ?

This is the capture of the actual issue.

M1 should be full speed, data being sent shows the Arduino sending the right serial data.

But M1 is barely running,
this same signal (as shown above) with out the following ‘brake low’ to M2, has the motor performing as expected.

changing ‘else’ the last line in the
from ‘brake low’ to Rev at 0 speed has fixed the ‘outside’ appearance of the code working.

if "xxx" else if "yyy" else tRexSerial.write(0xCD); tRexSerial.write(zero);

Confirmed, brake low needs a value
– i did try to brake and value early on but it did not work, (tho i was using the 01 brake low codes) , i have added the “data[i]” serial packet routines and its working, i don’t know if this actually made a difference for certain as there were many many more rewrites than i have posted here. ie i am also now using the 04 brake low codes.

else tRexSerial.write(0xCF); // brake low //tRexSerial.write(0xCD); //reverse accelerate tRexSerial.write(zero); // zero interger value

Sketch now physically tested on pumps and working.

Tested working code -

[code]/* written by Tony Matthews for the purpose of
Disabled assist sail winch control
in 303 and liberty Class Access dinghy’s

One brushed bidirectional motor drives a main sheet winch,
One brushed bidirectional motor drives a jib sheet (liberty) or rudder (303’s, 2.3’s)
One brushed motor is a bilge pump, to empty any water that splashes in
Or operate signalling device, horn/light.

Code here in is written by Tony Matthews, whom has TBI.
TBI – Traumatic Brain Injury …Use at your own risk.
For the benefit of Sailability Gold Coast, Queensland, Australia.

Serial.print is for testing.
tRexSerial.write is the software serial UART to communicate with the TReX.

Notes from Pololu’s documentation.
–Motor Current codes –
Code needs one of each ie, current and current limit
0x13: motor 1 current limit (default: 0 – no motor 1 current limit)
0x14: motor 2 current limit (default: 0 – no motor 2 current limit)
0x15: motor 1 current limit proportionality constant P (default: 0x0A)
0x16: motor 2 current limit proportionality constant P (default: 0x0A)

–Acceleration Codes–
Acceleration used over ‘set direction’ as TReX has in built soft start/stop
Less wear on the winches to have soft starts.
Motor 1 - BiDirectional
0xC4 - Brake Low M1
0xC5 - Reverse M1
0xC6 - Forward M1
0xC7 - Brake low M1

Motor 2 - BiDirectional
0xCC - Brake Low M2
0xCD - Reverse M2
0xCE - Forward M2
0xCF - Brake Low M2

Motor 3 - Single direction only
0xF1 - Accelerate Motor M3

– Motor speed settings –
May be represented as an integer as the Arduino converts it to HEX automatically (TReX reads HEX)
Must be positive number between 0-127
0 being stopped, 127 full speed
(Actual speed depends on acceleration logic and current draw V current limit)
eg M3 to full speed would be
tRexSerial.write(0xF1); //M3
tRexSerial.write(127); // full speed

All motor speed/direction/stopped need a speed value to go with them , eg stopped + 0 , forward + 127
*/

//Software serial settings
#include <SoftwareSerial.h>
const int rx = 7; // rx pin of Arduino, SO(serial out)of TRex.
const int tx = 8; // tx pin of Arduino, SI(serial in)of TRex.

SoftwareSerial tRexSerial (rx, tx); // RX to SO of Trex, TX to SI of Trex

// Pot inputs
// Main sheet M1
int mainPin = A0; //input A0 for mainsheet
int mainVal = 511; // int to hold main Input value, start up in neutral 511
int mainValmapin;
int mainValmapout;

// Jib sheet M2
int jibPin = A1;
int jibVal = 511;
int jibValmapin;
int jibValmapout;

// dead band settings
int deadVal = 300; // will change to pot values , one for each axis
int midVal = 511;
int fwdVal = (midVal + deadVal);
int revVal = (midVal - deadVal);

int zero = 0; // integer for serial data ‘0’ as 0 is ambiguous as used in a ‘serial.write(0)’

// Power/speed variables
// Current limit (desired current limit in milliamp’s / 150ma / 2 = ( )value)
// (rounded up) 2amps=7 , 10amps=33
int maxAmps = 2;//Current limit (desired current limit in milliamp’s / 150ma / 2 = ( )value)
int overAmpbeh = 0; // over Amp limit behaviour 0=turn motor off
// data packet settings
unsigned char data[4];
unsigned long timer = 0;

void setup()
{
delay (1000);
tRexSerial.begin(19200);
delay (400) ; // wait for serial to start.

// Write TReX Motor Settings/Behaviour.

// build M1 data packet for current limit and proportionally constant
// build M1 current limit packet
{
data[0] = (0x80); // set parameter bit instruction
data[1] = (0x07); // TReX id number (if i had more than one, still necessary with only one)
data[2] = (0x13); // Parameter id, 0x13 for M1 Current Limit
data[3] = (maxAmps); // Current limit (desired current limit in milliamps / 150ma / 2 = ( )value)
// eg, desired current limit 2amps, ergo 2000/150/2=6.66, rounded up to 7
for (unsigned char i = 0; i < 4; i++)
tRexSerial.write(data[i]);
}
delay(10);
// build M1 Proportionally constant settings packet
{
data[0] = (0x80); // set parameter bit instruction
data[1] = (0x07); // TReX id number (if i had more than one, still necessary with only one)
data[2] = (0x15); // Parameter id, 0x15 for M1 Proportionally constant current Limit (pccl)
data[3] = (overAmpbeh); // Behaviour of PCCL current limit // Proportionally constant 0 (turn motors off if over current)

for (unsigned char i = 0; i < 4; i++)
  tRexSerial.write(data[i]);

}
delay(10);
//Build M2 Parameter settings packets

//M2 data packet for current limit
{
data[0] = (0x80); // set parameter bit instruction
data[1] = (0x07); // TReX id number (if i had more than one, still necessary with only one)
data[2] = (0x14); // Parameter id, 0x14 for M2 Current Limit
data[3] = (maxAmps); // Current limit (desired current limit in milliamps / 150ma / 2 = ( )value)
// eg, desired current limit 2amps, ergo 2000/150/2=6.66, rounded up to 7
for (unsigned char i = 0; i < 4; i++)
tRexSerial.write(data[i]);
}
delay(10);
// Build M2 Proportionally constant settings packet
{
data[0] = (0x80); // set parameter bit instruction
data[1] = (0x07); // TReX id number (if i had more than one, still necessary with only one)
data[2] = (0x16); // Parameter id, 0x15 for M1 Proportionally constant current Limit
data[3] = (overAmpbeh); // Behaviour of PCCL Proportionally constant 0 (turn motors off if over current)

for (unsigned char i = 0; i < 4; i++)
  tRexSerial.write(data[i]);

}
delay (10); // give tRex time to apply settings.

}
void loop () {
// Main sheet control (M1)
{
mainVal = analogRead(mainPin);
delay(10);

if (mainVal > fwdVal)   // Forward M1
{
   mainValmapout = map(mainVal, fwdVal, 1023, 0 , 127); // map speed to return int 0-127
  data [0] = (0xC6); // accelerate motor 1
  data [1] = (mainValmapout);   // Analog read val ,mapped.
  for (unsigned char i = 0; i < 2; i++)
    tRexSerial.write(data[i]);
}
else if (mainVal < revVal )  // Reverse M1
{ 
  mainValmapin = map(mainVal, 0, revVal, 127 , 0); // map reverse speed to return int 0-127
  data [0] = (0xC5); //reverse accelerate motor 1
  data [1] = (mainValmapin); // Analog read val ,mapped.
  for (unsigned char i = 0; i < 4; i++)
    tRexSerial.write(data[i]);
}
else       // stop M1
  tRexSerial.write(0xC7);   // brake low
  tRexSerial.write(zero);   // zero integer value

}

//Jib sheet control (M2)
{
jibVal = analogRead(jibPin);
delay(10);

if (jibVal >= fwdVal)    // Forward M2
{
  jibValmapout = map(jibVal, fwdVal, 1023, 0, 127); // map speed to return positive int 0-127
  data [0] = (0xCE); // accelerate motor 2 forward
  data [1] = (jibValmapout); // Analog read val, mapped.
  for (unsigned char i = 0; i < 2; i++)
    tRexSerial.write(data[i]);
}

else if (jibVal <= revVal )    // Reverse M2
{
  jibValmapin = map(jibVal, 0, revVal, 127 , 0); // map reverse speed to return positive int 0-127
  data [0] = (0xCD); //reverse accelerate motor 2
  data [1] = (jibValmapin); // Analog read val ,mapped.
  for (unsigned char i = 0; i < 2; i++)
    tRexSerial.write(data[i]);
}

else   // brake M2
  tRexSerial.write(0xCF); // brake low
  tRexSerial.write(zero); // zero integer value

}

}

[/code]

I am glad you got everything working. You are correct; all TReX motor commands take a single data byte in order to properly set the direction of rotation and speed of the motor being controlled. In the case of braking, the data byte determines how hard it is braking.

-Jon