How do I make the robot turn?

I am trying to get my robot to turn. I am using the MD25 in serial mode, hooked up to an Arduino and 2 EMG30 motors. I looked at the MD25 documentation: robot-electronics.co.uk/htm/md25ser.htm I noticed in that spec sheet that there is a command called 0x32 SET SPEED2 / TURN So would the following code snippet be correct:?

[code]#define SETSPEED2 0x32

Serial.write(CMD);
Serial.write(SETSPEED2);
Serial.write( ?? );[/code]

Does the name TURN need to be somewhere in the code? What are the range of numbers allowed in the second Serial.write(??); command? Is this the correct code to begin with?

I looked at the code that you suggested, and I can’t figure out how to adapt it to the sample MD25 Serial code show here:
robot-electronics.co.uk/files/arduino_md25_serial.ino
I wrote this modification to the code in the link above:
#define TURN 0x32
while(encValue < 3000){ // While encoder 1 value less than 3000 move forward
Serial.write(CMD); // Set motors to drive forward at full speed
Serial.write(WRITESP1);
Serial.write(200);
Serial.write(TURN);
Serial.write(50);
encValue = readEncoder();
readVolts(); }

Shouldn’t the TURN value automatically increase the speed of motor 1 by 50 to 250, and decrease the speed of motor 2 by 50 to 150? Would you have some sample code that uses the James Henderson code (the link above), and modifies it to use the TURN command? When that James Henderson code is in mode 2, aren’t both motors controlled by Speed 1, and Speed 2 is only used when a TURN is called for? In the code you referenced, it looks like the program controls each motor separately, whereas in the James Henderson program, while in Mode 2, Speed 1 is used to control both motors. Do I just need to put the TURN command in a “while” statement or something? I’ve been experimenting to try to get the program to recongnize the TURN command, but nothing works. What should I do to get the TURN command to be recognized?

The program is in mode 2. The program is listed below in its entirety. It is almost the same as the original James Henderson code…I just modified it to include the TURN function. Three modifications are noted by the comment line: “This was added.” The other modification is changing the mode to 2. How do I get the program to respond to the TURN command? Whatever value I put in for TURN is ignored:

/****************************************************************

  •                Arduino MD25 example code                  *
    
  •               MD25 running in serial mode                 *
    
  •                                                           *
    
  •                 by James Henderson 2012                   *
    

*****************************************************************/

#include <SoftwareSerial.h>

// Values of 0 being sent using serial.write() have to be cast as a byte to stop them being misinterpereted as NULL
// This is a bug with arduino 1
#define CMD (byte)0x00 // MD25 command byte of 0

#define WRITESP1 0x31 // Byte writes speed to motor 1
#define TURN 0x32 // Byte writes speed to motor 2 <<<------------------------- This was added.
#define WRITEACCEL 0x33 // Byte writes a value of acceleration
#define RESETREG 0x35 // Byte resets encoders
#define SETMODE 0x34 // Byte sets mode
#define READIVS 0x2C // Byte reads motor currents and battery voltage
#define READENCS 0x25 // Byte reads both encoders
#define GET_VER 0x29

#define LCD_RX 0x02 // RX and TX pins used for LCD0303 serial port
#define LCD_TX 0x03
#define LCD03_HIDE_CUR 0x04
#define LCD03_CLEAR 0x0C
#define LCD03_SET_CUR 0x02

SoftwareSerial lcd03 = SoftwareSerial(LCD_RX, LCD_TX); // Define the serial port for the LCD03

long encValue = 0;
byte softwareRev = 0;

