Wixel + Dynamixel AX-12 Servos + Arbotix Commander

Hey folks,

I’m working on interfacing the Dynamixel AX-12 servos with the Wixel, as well as interfacing the Wixel with the Arbotix Commander controller.

The Commander part was easy. I documented the hack for this on another forum, here.

The part that’s tripping me up is the AX-12 + Wixel. I’ve previously used the AX-12 successfully with the Axon board, with the necessary tristate buffer circuit, and the Webbotlib libraries.

With the Wixel, I’m adapting the Wireless Serial app. I’m using a friend’s standalone AX-12 library, written for AVRs. I’ve converted it to be SDCC compatible (everything compiles fine).

The main thing I’m doing different is that the tristate buffer is being controlled with two direction pins, rather than one (with an inverter IC being used). This just means toggling two pins in software.

Here’s a pic of the board:



The other little board on there is the Sparkfun Level Converter to go from 3.3V to 5V. for RX and TX from the Wixel. I’ve found that the 3.3V high from the direction pin is enough to toggle the tristate buffers. Board features a 5V switching regulator, and headers for a either a 12V wall power supply, or a Lipo + battery monitor.

So the actual problem:
As yet, I’ve not gotten the servos to respond. I’ve hooked up the board to my computer, and I can verify that the Wixel is sending the correct packets at the correct baud rate, and that the packets are making in and out of the tristate buffer properly. I’ve gotten the same result rebuilding the circuit on a breadboard, too. Alas, when I hook up the servos, no luck. (I know I have the servo ID correct, too) Has anyone else succeeded with interfacing these servos to the Wixel?

I have two tests in mind to do next: (1) Modify Webbotlib to use two direction pins, and see if my Axon can control the AX-12s with the tristate buffer board; (2) Do the breadboard circuit again, and use an inverter instead of separate direction pins.

I forked the wixel-sdk on github. Said fork is here, and the actual modified app that I’m working with is here. Code isn’t the cleanest because it’s a work in progress :wink:

Hope someone’s got some insights out there. But I’ll keep poking at this and I’m sure I’ll figure it out eventually…




Hello.

Is this the level shifter you are using?
sparkfun.com/products/8745

I suspect that your output from the level shifter to the dynamixel isn’t actually going as high as you would expect, but I am not sure. How is everything wired? Do you have an oscilloscope so you can look at the signal going to the dynamixel, instead of just using the computer?

–David

Hi David,

That’s indeed the sparkfun board.

Unfortunately I lack a oscope. This does remind me, however that another test would be to see what the level-shifted voltage is for a pin that’s set to high. I’ll do that tonight, probably.

As for wiring… looks like I neglected to link this page, which has this diagram:

A more thorough diagram… (that might not link properly)


These use 74HC04N inverter. I’m taking the approach of using a second direction pin instead.

I don’t have a complete diagram with the level converter/regulator/wixel. I used the above and planned out the board layout in Inkscape…

Thanks,
-Gert

Testing just now with a breadboard, it looks to me like (one of the spare) level converter is doing fine with a pin at constant high. Obviously an oscope is still ideal.

I was looked at the source code of dynamixel_txrx on github and I don’t see any code that waits for the bytes to finish being transmitted, so I think you are calling dynamixel_setrx() too soon.

If you continue to have trouble, I suggest making a very simple one-file Wixel app with no radio code that just sends the proper bytes. This will make it easier for me to tell what you are doing.

–David

I’ll give creating an isolated program a try tonight, or this weekend.

I had wondered about my lack of delays… But it seemed to me the symptom of that being a problem would be if the packets were incomplete, e.g. when sent to the computer.

On another note; Other code I’ve seen (e.g. WebbotLib and Arbotix) has a function to clear the RX buffer (e.g. after a full packet is received from the Arbotix Commander). Is there an equivalent in the Wixel libraries? I was not able to find such when I looked.

No, there is no such function. You could wait until the return value of uart0TxAvailable() goes back up to 255. Unfortunately, that will stop working if we ever change the size of that buffer, so maybe it would be better to add a function to the UART library that tells you if the TX buffer is empty or not.

–David

I did some initial work on simplifying the code, but that’s not done yet. (I removed all the USB stuff… and voila, had to do a manual reset to get into bootloader mode – whoops/fun!)

I noticed that if I remove the level shifter board, just the yellow LED on the Wixel flashes. With the level shifter board plugged in, (no servo or Usartbee connected) the red LED lights up after maybe a second, indicating an error. This matches what I thought I observed with the breadboard setup - hooking the RX line up to the tristate buffer circuit results in an error happening.

Doing some testing just now with LED toggling in software, I used the Green LED to determine that the error is “uart1RxBufferFullOccurred” (and not “uart1RxFramingErrorOccurred”).

Figured I’d just note the above for future reference.

Thanks for the info on buffer handling. I’ll look into that when next I tackle this software. I may get access to an oscope tomorrow… I figure its still worth checking.

Thanks,
-Gert

Victory.

Finally found the mistake after a handful of different evenings where I compared the bytes being sent from the Wixel to the bytes being sent from the USB2AX device.

#define ax12SetGOAL_POSITION(servo,val) 	dynamixel_writeword(servo,AX_GOAL_SPEED_L,CLAMP(val,0,1023))

should have been

#define ax12SetGOAL_POSITION(servo,val) 	dynamixel_writeword(servo,AX_GOAL_POSITION_L,CLAMP(val,0,1023))

Basically human error when I wrote that line of code… the SPEED/POSITION variables are so similarly named… (and in some libraries, you use ‘speed’ to set the position…)

Thanks for the help David :slight_smile: