SOLVED: Rotating second AX12W in opposite direction with joystick

  1. What model(s) of servo are you using?
    Dynamixel AX12w

  2. Describe your control environment. Include the controller or interface, operating system (and version #) of your computer, and how you are powering your robot.

Arudino IDE on Jetson nano jetpack 4.5 (ubuntu 18.04)

  1. libraries:
    DynamixelShield

Hello, I watched the youtube video on the customer service channel about controlling the Dynamixel with a potentiometer, and adapted the code to run on an ax12w. I am having an issue adapting the code to run a second motor in the opposite direction to mount them on a car.

The code I am about to present is modified from the velocity mode example sketch for the ArduinoShiled.

With the following code, ID 1 works well, however ID2 exhibits erratic behaviors .

For example, when I move the stick -, it will rotate the wrong direction before beginning in the correct direction.

I tried using UNIT_PERCENT as well, and I couldn’t get that working normally either.

Any advice would be appreciated.

#include <DynamixelShield.h>

#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_MEGA2560)
#include <SoftwareSerial.h>
SoftwareSerial soft_serial(7, 8); // DYNAMIXELShield UART RX/TX
#define DEBUG_SERIAL soft_serial
#elif defined(ARDUINO_SAM_DUE) || defined(ARDUINO_SAM_ZERO)
#define DEBUG_SERIAL SerialUSB
#else
#define DEBUG_SERIAL Serial
#endif

const uint8_t DXL_ID = 1;
const uint8_t DXL_ID2 = 2;
const float DXL_PROTOCOL_VERSION = 1.0;

DynamixelShield dxl;

//This namespace is required to use Control table item names
using namespace ControlTableItem;

void setup() {
// put your setup code here, to run once:

// For Uno, Nano, Mini, and Mega, use UART port of DYNAMIXEL Shield to debug.
DEBUG_SERIAL.begin(115200);

// Set Port baudrate to 57600bps. This has to match with DYNAMIXEL baudrate.
dxl.begin(1000000);
//Serial.begin(9600);
// Set Port Protocol Version. This has to match with DYNAMIXEL protocol version.
dxl.setPortProtocolVersion(DXL_PROTOCOL_VERSION);
// Get DYNAMIXEL information
dxl.ping(DXL_ID);
dxl.ping(DXL_ID2);

// Turn off torque when configuring items in EEPROM area
dxl.torqueOff(DXL_ID);
dxl.torqueOff(DXL_ID2);
dxl.setOperatingMode(DXL_ID, OP_VELOCITY);
dxl.setOperatingMode(DXL_ID2, OP_VELOCITY);
dxl.torqueOn(DXL_ID);
dxl.torqueOn(DXL_ID2);
}

void loop() {
// put your main code here, to run repeatedly:

// Please refer to e-Manual(http://emanual.robotis.com) for available range of value.
// Set Goal Velocity using RAW unit

int val=analogRead(1);
int val2=val;

//Serial.println(val);

if (val >= 512) {
val=map(val,512,1023,1024,2047);
//Serial.println(val);

}

if (val <= 512) {
val=map(val,0,512,1023,0);
//Serial.println(val);

}

if (val2 >= 512) {
val2=map(val2,512,1023,0,1023);
//Serial.println(val2);

}

if (val2 <= 512) {

val2=map(val2,0,512,2047,1024);
//Serial.println(val2);

}

dxl.setGoalVelocity(DXL_ID,val);
dxl.setGoalVelocity(DXL_ID2,val2);

//0 ~ 2,047(0x7FF) can be used, the unit is about 0.1%.
//If a value in the range of 0 ~ 1,023 is used, it is stopped by setting to 0 while rotating to CCW direction.
//If a value in the range of 1,024 ~ 2,047 is used, it is stopped by setting to 1,024 while rotating to CW direction.
//That is, the 10th bit becomes the direction bit to control the direction.
//In Wheel Mode, only the output control is possible, not speed.
//For example, if it is set to 512, it means the output is controlled by 50% of the maximum output.

}

hi @FrankWizza,
The velocity range of AX series is different from that of X series.
Based on an assumption of your joystick ADC range is 0 ~ 1023 (whereas 512 is the centered value), the proper velocity mapping should look like below.
I haven’t tested the code tough.

if(val >= 512) {
  val = map(val, 512, 1023, 1024, 2047);  // ID 1 - CW
  val2 = map(val, 512, 1023, 0, 1023);  // ID 2 - CCW
} else if {
  val = map(val, 0, 511, 1023, 0);  // ID 1 - CCW
  val2 = map(val, 0, 511, 2047, 1024);  // ID 2 - CW
} else {
  val = val2 = 0;  // Stop
}
1 Like

Thanks, I ran it. It needed a couple of tweaks. This was very helpful.

If not using val2 in the map, eg val2 = map(val2,…);
motor2 runs clockwise with the joystick centered.

Here is the exact working code for anyone who needs it.

int val=analogRead(1);
int val2=val;

if(val >= 512) {
val = map(val, 512, 1023, 1024, 2047); // ID 1 - CW
val2 = map(val2, 512, 1023, 0, 1023); // ID 2 - CCW
}else if(val<512){
val = map(val, 0, 511, 1023, 0); // ID 1 - CCW
val2 = map(val2, 0, 511, 2047, 1024); // ID 2 - CW
} else {
val = val2 = 0; // Stop
}

dxl.setGoalVelocity(DXL_ID,val);
dxl.setGoalVelocity(DXL_ID2,val2);

2 Likes

Oh, you’re right.
The val is incorrectly used in the second map function in each conditional statement.
Thanks for the updates!

2 Likes