I bought some time ago a couple of motors from Dongbu: the Herkulex DRS-0101. These motors are ‘smart’ because they have inside a microprocessor that allow to manage many parameters and the behavior of the motors.
The Herkulex are an alternative to more famous motors like the Dynamixel. They have 4 wires and can be drove by a simple microprocessor with a UART (serial) port. My choice is to control them with an Arduino, so I wrote a simple library supporting all the most common Herkulex functionalities.
For the wiring of Herkulex to Arduino, it is important to consider that it is necessary to dedicate a serial port to the communication Arduino-Herkulex.It is not possible (or is not advisable) to use the standard Arduino port because it is dedicated to communication between PC and Arduino to see the values in the serial monitor. So it is important to use another serial port.
For the Arduino Mega it is easy, because the Mega has 4 serial ports, for the Arduino Uno/2009 that has only one serial port, it is mandatory to use a software serial port. So a library called SoftwareSerial has to be included if we want to use the Arduino Uno/2009.
To do this the last version of SoftwareSerial is not useful, so I included in the library also the right SoftwareSerial version in order to work well with Arduino Uno/2009.
For general knowledge about the Herkulex Dongbu motors, please see the manual: here
Download the library: Herkulex Library for Arduino
These are the commands supported by the library:
begin(long baud, int rx, int tx) | start the communication between Arduino Uno/2009 and Herkulex |
beginSerial1(long baud) | start the communication between Arduino Mega and Herkulex using the Serial Port 1 |
beginSerial2(long baud) | start the communication between Arduino Mega and Herkulex using the Serial Port 2 |
beginSerial3(long baud) | start the communication between Arduino Mega and Herkulex using the Serial Port 3 |
end() | stop the communication between Arduino and Herkulex |
initialize() | initialize all the motors |
stat(int servoID) | ask for the motor status to control the errors |
ACK(int valueACK) | set the answer of the motors to a request (verbose or not verbose) |
set_ID(int ID_Old, int ID_New) | change the ID of the motor |
clearError(int servoID) | clear the motor error |
torqueON(int servoID) | set the motor torque to ON |
torqueOFF(int servoID) | set the motor torque to OFF |
moveAll(int servoID, int Goal, int iLed) | prepare the motors to execute the movement in the same time to position (same start time – end time) – unison movement |
moveAllAngle(int servoID, float angle, int iLed) | prepare the motors to execute the movement in the same time to angle (same start time – end time) – unison movement |
moveSpeedAll(int servoID, int Goal, int iLed) | prepare the motors to execute the movement in continuous rotation with same start time and end time – unison movement |
actionAll(int pTime) | execute the unison movement |
moveSpeedOne(int servoID, int Goal, int pTime, int iLed) | motor continuous rotation with a specified speed |
moveOne(int servoID, int Goal, int pTime, int iLed) | move one motor to an absolute position |
moveOneAngle(int servoID, float angle, int pTime, int iLed) | move one motor to an angle |
getPosition(int servoID) | get the motor position |
getAngle(int servoID) | get the position in degrees |
getSpeed(int servoID) | get the motor speed (continuous rotation) |
reboot(int servoID) | reboot the motor |
setLed(int servoID, int valueLed) | set the led color |
writeRegistryRAM(int servoID, int address, int writeByte) | write a value in a register in the RAM memory |
writeRegistryEEP(int servoID, int address, int writeByte) | write a value in a register in the ROM memory |
I think the Herkulex are a good motors. My tests are not very deep and I don’t stressed the motors, but in general, compared to Dynamixel, I think they are good. The big difference is the possibility to set a large variety of parameters and the possibility to start and stop the movement for all the motors at the same time leaving to motors the definition of acceleration and speed needed to cover the distance assigned in the same time frame. Some time I experimented problems with the Serial port, receiving the data, I tried to limit them in the library, but sometimes these problems are present yet. This depends by the Herkulex motors, not by my library.
These are the details of each command.
begin
Command | void begin(long baud, int rx, int tx) |
Description | start the communication between Arduino Uno/2009 and Herkulex |
Arduino Type | Arduino Uno/2009 |
Input |
|
Output | None |
Example | begin(57600,10,11) |
beginSerial1
Command | void beginSerial1(long baud) |
Description | start the communication between Arduino Mega and Herkulex using the Serial Port 1 (pins Rx1 – 19 and Tx1 – 18) |
Arduino Type | Arduino Mega |
Input |
|
Output | None |
Example | beginSerial1(115200) |
beginSerial2
Command | void beginSerial2(long baud) |
Description | start the communication between Arduino Mega and Herkulex using the Serial Port 2 (pins Rx1 – 17 and Tx1 – 16) |
Arduino Type | Arduino Mega |
Input |
|
Output | None |
Example | beginSerial2(115200) |
beginSerial3
Command | void beginSerial3(long baud) |
Description | start the communication between Arduino Mega and Herkulex using the Serial Port 3 (pins Rx1 – 15 and Tx1 – 13) |
Arduino Type | Arduino Mega |
Input |
|
Output | None |
Example | beginSerial3(115200) |
End
Command | void end() |
Description | stop the communication between Arduino and Herkulex |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | None |
Output | None |
Example | end() |
Initialize
Command | void initialize () |
Description | initialize the motors. Correspond to commands: clearError(BROADCAST_ID) + ACK (1) + torqueON(BROADCAST_ID). Works for all the motors |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | None |
Output | None |
Example | initialize() |
Stat
Command | byte stat(int servoID) |
Description | return the status of the motor. Please note that the value of BROADCAST_ID (253) often doesn’t work well |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | servoID=servo ID value, value between 1-253 |
Output |
|
Example | int status = stat(1) |
ACK
Command | void ACK(int valueACK) |
Description | set the verbose answer from Herkulex. the value is valid for all the motors wired in the chain |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | valueACK
|
Output | None |
Example | ACK(1) |
set_ID
Command | void set_ID(int ID_Old, int ID_New) |
Description | Assign a new ID to a motor |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | Int ID_Old: the old ID motor. Values between 1-253Int ID_New: the new ID motor. Values between 1-253 |
Output | None |
Example | set_ID(253, 1) |
clearError
Command | void clearError(int servoID) |
Description | Clear the error code for a servo. Works also with BROADCAST_ID=253. Do not switch off the red led lightning |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | servoID: the servo ID. Values between 1-253 |
Output | None |
Example | clearError(BROADCAST_ID) |
torqueON
Command | void torqueON(int servoID) |
Description | Set the torque on for a motor. Works also with BROADCAST_ID=253 for all motors |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | Servo_ID: servo ID. Values between 1-253 |
Output | None |
Example | torqueON(BROADCAST_ID) |
torqueOFF
Command | void torqueOFF(int servoID) |
Description | Set the torque off for a motor. Works also with BROADCAST_ID=253 for all motors. The torque is Free, not Break |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | Servo_ID: servo ID. Values between 1-253 |
Output | None |
Example | torqueOFF(BROADCAST_ID) |
moveAll
Command | void moveAll(int servoID, int Goal, int iLed) |
Description | prepare the motors to execute the movement in the same time to position (same start time – end time) – unison movement. Start the movement with actionAll command |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input |
|
Output | None |
Example | moveAll(1, 300, LED_GREEN) |
moveAllAngle
Command | void moveAllAngle(int servoID, float angle, int iLed) |
Description | prepare the motors to execute the movement in the same time to angle (same start time – end time) – unison movement. Start the movement with actionAll command |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input |
|
Output | None |
Example | moveAllAngle(1,-120.5, LED_GREEN) |
moveSpeedAll
Command | void moveSpeedAll(int servoID, int Goal, int iLed) |
Description | prepare the motors to execute the movement in the same time in continuous rotation (same start time – end time) with different speeds – unison movement. Start the movement with actionAll command |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input |
|
Output | None |
Example | moveAll(1, 300, LED_GREEN) |
actionAll
Command | void actionAll(int pTime) |
Description | Start the unison movement prepared with moveAll, moveAllAngle, moveSpeedAll |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | pTime: execution time in milliseconds. Values between 0- 2856 ms. The execution time values are in step of 11.2 ms, so if your input is 1000, the real execution time is int(1000/11.2)*11,2=996,8 ms |
Output | None |
Example | actionAll(1000) |
moveSpeedOne
Command | void moveSpeedOne(int servoID, int Goal, int pTime, int iLed) |
Description | Move continuously a motor with a specific speed |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input |
|
Output | None |
Example | moveSpeedOne(1,-300, 1500, LED_GREEN) |
moveOne
Command | void moveOne(int servoID, int Goal, int pTime, int iLed) |
Description | Move one motor to an absolute position |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input |
|
Output | None |
Example | moveOne(1,-300, 1500, LED_GREEN) |
moveOneAngle
Command | void moveOneAngle(int servoID, floiat angle, int pTime, int iLed) |
Description | Move one motor to a position in degrees |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input |
|
Output | None |
Example | moveOneAngle(1,120, 1500, LED_GREEN) |
getPosition
Command | int getPosition(int servoID) |
Description | Get absolute position |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | servoID: servo ID, values between 1-253. BROADCAST_ID doesn’t work |
Output | Position. Values between 0-1024 |
Example | int pos=getPosition(253) |
getAngle
Command | float getAngle(int servoID) |
Description | Get position in degrees |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | servoID: servo ID, values between 1-253. BROADCAST_ID doesn’t work |
Output | angle. Values between -160.0 … 160.0 |
Example | float angleMotor=getAngle(253) |
getSpeed
Command | int getSpeed(int servoID) |
Description | Get speed in continuous rotation mode |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | servoID: servo ID, values between 1-253. BROADCAST_ID doesn’t work |
Output | Position. Values between 0-1024 |
Example | int pos=getSpeed(253) |
reboot
Command | void reboot(int servoID) |
Description | servo hardware reboot |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input | servoID: servo ID, values between 1-253. BROADCAST_ID doesn’t work |
Output | None |
Example | reboot(253) |
setLed
Command | void setLed(int servoID, int valueLed) |
Description | Set the led color |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input |
|
Output | None |
Example | setLed(253, LED_PINK) |
writeRegistryRAM
Command | void writeRegistryRAM(int servoID, int address, int writeByte) |
Description | Write a byte in the RAM registry |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input |
|
Output | None |
Example | writeRegistryRAM(BROADCAST_ID, 1,1) is equivalent to ACK(1) |
writeRegistryEEP
Command | void writeRegistryRAM(int servoID, int address, int writeByte) |
Description | Write a byte in the RAM registry |
Arduino Type | Arduino Mega- Arduino Uno/2009 |
Input |
|
Output | None |
Example | writeRegistryEEP(BROADCAST_ID, 1,1) is equivalent to ACK(1) in ROM memory |
Hi,
I’d like to ask you a question please: I’d like to move a motor to 90 degrees with moveOneAngle(). And then I’d like to move it again to 90 degrees with another moveOneAnge() which will be 180 degrees. I only have this one motor, and I really don’t want to destroy it, though I would like to test what will happen if if comes to 180 because normally, it should stop at 160 degrees. Does the motor moves or stays at its position and blink the red LED? or does it try to go until 180 degrees, and then gets blocked by 160 and then get damaged?
Thank you in advance for your answer, I would really like to know it
I love your writing style really loving this internet site.
Hello,
I’m controlling Herkulex 0101 with Arduino Uno Arduino Uno and from PC.
Therefore, the connection servo Arduino, be GND, and two digital ports Vin.
However, the red LED turns servo.
Using your library can send the data to Arduino Uno, but the servo does not turn at all and is still flashing red.
Can you help me? Thank you
Hi, i am working with Arduino Mega and DRS-0101 and 0201 motors.
it is stated in the library description that the the “moveSpeedOne” function has the parameter “pTime=execution time in milliseconds” so I assume that after setting the execution time, the motors should stop, right?
In reality they keep on moving. I am using following code:
#include
int n = 1;
void setup()
{
delay(1000); //a delay to have time for serial monitor opening
Serial.begin(115200); // Open serial communications
Serial.println(“Begin”);
Herkulex.beginSerial1(115200); //open serial port 1
Herkulex.initialize(); //initialize motors
Herkulex.moveSpeedOne(n, -300, 100, LED_GREEN);
}
void loop(){
}
Could you please let me know if the code I am using is correct and if there is something can/should be edited in the library to make the execution time parameter working?
Hi,
I’m controlling Herkulex 0101 with Arduino Uno and from Arduino Uno to PC.
So, the connection from servo to Arduino, it goes to GND, Vin and 2 digital ports.
However, the servo led turns red.
Using your library, I can send the data to Arduino Uno but the servo won’t rotate at all and still blinking red.
Can you help me? Thank you
Hi all,
Now I had a problem with Arduino Mega. When I test Herkulex drs-0201 with Herkulex Manager, it is working well. But when I test with Arduino, using example program in Library, there comes no error but motor is not moving. The program is perfectly executed such that I can see from the Serial Monitor. It would be really great if you could help me.
Thank you very much
Thank you very much now i have no problem with the sketch but when i load the “UNO one motor move angle”sketch my drs 101 not move in the right position
Any idea?
Hello,
For a project i try to control a drs 101 with an arduino uno.
For that i use your library but i have some error message:
UNO_one_motor_move_angle.ino: In function ‘void setup()’:
UNO_one_motor_move_angle:10: error: ‘Herkulex’ was not declared in this scope
UNO_one_motor_move_angle.ino: In function ‘void loop()’:
UNO_one_motor_move_angle:19: error: ‘Herkulex’ was not declared in this scope
UNO_one_motor_move_angle:19: error: ‘LED_BLUE’ was not declared in this scope
any idea? can you help me
Thank you
Analyzing these error messages I understand you haven’t installed correctrly the library. If the library is well installed you can find it in this menu: sketch -> import library
What happens if I keep torqueOFF and try to move the motor?
What does torqueON do? (What does Set the torque on for a motor mean?)
With torqueOn the motor can run.
It would be great to adapt this library to Arduino DUE
It works!!!
thank you so much!!!
Great work with the Library!
I had a few issues receiving serial feedback (position, angle, and speed) while running the Servo on a software serial port at 57600 baud. Switching back to a Arduino Mega at 115200 the feedback was received no problem. Is there something I am doing wrong, or is there an issue with the library / baud rate.
Hopefully, this is something straight forward!
I rewrite your Arduino library for processing recently.
Here is the link,
https://github.com/dongburobot/HerkuleXProcessing/blob/c39f07d7489484bfa02ed7dba83c3c9f21f5f74b/HerkuleX/src/dongburobot/herkulex/HerkuleX.java
I found that there is a minor bug in getSpeed() function.
=========================================
line 628~629
speedy = ((dataEx[10]&0xFF)<<8) | dataEx[9];
return speedy;
=========================================
This code is not be able to get CW speed (-1023~-1).
Fix it please.
=========================================
speedy = ((dataEx[10]&0x03)<<8) | dataEx[9];
if ((dataEx[10]&0x40) == 0x40)
speedy *= -1;
return speedy;
=========================================
Thanks in advance for your work for the library.
What a nice work!
Just one thing,
There is an error on writeRegistryEEP() description.^^