Building a Mobile Robot with an Integrated Robotic Arm Using Arduino and Bluetooth Control

In this tutorial, we’ll learn how to build the mobile robot arm Arm, a Bluetooth-controlled robot with a robotic arm, both controlled wirelessly via a custom Android app. The Arm combines mobility and manipulation, allowing it to move around and interact with objects. This guide covers everything from designing, assembling the Arm robot, wiring the electronics, programming the Arduino, and developing an intuitive app using MIT App Inventor.

 

Mobile robot arm OmObiArm showcasing its gripping mechanism, holding a toy car, designed with Arduino and 3D-printed componen

 

The mobile robot Arm is an upgraded project that combines two of our previous builds: a Bluetooth-controlled mobile robot, and the Arm, a 6-DOF robotic arm. Mounted on a mobile platform, the Arm can be controlled wirelessly using sliders in the app to move each axis of the arm. Additionally, the “Save” button allows recording specific positions, enabling the robot to execute automated tasks by replaying these steps. This versatile integration is perfect for DIY enthusiasts, offering a hands-on approach to robotics and automation.

 

Components Needed:

To build the Arm, you will need the following components:

3D-printed parts: Chassis and Arduino holder and robotic arm parts.

Chassis: Houses the motors, sensors, and Arduino board. - BUY NOW

Arduino Holder: Mounts the Arduino securely to the chassis. - BUY NOW 
 

Motors and wheels: 4 DC motors with gearboxes and 4 wheels.


4 DC Motors with Gearboxes: Drive the robot. - BUY NOW

 

Electronics: Adafruit Motor Shield V1.2, Arduino Mega, - BUY NOW

HC-05 Bluetooth Module,PCA9685 servo driver, LM2596 DC-DC Step-Down Module.

 

Servos: 3 SG90 Micro Servos. -BUY NOW

3 MG996R Servos - BUY NOW

 

Accessories: Jumper wires, screws, Inserts, a battery, and a smartphone with the MIT App Inventor app installed.

Jumper Wires: For connecting components.- BUY NOW

Screws and Inserts: To securely mount parts.

Battery (e.g., 7.4V LiPo): Powers the robot.

Power Switch: Optional - BUY NOW

 

Step 1: Arm 3D Model Design for the Mobile Robot Arm

The first step in this project is combining designs from the previous and Arm projects. Using Autodesk Inventor, we modified the base of the Arm and merged it with the top plate (lid) design from the to create a platform that securely mounts the robotic arm onto the mobile chassis. This integration ensures that the Arm is both functional and stable.

 

Step 2: 3D Printing the Robotic Parts

After finalizing the design, we moved on to 3D printing the components. Using a 3D printer like the Creality Ender 3, we printed all the parts for the robotic arm and the mobile platform. The designs were carefully optimized for easy assembly and robustness, forming the foundation of a stable and reliable Arm platform.

 

Step 3: Assembling the Robot

1. Mounting the Motors and Wheels

Attach the Motors
Secure the DC motors to the 3D-printed motor mounts using screws inserts and nuts. Make sure they are firmly attached to prevent any misalignment during movement.

Mount the Wheels
Attach the wheels to the motor shafts and ensure they are tightly fixed. Test for smooth rotation and proper alignment.

2. Mounting the Arduino, Motor Shield, PCA9685, LM2596 step-down converter and HC-05 Bluetooth Module

Attach the Arduino Holder
Secure the 3D-printed Arduino holder to the mobile chassis using screws.

Mount the Arduino and Motor Shield
Place the Arduino Uno in the holder and secure it with screws.
Attach the Adafruit Motor Shield on top of the Arduino Uno, ensuring all pins are correctly aligned and connected.
Fix the PCA9685, LM2596 step-down converter and HC-05 Bluetooth Module
Use zip ties or double-sided tape to fix the PCA9685 servo driver, LM2596 step-down converter and the HC-05 Bluetooth module onto the chassis.

3. Fixing the Top Plate and Robotic Arm Base

Attach the top plate, which serves as the robotic arm base, onto the moving platform. Use screws to secure it firmly. This provides a stable foundation for the robotic arm.

4. Assembling the Robotic Arm

 

Step 1: Securing the Servo Motor on the Base
Install the first servo motor onto the robotic arm’s base using M3x12 screws.
Add a 6806ZZ ball bearing (30x42x7mm) to reduce friction and enhance smooth rotation.
Attach the servo horn to the rotating upper part and secure it with M2x12 screws. Ensure the connection is tight and aligned.
Step 2: Mounting Servo Horns to Robot Arm Links
Align the servo horns with the arm links’ attachment points. Secure them with screws, tightening them firmly to prevent slippage.

Step 3: Mounting Servo Motors to Arm Links
Align the servo motors with the mounting points on the arm links. Secure them using screws, ensuring a tight and stable fit. Test the stability by gently moving the links.

