ACEBOTT ESP32-Powered Robotic Arm with Joystick, App & Web Control

ACEBOTT ESP32-Powered Robotic Arm with Joystick, App & Web Control

In this project, we are gonna introduce one of the best 4DOF Robot Arm kits powered by the ESP32. This robot arm is really fun to play with, and we can control it in several cool ways, like joystick module control, web-based control, mobile app control, and even automatic mode. My favorite method is the joystick module control. It feels just like operating a mini excavator, which makes it super fun and satisfying to use. This robot arm is also easy to assemble and program. If you’re a beginner, you can use ACECode, a block-based platform. I personally used the Arduino IDE because I’m more familiar with it, but you can choose whichever platform suits you best.

Alright, let’s assemble this robot arm step by step. You can also follow the ACEBOTT instruction guide for help. You can buy this Robot arm using the following links.

  • ACEBOTT Website — Buy
  • Amazon — Buy

Step 1

Firstly, unbox the robot arm kit and take a moment to identify all the components inside the box.

Step 2

Secondly, peel off the protective stickers from all the acrylic parts.

Step 3

Thirdly, mount the ESP32 controller board onto the base part.

Step 4

Next, attach the side parts of the robot arm to the base.

Step 5

Now, connect the Dupont wires to the joystick modules and mount them onto the acrylic plate. Make sure the wires are connected to the correct pins, usually GND, VCC, X, Y, and SW. After that, plug the other ends of the wires into the ESP32 controller board.

Step 6

Afterward, install the joystick module setup onto the main base.

Step 7

Now, install the chassis servo onto the chassis servo mounting plate and connect the pins so you can easily drive the steering disk. Then, attach the servo horn to the steering disk

Step 8

Next, install the disk bracket onto the steering disk setup. Then, connect the chassis servo motor’s signal wire to the GPIO5 pin on the ESP32. Power up the controller board to set the servo to its 90-degree position. After the servo is centered, install it on the chassis servo.

Step 9

Now, install the shoulder brackets onto the side panels.

Step 10

Afterward, install the two servo motors onto the other shoulder bracket. Then, carefully route the servo wires through the chassis disk to keep everything neat. Finally, connect the servo wires to GPIO16 and GPIO17 on the ESP32, and set them to 90 degrees for proper calibration.

Step 11

Now, connect the servo-driven arm to the other arm part.

Step 12

Afterward, install the left paw structure of the robot arm.

Step 13

Next, install the left paw structure of the robot arm.

Step 14

Now, install the servo motor onto the claws servo mounting plate. Then, connect this servo to GPIO18 on the ESP32 and set it to 90 degrees to center it properly. Afterward, attach both the left and right paws to the servo horn and the opposite side of the bracket. Make sure the claws open and close smoothly.

Step 15

Next, connect the servo horn to the elbow bracket. Afterward, attach the elbow bracket to the shoulder servo.

Step 16

Now, connect the servos to the ESP32 as follows:

  • Chassis servo → GPIO5
  • Shoulder servo → GPIO16
  • Elbow servo → GPIO17
  • Claws servo → GPIO18

Step 17

Next, fix the base of this robot arm. Then, install the battery holder and connect the power jack to the controller board.

Step 18

Now, install the non-slip mat on the bottom side of the robot arm base. Then, connect the controller board to your computer using a USB cable.

OK, now let’s upload the programs one by one and test each part.

Robot Arm Stacking

OK, now let’s copy and paste the following program into the Arduino IDE. Before uploading, make sure to include the required libraries.

#include <ACB_ARM.h>//Add the Robot arm libraries
ACB_ARM ARM;

bool RunningState = true;

int startx = 7, starty = 13, startz = 2;//Initial coordinates
int midz = 15;//Height of middle point
int endx = -7, endy = 13, endz = 0;//End point coordinates
int openAngle = 130, closeAngle = 90;
int count = 2;//Number of blocks
int i = 0;

