You are viewing notbrainsurgery

This · is · Not · a · Brain · Surgery


OWI Robotic Arm Edge USB protocol (and sampe code)

Recent Entries · Archive · Friends · Profile

* * *
In my last post I have described OWI-007 Robotic Arm parallel port protocol. They have a newer, more advanced model called Robotic Arm Edge:

Robotic Arm Edge

You can use USB interface module to connect it to PC. Unfortunately official software works only under Windows and do not provide API. I have been able to reverse engineer their USB protocol and write sample code which allows to control the arm from Mac and Linux.

This is USB device with vendor id 0x1267 and product id 0. The device is controlled by 3 byte commands sent via USB control transfers. Command format is byte0, byte1, byte2. Each byte controls a group of arm features. All motors could be controlled independently. Most commands start action which is continued until next action is signalled. Byte '00' universally used as stop action.

Bit numbering in byte:

7 (most significant) 6 5 4 3 2 1 0 (least significant)


Meaning of bits in each byte:

Byte 0

First byte controls grip, shoulder and wrist. Bits are assigned as following:

Bit numbers Controls Bit combinations
0,1 Grip 00-do not move, 01-close, 10-open
2,3 Wrist 00-do not move, 01-move up, 10-move down
4,5 Elbow 00-do not move, 01-move up, 10-move down
6,7 Shoulder 00-do not move, 01-move up, 10-move down


Sample commands, activating single motor:

Byte 0 Command
00 stop grip, wrist, elbow and shoulder movement
01 grip close
02 grip open
04 wrist up
08 wrist down
10 elbow up
20 elbow down
40 shoulder up
80 shoulder down


Sample commands activating 2 motors simultaneously:

Byte 0 Command
11 grip close and elbow up
82 grip open and shoulder down


Byte1

Second byte controls base.
Bits are assigned as following:

Bit numbers Controls Bit combinations
0,1 Base 00-do not move, 01-rotate clockwise, 10-rotate counter-clocwise


Sample commands:

Byte 1 Command
00 stop base rotation
01 rotate base clockwise
02 rotate base counter-clocwise


Byte 2

Third byte controls LED light inside the grip.
Bits are assigned as following:

Bit numbers Controls Bit combinations
0 LED 0-off, 1-on


Sample commands:

Byte 2 Command
00 LED off
01 LED on


Sample source code using libusb:

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>

#include <libusb-1.0/libusb.h>

#define EP_INTR	(1 | LIBUSB_ENDPOINT_IN)

#define ARM_VENDOR       0x1267
#define ARM_PRODUCT      0
#define CMD_DATALEN      3

libusb_device * find_arm(libusb_device **devs)
{
	libusb_device *dev;
	int i = 0;

	while ((dev = devs[i++]) != NULL) {
		struct libusb_device_descriptor desc;
		int r = libusb_get_device_descriptor(dev, &desc);
		if (r < 0) {
			fprintf(stderr, "failed to get device descriptor");
			return NULL;
		}
		if(desc.idVendor == ARM_VENDOR &&
		   desc.idProduct == ARM_PRODUCT)
		  {
		    return dev;
		  }
	}
	return NULL;
}

