PDA

View Full Version : Project of robotic Arm with dynamixel motors



urko_18
11-07-2017, 01:48 AM
Hello everyone!!

Frst of all, sorry about my english, i´m it improving slowly.:happy:

I'm doing the final project of my university degree, in which I have to be able to control a robot arm. The communication between the computer and the engines of the robot is established through arduino program (library ax12.h) and with an arbotix card.


So far, I have managed to move the robot with my hands, and then the program makes the robot repeat the same sequence, but now what I want is to be able to control the torque, so that when it repeats the sequence, if I hold it or I push it, i want to stop the sequence few seconds, as a security.


My doubt is that I do not know how to get the feedback or the data of the moments, and make the subsequent control, so that when I want to stop it stops.


The robot arm has 4 motors, two MX-64 and another two MX-106, each one are conected to an alimentation of 12V.


Thank you very much!!

Hugh
11-08-2017, 10:30 PM
You can use
Dxl.getLoad(inId);
to get the load. This is the amount of power required to drive the motor to the requested position.
Detecting a collision using this could be tricky because this includes the acceleration that would naturally be required to move the object, or resist gravity.
If it bumps up against a person, the feedback would increase the power to get the motor moving again, and this is what you might detect.
However, it might be easier to detect an sudden unexpected stop in position changes.
This is similar to how I ended up controlling my gripper. I set the torque limit, gripped the object and waited for the gripper to stop moving. This worked out more reliable than watching the load until it hit a certain level.
Hugh

urko_18
11-09-2017, 02:45 AM
Thank you very much for answering!


First, I can not read in the program the code that you sent me

Dxl.getLoad (inId);


and I've tried other ways like:


dxlGetLoad (inId);
dxlGetPresentLoad (inId);
Dxl.getPresentLoad (inId);
Dxl.Get.PresentLoad (inId);
...
and nothing, so I don´t know if there is any other way to obtain the Load.


I have tried with dxlGetTorque (inId); and I have obtained some values, but I don´t know in what units are the numbers that appear (they oscillate between 0 and 1800 more or less). Did you know it?


In any case, I also think that the second option that you mention could be better, in fact, what I want is a collaborative robot arm.
I already tried to do what you tell me about "set torque limit", but I did not get results. I don´t know what limit I should fix, and I don´t know if I have to fix the maxtorque or the mintorque.
If I hold and I block the arm, the engines try to follow the previous programmed sequence that they have, and they make more force and become hotter. I mean, they doesn´t stop (I know that i haven´t done the control yet), but the thing is that I don´t know how to start with the control.


Thanks again!!

Hugh
11-09-2017, 06:53 PM
The details of the api may be different depending on what code you are using. I was using the OpemCM code, which starts like:

Dynamixel Dxl(1 /*DXL_BUS_SERIAL1 = cm094 */);

I was using a register based api, to work around some issues I was having reading and writing with multiple serial ports and timing, like:



#define MAX_TORQUE 34
#define TORQUE_ENABLE 24

void setMaxTorque(int id, int torque)
{


for(int attempt=0;attempt<10;attempt++)
{
Dxl.writeWord( id, MAX_TORQUE, torque);
if ( Dxl.getResult( ) == COMM_RXSUCCESS )
break;
delay(1);
}
}


And would do something like:



enableTorque(GRIP_ID,true);
setSpeed(GRIP_ID,1023);
setMaxTorque(GRIP_ID,200);
setPosition(GRIP_ID,1023);



Now, these number are for the Ax12 (my gripper) - for the more powerful dynamixels, the range is 0-4095 so the torque/position values need to be 4x as big.



Reading the load is a bit tricky because there is a sign bit in there. I also found it changed in quite big steps, so not great for fine motor control.

This is the code I used for the load (again, Ax12 - the hex constants will need an extra 'f' on the end for MX)


int getLoad(int inId)
{
for(int i=0;i<10;i++)
{
int result = Dxl.getLoad(inId);
if(result<0 || result>=4096)
{
delay(1);
continue;
}
if (result & 0x400)
result = 1024 - (result&0x3ff);
else
result = 1024 + (result&0x3ff);


return result*2;
}
return -1;
}

Here I am converting from a signed value to an unsigned value centred on 1024 - you will need to check the details for MX motors. And this makes more sense to my application.

To manually position the arms, I just completely disabled the torque and then they were easy to move (I used a keyboard command to close the gripper).

To control the sequence, I used a program that set a target position, and then waited for the arm to get close and to stop moving, rather than wait a specific amount to time, before issuing the next command. This allows the sequence to be interrupted or slowed depending on the environment. For the gripper, I set the torque depending on what I was grapping, and then waited for it to stop moving.

Especially for the Ax12 gripper, you do need to set a lower max-torque or you will overheat pretty quickly. A fan or aluminium casing of the newer motors may help a lot here too.