void setup() {
  ARM.Chassis_angle_adjust(8);//Chassis error calibration
  ARM.Slight_adjust(0,2);//Small calibration error
  ARM.ARM_init(5,16,17,18);//The parameters are four Servo pins
  Serial.begin(115200);
}

void loop() {
  while(i < count) {
    ARM.ClawsCmd(openAngle);//open claws
    delay(1000);
    ARM.PtpCmd(startx, starty, startz-i*2);//The target point is the upper object
    delay(1000);
    ARM.ClawsCmd(closeAngle);//close claws
    delay(1000);
    ARM.PtpCmd(startx, starty, midz);//Lift the object after picking it up
    delay(1000);
    ARM.PtpCmd(endx, endy, midz);//Rotate above the target point
    delay(1000);
    ARM.PtpCmd(endx, endy, endz+i*2);//Placing Objects
    delay(1000);
    ARM.ClawsCmd(openAngle);
    delay(1000);
    ARM.PtpCmd(endx, endy, midz);//Raise arms
    delay(1000);
    i = i + 1;
  }
  ARM.Zero();//Servo initialization
}
  • Now, select the board and port. After, click the upload button.
  • After uploading the code, remove the USB cable from the controller board. Then, insert the 18650 Li-ion batteries into the battery holder. Finally, power on the robot arm using the battery switch. Now you can test Your robot arm using the blocks.

JoyStick Controlled Robot Arm

Copy and paste the following program into the Arduino IDE. Before uploading, make sure to include the required libraries.

#include <ACB_ARM.h>//Add the Robot arm libraries
ACB_ARM ARM;

void setup() {
  ARM.ARM_init(5,16,17,18);//The parameters are four Servo pins
  ARM.JoyStick_init(32,33,34,35,36,39); // Joystick initialization
  
}
void loop() {
  ARM.get_JoyStick();
  if (ARM.JoyY1 < 50) {//chassis left
    ARM.chassis_angle = ARM.chassis_angle + 1;
    ARM.JoyChassisCmd(ARM.chassis_angle);
  }
  if (ARM.JoyY1 > 3500) {//chassis right
    ARM.chassis_angle = ARM.chassis_angle - 1;
    ARM.JoyChassisCmd(ARM.chassis_angle);
  }
  if (ARM.JoyX1 < 50) {//Shoulder down
    ARM.shoulder_angle = ARM.shoulder_angle + 1;
    ARM.JoyShoulderCmd(ARM.shoulder_angle);
  }
  if (ARM.JoyX1 > 4000) {  // Shoulder up
    ARM.shoulder_angle = ARM.shoulder_angle - 1;
    ARM.JoyShoulderCmd(ARM.shoulder_angle);
  }

  if (ARM.JoyX2 < 50) { // Elbow up 
    ARM.elbow_angle =  ARM.elbow_angle + 1;
    ARM.JoyElbowCmd(ARM.elbow_angle);
  }
  
  if (ARM.JoyX2 > 4000) { // Elbow dwon 
    ARM.elbow_angle =  ARM.elbow_angle - 1;
    ARM.JoyElbowCmd(ARM.elbow_angle);
  }

  if (ARM.JoyY2 > 4000) { // Claws open
    ARM.claws_angle = ARM.claws_angle + 1;
    ARM.JoyClawsCmd(ARM.claws_angle);
  }

  if (ARM.JoyY2 < 50) {  // Claws close
    ARM.claws_angle = ARM.claws_angle - 1;
    ARM.JoyClawsCmd(ARM.claws_angle);
  }

}
  • Now, select the board and port. After, click the upload button.
  • Once the code is uploaded, you can control your robot arm using the joysticks.

Web Controlled Robot Arm

Copy and paste the following program into the Arduino IDE. Before uploading, make sure to include the required libraries.

#include <ACB_ARM.h>
#include <WiFi.h>

#define FIRMWARE_VERSION "ACB_ARM V2.0"

ACB_ARM ARM;

// WiFi user name and password
const char* ssid = "Robot_Arm";
const char* password = "12345678";