int main(int ac, char **av)
{
    if(ac!=4)
    {
        fprintf(stderr,"Usage: armedgetest CMD0 CMD1 CMD2\n");
        return 1;
    }

    unsigned char cmd[3];

    cmd[0]=(unsigned char)strtol(av[1],NULL,16);
    cmd[1]=(unsigned char)strtol(av[2],NULL,16);
    cmd[2]=(unsigned char)strtol(av[3],NULL,16);
    
	libusb_device **devs;
    libusb_device *dev;
    struct libusb_device_handle *devh = NULL;
	int r;
	ssize_t cnt;

	r = libusb_init(NULL);
	if (r < 0)
    {
	    fprintf(stderr, "failed to initialize libusb\n");
	    return r;
    }

    libusb_set_debug(NULL,2);
    
	cnt = libusb_get_device_list(NULL, &devs);
	if (cnt < 0)
		return (int) cnt;
    dev=find_arm(devs);
    if(!dev)
    {
	    fprintf(stderr, "Robot Arm not found\n");
	    return -1;
    }

    r = libusb_open(dev,&devh);
    if(r!=0)
    {
	    fprintf(stderr, "Error opening device\n");
       	    libusb_free_device_list(devs, 1);
             libusb_exit(NULL);
	    return -1;
    }


    fprintf(stderr, "Sending %02X %02X %02X\n",
            (int)cmd[0],
            (int)cmd[1],
            (int)cmd[2]
    );

    int actual_length=-1;
    
    r = libusb_control_transfer(devh,
                                0x40, //uint8_t 	bmRequestType,
                                6, //uint8_t 	bRequest,
                                0x100, //uint16_t 	wValue,
                                0,//uint16_t 	wIndex,
                                cmd,
                                CMD_DATALEN,
                                0	 
    );
    
    if(!(r == 0 && actual_length >= CMD_DATALEN))
    {
        fprintf(stderr, "Write err %d. len=%d\n",r,actual_length);
    }
    
    libusb_close(devh);
	libusb_free_device_list(devs, 1);
	libusb_exit(NULL);

    fprintf(stderr, "Done\n");
	return 0;
}


Sample usage:
./armedgetest 00 00 01
sleep 3
./armedgetest 00 00 00

will turn the light on for 3 seconds and then would turn it off. It have been tested on MacOS X, but should work on Linux as well.
* * *
* * *
On November 7th, 2010 02:42 pm (UTC), (Anonymous) commented:
Reverse engineering
Nice! Can you tell how did you reverse-engineer USB protocol?
* * *
On December 5th, 2010 03:58 pm (UTC), (Anonymous) commented:
linux
Seems to work on linux as well. Some minor whinging about the return value from the write, but the robot moves as commanded.

~/development/robot_arm$ ./armedgetest 0 0 0
Sending 00 00 00
Write err 3. len=-1
Done

Nice, thanks. I too am very curious how you reverse engineered the USB protocol.

On June 19th, 2011 06:51 pm (UTC), (Anonymous) replied:
Re: linux
What is the best way to install libusb library in ubuntu?
I tried, several times but sems make-install is givenme sobre troubles.
[User Picture]
On June 19th, 2011 11:08 pm (UTC), vzaliva replied:
Re: linux
there is libusb package for ubuntu. Install via apt-get, in usual manner.
* * *
[User Picture]
On January 15th, 2011 11:38 pm (UTC), polwart commented:
Thanks for the details of the protocol
I'm using controlling this arm as a way to polish my Python skills, so your details of the USB structure were very helpful. I've got the basics working in Python and will tidy up the code and post it on line for others who may be interested in the next day or so. I've created a blog for the purpose here: http://python-poly.blogspot.com
[User Picture]
On January 17th, 2011 01:14 am (UTC), notbrainsurgery replied:
Re: Thanks for the details of the protocol
good to hear this! Perhaps you can set up a project at google code and post both my C and your Python code there under open-source license?
[User Picture]
On January 27th, 2011 07:13 pm (UTC), polwart replied:
Re: Thanks for the details of the protocol
Notbrainsurgery, I'm not really familiar with the world of "google code" nor is my code really that sophisticated that it needs a "project". All my code is on my blog, and I've no issues with others using it for non-commercial purposes. I've already got a link back here from the blog - and to the C# code on linux questions.

If someone wants to create a project I'd happily contribute my python code, but my main aim is to get my python skills up to practical levels - so the code I write might not be much interest to others beyond the basic control functions. I'll be adding an upgrade later tonight or tomorrow.
* * *
On February 22nd, 2011 07:26 pm (UTC), (Anonymous) commented:
libusb
can you help me with libusb installation on mac os x? Xcode is unable to find it after doing ./configure, make and make install.

if I put the complete path, it throws me a lot of errors about linking and symbols.

how do you installed it?? thanks a lot, I wanna do a lot with this arm!!
[User Picture]
On February 22nd, 2011 09:12 pm (UTC), notbrainsurgery replied:
notbrainsurgery
Use macports: http://www.macports.org/ to install libusb
* * *
On March 2nd, 2011 12:18 am (UTC), (Anonymous) commented:
how to get it work on window 7 64bit
great work !!!