Here is my experiment controlling dynamixels on a robot arm:
<a href="https://www.youtube.com/watch?v=xPKi3ssETbM" target="_blank">
https://www.youtube.com/watch?v=xPKi3ssETbM (https://www.youtube.com/watch?v=xPKi3ssETbM)

And a final sequence:
<a href="https://www.youtube.com/watch?v=B417vTm4DDM" target="_blank">
https://www.youtube.com/watch?v=B417vTm4DDM (https://www.youtube.com/watch?v=B417vTm4DDM)

urko_18
11-15-2017, 02:51 AM
Hi everyone!!!

Thank you very much Hugh!! As I say you, I´m proving your advices! but at the moment without succes.

I have recorded a video, where you can see that the robot movements are slow and jerky, I do not know if it is because the strucuturee is very heavy, or if I have to change some feature in the engines ...

https://www.youtube.com/watch?v=pJGe6f-Kouw&feature=youtu.be




I have already tried without success to change the present speed, torque max and torque min ... but the robot keeps going at the same ritm/speed.


On the other hand, I'm still immersed in torque control, with the intention of making a collaborative robot, but without results. If someone could help me with ideas or with the program to make that control (that is, to stop the sequence of the robot when I touch it), I would really appreciate it!

Brooks
11-15-2017, 11:24 AM
I've watched the video. When the top are is upright it doesn't seem to move any faster. Based up this observation I don't think the servos are slow because of loading issues.

I also see you have the servos geared down quite a bit. I think this is why the arms move so slowly.

You might consider a couple of RoboClaw controllers and motors with quadrature encoders. The Roboclaw will let you set the desired target and speed...

Hugh
11-15-2017, 10:58 PM
This is looking pretty good I think.
I have experienced this sort of jerkiness when trying to get a pair of dynamixes to trace a path.
The truth is that these are not stepper motors, and can't really be used as such.
So you can NOT easily get two motors to move in a line very nicely by doing (pseudo-code)


for(i=0; i<1000;i++)
{
setPosition(0, i);
setPosition(1, i/2);
}

because there is an acceleration-phase followed by a linear phase, followed by a deceleration phase.
If you ask it to go a small distance it will accelerate and then decelerate quicky, never hitting the linear phase, and you get this jerkiness.

But there is a trick to it - setting the speed small enough.
The idea is that you set the speed depending on the new target position and the current position, and small enough that the target position "leads" the current position by enough that the motor stays is its constant velocity phase (at a low speed).
If you want to move faster and smoothly, you need to issue fewer "setPosition" calls. One "setPosition" at full speed should move pretty quickly.

urko_18
11-16-2017, 02:49 AM
Thanks for answering!!!


1-First, Brooks, the thing/problem is that the design of the components and the structure for my project is already fixed, that is, I have to do the project with:


2 dynamixel MX-64 engines
2 dynamixel MX-106 engines
Arbotix electronic card
Program in arduino
The structure of the video


and I can´t change anything, so, i can´t use any other controller/any other form of structure.


2-Huhg, okey between today and tomorrow I will try to prove what you tell me of set a smaller speed! Let's see if I can get something, I'll let you know!


Anyway, this problem now has less importance, because yesterday I achieve the robot to be much faster (I changed the Delay commands by Delaymicroseconds), and now the robot repeats the movements really fast!
That's why now, when going faster, those blockages of the robot when moving are less noticeable and the problem become less important.


In conclusion, from next week I think I'm going to focus more on the other problem, on the code to get the load or torque of the robot, and try to make it stop when I touch it with my hands. Huhg, I'm still trying to try the advices you gave me! I'll tell you if I get something! Meanwhile I am open to new tracks/advices:happy:!!

Urko.

urko_18
11-21-2017, 05:34 AM
Hi!!

Unfortunately I have not been able to advance the project this week because I have broken the arbotix. I can´t upload the program to the card (I've done all kinds of tests) and it does not even turn on the LED. That is why it will take longer to have results with torque control.
I will also ask in other forums but, do you know what the problem could be?


The answer that the program gives me is the following:


avrdude: stk500_recv (): programmer is not responding
avrdude: stk500_getsync () attempt 10 of 10: not in sync: resp = 0xff
Problem uploading to arbotix.


I have already requested a new arbotix, to see how long it takes me to arrive, meanwhile I will try to find solutions to see if this can be fixed.


Thank you very much!

urko_18
11-21-2017, 08:37 AM
Hello again!


Throughout the morning I managed to solve the problem with the arbotix, so tomorrow I will continue with the control of the torque.


Urko.

KurtEck
11-21-2017, 08:49 AM
I tried to answer in the other thread. As I mentioned there, it was difficult to answer without additional information.

With this thread, I will assume you have programmed the board before, so you have Arduino and hardware folder installed.

Again check to make sure your Arduino board type is correctly set.

Try unplugging everything from your board (except power and FTDI cable). Again assuming you are using FTDI cable to program your board and not USB AVR programmer (personally I recommend using these).

If you have some form of Volt meter try checking to make sure you have voltages in different places. Check jumper settings.

Do you have a different FTDI cable you can try. One of mine that came with a PhantomX failed. This one was a combination XBee and FTDI cable. I think it was one of these (http://www.trossenrobotics.com/uartsbee). I instead use one of these: http://www.trossenrobotics.com/store/p/6406-FTDI-Cable-5V.aspx

Again hard to say. But again try unplugging everything as maybe there is a short on one of the Servos, or ...

urko_18
11-22-2017, 02:09 AM
Thank you KurtEck again!


As I say to you in the other thread, yesterday I managed to get it working by downloading the arbotix libraries again and also downloading and updating the drivers for the cable connection.

I do not know what the sudden error should be but it's already solved, thanks anyway!
I will continue with my project from today!

Urko

urko_18
01-08-2018, 05:42 AM
Hello again!!

I still working with the robotic arm!

And I want to make a program in arduino that has an emergency button , (I have managed to make an interruption in the pin), and what I want now is that when I press the emergency button, i want the robot stops (that is, to stop the motors). I have tried to do it by means of the following code: (the part of the code that I teach below is the one that is inside the function of the button, that is, what happens once you press the button.)




ISR(PCINT1_vect) {
interrupt_state = (PINB & 0x1E) >> 1;
j=1;
while (j=1) {
Serial.println("EMERGENCY BUTTON!");
TorqueOn(SERVO_ID[0]);
TorqueOn(SERVO_ID[1]);
TorqueOn(SERVO_ID[2]);
TorqueOn(SERVO_ID[3]);
delay(2000);
}
}



And yes, it works, but what happens is that depending on what position is the robot when i press the botton, it asks for too much load in one or more motors, and that motor makes a strange noise, as of not being able to support so much load, and then it stops working and the red alarm LED goes on, so the robot does not get stop (the motor that stop working get free and this part of the arm fall down.


Having seen this problem, and since at the moment I do not know how to solve it, I have thought about doing something different. I explain, instead of pressing the emergency button and the robot stops, I thought about making the robot go to a fixed position, at a very small speed.


The problem now is that by putting the code "setgoalposition" to the motors, the motors go to that position as quickly as possible, so,i have been testing different codes like setting the torque, speed,... before give the order to move but... :



ISR(PCINT1_vect) {
interrupt_state = (PINB & 0x1E) >> 1;
j=1;
while (j=1) {
Serial.println("EMERGENCY BUTTON!");
ax12SetRegister(SERVO_ID[0], AX_TORQUE_LIMIT_L ,50);
ax12SetRegister(SERVO_ID[1], AX_TORQUE_LIMIT_L ,50);
ax12SetRegister(SERVO_ID[2], AX_TORQUE_LIMIT_L ,50);
ax12SetRegister(SERVO_ID[3], AX_TORQUE_LIMIT_L ,50);
dxlSetGoalPosition(SERVO_ID[0], 3820);
dxlSetGoalPosition(SERVO_ID[1], 400);
dxlSetGoalPosition(SERVO_ID[2], 230);
dxlSetGoalPosition(SERVO_ID[3], 2395);
delay(2000);
}
}


But they do not work for me, so if someone knew how to make the robot not ask for so much load (first problem) or if someone knew how to make the engines go at a low speed to the desired position, I would appreciate it.


Urko

KurtEck
01-08-2018, 08:37 AM
I don't have MX servos and the GoalSpeed did not work very well on AX servos, but I thought it worked reasonably on MX servos.

Have you tried setting it to a low number?

http://support.robotis.com/en/product/actuator/dynamixel/mx_series/mx-64at_ar.htm#Actuator_Address_20

Hugh
01-08-2018, 08:26 PM
Do you mean 'TorqueOff' ?

urko_18
01-09-2018, 05:11 AM
thank you for answering!!

Hugh, no, i mean Torqueon, my idea is that when i press the button the robot stop in the position that is at that moment, so i have to put torque on, to force the robot to stay at that position. The problem is that as the material of the robot is very heavy, when i want to stop the robot in a extreme position (with the arm lifted), the motor suffer a overload, and gets off. So, i don´t know what can i do, and in consequence, i have planed the other idea of moving the motor to the initial position.

KurtEck, i have proved what yo say (goalspeed), and the robot do the same as before. But the clue is that i think i have other different problem, because i have beern fixing and the program neither do the println("EMERGENCY BUTTON!!"), only is printing "EM", as if it has not time to print... the program print "EM" and then the robot move fastly to the rest position, so i don´t know what problem can i have...

Urko.

KurtEck
01-09-2018, 10:56 AM
Again sorry, it is hard to offer very much advice without additional information. Like maybe post a small program that demonstrates what you are trying to do and the failure. Sometimes it is the order things are called or maybe something else that is happening. For example are you using protocol 1 or 2... I have only used protocol 1 (AX servos).

AX library (which one?) Do you have a link to it? If Trossen/Interbotix libraries, than they have the Bioloid part of the library with multiple servo moves with timing... So you should for example when you hit the button, be able to first do a query of the current positions, and then tell them all to go to some new position and say take 1 second or the like.

But there could be several other possible issues, like maybe there is a power drain that happens which causes the voltage to drop too low and the board resets, or some bad call, that is resetting the program or ...

Again hard to know without seeing much.

urko_18
01-10-2018, 07:00 AM
You're right, I should put more information, sorry, it's my first posts here!


Regarding the protocol, I do not know what you mean, so I can not answer you, I'm sorry.


The library that I use is the <ax12.h>, and the link is the following:


https://github.com/vanadiumlabs/arbotix/blob/master/libraries/Bioloid/ax12.h


This morning I tried to do the following:



ISR(PCINT1_vect) {
interrupt_state = (PINB & 0x1E) >> 1;

Serial.println("EMERGENCY BUTTON!");
TorqueOn(SERVO_ID[0]);
TorqueOn(SERVO_ID[1]);
TorqueOn(SERVO_ID[2]);
TorqueOn(SERVO_ID[3]);
int pos_em_1 = dxlGetPosition(SERVO_ID[0]); //Actual servo position
int pos_em_2 = dxlGetPosition(SERVO_ID[1]);
int pos_em_3 = dxlGetPosition(SERVO_ID[2]);
int pos_em_4 = dxlGetPosition(SERVO_ID[3]);
int pos2_1 = 3820; //rest position of the robot (the positions of the 4 dynamixel)
int pos2_2 = 400;
int pos2_3 = 230;
int pos2_4 = 2395;


go_position_EMERGENCY(pos_em_1, pos_em_1, pos_em_1, pos_em_1, pos2_1, pos2_2, pos2_3, pos2_4);//function
while(1);
}



I think that's what you told me to do, right? I register the positions when I give the button, and then send the robot to the new position (rest position), (go_position_EMERGENCY is a funciton that moves the robot to the rest position), here is the function:



//The following function will move the robot to the initial position and to the resting position when you have presed the EMERGENCY BUTTON!!
void go_position_EMERGENCY(int pos_em_1, int pos_em_2, int pos_em_3, int pos_em_4, int pos2_1, int pos2_2, int pos2_3, int pos2_4)
{
while (pos_em_1 != pos2_1 || pos_em_2 != pos2_2 || pos_em_3 != pos2_3 || pos_em_4 != pos2_4)
{
//ID1
if (pos2_1 < pos_em_1)
{
dxlSetGoalPosition(SERVO_ID[0], pos_em_1);
pos_em_1--;
delayMicroseconds(2000);
}
else if (pos2_1 > pos_em_1)
{
dxlSetGoalPosition(SERVO_ID[0], pos_em_1);
pos_em_1++;
delayMicroseconds(2000);
}
//ID2
if (pos2_2 < pos_em_2)
{
dxlSetGoalPosition(SERVO_ID[1], pos_em_2);
pos_em_2--;
delayMicroseconds(2000);
}
else if (pos2_2 > pos_em_2)
{
dxlSetGoalPosition(SERVO_ID[1], pos_em_2);
pos_em_2++;
delayMicroseconds(2000);
}
//ID3
if (pos2_3 < pos_em_3)
{
dxlSetGoalPosition(SERVO_ID[2], pos_em_3);
pos_em_3--;
delayMicroseconds(2000);
}
else if (pos2_3 > pos_em_3)
{
dxlSetGoalPosition(SERVO_ID[2], pos_em_3);
pos_em_3++;
delayMicroseconds(2000);
}
//ID4
if (pos2_4 < pos_em_4)
{
dxlSetGoalPosition(SERVO_ID[3], pos_em_4);
pos_em_4--;
delayMicroseconds(2000);
}
else if (pos2_4 > pos_em_4)
{
dxlSetGoalPosition(SERVO_ID[3], pos_em_4);
pos_em_4++;
delayMicroseconds(2000);
}
}
}




But the robot firstly moves very fast to other position (i don´t know why) and then it returns slowly to the rest position, so i don´t understand why the robot do that.
Also, in this program the Serial.println("EMERGENCY BUTTON!") didn´t print at all while i press the button... other time only is printing "EM"...

I don´t think that there is a power drain that happens which causes the voltage to drop too low and the board resets, or some bad call, that is resetting the program or, because after that the program continues running ok.


So, i don´t know what can be the problem...