int Chassis_input, Shoulder_input, Elbow_input, Claws_input;
int Chassis_slide, Shoulder_slide, Elbow_slide, Claws_slide;
int PTPX,PTPY,PTPZ;
bool record = false;

void setup() {    // initialize
  
  Serial.begin(115200);  // set the baud rate to 115200

  ARM.Chassis_angle_adjust(8);  // Default 0
  ARM.Slight_adjust(0,2);   // Default 0,0
  ARM.ARM_init(5,16,17,18); // The parameters are four Servo pins
  ARM.JoyStick_init(32,33,34,35,36,39); // Joystick initialization

  WiFi.setTxPower(WIFI_POWER_19_5dBm);  // Set the transmit power of WiFi
  WiFi.mode(WIFI_AP); // Set WiFi mode to AP (Access Point) mode
  WiFi.softAP(ssid, password, 9); // Set the WiFi hotspot name and password, and enable AP mode
  IPAddress myIP = WiFi.softAPIP(); // Obtain the IP address of the AP mode
  Serial.print("AP IP address: ");
  Serial.println(myIP); // address: 192.168.4.1
  
  ARM.startWebServer();
}

void loop() {
  //---------------------JoyStick---------------------
  handleJoystick();

  //---------------------  W E B  --------------------
  // NULL
  if (ARM.val == 3){

  }

  // button
  else if (ARM.val == 1){
    ARM.web_claw_x();
  } else if (ARM.val == 2){
    ARM.web_claw_y();
  } else if (ARM.val == 4){
    ARM.web_turn_x();
  } else if (ARM.val == 5){
    ARM.web_turn_y();
  } else if (ARM.val == 6){
    ARM.web_lower_arm_x();
  } else if (ARM.val == 7){
    ARM.web_lower_arm_y();
  } else if (ARM.val == 8){
    ARM.web_upper_arm_x();
  } else if (ARM.val == 9){
    ARM.web_upper_arm_y();
  }

  // Slide input
  else if (ARM.val == 21) {         // chassis
    Chassis_input = ARM.Chassis_Silde_Angle;
    ARM.ChassisCmd(Chassis_input);  
    ARM.chassis_angle = Chassis_input;
  } else if (ARM.val == 22) {         // shoulder
    Shoulder_input = ARM.Shoulder_Silde_Angle;
    ARM.ShoulderCmd(Shoulder_input);  
    ARM.shoulder_angle = Shoulder_input;
  } else if (ARM.val == 23) {         // elbow
    Elbow_input = ARM.Elbow_Silde_Angle;
    ARM.ElbowCmd(Elbow_input);  
    ARM.elbow_angle = Elbow_input;
  } else if (ARM.val == 24) {         // claws
    ARM.Speed(50);
    Claws_input = ARM.Claws_Silde_Angle;
    ARM.ClawsCmd(Claws_input); 
    ARM.claws_angle = Claws_input; 
  } 

  // Silde control
  else if (ARM.val == 25) {         // chassis
    Chassis_slide = ARM.Chassis_Silde_Angle;
    ARM.JoyChassisCmd(Chassis_slide);  
    ARM.chassis_angle = Chassis_slide;
  } else if (ARM.val == 26) {         // shoulder
    Shoulder_slide = ARM.Shoulder_Silde_Angle;
    ARM.JoyShoulderCmd(Shoulder_slide);  
    ARM.shoulder_angle = Shoulder_slide;
  } else if (ARM.val == 27) {         // elbow
    Elbow_slide = ARM.Elbow_Silde_Angle;
    ARM.JoyElbowCmd(Elbow_slide);  
    ARM.elbow_angle = Elbow_slide;
  } else if (ARM.val == 28) {         // claws
    Claws_slide = ARM.Claws_Silde_Angle;
    ARM.JoyClawsCmd(Claws_slide);  
    ARM.claws_angle = Claws_slide; 
  } 

  // Mode control
  else if (ARM.val == 31 && record) {         // save
    ARM.saveState();
    delay(200);
    ARM.val = 3;
  } else if (ARM.val == 32) {         // end Record
    record = true;
  } else if (ARM.val == 33) {         // start Record
    record = false;
  } else if (ARM.val == 34 && !record) {         // Run
    ARM.executeStates();
    delay(200);
  } else if (ARM.val == 55 && !record) {         // Run
    ARM.executeStates();
    delay(200);
  } else if (ARM.val == 35 && !record) {         // Reset
    ARM.clearSavedStates();
    delay(200);
    ARM.val = 3;
  } 

  // Mode select 1-6
  else if (ARM.val == 40) {           // 0
    ARM.mode = 0;
  } else if (ARM.val == 41) {         // 1
    ARM.mode = 1;
  } else if (ARM.val == 42) {         // 2
    ARM.mode = 2;
  } else if (ARM.val == 43) {         // 3
    ARM.mode = 3;
  } else if (ARM.val == 44) {         // 4
    ARM.mode = 4;
  } else if (ARM.val == 45) {         // 5
    ARM.mode = 5;
  } else if (ARM.val == 46) {         // 6
    ARM.mode = 6;
  }
  
  // Spatial coordinate
  else if (ARM.val == 51) {         // x
    PTPX = ARM.PTP_X;
  } else if (ARM.val == 52) {         // y
    PTPY = ARM.PTP_Y;
  } else if (ARM.val == 53) {         // z
    PTPZ = ARM.PTP_Z;
  } else if (ARM.val == 54) {         // ptp
    ARM.PtpCmd(PTPX,PTPY,PTPZ);
    delay(100);
    ARM.val = 3;
  }

}

