The Arm Link library, firmware, and software will allow you to control the RobotGeek Arm by sending an absolute value to each coordinate. These coordinates are sent over a serial port connection to the Geekduino that controls the arm. The Geekduino will receive the coordinates, do any required calculations, and then move the servos appropriately.
The Arm Link library and software was initialliy designed for the InterbotiX line of Robotic Arms but it is fully compatible with the RobotGeek Snapper Arm.
- Firmware and Software
- Arm Modes
- Serial Port Settings
- Arm Link Packet Structure
- Low Byte/High Byte Calculations
- Button Byte Structure
- Extended Byte Structure
- Negative/Offset Values
- Arm Limits & Defaults
- Reading Analog Data
- Arm ID Response Packet
- Arm Link Packet Calculator
- Arm Link Packet Examples
Firmware and Software
The Arm Link Library and Firmware examples are installed within the Geekduino Libraries files installed during the Geekduino Getting Started Guide. Alternatively they can be found here. Details on installing the library manually and loading the
ArmLinkSerial firmware can be found here.
A demo application, the Arm Link PC Control Software is also available. This open source application allows a computer to control the robot arm. This application can set arm position, as well as control digital I/O and read analog input.
The Snapper Arm currently only supports Cartesian IK mode. Other modes will be available in the future
Serial Port Settings
To support the Arm Link protocol, your programming language will need to support sending byte data over a serial port. See the documentation for your language to see if it is capable of sending byte packets over a serial port.
The Arm can also be controlled by other microcontrollers using a serial port.
Your serial connection should have the following settings to communicate with the Robot Arm.
- Baud: 38400
- Parity: None
- Data Bits: 8
- Stop Bits: 1
Arm Link Packet Structure
The Arm Link packet holds the coordinate data to be sent from a computer or other controller to the Geekduino. The packet is always 17 bytes long. Packets 10 and 11 are not used by the snapper arm - send a '0' on each of these packets.
Positional packets can be sent discretely or at a regular interval. The Arm will finish a movement before it performs the next movement. If you are sending packets at an interval, do not send them faster than 30hz (one packet every 33ms).
|Packet #||Cartesian Mode|
|2||X-Axis Coordinate High Byte|
|3||X-Axis Coordinate Low Byte|
|4||Y-Axis Coordinate High Byte|
|5||Y-Axis Coordinate Low Byte|
|6||Z-Axis Coordinate High Byte|
|7||Z-Axis Coordinate Low Byte|
|8||Wrist Angle High Byte|
|9||Wrist Angle Low Byte|
|10||Wrist Rotate High Byte|
|11||Wrist Rotate Low Byte|
|12||Griper High Byte|
|13||Gripper Low Byte|
|16||Extended Instruction Byte|
Low Byte/High Byte Calculations
Arduino serial communications sends data as discrete byte-sized packets. An 8-bit byte can only hold values from 0-255. This is too small for the X/Y/Z coordinate values and the absolute servo positions values. To compensate for this, each parameter is split into two bytes - a low byte and a high byte. Once received by the Robot Arm, these bytes will be combined into the original value.
|Value (Decimal)||High Byte (Decimal)||Low Byte (Decimal)||Value (Binary)||High Byte (Binary)||Low Byte (Binary)||Value (Hex)||High Byte (Hex)||Low Byte (Hex)|
The low byte corresponds to the first 8 bits of the value. To obtain this value we simply remove anything past the first 8 bits of the value. This can be done many ways, but the easiest way is to use the modulus operator (%).
Low Byte Pseudo Code
//coordinate is a previously defined integer value byte lowByte = coordinate % 256 ;
The low byte corresponds to the second 8 bits of the value. First we will shift the second byte down 8 values. To do this we can divide the value by 28 or 256. As these operations are being done on integers/bytes, the lower byte is discarded. Once we have shifted the second byte, we will use the modulus operator to ensure that only a single byte is isolated.
High Byte Pseudo Code
//coordinate is a previously defined integer value byte highByte = (coordinate / 256)%256;
Here's an alternative way to come up with the high/low byte using bitwise operators
//coordinate is a previously defined integer value byte highByte = (coordinate >> 8) & 0xFF; //shift the value down 8 bits and mask it with 255/0xFF to isolate the byte byte lowByte = coordinate & 0xFF; //mask the value with 255/0xFF to isolate the byte
The Delta value determines how long it will take for the arm to move from its current position to the new position. The amount of time that the move takes is calculated by multiplying
Delta by 16. The result will give you the time interval in milliseconds.
Time Interval = Delta * 16
For example, a delta of 125 means that the move will take 2000 milliseconds, or 2 seconds.
Button Byte Structure
The button byte can control digital outputs on the Geekduino. These outputs can be connected to LEDs, Buzzers, Lasers, or any other 5v digital output. Relays can be used to activate higher voltage devices.
|Geekduino Digital Output||N/A||13||12||11||8||7||4||2|
|Hex||Decimal||Binary||Digital Outputs Active|
Extended Byte Structure
|0x00||0||Move Arm to Position*|
|0x60||96||Put Arm in Sleep mode - move to sleep position and turn servo torque off|
|0x70||112||ID Packet Request|
|0x80||128||IK Status Request (Not Implemented)|
|0xC8||200||Request Analog Packet on Analog 0|
|0xC9||201||Request Analog Packet on Analog 1|
|0xCA||202||Request Analog Packet on Analog 2|
|0xCB||203||Request Analog Packet on Analog 3|
|0xCC||204||Request Analog Packet on Analog 4|
|0xCD||205||Request Analog Packet on Analog 5|
|0xCE||206||Request Analog Packet on Analog 6|
|0xCF||207||Request Analog Packet on Analog 7|
*Sending the arm an extended byte of
0 will send it to the current coordinates based on packets 2-15. Sending a packet with any other extended byte will ignore packets 2-15
The checksum is a dynamic value that will change if any of the values in the packet changes. This allows the arm to confirm the packet was received without any errors. The checksum can be calculated as follows:
- Add up bytes 2 - 16 (do not include the header)
- Isolate the low-byte of the sum (%256)
- Invert the byte (255-)
The Pseudo Code for this operation would be
sum = xHighByte + xLowByte + yHighByte + yLowByte + zHighByte + zLowByte + wristAngleHighByte + wristAngleLowByte + wristRotateHighByte + wristRotateLowByte + gripperHighByte + gripperLowByte + deltaValBytes + buttonByte + extValBytes;//add up bytes 2-16 invertedChecksum = sum % 256;//isolate the lowest byte checksum = 255 - invertedChecksum; //invert value to get file checksum
WristAngle both can have negative values. However all of the values transmitted via the ArmControl serial packet are unsigned bytes that are converted into unsigned integers - that is, they can only have positive values. To compensate for this fact,
WristAngle are transmitted as offset values.
Add 512 to
X to obtain the value to transmit over Arm Link.
|Transmitted Value||Interpreted X-Coordinate Value|
Add 90 to
Wrist Angle to obtain the value to transmit over Arm Link.
|Transmitted Value||Interpreted Wrist Angle|
Arm Limits & Defaults
The following list of limits are all 'interpreted' values. Parameters with a '*' must be offset to a positive range before transmission.
|Parameter||Lower Limit||Upper Limit||Default|
Notes on Values
A '0' value will close the gripper all the way while a '512' value will open it all the way.
Reading Analog Data
It is possible to read Analog Data from the Geekduino and send the data back over the serial link. Sending the arm a specific extended instruction will cause the arm to report the current value of the corresponding analog value. See the Extended Table to see which instructions correspond to which analog ports.
|Packet #||Packet Info|
|1||Fixed Header - 0xff|
|2||Extended Instruction Echo|
|3||Analog Value High Byte|
|4||Analog Value Byte|
Arm ID Response Packet
Sending a packet with the extended instruction of
112 will cause the arm to send an ID response packet. This can be useful for determining what arm you are communicating with, or just to check if the arm is available.
The arm will also send this ID packet after its mode is changed, including sleep mode
The arm will respond with a 5-byte packet with the following data.
|Packet #||Packet Info|
|1||Fixed Header - 0xff|
|4||Fixed - 0|
|Robot Arm||Arm ID|
|InterbotiX PhantomX Pincher Arm||1|
|InterbotiX PhantomX Reactor Arm||2|
|InterbotiX WidowX Arm||3|
|RobotGeek Snapper Arm||5|
|Robot Arm||Arm ID|
|Cartesian - Normal Wrist||1|
|Cartesian - 90° Wrist||2|
|Cylindrical - Normal Wrist||3|
|Cylindrical - 90° Wrist||4|
Arm Link Packet Calculator
You can find a basic Arm Link calculator here
Arm Link Packet Examples
You can find basic Arm Link example packets here