i tried to get it work on my window 7 64bit.

so sad that libusb-1.0 not working on window platform.

tried libusb-win32, but no lucky.

always return err -116 when sending the control msg.

any idea could help me out?

anyway, thanks for your great work !!!
On March 2nd, 2011 12:58 am (UTC), (Anonymous) replied:
Re: how to get it work on window 7 64bit
just found out the problem by myself. the timeout value of usb_control_msg() need to be set. shouldn't leave it as 0. i put 10 and it works. yeah.
On June 2nd, 2011 03:36 pm (UTC), (Anonymous) replied:
Re: how to get it work on window 7 64bit
I saw that you worked with OWI-535
I too am trying to program the robot in VB 6
have you received help and if you can help me make a VB6 program that controls the robot
On March 3rd, 2011 02:34 am (UTC), (Anonymous) replied:
Re: how to get it work on window 7 64bit
finally, got the robot arm work with face tracking.

http://www.youtube.com/watch?v=i_26gfocQp4

thanks for your great stuff !!! save me a lot of time.
* * *
[User Picture]
On August 23rd, 2011 03:00 am (UTC), Erle Czar Mantos commented:
Have you figured out how to use a wall-wart with it?
Hi,

First off, great job. I tried reverse-engineering that thing before
but I had to put it off for some reason. Finally, somebody did it
and now I can go back to hack it. Thank you very much.

Second, have you tried wiring that thing so that it uses a wall wart
adapter instead of a battery? The battery is such a waste of money.

If you have, mind sharing how? Email me at emantos@gmail.com
* * *
[User Picture]
On March 14th, 2012 11:09 am (UTC), vitasam commented:
This is exactly what I'm looking for! My robotic arm kit just arrived few days ago,and I'm already bored with it's software. Thanks!
* * *
[User Picture]
On March 14th, 2012 09:51 pm (UTC), vitasam commented:
Just thinking why manufacturer did not use USB-serial adapter instead of pure USB. It will be much more easier to control the arm from any PC platform, without having pain in the ass with USB SW development.
* * *
[User Picture]
On May 21st, 2012 05:29 pm (UTC), Николай Кузнецов commented:
Hello fellow`s! Would somebody like send me project C++ or Delphi to "zodrax@yandex.ru" . I mean your soft to control Robotic Arm
* * *
[User Picture]
On June 13th, 2012 08:02 pm (UTC), vitasam commented:
I've installed libusb from sources in to Debian PC. But for some reason compilation failed like shown below. What could be missed in my Debian system?
gcc -Wall -o "robotarm" "robotarm.c"
/tmp/ccw4X3H9.o: In function `find_arm':
robotarm.c:(.text+0x1d): undefined reference to `libusb_get_device_descriptor'
/tmp/ccw4X3H9.o: In function `main':
robotarm.c:(.text+0x154): undefined reference to `libusb_init'
robotarm.c:(.text+0x1a4): undefined reference to `libusb_set_debug'
robotarm.c:(.text+0x1b8): undefined reference to `libusb_get_device_list'
robotarm.c:(.text+0x229): undefined reference to `libusb_open'
robotarm.c:(.text+0x270): undefined reference to `libusb_free_device_list'
robotarm.c:(.text+0x27c): undefined reference to `libusb_exit'
robotarm.c:(.text+0x30c): undefined reference to `libusb_control_transfer'
robotarm.c:(.text+0x350): undefined reference to `libusb_close'
robotarm.c:(.text+0x364): undefined reference to `libusb_free_device_list'
robotarm.c:(.text+0x370): undefined reference to `libusb_exit'
collect2: ld returned 1 exit status
Compilation failed.
On July 23rd, 2014 06:54 am (UTC), Melvin Chan replied:
Byte 0 - 80 shoulder down
when you mentioned byte 0, it means 8 bit and command 80 in bits is 01010000

which means elbow and shoulder up ?

sorry, im trying to understand here.
[User Picture]
On July 23rd, 2014 07:47 pm (UTC), vitasam replied:
Re: Byte 0 - 80 shoulder down
Hi,

