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

Pololu Forum

Arduino and Trex JR


#1

Hi all,

Hopefully someone can spare a few minutes to help a beginner out.

I have purchased a Trex JR and wish to control it from my Arduino Diecimila.

The first thing i did was remove the chip from the arduino and hook up the Trex JR to it hardware serial pins and set up the jumpers to allow serial control. Then i ran the Trex configuration software to change the baud rate down to 9600 with E parity and one stop bit. Then i had a play with controlling my motors (i love it!).

My next step was to set up a sketch for arduino with software serial. I want to be able to send commands and receive data back from the trex jr, and leave the hardware serail open to allow me to debug with the arduinos usb port and the arduino’s ide serial monitor.

And thats where i am struggling. (didn’t get very far did i? :blush: )

I wrote a very simple sketch that sets up a software serial port and sends what i think (probably way off) is a command to the trex jr to set motor ones speed to 127.

Heres the sketch

[code]#include <AFSoftSerial.h>

AFSoftSerial mySerial = AFSoftSerial(7, 6);

void setup() {
// set the data rate for the SoftwareSerial port
mySerial.begin(9600);
}

void loop() // run over and over again
{

unsigned char buff[32]; // create a buffer

buff[0]=0xC2; // Motor one forward COMMAND
buff[1]=0x7F; // Motor one speed 127 DATA

for(int i=0;i<2;i++){
mySerial.print(buff[i],BYTE);
}

delay (5555);
}[/code]

I get nothing. I can see the trex’s green LED light up very briefly, but thats all.

I have no prior knowledge of anything like this, and would really really appriciate a little guidance.

Please help :smiley:


#2

Hi Eggcob,

Neat trick removing the AVR and using the USB to Serial adapter to talk directly to your TRex. What connections do you have right now between the Arduino and your TRex? Did you move the serial connections to the TRex to the Diecimila’s pins 6 and 7? Is there a reason you’re trying to use the software serial library instead of the hardware?

It occurs to me that to make that trick work you would have to connect your TRex in such a way that it would be listening on the Diecimila’s Pin 0 (SI to RX) and talking on the Diecimila’s Pin 1 (SO to TX). To get the Diecimila to talk directly to the TRex over the serial hardware you would need to switch those up (SI to TX, SO to RX).

For an example of a sketch using the Arduino’s serial hardware you can look here.

Good luck,

-Adam


#3

Hehe yeah I read somewhere else (I can’t take credit for it) that if you remove the chip it functions as a usb to serial adaptor. So you can use pins 0 and 1 as a serial port for your pc. Works great!

The reason for using the software serial is to allow me to debug using the serial monitor in the arduino IDE (the usb cable uses the hardware serial on the arduino to communicate to the board) and if i can get it to work with the software serial package i can add other serial devices at a later date.

I have the tx and rc from the Trex Jr connected to pins 6 and 7.

