An interview about me, the reasons to build little robots, to have a blog about robotics. Here
Dec 15
Posted by robottini in Dongbu Herkulex, Dynamixel, Robottini | 2 Comments
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
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 |
Although it is one of the classics of robotics for beginners, the line follower robot, made at high level, is quite complex. On Youtube you can see line follower running at 3 m / s and more, with optimization and maximum performance research that achieves discrete levels.
Usually a line follower competition is based on pure speed and the path is quite linear and simple, with large curves and wide straights. In this case the hardware part is the most important, because the sw part is quite simple to build. it is important to find the right compromise between the mechanical parts and the engine, to make it running as fast as possible. Unfortunately requires a lot of money, because the engine performance search or the wheels with special tires can be very expensive.The alternative is based on paths that are rather difficult or very twisted, with right angles, intersecting lines, lines breaks, obstacles and so on. In this case the HW is much less important. More important is the algorithm and then the sw. The ability of the robot builder is to build a powerful algorithm that allows the robot to drive fast in every situation.
In this tutorial I would describe the robot that I have realized, that is able to face a tortuous path made of curves at 180 ° rather than tight coils, trying to have a good speed.
The robot ,according to tradition, was home built. It is also already equipped with an infrared sensor front in case you wish to use it in a path with obstacles.
Questo è Microbo(t) – line follower robot:
It ‘s built with the following elements:
- Chassis 5 mm PVC foam (few cents)
- Arduino Nano (about 40 euros)
- Drive Pololu 50:1 HP (about 30 euros both)
- Pololu motor bracket (both about 6 euros)
- Caster wheel Pololu 3.8 “plastic (about 3 euros)
- Pololu Wheels 42×19 (both about 10 euros)
- Motor driver SparkFun TB6612FNG (about 9 euros)
- Sharp IR Distance sensor 4-30 cm (about 15 euros)
- Sensor line Pololu QT-8RC (about 12 euros)
- 7.4V 900mAh Battery Li-Po (about 9 euros)
- some screws and wires
As you can see the components expensive are Arduino Nano and the motors. Nothing forbids to use a traditional Arduino with an obvious saving of money. In my configuration it weighs about 160 grams. You can do much better, in fact on the internet there are line follower with Arduino that weigh 100 grams.
Some comments on hw components used. The driving system, formed by Pololu wheels and motors is almost good. I think that even better is using HP 100:1 Pololu motors which provide even more traction and fluidity in the changes of direction, even if it has a lower number of revolutions/minute. I tested also the 30:1 motors, but they were too nervous. Absolutely bad is the plastic wheel caster form Pololu. Unfortunately I had no other small than this, so I kept it. Not recommend its use. Terrible.
The motor driver SparkFun TB6612FNG is a little undersized. In fact it provides 1.2A at full speed, when the Pololu HP motors may require up to 1.6A. But I had no problem with these drivers and they still work, so I can only advise them. Unfortunately they have a lot of wires, 7 for driving, 2 for the Vcc voltage (+5 V), one (or two with the ground) for the motor voltage and 4 wires for motors. In total 14 wires that are several. They are simple to program and manage. The full brake function is not good. In fact, if you need to brake, however, takes a little bit to stop, victim of inertia. I think that the engines 100:1 can help on this.
The line sensor Pololu QT-8RC is good. It provides out-of-the-box a digital output and can be connected directly to the Arduino digital ports. After a stage of self-learning during the first few seconds (see the video), it is able to calibrate with the best values taking into account the reflectivity of the surface and the ambient light conditions. It can follow the black lines on white background or white on black background. For this sensor there is an Arduino library written by Pololu that provides a value between 0 and 8000 depending on the sensor (from left to right) which is above the black line. I modified the library to get a response that goes from -800 to +800 with zero when the line is well below the IR sensor in the middle. This from my point of view makes easier the control. The only real problem I had was in the presence of right angles. In this case the robot has not always stopped in time and managed to turn. Unfortunately I have no videos on this particular problem.
Once built the robot, the biggest difficulty is the control parameters determination, that allow the robot to come back to the line when goes away. In this case I have put in place the usual PID control, although in my version was reduced only in PD, proportional and derivative. The integral control, with the frequent changes of direction, is extremely difficult to detect.
I also wrote some simple routines for the detection of right angles. In this case the robot tries to stop and turns 90°. This technique has worked quite, but you can sure do better.
For the IR front sensor I didn’t have any important test for obstacle avoidance. The main problem is due to the need to rotate the robot for the obstacle avoidance operating in open-chain, ie, without feedback. The robot should pass the obstacle, but that succeeded a few times because the motors battery voltage varies over time, with a variation of path. I did not do further tests, but there are two possibilities:
The dc-dc converter costs less than 10 euros, while the cost for the Pololu encoder is about 25 euros. Maybe in the next version of the Microbo(t) I will decide which solution to adopt. Clearly the solution encoder is more sophisticated but requires more programming effort (and verify that there are still pins available on the Arduino!).
This is the code for Arduino, commented but not very clean. Link
This is the Microbo(t) in action:
Tags: Arduino, Line follower, robottini
You are currently browsing the archives for the Robottini category.
Arclite theme by digitalnature | powered by WordPress