Robotic Arm Project #1 #2 #3

Robotic Arm Project #1


I have begun partial assembly of a small robotic arm from a kit containing the mechanical parts and the body pieces and the servos. I have been test fitting parts and have already discovered an issue with the servo wheels which are cogged for gears aren't fitting well on the gear on the MG996R servos. I checked how well the Hexfly servos fit the servo wheels .

2018-08-10-robotics-01.jpg 2018-08-10-robotics-02.jpg

Servo Replacement
From advice gleaned from various places I will be replacing (4) of the original servos MG996R (I have already obtained two replacements) which are much better quality but need to locate a couple more Redcat Racing Hexfly HX-15S servos (will be replacing 4 of them. They seem to be out of stock everywhere I have checked. I can re-use the original servos in some less critical application so the MG996R won't be wasted hopefully.


I attached the servo wheels to the two Hexfly servos and the gears are incredibly tight. I checked the MG996R servos and they were also unbelivably tight so I think there is a slight mistake in the servo wheels as two different brand of servo was almost too tight to work. I really had to struggle and use a lot of pressure to get them on.


I am waiting on the arrival of (2) servo controllers, one of which will be used to calibrate the servo motors. I am only test fitting everything right now as I can't move forward until I receive the servo controllers.

The Arduino code to calibrate the servos is provided by the vendor but I did a lot of research before buying this particular model because I tracked it to 5 or 6 vendors all selling chinese hardware and designs. I found a duplicate on eBay that was exactly the same as the vendor model so I ordered a second robotic arm to work with. I am building the current one which I have called Project #1 using higher quality servos and plan on making this a precision device.

That could mean writing more of my own code and searching for better servos if the Hexfly models aren't precise enough. I hope to also work with some machine vision designs to see if the arm can be made to do something useful.

I am sure there is a lot of work to do before that.

32-Channel Servo Controller

I was able to obtain a lot of software to control the robot but using a specific 32-channel servo controller which is why I have to wait but I am going to archive everything here so that perhaps someday it will become useful when the originals vanish from the net.

It seems I can't upload it all here as one of the files is around 60MB which seems to have hit a wall on file-size during the site upload. I have a ticket in with the wiki provider to ask to be able to upload larger files I used to be able to store CD images which were over 300MB so something has changed lately.

Meanwhile I do have the Linux code for this see SUTD_Linux_2.1.0_X64.tar.bz2 MD5 e5bd7c9457b5c378824ae38a9c20fb2e however I found software for Windows, MacOS, Android!

I will try to find out some way to get it all archived here. I got the software and the manual for the 32-channel servo controller from and the manual is located here see

I have a local copy 38641-manual-english-V3.0.pdf

The Windows version is MD5 bdc5e2a2ee00114acf723ed8d4c0d102

The MacOS version is MD5 b7b22fef5d4d85bf48d9c09a1a7063b0

The Android version is

The card is available from all the places that sell all the generic Chinese hardware that we all seem to be able to get from different places that may even have a different brand name but it is exactly the same as the next one. The Generic 32-Channel Servo Controller! I have found it at NewEgg, eBay (various vendors), I found it on Amazon as well.

I found several tutorials even one on Instrictables. See

I found more documentation and



I have replaced all the servos with Hexfly 15S 15kg Metal Gear 205-oz Servos. I can use the cheap TowerPro and the no-name brand servos in a less-demanding application.

I also repaired the terrible-quality jaw gear mechanism. The center-hole for the "passive" part of the jaw gearing was off by about 2mm so I drilled it out and installed a larger screw that keeps the (2) gears meshed. What a shame it was such poor quality. The so-called stainless screws are somewhat soft and the screw heads are getting chewed up.

I have been writing Arduino sketches for the arm and am going to publish it here soon. I have been writing all sorts of test programs this last week.

I am also working on covering all the loose wires with cable sleeves.

My workbench is such a mess right now.
#include <Servo.h>

Servo jaws;
Servo wrist;
Servo joint1;
Servo joint2;
Servo joint3;

int i = 0;

void setup()
    // initialize digital pin LED_BUILTIN as an output.


void loop()


    for (int i = 0; i <= 45; i++) {
        digitalWrite(LED_BUILTIN, HIGH); 
        digitalWrite(LED_BUILTIN, LOW); 




  for (int x = 0; x <= 120; x++) {
     digitalWrite(LED_BUILTIN, HIGH); 

        digitalWrite(LED_BUILTIN, LOW); 




  for (int z = 90; z >= 45; --z) {
    digitalWrite(LED_BUILTIN, HIGH); 




I am trying to get the documentation for this servo controller/ps2 interface I got it from eBay but then could not find any documentation with it. I hate this when I purchase stuff from chinese ebay sellers and they don't have documentation in my language. I am usually very good at locating that kind of documentation but this time I have not been successful (yet.)

[393914.212377] usb 2-1.7: new full-speed USB device number 17 using ehci-pci
[393914.306578] usb 2-1.7: New USB device found, idVendor=10c4, idProduct=ea60
[393914.306586] usb 2-1.7: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[393914.306590] usb 2-1.7: Product: CP2102 USB to UART Bridge Controller
[393914.306594] usb 2-1.7: Manufacturer: Silicon Labs
[393914.306597] usb 2-1.7: SerialNumber: 0001
[393914.429446] usbcore: registered new interface driver usbserial
[393914.429467] usbcore: registered new interface driver usbserial_generic
[393914.429483] usbserial: USB Serial support registered for generic
[393914.447390] usbcore: registered new interface driver cp210x
[393914.447425] usbserial: USB Serial support registered for cp210x
[393914.447456] cp210x 2-1.7:1.0: cp210x converter detected
[393914.516553] usb 2-1.7: reset full-speed USB device number 17 using ehci-pci
[393914.609869] usb 2-1.7: cp210x converter now attached to ttyUSB0

I keep asking the eBay vendor for documentation and they sent me a word document that had this version of the controller.



Unit #1, #2 and #3 sitting on the bench awaiting further work. All units are functional but upgrading some servos and wqriting software on a daily basis. So fr the software has only been basic exercising of each segment of the arm.

One of the things I have learned as I went a long was to use a movement algorithm that only moves one degree at a time instead of a "hard slew" motion slowly and gradually make the movement and the arm is more stable as well. I have added aluminum plates to be the base of each arm unit.



I had bought some used servos on eBay and one of them was defective. I was ripped off, they sold me a servo that keeps losing it's position. If you are buying Hexfly servos, Redcat Racing sells them cheaper than anywhere else. You should buy direct from them.

I tried to make a video that may or may not be funny. Please enjoy (MPEG)

There is also a flash version. Please enjoy

There is a link to play the flash version but many people don't support flash in their browsers due to security concerns.


As you can see there are now three robotic arms.


This is a mess. There are (3) Arduino Uno R3 driving three robotic arms with power supplied from a common bus (in this case the breadboard.) It was something that was always a bad idea for more than initial testing and I'm using (6) digital I/O ports on each Arduino. That is a lot of jumper wiring.



Instead of the breadboard spaghetti (see image above) I decided that the PCA9685 was how I could simplify everything. I will be communicating with the servo controller via i2c. This is a 16-channel version of the servo controller. It can handle up to 8A safely so I'm fine with that. All I need to add now is a cable running from the bench power supply to the servo controller to provide "Servo Power" (V+) 6V @ 5A (dialed-in settings on the bench supply.)

I will be using (3) of them, one for each robotic arm unit. The servo controller has it's own clock so all your servers will hold their position as you have defined it in the software.

I had ordered (4) clone boards of the Adafruit PCA9685 driver board and none of them seem to work. I can't get the green LED to illuminate (V+) I just ordered a genuine Adafruit version.


I got the Adafruit PCA9685 and plugged in some power and some servos and it simply works.


This has been the most useful item I have located in awhile. I tested about 8 servos, all chinese "Tower Pro" MG996 servos. Of the 6-servos that came with the last arm kit, only one has not failed yet. The symptom is the servo simply locks up. Sometimes you can get it started again by smacking it against the top of the lab bench. I advise now do not buy chinese servos until they get the quality problem solved. By using the above I was able to quickly locate the bad servos. Honestly, 5 of 6 servers included with Arm #3 kit failed within 4 hours of running the test code below.


I am trying to return all the parts that did not work and/or were not documented from this vendor I bought on eBay. I have already opened a return but they are being difficult. I am going to return Arm kit #3 because other than the metal (aluminum) pieces, the servo wheels and only a tiny part of the hardware it has all been useless. I say only a tiny part of the hardware was useful because the included a lot of hardware that was not supposed to be used (stainless steel screws only for countersunk holes, of which there are none.) I had to use a lot of my own hardware to get the arm completed. I did not use any of the chinese servos, but used Hexfly servos.

When I was about to initiate the return process for Arm kit #3 I tested all the chinese servos (that came with the kit.) I did not use and all but one failed within 4-hours of testing. Completely lock up frozen.

#include <Adafruit_PWMServoDriver.h>

  This is an example for our Adafruit 16-channel PWM & Servo driver
  Servo test - this will drive 8 servos, one after the other on the
  first 8 pins of the PCA9685

  Pick one up today in the adafruit shop!

  These drivers use I2C to communicate, 2 pins are required to  

  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// called this way, it uses the default address 0x40
// Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// you can also call it with a different address you want
// Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
// you can also call it with a different address and I2C interface
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(&Wire, 0x40);

// Depending on your servo make, the pulse width min and max may vary, you 
// want these to be as small/large as possible without hitting the hard stop
// for max range. You'll have to tweak them as necessary to match the servos you
// have!
#define SERVOMIN  150 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  600 // this is the 'maximum' pulse length count (out of 4096)

// our servo # counter
uint8_t servonum = 0;

void setup() {
  Serial.println("16-channel Servo test!");


  pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates


// you can use this function if you'd like to set the pulse length in seconds
// e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. its not precise!
void setServoPulse(uint8_t n, double pulse) {
  double pulselength;

  pulselength = 1000000;   // 1,000,000 us per second
  pulselength /= 60;   // 60 Hz
  Serial.print(pulselength); Serial.println(" us per period"); 
  pulselength /= 4096;  // 12 bits of resolution
  Serial.print(pulselength); Serial.println(" us per bit"); 
  pulse *= 1000000;  // convert to us
  pulse /= pulselength;
  pwm.setPWM(n, 0, pulse);

void loop() {
  // Drive each servo one at a time
  for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
    pwm.setPWM(servonum, 0, pulselen);

  for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
    pwm.setPWM(servonum, 0, pulselen);

// We have 16-channels
  servonum ++;
  if (servonum > 16) servonum = 0;


Yesterday I started testing the Arduino Sensor Shield v5.0 and it is all I need for now to drive the robotic arm. It allows me to attach all the servo cables directly (up to 14 of them) and I can use my code that does movements in one degree intervals which makes servo movement a lot smoother. In addition since I am not using the i2c PCA9685 I can still read servo position. This last fact is what made me find another solution for the robotic arm as I need to be able to read that value all the time.


I had to use stacking headers because the Arduino acrylic case did not let me get the shield seated very well.

For awhile I had (3) separate wiki pages for the (3) arm units but I combined them all today. In case all of this is confusing I have (3) robotic arm units exactly alike with mostly Hexfly servos. I am working on finding the best way to control them. So you will know (and so I will as well) I labeled each Arm Unit #1, @2, #3.


I ordered these cards a long time ago from China. They finally arrived today.

[681991.847526] usb 2-1.7: new full-speed USB device number 5 using ehci-pci
[681991.943376] usb 2-1.7: New USB device found, idVendor=0415, idProduct=0115
[681991.943383] usb 2-1.7: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[681991.943388] usb 2-1.7: Product: RTrobot Servo Controller
[681991.943391] usb 2-1.7: Manufacturer: RTrobot
[681991.943395] usb 2-1.7: SerialNumber: 48E26F373036
[681991.943923] cdc_acm 2-1.7:1.0: This device cannot do calls on its own. It is not a modem.
[681991.943969] cdc_acm 2-1.7:1.0: ttyACM0: USB ACM device

Command Examples

Servo Moves
Format: # <ch> P <pw> … # <ch> P <pw> T <time> \n\r

<ch> = Servo number, range 1~32 (decimal number)
<pw> = Pulse width (servo position), range: 500~2500. Unit: us (microseconds)
<time> = Time used to move to the position, effective for all servos.
\ n \ r = Binary number 0x0d, 0x0a (carriage return), the command terminator



Move Servo 8 to pulse width 600us, using time 1000 microseconds The greater the value the slower the servo will move.


Move Servo 11 to pulse width 2000us, Servo 30 to pulse width 2500us, using time 1500ms (1.5s.) The servo's speed depends on the steering location of the previous time.Servo.11 and Servo 30 arrive at the designated location at the same time.

Initiate a servo group action


The value G1 selects the servo group number.
The value of F3 says run 3-times. Frequency.

I can't seem to find any documentation on this board but I should be able to reverse engineer it well enough.

Controlling Robotic Arm Unit with potentiometers (6-DOF)

I finally had a chance to get this wired up and tested today. I wrote some new code as well which will be included.


The code is very simple. I make use of (6) analog inputs on the Arduino Uno to read the values of (6) 10-K potentiometers. Each values is used to position the corresponding servo motor. I make use of the standard Arduino Servo library #include <Servo.h>

#include <Servo.h> 

Servo base, joint3, joint2, joint1, wrist, jaws ; // 6-DOF

// Specify analog input ports

int baseIn= 0; 
int joint3In = 1;  
int joint2In = 2;  
int joint1In = 3;  
int wristIn = 4; 
int jawsIn = 5; 

int baseVal, joint3Val, joint2Val, joint1Val, wristVal, jawsVal = 0;

void setup() 

  // attach servos


void loop() 

  // Read the Potentiomers with a .2 sec delay 
    baseVal = analogRead(baseIn);
    joint3Val = analogRead(joint3In);
    joint2Val = analogRead(joint2In);
    joint1Val = analogRead(joint1In);
    wristVal = analogRead(wristIn);
    jawsVal = analogRead(jawsIn);

 // for debugging comment out if not troubleshooting.
  Serial.print("Pot 1:");
  Serial.print(" ");
  Serial.print("Pot 2:");
  Serial.print(" ");
  Serial.print("Pot 3:");
  Serial.print(" ");
  Serial.print("Pot 4:");
  Serial.print(" ");
  Serial.print("Pot 5:");
  Serial.print(" ");

  // Range is 0-180 
  baseVal = map(baseVal, 0, 1023, 0, 180); 
  joint3Val = map(joint3Val, 0, 1023, 0, 180); 
  joint2Val = map(joint2Val, 0, 1023, 0, 180); 
  joint1Val = map(joint1Val, 0, 1023, 0, 180);
  wristVal = map(wristVal, 0, 1023, 0, 180);
  jawsVal = map(jawsVal, 0, 1023, 0, 180);

  // This needs to be re-coded to move more smoothly. 


Robotic Tank with Robotic Arm Unit #2


This is the controller. I can't seem to find any documentation matching this one in English.


The TP-LINK WR792N has OpenWRT installed but they have changed the password and it isn't documented. I am trying to get the password from the manufacturer. DOIT.AM team in Shenzen, China.

root@spectral:~# nmap -q

Starting Nmap 6.49BETA4 ( ) at 2018-10-03 19:40 MDT
Nmap scan report for OpenWrt.lan (
Host is up (0.0016s latency).
Not shown: 994 closed ports
22/tcp   open  ssh
53/tcp   open  domain
80/tcp   open  http
8080/tcp open  http-proxy
9001/tcp open  tor-orport
9002/tcp open  dynamid
MAC Address: 30:B4:9E:70:80:1F (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 96.30 seconds

The camera is 720P here is a screenshot of my browser attached to the TP-Link AP streaming live video from port 8080.