Here we are going to make a 6 DOF or degrees of freedom arm robot. We need to understand first on how degrees of freedom is calculated.
Six degrees of freedom (6DoF) is also referred as the movement of a rigid body in three-dimensional space. It can commonly be attributed to yaw as the normal axis, pitch as transverse axis, and roll as the longitudinal axis.
Parts List
Components that was used for this build.
- 1x Arduino Uno
- 1x GPIO Expansion Shield
- 6x Servo Motor MG996R
- 1x Bluetooth HC 06 Serial Module
- 1x Wall Power Adapter 5VDC 3A
- 1x DC Male Female Power Adapter
Installation
Screw the servo motor to the base
The 3D Parts
Connecting Everything:
Connect the Bluetooth Module to the D2, D3, GND, and 5V pins of Arduino on top of GPIO Expansion shield.
Add a wire to our DC jack adapter, tighten the screw with a screwdriver. We will use this for the input power of our robot arm.
Connect the DC Jack Adapter to GPIO Expansion Shield power terminal.
Lastly connect all the Servo motor to arduino.
*for the servo 1 connect it to D9, Gnd, 5V
*for the servo 2 connect it to the D5,Gnd,5v
*for the servo 3 connect it to the D6,Gnd,5V
*for the servo 4 connect it to the D10,Gnd,5V and
*for the servo 5 connect it to the D11,Gnd,5V of arduino
Powering-Up
Schematic Diagram
See this schematic Diagram to double check your wirings.
Code:
Arduino
First you need to Setup the Name, Pin, and the Baudrate of your Bluetooth Module
#include <SoftwareSerial.h>
SoftwareSerial hc06(2,3); //Rx, Tx
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
hc06.begin(9600);
Serial.println("Enter AT commands:");
}
void loop() {
// put your main code here, to run repeatedly:
if (hc06.available()){
Serial.write(hc06.read());
}
//Write from Serial Monitor to HC06
if (Serial.available()){
hc06.write(Serial.read());
}
//need to set up to more information check this link https://www.aranacorp.com/en/arduino-and-bluetooth-module-hc-06/
//AT COMMAND
//AT+NAMEROBOTARMBLE = to set your bluetooth name to ROBOTARMBLE
//AT+PIN0000 = to set your pin to 0000
//AT+BAUD8 = baud to 115200 = to set the baudrate of your bluetooth to 115200
}
Time to upload your code to your Arduino Uno.
#include <Servo.h>
#include <SoftwareSerial.h>
SoftwareSerial hc06(2,3); //Rx, Tx
Servo myservo;
Servo myservo1;
Servo myservo2;
Servo myservo3;
Servo myservo4;
String cmd="";
String serId = "";
String serVal = "";
int serval0 = 90;
int serval1 = 90;
int serval2 = 90;
int serval3 = 90;
int serval4 = 40;
void setup() {
Serial.begin(115200);
hc06.begin(115200);
myservo.attach(9);
myservo1.attach(5);
myservo2.attach(6);
myservo3.attach(10);
myservo4.attach(11);
myservo.write(90);
myservo1.write(90);
myservo2.write(90);
myservo3.write(90);
myservo4.write(40);
}
void loop() {
while(hc06.available()>0){
cmd += (char)hc06.read();
cmd.trim();
}
char *serIdChar = strtok(&cmd[0], ",");
char *serValChar = strtok(NULL, ",");
serId = serIdChar;
serVal = serValChar;
if(cmd!= ""){
Serial.println(cmd);
Serial.println(serId);
Serial.println(serVal);
if(serId == "0"){
if(serval0 > serVal.toInt()){
for(int iter = serval0; iter > serVal.toInt()+1; iter--){
myservo.write(iter);
Serial.println(iter);
delay(10);
}
}else{
for(int iter = serval0; iter < serVal.toInt(); iter++){
myservo.write(iter);
Serial.println(iter);
delay(10);
}
}
serval0 = serVal.toInt();
Serial.println(serval0);
}else if(serId == "1"){
if(serval1 > serVal.toInt()){
for(int iter = serval1; iter > serVal.toInt()+1; iter--){
myservo1.write(iter);
Serial.println(iter);
delay(10);
}
}else{
for(int iter = serval1; iter < serVal.toInt(); iter++){
myservo1.write(iter);
Serial.println(iter);
delay(10);
}
}
serval1 = serVal.toInt();
Serial.println(serval1);
}else if(serId == "2"){
if(serval2 > serVal.toInt()){
for(int iter = serval2; iter > serVal.toInt()+1; iter--){
myservo2.write(iter);
Serial.println(iter);
delay(10);
}
}else{
for(int iter = serval2; iter < serVal.toInt(); iter++){
myservo2.write(iter);
Serial.println(iter);
delay(10);
}
}
serval2 = serVal.toInt();
Serial.println(serval2);
}else if(serId == "3"){
myservo3.write(serVal.toInt());
}else if(serId == "4"){
int serArm = map(serVal.toInt(),0,90,40,90);
myservo4.write(serArm);
}
cmd="";
serId="";
serVal="";
}
}
Android Studio
we do the app using Android Studio. first you need to create a Basic Activity in Android Studio then add the following code.
Layout: activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@drawable/ic_bluetooth_black_24dp"
app:backgroundTint="@color/colorBlack"/>
</android.support.design.widget.CoordinatorLayout>
Layout: content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/activity_main"
tools:context=".MainActivity"
android:background="@drawable/bg">
<!--<com.ramotion.fluidslider.FluidSlider-->
<!--android:id="@+id/fluidSlider"-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="wrap_content"-->
<!--android:layout_marginEnd="16dp"-->
<!--android:layout_marginStart="16dp"-->
<!--android:elevation="2dp"-->
<!--app:layout_constraintBottom_toBottomOf="parent"-->
<!--app:layout_constraintEnd_toEndOf="parent"-->
<!--app:layout_constraintStart_toStartOf="parent"-->
<!--app:layout_constraintTop_toTopOf="parent"-->
<!--app:size="small"-->
<!--app:duration="@android:integer/config_mediumAnimTime"-->
<!--tools:targetApi="lollipop" />-->
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressDrawable="@drawable/custom_seekbar_progress"
android:thumb="@drawable/custom_seekbar_thumb"
android:max="90"
android:progress="0"
android:padding="20dp"
android:id="@+id/seekBararm"/>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressDrawable="@drawable/custom_seekbar_progress"
android:thumb="@drawable/custom_seekbar_thumb"
android:max="180"
android:progress="90"
android:padding="20dp"
android:id="@+id/seekBarancle"/>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressDrawable="@drawable/custom_seekbar_progress"
android:thumb="@drawable/custom_seekbar_thumb"
android:max="180"
android:progress="90"
android:padding="20dp"
android:id="@+id/seekBarelbow"/>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressDrawable="@drawable/custom_seekbar_progress"
android:thumb="@drawable/custom_seekbar_thumb"
android:max="180"
android:progress="90"
android:padding="20dp"
android:id="@+id/seekBarafterBase"/>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progressDrawable="@drawable/custom_seekbar_progress"
android:thumb="@drawable/custom_seekbar_thumb"
android:max="180"
android:progress="90"
android:padding="20dp"
android:id="@+id/seekBarbase"/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
create a custom_seekbar_progress.xml to your drawable
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background"
android:gravity="center_vertical|fill_horizontal">
<shape android:shape="rectangle"
android:tint="#000000">
<corners android:radius="8dp"/>
<size android:height="30dp" />
<solid android:color="#000000" />
</shape>
</item>
<item android:id="@android:id/progress"
android:gravity="center_vertical|fill_horizontal">
<scale android:scaleWidth="100%">
<selector>
<item android:state_enabled="false"
android:drawable="@android:color/transparent" />
<item>
<shape android:shape="rectangle"
android:tint="#000000">
<corners android:radius="8dp"/>
<size android:height="30dp" />
<solid android:color="#000000" />
</shape>
</item>
</selector>
</scale>
</item>
</layer-list>
also create custom_seekbar_thumb.xml to your drawable
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:thickness="4dp"
android:useLevel="false"
android:tint="#7ddcff">
<solid
android:color="#7ddcff" />
<size
android:width="32dp"
android:height="32dp" />
</shape>
also create ic_bluetooth_black_24dp.xml to your drawable
<vector android:height="24dp" android:tint="#ffffff"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M17.71,7.71L12,2h-1v7.59L6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 11,14.41L11,22h1l5.71,-5.71 -4.3,-4.29 4.3,-4.29zM13,5.83l1.88,1.88L13,9.59L13,5.83zM14.88,16.29L13,18.17v-3.76l1.88,1.88z"/>
</vector>
and last create ic_bluetooth_connected_black_24dp.xml to your drawable
<vector android:height="24dp" android:tint="#0F03FF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M7,12l-2,-2 -2,2 2,2 2,-2zM17.71,7.71L12,2h-1v7.59L6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 11,14.41L11,22h1l5.71,-5.71 -4.3,-4.29 4.3,-4.29zM13,5.83l1.88,1.88L13,9.59L13,5.83zM14.88,16.29L13,18.17v-3.76l1.88,1.88zM19,10l-2,2 2,2 2,-2 -2,-2z"/>
</vector>
Add this code to values > colors.xml
<color name="colorBlack">#000000</color>
java: MainActivity.java
package com.project.robotarm;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.SeekBar;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
private SeekBar seekBarBase;
private SeekBar seekBar1;
private SeekBar seekBar2;
private SeekBar seekBar3;
private SeekBar seekBar4;
private String dataToSend;
private String TAG = "DEBUG";
private BluetoothAdapter myBluetooth = null;
private static String address = "98:D3:31:F6:1B:DB"; //address of your bluetooth module. to check the address of your bluetooth module first pair it with your android phone then check the address of the bluetooth module
private ProgressDialog progress;
BluetoothSocket btSocket = null;
private boolean isBtConnected = false;
private boolean isConnected = false;
static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private OutputStream outStream = null;
private InputStream inStream = null;
Handler handler = new Handler();
byte delimiter = 10;
boolean stopWorker = false;
int readBufferPosition = 0;
byte[] readBuffer = new byte[1024];
FloatingActionButton fab;
@Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
Toolbar toolbar = findViewById( R.id.toolbar );
setSupportActionBar( toolbar );
seekBarBase = findViewById( R.id.seekBarbase );
seekBar1 = findViewById( R.id.seekBarafterBase );
seekBar2 = findViewById( R.id.seekBarelbow );
seekBar3 = findViewById( R.id.seekBarancle );
seekBar4 = findViewById( R.id.seekBararm );
fab = findViewById( R.id.fab );
fab.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick( View view ) {
myBluetooth = BluetoothAdapter.getDefaultAdapter();
if(myBluetooth == null)
{
//Show a mensag. that thedevice has no bluetooth adapter
Toast.makeText(getApplicationContext(), "Bluetooth Device Not Available", Toast.LENGTH_LONG).show();
//finish apk
finish();
}else
{
if (myBluetooth.isEnabled())
{
Log.d( TAG, "Bluetooth is enable" );
if(isConnected){
Disconnect();
}else{
ConnectBT connectBT = new ConnectBT();
connectBT.execute( );
}
}
else
{
//Ask to the user turn the bluetooth on
Intent turnBTon = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnBTon,1);
}
}
}
} );
seekBar4.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {
int progress= 0;
@Override
public void onProgressChanged( SeekBar seekBar, int i, boolean b ) {
progress=i;
}
@Override
public void onStartTrackingTouch( SeekBar seekBar ) {
}
@Override
public void onStopTrackingTouch( SeekBar seekBar ) {
dataToSend = "4,"+Integer.toString( progress );
writeData(dataToSend);
}
} );
seekBar3.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {
int progress = 0;
@Override
public void onProgressChanged( SeekBar seekBar, int i, boolean b ) {
progress=i;
}
@Override
public void onStartTrackingTouch( SeekBar seekBar ) {
}
@Override
public void onStopTrackingTouch( SeekBar seekBar ) {
dataToSend = "3,"+Integer.toString( progress );
writeData(dataToSend);
}
} );
seekBar2.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {
int progress = 0;
@Override
public void onProgressChanged( SeekBar seekBar, int i, boolean b ) {
progress = i;
}
@Override
public void onStartTrackingTouch( SeekBar seekBar ) {
}
@Override
public void onStopTrackingTouch( SeekBar seekBar ) {
dataToSend = "2,"+Integer.toString( progress );
writeData(dataToSend);
}
} );
seekBar1.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {
int progress = 0;
@Override
public void onProgressChanged( SeekBar seekBar, int i, boolean b ) {
progress = i;
}
@Override
public void onStartTrackingTouch( SeekBar seekBar ) {
}
@Override
public void onStopTrackingTouch( SeekBar seekBar ) {
dataToSend = "1,"+Integer.toString( progress );
writeData(dataToSend);
}
} );
seekBarBase.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {
int progress = 0;
@Override
public void onProgressChanged( SeekBar seekBar, int i, boolean b ) {
progress = i;
msg( "Changing seekbar's progress" );
}
@Override
public void onStartTrackingTouch( SeekBar seekBar ) {
msg( "Started tracking seekbar" );
}
@Override
public void onStopTrackingTouch( SeekBar seekBar ) {
dataToSend = "0,"+Integer.toString( progress );
writeData(dataToSend);
msg( "Stopped tracking seekbar" );
}
} );
}
private void writeData(String data) {
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
Log.d(TAG, "Bug BEFORE Sending stuff", e);
}
String message = data;
byte[] msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
} catch (IOException e) {
Log.d(TAG, "Bug while sending stuff", e);
}
}
private void Disconnect()
{
if (btSocket!=null) //If the btSocket is busy
{
try
{
msg( "Bluetooth Disconnect" );
btSocket.close(); //close connection
btSocket = null;
fab.setImageResource( R.drawable.ic_bluetooth_black_24dp );
isConnected = false;
}
catch (IOException e)
{ msg("Error");}
}
// finish(); //return to the first layout
}
private void msg(String s)
{
Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();
}
@Override
public boolean onCreateOptionsMenu( Menu menu ) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate( R.menu.menu_main, menu );
return true;
}
@Override
public boolean onOptionsItemSelected( MenuItem item ) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if( id == R.id.action_settings ) {
return true;
}
return super.onOptionsItemSelected( item );
}
private class ConnectBT extends AsyncTask<Void, Void, Void> // UI thread
{
private boolean ConnectSuccess = true; //if it's here, it's almost connected
@Override
protected void onPreExecute()
{
progress = ProgressDialog.show(MainActivity.this, "Connecting...", "Please wait!!!"); //show a progress dialog
}
@Override
protected Void doInBackground(Void... devices) //while the progress dialog is shown, the connection is done in background
{
try
{
if (btSocket == null || !isBtConnected)
{
myBluetooth = BluetoothAdapter.getDefaultAdapter();//get the mobile bluetooth device
BluetoothDevice device = myBluetooth.getRemoteDevice(address);//connects to the device's address and checks if it's available
btSocket = device.createInsecureRfcommSocketToServiceRecord(myUUID);//create a RFCOMM (SPP) connection
BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
btSocket.connect();//start connection
}
}
catch ( IOException e)
{
ConnectSuccess = false;//if the try failed, you can check the exception here
}
return null;
}
@Override
protected void onPostExecute(Void result) //after the doInBackground, it checks if everything went fine
{
super.onPostExecute(result);
if (!ConnectSuccess)
{
msg("Connection Failed. Check the address of your BLE if it is"+address+", if not the same contact the developer. \nOr Is it a SPP Bluetooth? Try again. ");
// finish();
}
else
{
msg("Connected.");
isBtConnected = true;
beginListenForData();
fab.setImageResource( R.drawable.ic_bluetooth_connected_black_24dp );
isConnected = true;
}
progress.dismiss();
}
}
public void beginListenForData() {
try {
inStream = btSocket.getInputStream();
} catch (IOException e) {
}
Thread workerThread = new Thread(new Runnable()
{
public void run()
{
while(!Thread.currentThread().isInterrupted() && !stopWorker)
{
try
{
int bytesAvailable = inStream.available();
if(bytesAvailable > 0)
{
byte[] packetBytes = new byte[bytesAvailable];
inStream.read(packetBytes);
for(int i=0;i<bytesAvailable;i++)
{
byte b = packetBytes[i];
char ch = (char)b;
Log.i("DEBUG", Character.toString( ch ));
}
}
}
catch (IOException ex)
{
stopWorker = true;
Log.d( "DEBUG", "WORKERS: Stop WORKERS TRUE" );
}
}
}
});
workerThread.start();
}
}
Manifests: AndroidManifest.xml
Add this 2 permission to your Manifest:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>