void handleJoystick() {
  ARM.get_JoyStick();

  if (ARM.JoyY1 < 50) {  // chassis left
    ARM.chassis_angle = ARM.chassis_angle + 1;
    ARM.JoyChassisCmd(ARM.chassis_angle);
  }

  if (ARM.JoyY1 > 3500) { // chassis right
    ARM.chassis_angle = ARM.chassis_angle - 1;
    ARM.JoyChassisCmd(ARM.chassis_angle);
  }

  if (ARM.JoyX1 < 50) {  // Shoulder down
    ARM.shoulder_angle = ARM.shoulder_angle + 1;
    ARM.JoyShoulderCmd(ARM.shoulder_angle);
  }

  if (ARM.JoyX1 > 4000) {  // Shoulder up
    ARM.shoulder_angle = ARM.shoulder_angle - 1;
    ARM.JoyShoulderCmd(ARM.shoulder_angle);
  }

  if (ARM.JoyX2 < 50) { // Elbow up 
    ARM.elbow_angle = ARM.elbow_angle + 1;
    ARM.JoyElbowCmd(ARM.elbow_angle);
  }
  
  if (ARM.JoyX2 > 4000) { // Elbow dwon 
    ARM.elbow_angle = ARM.elbow_angle - 1;
    ARM.JoyElbowCmd(ARM.elbow_angle);
  }

  if (ARM.JoyY2 > 4000) { // Claws open
    ARM.claws_angle = ARM.claws_angle + 1;
    ARM.JoyClawsCmd(ARM.claws_angle);
  }

  if (ARM.JoyY2 < 50) {  // Claws close
    ARM.claws_angle = ARM.claws_angle - 1;
    ARM.JoyClawsCmd(ARM.claws_angle);
  }
}

  • Now, select the board and port in the Arduino IDE. Once the upload is complete, open the Serial Monitor by going to Tools > Serial Monitor. You should see the IP address of your robot arm displayed there.
  • Then, connect to the robot arm’s hotspot using your phone. Next, open your favorite browser and enter the IP address you saw in the Serial Monitor. You should now see the web interface for controlling your robot arm! From there, you can control the arm’s movements directly from your phone’s browser.

APP Controlled Robot Arm

Copy and paste the following program into the Arduino IDE. Before uploading, make sure to include the required libraries.