void setup(){
Serial.begin(38400);
lcd03.begin(9600);

Serial.write(CMD);                                            // Set MD25 accelleration value
Serial.write(WRITEACCEL);
Serial.write(10);
delayMicroseconds(10);                                        // Wait for this to be processed
Serial.write(CMD);                                            // Reset the encoder registers to 0
Serial.write(RESETREG);         
Serial.write(CMD);                                            // <<<------------------------------------------- The mode was set to 2.
Serial.write(SETMODE);
Serial.write(2);    

Serial.write(CMD);                                            // Get software version of MD25
Serial.write(GET_VER);
while(Serial.available() < 1){}                               // Wait for byte to become available         
softwareRev = Serial.read();  

lcd03.write(LCD03_CLEAR);                                     // Clear the LCD03 screen
lcd03.write(LCD03_HIDE_CUR);                                  // Hide the LCD03 cursor

}

void loop(){

while(encValue < 3000){               // While encoder 1 value less than 3000 move forward
  Serial.write(CMD);                  // Set motors to drive forward at full speed
  Serial.write(WRITESP1);
  Serial.write(200);
 Serial.write(TURN);    //<<<----------------------------------------------------------------This was added.
 Serial.write(50);        // <<<----------------------------------------------------------------This was added.
  encValue = readEncoder();
  readVolts();
}
delay(100);
while(encValue > 100){
  Serial.write(CMD);                  // Drive motors reverse at full speed
  Serial.write(WRITESP1);
  Serial.write(100);
  encValue = readEncoder();
  readVolts();
}
delay(100);

}

long readEncoder(){ // Function to read and display the value of both encoders, returns value of first encoder
long result1 = 0;
long result2 = 0;
Serial.write(CMD);
Serial.write(READENCS);
while(Serial.available() < 8){} // Wait for 8 bytes, first 4 encoder 1 values second 4 encoder 2 values
result1 = Serial.read(); // First byte for encoder 1, HH.
result1 <<= 8;
result1 += Serial.read(); // Second byte for encoder 1, HL
result1 <<= 8;
result1 += Serial.read(); // Third byte for encoder 1, LH
result1 <<= 8;
result1 += Serial.read(); // Fourth byte for encoder 1, LL
result2 = Serial.read();
result2 <<= 8;
result2 += Serial.read();
result2 <<= 8;
result2 += Serial.read();
result2 <<= 8;
result2 += Serial.read();

lcd03.write(LCD03_SET_CUR);              // Set the LCD03 cursor position
lcd03.write(21);
lcd03.print("Encoder 1:");               // Displays data to the LCD03 screen
lcd03.print(result1,DEC);
lcd03.print(" ");                        // Print a blank space to clear any unwanted characters that are leftover on the LCD03 display

delay(5);                                // Delay for LCD03 to process data

lcd03.write(LCD03_SET_CUR);
lcd03.write(41); 
lcd03.print("Encoder 2:");
lcd03.print(result2,DEC);
lcd03.print(" ");
return result1;                                   

}

void readVolts(){ // Function reads current for both motors and battery voltage
byte batteryVolts, mot1_current, mot2_current = 0;
Serial.write(CMD);
Serial.write(READIVS); // Send byte to readbattery voltage and motor currents
while(Serial.available() < 3){} // Wait for the 3 bytes to become available then get them
batteryVolts = Serial.read();
mot1_current = Serial.read();
mot2_current = Serial.read();

lcd03.write(LCD03_SET_CUR);
lcd03.write(61);
lcd03.print("Mot1 I:");
lcd03.print(mot1_current,DEC);
lcd03.print(" Mot2 I:");
lcd03.print(mot2_current,DEC);
lcd03.print(" "); 

delay(5);

lcd03.write(LCD03_SET_CUR);
lcd03.write(1);
lcd03.print("Rev:");
lcd03.print(softwareRev, DEC);
lcd03.print(" ");
lcd03.print("Volts:");
lcd03.print(batteryVolts/10,DEC);                               // Seperate whole number and descimal place of battery voltage and display
lcd03.print(".");  
lcd03.print(batteryVolts%10,DEC);
lcd03.print(" ");   

}

Hi James,
That worked! It’s great to regain control of my robot’s motors!
Much thanks for your help,
Dexter

