Log in

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


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 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)
        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;

	cnt = libusb_get_device_list(NULL, &devs);
	if (cnt < 0)
		return (int) cnt;
	    fprintf(stderr, "Robot Arm not found\n");
	    return -1;

    r = libusb_open(dev,&devh);
	    fprintf(stderr, "Error opening device\n");
       	    libusb_free_device_list(devs, 1);
	    return -1;

    fprintf(stderr, "Sending %02X %02X %02X\n",

    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,
    if(!(r == 0 && actual_length >= CMD_DATALEN))
        fprintf(stderr, "Write err %d. len=%d\n",r,actual_length);
	libusb_free_device_list(devs, 1);

    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.
* * *
* * *
[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

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

#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"
On February 21st, 2015 08:58 am (UTC), John Walker replied:
compilation failed
You need to remember to add the usb library.
gcc -Wall robotarm.c usb -o robotarm
* * *

Previous Entry · Leave a comment · Share · Next Entry