Step 4: Connecting the Arm Links
Align the links and connect them using screws through the servo horns. Double-check that the joints move smoothly and are securely fastened.

Step 5: Assembling the Gripper
Attach the gripper to the end link of the robotic arm using M3x20 screws. Verify that the gripper operates smoothly and integrates seamlessly with the rest of the arm.

5. Final Checks

Once the robotic arm and mobile platform are fully assembled, test all components for stability and smooth operation. Ensure that the motors, servos, and gripper are functioning as expected before proceeding to the electronic wiring and programming phase.

 

Step 4: Wiring the Components

Wiring the components properly is essential for the functionality and safety of this Bluetooth-controlled robot project. The following steps guide you through the connections:

1. Connecting the Motors to the Motor Shield

Attach the left motors to the terminals labeled M1 and M2 on the Adafruit Motor Shield.Attach the right motors to the terminals labeled M3 and M4.

2. Powering the System with a 7.4V 2S LiPo Battery

Use a 7.4V 2S LiPo battery with 5300mAh capacity and an EC3 connector.Solder a compatible EC3 plug to the input of the circuit.Add a switch between the battery and the circuit to easily control power flow.

3. Using the LM2596 DC-DC Step-Down Converter

Connect the battery in parallel to the LM2596 step-down converter.Adjust the potentiometer on the converter to step down the voltage to 6V, which will power the PCA9685 servo driver board.Ensure the output is connected to the VCC and GND terminals on the PCA9685 board.

4. Powering the PCA9685 and Servos

It’s critical to use this independent power source (6V from the LM2596) to avoid overloading the Arduino’s onboard regulator.Connect each servo to the PCA9685 servo driver board, ensuring proper alignment of the signal, VCC, and GND pins.

6. Connecting the HC-05 Bluetooth Module

VCC to 5V on the Arduino Mega.GND to GND on the Arduino Mega.TXD to RX (Pin 0) on the Arduino Mega.RXD to TX (Pin 1) on the Arduino Mega.

6. Connecting the Adafruit Motor Shield to the Arduino

Place the Motor Shield securely onto the Arduino Mega, ensuring all pins are aligned and seated correctly.

7. Testing the Power Distribution

Verify all power connections, ensuring there is no short circuit.Check that the motors, servos, and HC-05 module are receiving the correct voltage as per their requirements.

Following these steps ensures that the robot is wired safely and efficiently, ready for programming and operation.

OmObiArm Wiring Diagram: Bluetooth-controlled robotic arm and mobile robot powered by Arduino with detailed circuit connectio

 

Step 5: Programming the Mobile Robot Arm for Bluetooth Control

In this step, we program the Arduino to control the robotic arm and the mobile platform via Bluetooth. The code is divided into logical sections for better understanding. Below, each block of code is given:

 

Step 6: Developing the ArmControl App for Bluetooth Control

The ArmControl App is a custom-built Android application designed to control the Arm platform wirelessly via Bluetooth. This intuitive app allows users to precisely control the robotic arm, save poses, and manage the movement of the mobile platform. Here’s how the app was developed step by step:

 

Key Features of the App

 

Bluetooth Connectivity:

The app connects to the HC-05 Bluetooth module attached to the robotic platform.Users can pair their device and establish a connection via the “Select Device” button.

 

Robotic Arm Control:

Six sliders control the arm’s joints, from the base to the gripper. Each slider sends position data to the corresponding servo motor in real-time.The app ensures smooth and precise movements of the robotic arm.

Mobile Platform Control:

Four directional buttons (Forward, Backward, Left, Right) manage the movement of the rover.A stop button halts all motor actions immediately.

Pose Management:

“Save” button stores the current arm position as a pose.“Play” initiates playback of saved poses, while “Reset” clears all saved configurations.A toggle switch enables or disables looped playback.

Feedback Display:

The app shows the connection status and the number of saved poses, ensuring clarity for the user.

Steps to Build the App

1. Bluetooth Connection Setup

ListPicker Before/After Picking:The app scans for available Bluetooth devices and displays them in a list. Once the user selects a device, the app attempts to connect.On successful connection, the app updates the interface to indicate a “Connected” status.

2. Arm Joint Control with Sliders

Six Sliders for Joint Movement:Each slider corresponds to one of the six servos of the robotic arm.When a slider is adjusted, the app sends the position as a command (e.g., 1,90\n for Servo 1 to move to 90°).This ensures precise manual control over each joint.

Bluetooth blocks for OmObiArm app showing slider functionality for servo control and Bluetooth connection setup.

3. Rover Movement Control