First, you need to use the SET MODE command to change modes.
The MD25 defaults to mode 0, that is each motor operates independently. To use the turn feature you need to change to mode 2 where the range is 0 (Full Reverse) 128 (Stop) 255 (Full Forward), or mode 3 where the range is -128 (Full Reverse) 0 (Stop) 127 (Full Forward).

Gerry.

Hi Dexter,

It looks like you are not sending the command byte before you are trying to set the turn register. The command byte has to be sent before each command being issued.

Serial.write(CMD); // Set motors to drive forward at full speed
Serial.write(WRITESP1);
Serial.write(200);
Serial.write(CMD);  //<---- This was missing
Serial.write(TURN); 
Serial.write(50);

James.

Does anyone have some sample code which shows how to get the Hagisonic Stargazer to talk to the Arduino? I’m unsure how the Stargazer Monitor program is used in this process. I have the Stargazer connected to my laptop with a 9-pin connection on each end. Then I have the Arduino connected to my laptop with a USB cable. How do I get the data that’s coming in from the Stargazer Monitor program to get to the Arduino? Here is the code I have now, which controls the motors on my robot…I just need to know how to alter this code to include the Stargazer data:

[code]/****************************************************************

  • Arduino MD25 example code *
  • MD25 running in serial mode *
  • by James Henderson 2012 *
    *****************************************************************/

#include

// Values of 0 being sent using serial.write() have to be cast as a byte to stop them being misinterpereted as NULL
// This is a bug with arduino 1
#define CMD (byte)0x00 // MD25 command byte of 0

#define WRITESP1 0x31 // Byte writes speed to motor 1
#define TURN 0x32 // Byte writes speed to motor 2 <<<------------------------- This was added.
#define WRITEACCEL 0x33 // Byte writes a value of acceleration
#define RESETREG 0x35 // Byte resets encoders
#define SETMODE 0x34 // Byte sets mode
#define READIVS 0x2C // Byte reads motor currents and battery voltage
#define READENCS 0x25 // Byte reads both encoders
#define GET_VER 0x29

#define LCD_RX 0x02 // RX and TX pins used for LCD0303 serial port
#define LCD_TX 0x03
#define LCD03_HIDE_CUR 0x04
#define LCD03_CLEAR 0x0C
#define LCD03_SET_CUR 0x02

SoftwareSerial lcd03 = SoftwareSerial(LCD_RX, LCD_TX); // Define the serial port for the LCD03

long encValue = 0;
byte softwareRev = 0;

void setup(){
Serial.begin(38400);
lcd03.begin(9600);

Serial.write(CMD); // Set MD25 accelleration value
Serial.write(WRITEACCEL);
Serial.write(10);
delayMicroseconds(10); // Wait for this to be processed
Serial.write(CMD); // Reset the encoder registers to 0
Serial.write(RESETREG);
Serial.write(CMD); //<<< ------------------------------------------- The mode was set to 2.
Serial.write(SETMODE);
Serial.write(2);

Serial.write(CMD); // Get software version of MD25
Serial.write(GET_VER);
while(Serial.available()< 1){} // Wait for byte to become available
softwareRev = Serial.read();

lcd03.write(LCD03_CLEAR); // Clear the LCD03 screen
lcd03.write(LCD03_HIDE_CUR); // Hide the LCD03 cursor
}

void loop(){

while(encValue < 3000){ // While encoder 1 value less than 3000 move forward
Serial.write(CMD); // Set motors to drive forward at full speed
Serial.write(WRITESP1);
Serial.write(200);
Serial.write(TURN); //<<<----------------------------------------------------------------This was added.
Serial.write(50); //<<< ----------------------------------------------------------------This was added.
encValue = readEncoder();
readVolts();
}
delay(100);
while(encValue > 100){
Serial.write(CMD); // Drive motors reverse at full speed
Serial.write(WRITESP1);
Serial.write(100);
encValue = readEncoder();
readVolts();
}
delay(100);
}