it is Ok now, below was my another comment:

"I got it compiled in my Debian PC. First, libusb-dev should be installed in system.

Instead of
#include libusb-1.0/ libusb.h

use
#include libusb.h

Build it:

gcc robotarm.c `pkg-config --libs --cflags libusb-1.0` -o robotarm

..:~/Programming/robotarm$ ./robotarm
Usage: armedgetest CMD0 CMD1 CMD2"
* * *
[User Picture]
On June 14th, 2012 07:21 pm (UTC), vitasam commented:
I got it compiled in my Debian PC. First, libusb-dev should be installed in system.

Instead of
#include libusb-1.0/ libusb.h

use
#include libusb.h

Build it:

gcc robotarm.c `pkg-config --libs --cflags libusb-1.0` -o robotarm

..:~/Programming/robotarm$ ./robotarm
Usage: armedgetest CMD0 CMD1 CMD2




Edited at 2012-06-14 07:23 pm (UTC)
* * *
[User Picture]
On July 25th, 2012 07:10 pm (UTC), lordyosch commented:
Hi,

I'm trying to get my robot to work under Ubuntu 12.04 using your code but I am getting the following error:

./armedgetest.sh: line 14: syntax error near unexpected token `('
./armedgetest.sh: line 14: `libusb_device * find_arm(libusb_device **devs)'

The USB is being detected, as evidenced by DMESG
[ 2573.966139] usb 4-3: USB disconnect, device number 6
[ 2579.624038] usb 4-3: new low-speed USB device number 7 using ohci_hcd

(turned off, then on again)

I am a noob at the inner workings of linux so I have no idea what causes the error.

Any ideas?

Thanks,

Jay
* * *
[User Picture]
On September 5th, 2012 12:22 pm (UTC), Rudolf Hoehler commented:
Got it working perfectly on Windows 7 64bit. Took a while, but got there.

Thanks a lot for this clear howto! You sir, are a legend. :)
* * *
[User Picture]
On October 6th, 2012 02:25 pm (UTC), Richard Steele commented:
Please can anyone help looking for a ready to go zip of a complete project for this for MSVC 6.0 under windows XP, ive been trying for an hour or two but not having any luck getting usblib up and running. Ive not worked with usblib before and its proving tricky, Ive not managed to build a robotarm sucessfully yet, added various files and headers etc including the lib but no luck. If someone can please help. cheers regards Richard
* * *
On January 23rd, 2013 04:01 pm (UTC), slamdunkers commented:
Hi, Firstly thanks for posting this it was very clear and useful! Last summer I managed to get the Robot Arm working fairly quickly on an Arm Linux Box (Ubuntu).

However, I am experiencing a lock up now and then (just got around to looking at it). An educated guess told me that libusb_control_transfer was waiting forever - and so I changed the timeout to 100ms and approximately once a minute it returns -7 (LIBUSB_ERROR_TIMEOUT). So I used libusb_reset_device to do the obvious and it recovered most times, but not all... Occassionally this also fails and then I don't seem to be able to recover 'gracefully'.

Do you have any suggestions please. I know its a cheap 'toy' but its still a bit annoying ;-)

Thanks Matt
* * *
On June 20th, 2013 06:19 pm (UTC), ateeq999 commented:
plz can anybody help me. iam making a robotic arm with 4 degree of freedom using servo motors and pic micro controller. how can i connect usb port to controller and will this coding work for it? am new to robotics so plz bare with me

my emial id is terrorist_999@yahoo.com
* * *
On January 13th, 2014 04:09 pm (UTC), 00david commented:
Excellent work!

I have the Maplin / OWI-535 arm working on XP and windows 7 with vb6, using the open source libusb-win32.

I put together some notes in case they helped others- Re-assemble the link without the "_" as it was the only way this forum would let it through:
davepatterson_
.me.uk_
/public/armnotes.txt

There is a picture of my VB interface in the same folder called interface.jpg

David

Edited at 2014-01-13 04:15 pm (UTC)
* * *

Previous Entry · Leave a comment · Share · Next Entry

* * *