Directional Buttons:Each button corresponds to a movement direction for the mobile platform.Example:Forward: Sends F\n to move the rover forward.Backward: Sends B\n to move the rover backward.Left: Sends L\n, and Right: Sends R\n.The Stop button halts all movement with the S\n command.

Bluetooth button controls for OmObiArm app managing robot movement commands.

4. Pose Management

Save, Play, Reset, and Loop Playback:Save: Captures the current servo positions and sends v\n to the robot for storage.Play: Starts playback of stored poses with the l\n command.Reset: Clears all saved poses with the r\n command.Loop Playback: A toggle switch sends o\n for enabling loops or f\n to disable them.

5. Real-Time Feedback

The app dynamically updates the number of saved poses and provides visual feedback on Bluetooth connection status.

Control logic for managing pose saving, stopping, playing, resetting, and loop mode in OmObiArm app.

How It Works

Connecting to the Robot:

Open the app and click “Select Device.”Choose the HC-05 module from the list of available devices.Once connected, the status changes to “Connected.”

Controlling the Robotic Arm:

Use the sliders to move the robotic arm’s joints. Adjustments are sent to the robot in real-time.

Managing Poses:

Save poses with the “Save” button and play them back with “Play.”Enable looping for continuous playback using the toggle switch.

Driving the Rover:

Use directional buttons to move the rover and the Stop button to halt all actions immediately.

Step 7: Final Calibration and Testing

Connecting to the Robot:

Open the app and click “Select Device.”Choose the HC-05 module from the list of available devices.Once connected, the status changes to “Connected.”

Controlling the Robotic Arm:

Use the sliders to move the robotic arm’s joints. Adjustments are sent to the robot in real-time.

Managing Poses:

Save poses with the “Save” button and play them back with “Play.”Enable looping for continuous playback using the toggle switch.

Driving the Rover:

Use directional buttons to move the rover and the Stop button to halt all actions immediately.

Conclusion

The project demonstrates a comprehensive approach to robotics by combining mobility with manipulation, making it ideal for beginners and enthusiasts. The step-by-step guide covered 3D design, assembly, wiring, programming, and app development to achieve a fully functional, Bluetooth-controlled robot. This integration of the robotic arm and mobile platform provides hands-on experience in mechatronics, automation, and software development. In the next project, we plan to equip the Arm with four ultrasonic sensors to enable obstacle avoidance and object detection, allowing the arm to autonomously locate and grasp objects.

 

 

CODE
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <AFMotor.h>
 
// Constants and definitions
const int numServos = 6; // Number of servos
const int maxConfigurations = 10; // Maximum number of storable poses
const int stepDelay = 10; // Delay between each step to slow down the servo movement
const int stepSize = 1;   // The number of degrees to move per step
 
// Servo channels on the PCA9685
const int servoChannels[numServos] = {0, 4, 8, 9, 12, 13};
 
// Storage structures
int savedConfigurations[maxConfigurations][numServos];
int currentServoPositions[numServos] = {375, 375, 375, 375, 375, 375}; // Default positions
int configCount = 0;            // Counter for stored poses
bool isPlaying = false;         // Status indicating if poses are being played
bool loopPlayback = false;      // Status indicating if poses should be played in a loop
bool stopPlaying = false;       // Status indicating if playback should be stopped
int currentPoseIndex = 0;       // Index of the current pose during playback
 
// Motor instances for the rover
AF_DCMotor motor1(1);
AF_DCMotor motor2(2);
AF_DCMotor motor3(3);
AF_DCMotor motor4(4);
 
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
String input = ""; // Holds incoming Bluetooth data
 
void setup() {
  Serial.begin(9600); // Serial communication for Bluetooth
 
  // Initialize motors
  motor1.setSpeed(255);
  motor2.setSpeed(255);
  motor3.setSpeed(255);
  motor4.setSpeed(255);
 
  // Initialize servo controller
  pwm.begin();
  pwm.setPWMFreq(50); // Set frequency to 50 Hz for servos
 
  // Initialize servo positions
  for (int i = 0; i < numServos; i++) {
    pwm.setPWM(servoChannels[i], 0, currentServoPositions[i]);
  }
 
  Serial.println("Bluetooth Robot Controller ready. Waiting for commands...");
}
 
void loop() {
  // Process incoming commands
  if (Serial.available()) {
    input = Serial.readStringUntil('\n'); // Read data from Bluetooth
    input.trim();
 
    Serial.println("Received command: " + input);
    processCommand(input);
  }
 
  // Check if robot arm is playing poses
  if (isPlaying && !stopPlaying) {
    if (loopPlayback) {
      playPosesInLoop();
    } else {
      playNextPose();
    }
  }
}
 