long readEncoder(){ // Function to read and display the value of both encoders, returns value of first encoder
long result1 = 0;
long result2 = 0;
Serial.write(CMD);
Serial.write(READENCS);
while(Serial.available()< {} // Wait for 8 bytes, first 4 encoder 1 values second 4 encoder 2 values
result1 = Serial.read(); // First byte for encoder 1, HH.
result1 <<= 8;
result1 += Serial.read(); // Second byte for encoder 1, HL
result1 <<= 8;
result1 += Serial.read(); // Third byte for encoder 1, LH
result1 <<= 8;
result1 += Serial.read(); // Fourth byte for encoder 1, LL
result2 = Serial.read();
result2 <<= 8;
result2 += Serial.read();
result2 <<= 8;
result2 += Serial.read();
result2 <<= 8;
result2 += Serial.read();

lcd03.write(LCD03_SET_CUR); // Set the LCD03 cursor position
lcd03.write(21);
lcd03.print(“Encoder 1:”); // Displays data to the LCD03 screen
lcd03.print(result1,DEC);
lcd03.print(" "); // Print a blank space to clear any unwanted characters that are leftover on the LCD03 display

delay(5); // Delay for LCD03 to process data

lcd03.write(LCD03_SET_CUR);
lcd03.write(41);
lcd03.print(“Encoder 2:”);
lcd03.print(result2,DEC);
lcd03.print(" ");
return result1;
}

void readVolts(){ // Function reads current for both motors and battery voltage
byte batteryVolts, mot1_current, mot2_current = 0;
Serial.write(CMD);
Serial.write(READIVS); // Send byte to readbattery voltage and motor currents
while(Serial.available()< 3){} // Wait for the 3 bytes to become available then get them
batteryVolts = Serial.read();
mot1_current = Serial.read();
mot2_current = Serial.read();

lcd03.write(LCD03_SET_CUR);
lcd03.write(61);
lcd03.print(“Mot1 I:”);
lcd03.print(mot1_current,DEC);
lcd03.print(" Mot2 I:");
lcd03.print(mot2_current,DEC);
lcd03.print(" ");

delay(5);

lcd03.write(LCD03_SET_CUR);
lcd03.write(1);
lcd03.print(“Rev:”);
lcd03.print(softwareRev, DEC);
lcd03.print(" “);
lcd03.print(“Volts:”);
lcd03.print(batteryVolts/10,DEC); // Seperate whole number and descimal place of battery voltage and display
lcd03.print(”.");
lcd03.print(batteryVolts%10,DEC);
lcd03.print(" ");
}[/code]

I am using the Marvelmind navigation system with the MD25 motor controller…I am trying to get the robot motors to execute a turn. Referring to the code snippet below: when I tell the motors to drive forward (by changing the z position of the hedgehog) and then tell them to drive the motors backward, the system works fine. However, when I tell the motors to drive forward, and then tell them to make a turn (notice some of the code is commented out), the motors go into the turn, but stay in the turn, and don’t go back to driving the motors forward (when the z coordinate is changed). In other words, the system stops listening to the z-position of the hedgehog when it executes a turn. I can get the system to make a turn…how do I get it to come out of the turn?

if(hedgehog_z >= 600) {hedgehog_z_marker = 0;} else{hedgehog_z_marker = 1;} switch(hedgehog_z_marker) { case 0: { Serial.write(CMD); // Set motors to drive forward Serial.write(WRITESP1); Serial.write(150); delay(70); break; } case 1: { Serial.write(CMD); // Drive motors into right turn Serial.write(TURN); Serial.write(190); delay(70); break; /* Serial.write(CMD); // Set motors to drive reverse Serial.write(WRITESP1); Serial.write(100); delay(70); break; */ /* Serial.write(CMD); // Drive motors into left turn Serial.write(TURN); Serial.write(80); delay(70); break; */ } }

The words do not go in the code, use the commands codes instead. See this thread about making code for this controller in arduino: robot-electronics.co.uk/forum/viewtopic.php?f=4&t=400

We contacted the manufacturer in order to get more information about this issue. We will get back to you as soon as they reply.