I’ll try using the Hardware serial and try again. I’m not entirely sure about what settings to use on the Trex to get the serials to match (8 bit, 7 bit e n o, its all gibberish to me at this stage :smiley: .

I’ll keep trying :smiley:


#4

Cracked it :smiley: I needed the serial settings on the Trex to be set to “No Error Checking”.

Have the motor spinning from the hardware serial. Now i’ll try porting that over to the software serial.

Heres the code i used to get motor one to turn a little (Just in case its useful to anyone)


void setup()
{
  //Set up Serial library at 9600 bps
  //Note: The Trex has to match this. No error checking, one stop bit and the same baud rate. The Trex does NOT automatically detect the correct baud.
  Serial.begin(9600);
}

void loop() 
{

  go();
  
  //Delay so you can see the servo controller's serial status LED blink
  delay(1000);
}

void go()
{
  //servo is the servo number (typically 0-7)
  //angle is the absolute position from 500 to 5500

  unsigned char buff[6]; //our buffer

  
 
  buff[0]=0xC2; //Motor One Forward
  buff[1]=0x45; //69 speed
  

  
  //Send the command to the Trex
  for(int i=0;i<2;i++){
    Serial.print(buff[i],BYTE);
  }
}

#5

Hello.

Thank you for sharing your Arduino code with us. I’m glad to hear that you’re making progress getting things working. Please let us know if you have any further problems getting things working.

- Ben


#6

Hi,
I am new to posting and this Forum, and Trex Jr. Eggcob’s post helped me a lot but I am having trouble with some code.
I am using a distance sensor and rotating my robot to look in other directions. It is rudimentary approach, just learning how to control it but, when I tell my motor to go forward, 0xCA, it will not stop for a long time (~3 secs). I rotate backwards, stop, take a look (analogue read) then reverse directions by going forward to the initial position, the other wheel is stopped. The 0xCA command does not stop in the allotted time (delay(1000):wink: it just happens on motor 2, when I do the same with motor 1, it works fine. Here is that part of the code.

mySerial.print(0xC9,BYTE); //turn other way mySerial.print(40,DEC); delay(100); mySerial.print(0xC8,BYTE); delay(500); valL=analogRead(analogPin)*.0049; //read the input delay(1000); mySerial.print(0xCA,BYTE); mySerial.print(40,DEC); delay(1000); mySerial.print(0xCB,BYTE); mySerial.print(0,DEC); delay(2000);

Any insight will be appreciated. The whole thing is here and please note that I was just testing using decimals to see if they worked.
I realize that it is fat code but this is just a test bed robot.

[code]#include <SoftwareSerial.h>

//#include <SoftwareSerial.h>

SoftwareSerial mySerial =  SoftwareSerial(7, 6);

double analogPin = 3; // potentiometer wiper (middle terminal) connected to analog pin 3
// outside leads to ground and +5V
double val = 0; // variable to store the value read
double valL = 0;
double valR = 0;

void setup()
{
  //Set up Serial library at 9600 bps
  //Note: The Trex has to match this. No error checking, one stop bit and the same baud rate. The Trex does NOT automatically detect the correct baud.
  pinMode(6,OUTPUT);
  mySerial.begin(9600);
  Serial.begin(9600);          //  setup serial
}

void loop()
{

val = analogRead(analogPin)*0.0049; // read the input pin
Serial.println(val); // debug value
delay(50);
if(val<1){
go();
}
if(val>1){
stop();
}
}

void stop()
{
unsigned char buff[6]; //our buffer
mySerial.print(0xC0,BYTE);
mySerial.print(0xC8,BYTE);
delay(1000);

  Serial.println("Turn R");
  
  mySerial.print(0xC2,BYTE); //turn one way
  mySerial.print(0x20,BYTE);
  delay(30);
  mySerial.print(0xC3,BYTE);
  delay(500);
  valR=analogRead(analogPin)*.0049; //read the input
  delay(1000);
  mySerial.print(0xC1,BYTE);
  mySerial.print(0x20,BYTE);
  delay(30);
  mySerial.print(0xC0,BYTE);
  delay(500);

  Serial.println("Turn L");

  mySerial.print(0xC9,BYTE); //turn other way
  mySerial.print(40,DEC);
  delay(100);
  mySerial.print(0xC8,BYTE);
  delay(500);
  valL=analogRead(analogPin)*.0049; //read the input
  delay(1000);
  mySerial.print(0xCA,BYTE);
  mySerial.print(40,DEC);
  delay(1000);
  mySerial.print(0xCB,BYTE);
  mySerial.print(0,DEC);
  delay(2000);

  Serial.println("Check Readings");
  Serial.print("valR: ");
  Serial.println(valR);             // debug value
  Serial.print("valL: ");
  Serial.println(valL);   
  delay(2000);

}
void go()
{
mySerial.print(0xC2,BYTE); //Motor One Forward
mySerial.print(0x20,BYTE);
mySerial.print(0xCA,BYTE); //Motor two Forward
mySerial.print(0x20,BYTE);
delay(100);
}[/code]

Thanks for any help!
Brett


#7

Hello.

I’m actually not sure why your code works at all. Why do you send some serial bytes as bytes and others as ASCII-encoded decimals? The TReX Jr expects its commands as serial byte packets, so you need send all of your data as raw bytes. It seems like you think that the second argument to the println() function must correspond with the representation you’ve chosen for the first argument, but this is not the case. A number’s value is independent of the way you choose to represent it, and you are telling the compiler how you’re representing the number when you append the prefix “0x” (hex) or leave it off (decimal).

The following code will send the values {0xCA, 40} to the TReX Jr:

mySerial.print(0xCA,BYTE);
mySerial.print(40,BYTE);

If my understanding of the Arduino SofwareSerial library is correct, your code:

mySerial.print(0xCA,BYTE);
mySerial.print(40,DEC);

sends the values {0xCA, ‘4’, ‘0’} to the TReX Jr.

There might be other problems at work, but I think first you should see what happens if you send all of your data as raw bytes.

- Ben


#8

You are right, I original code only sent the hex values and performed the same way. The decimal values were just a test and they worked exactly the same ( I made sure I was sending the decimals/hex equivalent but then upped it to 40. Like I said, I would not normally mix dec and bytes but it was a neat experiment. I can send the original code later from my computer.

My problem, though, was stopping the motor. It just would not stop turning for about 3 seconds unless I sent a value like 0x00 after the stop byte. What do I need to send after the “motor brake low” byte? i.e. after 0xC8, and what is the difference between 0xC8 and 0xCB?

Thanks,
Brett


#9

Ben,
Apparently, the delay function is very unpredictable and I have not found a way to fix it. I think it is the Arduino code. Do you know of another way to send a delay to the controller such as run the wheel for x seconds? The extra batteries really helped but didn’t solve it so I tested the delay and the it works in some places but not others. Here is my code.

[code]#include <SoftwareSerial.h>

//#include <SoftwareSerial.h>

SoftwareSerial mySerial =  SoftwareSerial(7, 6);

double analogPin = 3; // potentiometer wiper (middle terminal) connected to analog pin 3
// outside leads to ground and +5V
double val = 0; // variable to store the value read
double valL = 0;
double valR = 0;

void setup()
{
  //Set up Serial library at 9600 bps
  //Note: The Trex has to match this. No error checking, one stop bit and the same baud rate. The Trex does NOT automatically detect the correct baud.
  pinMode(6,OUTPUT);
  mySerial.begin(9600);
  Serial.begin(9600);          //  setup serial
}

void loop()
{
val = analogRead(analogPin)*0.0049; // read the input pin
Serial.println(val); // debug value
delay(50);
if(val<1){
go();
}
if(val>1){
stop();
delay(2000);
right();
delay(2000);
left();
delay(2000);
read1();
}
}
void stop()
{
unsigned char buff[6]; //our buffer
mySerial.print(0xC0,BYTE);
mySerial.print(0xC8,BYTE);
delay(1000);
}
void right()
{
Serial.println(“Turn R”);

  mySerial.print(0xC2,BYTE); //turn one way
  mySerial.print(0x15,BYTE);
  delay(100);
  mySerial.print(0xC3,BYTE);
  delay(100);
  valR=analogRead(analogPin)*.0049; //read the input
  delay(1000);
  mySerial.print(0xC1,BYTE);
  mySerial.print(0x15,BYTE);
  delay(100);
  mySerial.print(0xC0,BYTE);

}

void left()
{
Serial.println(“Turn L”);

  mySerial.print(0xC9,BYTE); //turn other way
  mySerial.print(0x12,BYTE);
  delay(100);
  mySerial.print(0xC8,BYTE);
  delay(100);
  valL=analogRead(analogPin)*.0049; //read the input
  delay(1000);
  mySerial.print(0xCA,BYTE);
  mySerial.print(0x12,BYTE);
  delay(300);
  mySerial.print(0xC8,BYTE);
  //mySerial.print(0x00,BYTE);

}
void read1()
{
Serial.println(“Check Readings”);
Serial.print("valR: ");
Serial.println(valR); // debug value
Serial.print("valL: ");
Serial.println(valL);
delay(2000);
}
void go()
{
mySerial.print(0xC2,BYTE); //Motor One Forward
mySerial.print(0x15,BYTE);
mySerial.print(0xCA,BYTE); //Motor two Forward
mySerial.print(0x15,BYTE);
delay(100);
}[/code]

Thanks,
Brett


#10

Brett,

The Arduino delay() function should be fairly predictable, so I think something strange is going on with your code. Unfortunately, it’s a bit too unwieldy for me to be able to offer you any real help. Can you strip it down to the simplest program that should work but doesn’t? What happens if take out the software serial calls and instead flash the LED before and after every delay? Does the led flash when you’d expect or are the delays still unpredictable?

Also, I seem to remember your telling me on the phone that you have your Arduino powered via USB and your TReX Jr powered with batteries. Did you make sure that your TReX Jr and your Arduino share a common ground?

- Ben


#11

On the “ground”, good idea. I will try it and write some debug code tomorrow night. Thanks for your help and I will try not to be too cumbersome.
Thanks again,
Brett


#12

Your problems could be fully explained by a lack of a common ground between the Arduino and the TReX Jr, so I suggest you make sure this isn’t the cause before you spend time trying to debug your program. Good luck getting things working. Please let me know how things go!

- Ben


#13

Hey Ben,
My ground is attached as shown on page 7 of the trex jr users guide for the microcontroller. Is that all that is needed?

I think I have figured it out. I wasn’t using the brake low properly, I did not know that a motor speed had to be sent “0x00” after the “0xC8” byte. I added an LED to turn off for the backwards move and on for the forward move. I put it together in my debug code below and it worked fine. Everything has a learning curve. I am looking forward to my new motors when they become available.

Thanks for your help and let me know if you see anything wrong in the void loop.

[code]#include <SoftwareSerial.h>

//#include <SoftwareSerial.h>

SoftwareSerial mySerial =  SoftwareSerial(7, 6);

#define LED 13

void setup()
{
  //Set up Serial library at 9600 bps
  //Note: The Trex has to match this. No error checking, one stop bit and the same baud rate. The Trex does NOT automatically detect the correct baud.
  pinMode(6,OUTPUT);
  mySerial.begin(9600);
  Serial.begin(9600);          //  setup serial
  pinMode(LED, OUTPUT);
}

void loop()
{
Serial.println(“Turn L”);

  mySerial.print(0xC9,BYTE); //reverse turn
  mySerial.print(0x15,BYTE);
  delay(2000);
  mySerial.print(0xC8,BYTE); //stop
  mySerial.print(0x00,BYTE);
  delay(2000);

  digitalWrite(LED, HIGH);

  mySerial.print(0xCA,BYTE); //forward
  mySerial.print(0x15,BYTE);
  delay(2000);

  mySerial.print(0xC8,BYTE); //stop
  mySerial.print(0x00,BYTE);
  delay(2000);
  digitalWrite(LED, LOW);

}[/code]


#14

Yeah, that’s all you need.

I’m glad you figured out the problem. The TReX and TReX Jr allow variable braking, so as you’ve now figured out, the brake commands take an argument that tells the controller how hard you want to brake. This argument does not correspond to the speed of the motor for brake commands. Instead, think of it as a way to control the percentage of the time the driver carries out the command. If the command is brake, an argument value of 127 corresponds to full braking and 0 to full coast. If the command is forward, an argument value of 127 corresponds to full forward and 0 to full coast.

If you want to brake hard, you should send the command: {0xC8, 0x7F}. If you want to coast to a stop, you can just set the motor speed to 0 or brake with an argument of 0. You can write a simple test program that shows you the difference between coast and brake. Have one program send {0xC8, 0} in setup() and do nothing in loop() and have the other program send {0xC8, 127} in setup and do nothing in loop(). While each program is running, try spinning your motor by hand and note the resistance in both cases.

- Ben


#15

Thanks again Ben, excellent info!
Brett


#16

[quote=“Ben”]
If you want to brake hard, you should send the command: {0xC8, 0x7F}. If you want to coast to a stop, you can just set the motor speed to 0 or brake with an argument of 0. You can write a simple test program that shows you the difference between coast and brake. Have one program send {0xC8, 0} in setup() and do nothing in loop() and have the other program send {0xC8, 127} in setup and do nothing in loop(). While each program is running, try spinning your motor by hand and note the resistance in both cases.

  • Ben[/quote]

How does using 0xCB differ from using 0xC8 in this scenario?


#17

Hello.

Command bytes 0xC8 and 0xCB both have the same effect: brake motor 2 by shorting both leads to ground. The percentage of the time spent braking (vs coasting) is determined by the “speed” argument (127 = 100% braking).

- Ben