#include <ACB_ARM.h>
#include <WiFi.h>

#define FIRMWARE_VERSION "ACB_ARM V2.1 20240925"

ACB_ARM ARM;

// WiFi user name and password
const char* ssid = "Robot_Arm";
const char* password = "12345678";

int Chassis_input, Shoulder_input, Elbow_input, Claws_input;
int Chassis_slide, Shoulder_slide, Elbow_slide, Claws_slide;
int PTPX,PTPY,PTPZ;
bool record = false;

void setup() {    // initialize
  
  Serial.begin(115200);  // set the baud rate to 115200

  ARM.Chassis_angle_adjust(8);  // Default 0
  ARM.Slight_adjust(0,2);   // Default 0,0
  ARM.ARM_init(5,16,17,18); // The parameters are four Servo pins
  ARM.JoyStick_init(32,33,34,35,36,39); // Joystick initialization

  WiFi.setTxPower(WIFI_POWER_19_5dBm);  // Set the transmit power of WiFi
  WiFi.mode(WIFI_AP); // Set WiFi mode to AP (Access Point) mode
  WiFi.softAP(ssid, password, 9); // Set the WiFi hotspot name and password, and enable AP mode
  IPAddress myIP = WiFi.softAPIP(); // Obtain the IP address of the AP mode
  Serial.print("AP IP address: ");
  Serial.println(myIP); // address: 192.168.4.1
  
  ARM.startAppServer();
}

void loop() {
  //---------------------JoyStick---------------------
  handleJoystick();

  //---------------------  A P P  --------------------
  // NULL
  if (ARM.val == 3){

  }

  // speed
  // else if (ARM.val == 20) {         // speed
  //   ARM.Speed(50);  
  // } 
  
  // Slide input
  else if (ARM.val == 21) {         // chassis
    Chassis_input = ARM.Chassis_Silde_Angle;
    ARM.ChassisCmd(Chassis_input);  
    ARM.chassis_angle = Chassis_input;
    ARM.getPositon();
    ARM.val = 3;
  } else if (ARM.val == 22) {         // shoulder
    Shoulder_input = ARM.Shoulder_Silde_Angle;
    ARM.ShoulderCmd(Shoulder_input);  
    ARM.shoulder_angle = Shoulder_input;
    ARM.getPositon();
    ARM.val = 3;
  } else if (ARM.val == 23) {         // elbow
    Elbow_input = ARM.Elbow_Silde_Angle;
    ARM.ElbowCmd(Elbow_input);  
    ARM.elbow_angle = Elbow_input;
    ARM.getPositon();
    ARM.val = 3;
  } else if (ARM.val == 24) {         // claws
    Claws_input = ARM.Claws_Silde_Angle;
    ARM.ClawsCmd(Claws_input); 
    ARM.claws_angle = Claws_input; 
    ARM.getPositon();
    ARM.val = 3;
  } 

  // Silde control
  else if (ARM.val == 25) {         // chassis
    Chassis_slide = ARM.Chassis_Silde_Angle;
    ARM.JoyChassisCmd(Chassis_slide);  
    ARM.chassis_angle = Chassis_slide;
    ARM.getPositon();
    ARM.val = 3;
  } else if (ARM.val == 26) {         // shoulder
    Shoulder_slide = ARM.Shoulder_Silde_Angle;
    ARM.JoyShoulderCmd(Shoulder_slide);  
    ARM.shoulder_angle = Shoulder_slide;
    ARM.getPositon();
    ARM.val = 3;
  } else if (ARM.val == 27) {         // elbow
    Elbow_slide = ARM.Elbow_Silde_Angle;
    ARM.JoyElbowCmd(Elbow_slide);  
    ARM.elbow_angle = Elbow_slide;
    ARM.getPositon();
    ARM.val = 3;
  } else if (ARM.val == 28) {         // claws
    Claws_slide = ARM.Claws_Silde_Angle;
    ARM.JoyClawsCmd(Claws_slide);  
    ARM.claws_angle = Claws_slide; 
    ARM.getPositon();
    ARM.val = 3;
  } 

  // Mode control
  else if (ARM.val == 31 && record) {         // save
    ARM.saveState();
    delay(200);
    ARM.val = 3;
  } else if (ARM.val == 32) {         // end Record
    record = true;
  } else if (ARM.val == 33) {         // start Record
    record = false;
  } else if (ARM.val == 34 && !record) {         // Run
    ARM.executeStates();
    delay(200);
    ARM.val = 3;
  } else if (ARM.val == 55 && !record) {         
    ARM.executeStates();
    delay(100);
  } else if (ARM.val == 35 && !record) {         // Reset
    ARM.clearSavedStates();
    delay(200);
    ARM.val = 3;
  } 

  // Mode select 1-6
  else if (ARM.val == 40) {           // 0
    // ARM.mode = 0;
  } else if (ARM.val == 41) {         // 1
    ARM.mode = 1;
  } else if (ARM.val == 42) {         // 2
    ARM.mode = 2;
  } else if (ARM.val == 43) {         // 3
    ARM.mode = 3;
  } else if (ARM.val == 44) {         // 4
    ARM.mode = 4;
  } else if (ARM.val == 45) {         // 5
    ARM.mode = 5;
  } else if (ARM.val == 46) {         // 6
    ARM.mode = 6;
  }
  
  else if (ARM.val == 54) {         // ptp
    ARM.PtpCmd(ARM.PTP_X,ARM.PTP_Y,ARM.PTP_Z);
    
  }

  //zero
  else if (ARM.val == 60) {         // x
    ARM.Zero();
  }

}

