PDA

View Full Version : Dynamixel MX-106T with arduino feedback problems



mtete
04-26-2016, 08:53 AM
Hello,

I wired a Dynamixel MX-106T with a Arduino Uno just like on this website:
http://savageelectronics.blogspot.nl/2011/01/arduino-y-dynamixel-ax-12.html

And here is the wire schem:
http://3.bp.blogspot.com/-PhiRUiPEdnc/UFjq0vjsiUI/AAAAAAAABCc/iBCRto0oIlU/s1600/g4084.png

And this library:
https://github.com/zcshiner/Dynamixel_Serial

It works half, I can make the set the Dynamixel in wheel or servo mode.
But I cannot get any feedback from the Dynamixel.

################################################## #####
Servo ID:1 NO! packet recived from Dynamixel
Servo ID:1 NO! packet recived from Dynamixel
Servo ID:1 NO! packet recived from Dynamixel
Servo ID:1 NO! packet recived from Dynamixel
Servo ID:1 NO! packet recived from Dynamixel
################################################## #####


De half to full duplex I use:
http://nl.farnell.com/texas-instruments/sn74ls241n/ic-logic-74ls-buffer-driver/dp/1607639

I cannot find a solution, googled the heck out of it.
Tried different arduino uno's and a Mega.
Applied 12V, wired the thing over about 10 times.

I also tried different Library's but they did not work at all.

Do somebody knows a solution?

Thank you.
M.

jwatte
04-26-2016, 05:09 PM
First, make sure that the servo works OK and is not damaged. Use an USB2AX (http://amzn.to/1SIF0c8) or USB2Dynamixel (http://www.trossenrobotics.com/robotis-bioloid-usb2dynamixel.aspx) to do this, with the Dynamixel Wizard program from Robotis.

Once that's done, you can try different things. Most important is to figure out whether the problem is that you're holding the wire high when you shouldn't, or whether you're not properly receiving the data but the data is actually on the wire.
Easiest might be to wire TX to a 1 kOhm resistor, then that resistor to the TTL bus and to the RX pin of your Arduino.
That way, you will receive everything you send, which you have to manually read and discard. But, then, anything the servo sends should also be received by the RX.
It's not a super efficient way of doing bi-directional -- servos will drain about 5 mA when sending -- but it will get the job done.

It also helps if you have an oscilloscope (http://amzn.to/1VAReqQ), and/or a logic analyzer (http://amzn.to/1qRqvsU).

KurtEck
04-26-2016, 06:29 PM
Would help to see your actual code and picture of your actual hookup.

I have a board that uses the SNLS241, like you mentioned here, however I am using it with a Teensy 3.2 processor. I am also using my own library code, which I adapted to optionally use a direction pin.

However my changes to my library (https://github.com/KurtE/BioloidSerial) currently would not work unchanged with the Arduino UNO. As it relies on support that Teensy has built in to the hardware serial port code to automatically change the direction port when the outputs have completed. Where on the UNO you would need to do the changes to the direction pin manually using digitalWrite.

From your description I assume you have an IO pin connected up to pins 1 and 19 of the SNLS241. Likewise I assume your program calls off to Dynamixel.setDirectionPin with that IO pin. There are some minor things I would play with in the library you are mentioning to see if it makes a difference. Like in DynamixelClass::transmitInstructionPacket not sure why they are disabling interrupts during trying to send the end of the packet. I would have a tendency to comment out the noInterrupts() and interrupts() calls. I would also probably simplify and always call: _serial->flush();

And as jwatte mentioned, I would also hook up a Logic Analyzer to see what data is being sent and likewise see the state of the direction pin.

Kurt

jwatte
04-27-2016, 11:39 AM
not sure why they are disabling interrupts during trying to send the end of the packet

My guess is to get a precise end of the packet, to know when to flip the I/O pin, so it doesn't hold the bus too long?
I haven't read the code, so if I/O pin flipping isn't inside the interrupt bracket, then that's not it.

KurtEck
04-27-2016, 12:13 PM
My guess is to get a precise end of the packet, to know when to flip the I/O pin, so it doesn't hold the bus too long?
I haven't read the code, so if I/O pin flipping isn't inside the interrupt bracket, then that's not it.
Possibly, but if your hardware Serial port works on ISR to queue bytes, may never complete...
The function, that makes me nervous...

void DynamixelClass::transmitInstructionPacket(void){ // Transmit instruction packet to Dynamixel

if (Direction_Pin > -1){
digitalWrite(Direction_Pin,HIGH); // Set TX Buffer pin to HIGH
}

_serial->write(HEADER); // 1 Write Header (0xFF) data 1 to serial
_serial->write(HEADER); // 2 Write Header (0xFF) data 2 to serial
_serial->write(Instruction_Packet_Array[0]); // 3 Write Dynamixal ID to serial
_serial->write(Instruction_Packet_Array[1]); // 4 Write packet length to serial
_serial->write(Instruction_Packet_Array[2]); // 5 Write instruction type to serial

unsigned int checksum_packet = Instruction_Packet_Array[0] + Instruction_Packet_Array[1] + Instruction_Packet_Array[2];

for (unsigned char i = 3; i <= Instruction_Packet_Array[1]; i++){
_serial->write(Instruction_Packet_Array[i]); // Write Instuction & Parameters (if there are any) to serial
checksum_packet += Instruction_Packet_Array[i];
}

noInterrupts();

_serial->write(~checksum_packet & 0xFF); // Write low bit of checksum to serial

#if defined(__AVR_ATmega32U4__) || defined(__MK20DX128__) || defined(__AVR_ATmega2560__) // Leonardo and Mega use Serial1
if ((UCSR1A & B01100000) != B01100000){ // Wait for TX data to be sent
_serial->flush();
}

#elif defined(__SAM3X8E__)

//if(USART_GetFlagStatus(USART1, USART_FLAG_TC) != RESET)
_serial->flush();
//}

#else
if ((UCSR0A & B01100000) != B01100000){ // Wait for TX data to be sent
_serial->flush();
}

#endif

if (Direction_Pin > -1){
digitalWrite(Direction_Pin,LOW); //Set TX Buffer pin to LOW after data has been sent
}

interrupts();

}
Again I may be wrong, but personally I would try to simplify some, like:

void DynamixelClass::transmitInstructionPacket(void){ // Transmit instruction packet to Dynamixel

if (Direction_Pin > -1){
digitalWrite(Direction_Pin,HIGH); // Set TX Buffer pin to HIGH
}

_serial->write(HEADER); // 1 Write Header (0xFF) data 1 to serial
_serial->write(HEADER); // 2 Write Header (0xFF) data 2 to serial
_serial->write(Instruction_Packet_Array[0]); // 3 Write Dynamixal ID to serial
_serial->write(Instruction_Packet_Array[1]); // 4 Write packet length to serial
_serial->write(Instruction_Packet_Array[2]); // 5 Write instruction type to serial

unsigned int checksum_packet = Instruction_Packet_Array[0] + Instruction_Packet_Array[1] + Instruction_Packet_Array[2];

for (unsigned char i = 3; i <= Instruction_Packet_Array[1]; i++){
_serial->write(Instruction_Packet_Array[i]); // Write Instuction & Parameters (if there are any) to serial
checksum_packet += Instruction_Packet_Array[i];
}

_serial->write(~checksum_packet & 0xFF); // Write low bit of checksum to serial

_serial->flush();
if (Direction_Pin > -1){
digitalWrite(Direction_Pin,LOW); //Set TX Buffer pin to LOW after data has been sent
}

}

Or better yet use a Teensy!