void processCommand(String command) {
  // If playing, ignore all rover commands
  if (isPlaying) {
    if (command == "s") { // Allow stop playback command
      stopPlayingPoses();
    } else {
      Serial.println("Playback in progress. Ignoring command: " + command);
    }
    return;
  }
 
  // Control rover movement
  if (command == "F") {
    forward();
  } else if (command == "B") {
    backward();
  } else if (command == "L") {
    turnLeft();
  } else if (command == "R") {
    turnRight();
  } else if (command == "S") {
    stopMotors(); // Stop motors immediately on "S" command
 
  // Control robotic arm
  } else if (command.startsWith("1,")) {
    processServoCommand(command, 0); // Control Servo 1
  } else if (command.startsWith("2,")) {
    processServoCommand(command, 1); // Control Servo 2
  } else if (command.startsWith("3,")) {
    processServoCommand(command, 2); // Control Servo 3
  } else if (command.startsWith("4,")) {
    processServoCommand(command, 3); // Control Servo 4
  } else if (command.startsWith("5,")) {
    processServoCommand(command, 4); // Control Servo 5
  } else if (command.startsWith("6,")) {
    processServoCommand(command, 5); // Control Servo 6
 
  // Save, play, reset poses
  } else if (command == "v") {
    saveCurrentPose();
  } else if (command == "l") {
    startPlayingPoses();
  } else if (command == "r") {
    resetPoses();
  } else if (command == "s") {
    stopPlayingPoses();
  } else if (command == "o") {
    loopPlayback = true;
    Serial.println("Loop playback enabled.");
  } else if (command == "f") {
    loopPlayback = false;
    Serial.println("Loop playback disabled.");
  } else {
    Serial.println("Unknown command: " + command);
  }
}
 
void processServoCommand(String command, int servoIndex) {
  int commaIndex = command.indexOf(',');
  if (commaIndex > 0) {
    int position = command.substring(commaIndex + 1).toInt();
    int pwmValue = map(position, 0, 180, 150, 600);
    moveToPositionSmoothly(servoIndex, pwmValue);
  }
}
 
// Rover motor control
void forward() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
  Serial.println("Moving forward");
}
 
void backward() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
  Serial.println("Moving backward");
}
 
void turnLeft() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
  Serial.println("Turning left");
}
 
void turnRight() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
  Serial.println("Turning right");
}
 
void stopMotors() {
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
  Serial.println("Motors stopped");
}
 
// Arm servo control
void moveToPositionSmoothly(int servoIndex, int targetPwmValue) {
  int currentPwmValue = currentServoPositions[servoIndex];
  if (targetPwmValue > currentPwmValue) {
    for (int pos = currentPwmValue; pos <= targetPwmValue; pos += stepSize) {
      pwm.setPWM(servoChannels[servoIndex], 0, pos);
      delay(stepDelay);
    }
  } else {
    for (int pos = currentPwmValue; pos >= targetPwmValue; pos -= stepSize) {
      pwm.setPWM(servoChannels[servoIndex], 0, pos);
      delay(stepDelay);
    }
  }
  currentServoPositions[servoIndex] = targetPwmValue;
  Serial.println("Servo " + String(servoIndex + 1) + " set to position: " + String(targetPwmValue));
}
 
// Pose handling for the arm
void saveCurrentPose() {
  if (configCount < maxConfigurations) {
    for (int i = 0; i < numServos; i++) {
      savedConfigurations[configCount][i] = currentServoPositions[i];
    }
    configCount++;
    Serial.println("Pose saved. Total poses: " + String(configCount));
  } else {
    Serial.println("Memory full. Cannot save pose.");
  }
}
 
void startPlayingPoses() {
  if (configCount > 0) {
    stopMotors(); // Ensure rover is stopped during playback
    isPlaying = true;
    stopPlaying = false;
    currentPoseIndex = 0;
    Serial.println("Starting pose playback");
  } else {
    Serial.println("No poses saved");
  }
}
 
void playNextPose() {
  if (currentPoseIndex < configCount) {
    for (int i = 0; i < numServos; i++) {
      moveToPositionSmoothly(i, savedConfigurations[currentPoseIndex][i]);
    }
    delay(1000);
    currentPoseIndex++;
  } else {
    isPlaying = false;
    Serial.println("Pose playback finished");
  }
}
 
void playPosesInLoop() {
  for (int i = 0; i < configCount; i++) {
    if (stopPlaying) break; // Immediate stop on command
    for (int j = 0; j < numServos; j++) {
      moveToPositionSmoothly(j, savedConfigurations[i][j]);
    }
    delay(1000);
  }
}
 
void stopPlayingPoses() {
  stopPlaying = true;
  isPlaying = false;
  Serial.println("Pose playback stopped");
}
 
void resetPoses() {
  configCount = 0;
  isPlaying = false;
  loopPlayback = false;
  currentPoseIndex = 0;
  Serial.println("All poses reset");
}
License
All Rights
Reserved
licensBg
0