void handleJoystick() {
  ARM.get_JoyStick();

  if (ARM.JoyY1 < 50) {  // chassis left
    ARM.chassis_angle = ARM.chassis_angle + 1;
    ARM.JoyChassisCmd(ARM.chassis_angle);
  }

  if (ARM.JoyY1 > 3500) { // chassis right
    ARM.chassis_angle = ARM.chassis_angle - 1;
    ARM.JoyChassisCmd(ARM.chassis_angle);
  }

  if (ARM.JoyX1 < 50) {  // Shoulder down
    if (ARM.limit_z > 0 ){
      ARM.shoulder_angle = ARM.shoulder_angle + 1;
    }
    ARM.JoyShoulderCmd(ARM.shoulder_angle);
  }

  if (ARM.JoyX1 > 4000) {  // Shoulder up
    ARM.shoulder_angle = ARM.shoulder_angle - 1;
    ARM.JoyShoulderCmd(ARM.shoulder_angle);
  }

  if (ARM.JoyX2 < 50) { // Elbow up 
    
    ARM.elbow_angle = ARM.elbow_angle + 1;
    ARM.JoyElbowCmd(ARM.elbow_angle);
  }
  
  if (ARM.JoyX2 > 4000) { // Elbow dwon 
    if (ARM.limit_z > 0 ){
      ARM.elbow_angle = ARM.elbow_angle - 1;
    }
    ARM.JoyElbowCmd(ARM.elbow_angle);
  }

  if (ARM.JoyY2 > 4000) { // Claws open
    ARM.claws_angle = ARM.claws_angle + 1;
    ARM.JoyClawsCmd(ARM.claws_angle);
  }

  if (ARM.JoyY2 < 50) {  // Claws close
    ARM.claws_angle = ARM.claws_angle - 1;
    ARM.JoyClawsCmd(ARM.claws_angle);
  }
}

  • Now, select the board and port. After, click the upload button.
  • Then, download and install the ACEBOTT app from the Play Store or App Store. Once installed, connect your phone to the robot arm’s hotspot just like before. Now, open the app and you’ll be able to control your robot arm straight from your phone! Ok, enjoy your robot arm. The full video guide is below. So, we hope to see you in the next project.

ACEBOTT ESP32-Powered Robotic Arm with Joystick, App & Web Control

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *