The purpose of this tutorial is to develop step-by-step a project for controlling and programming of a Robot Arm, simulating the basic functions of an industrial robot.
Step 1: SpecificationsThe robot has two basic functions:
- Program: Record arm positions in three dimensions (each record is a "step")
- Run: Perform in sequence the positions recorded in the "Program". The robot will run the program until the command "ABORT" is used.
Main characteristics:
- The project can be used to control robots with 3 or 4 DOF ("Degrees of Freedom").
- The robot can be controlled in "LOCAL" and "REMOTE" modes (the last one via an Android device)
- During the program phase, user can change the control mode from "LOCAL" to "REMOTE" and vice and versa.
- Information to user will be provided thru colored LEDs, a 2 lines LED display and sound (a buzzer).
- The sound alarm can also be triggered remotely.
The block diagram on the previous step shows the "Bill of Material" which will be used in this project.
I opted by the Arduino MEGA in order not to worry about the number of available Arduino ports (I/Os). The UNO for example, would work without problems but a port expansion method should be used. There are several options that can be easily found on the internet, as a 74138 decoder for example.
Here, the First prototype being programmed in "local mode".
For the Bluetooth network, the HC-06 will be used.
The Android app used for "remote mode
", was developed using the tool MIT Appinventor2, which is a powerful single platform for this kind of app based on Android devices. The app is available to be downloaded free of charge at Google store: MJRoBot Arduino Robot Arm Control.
The video below can give you an idea of what should be the final project with remote programming:
Step 3: Project DevelopmentRobotic Arms can be classified according to the number of "joints" or "Degrees Of Freedom" (DOF) they have.
- The "Base", or "Waist", usually can turn the arm 180o or 360o, depending of the Servo type used (here in this project, a 180o Servo was used).
- The "Shoulder", is the responsible for "raising or lowering" the arm vertically.
- The "Elbow" will make the arm "go forward or backward".
- The "Claw" or "Gripper" works by opening or closing to "grab things."
Servo motors will be used to drive the joints, connected directly to the Arduino. Note that is not uncommon see "Stepper Motors" used at the base for greater torque and precision. The proper choice of servos are very important (there are cheap Chinese servos who are very poorly constructed such as MG995, which unfortunately are the ones that came with my SanSmart 3DOF AARM). But for the propose of this project worked fine.
The DC power for the servos should be separated from the Arduino and other components. An external power supply of 5 or 6V should work without problems (check the DataSheet of your servors to verify the proper voltage range). A common practice is also using 470uF capacitors between VCC and GND to minimize the noise generated by the DC motors inside the servors. Be sure to connect all the "Grounds" (external Power Source with the Arduino GND pin).
If the servos have problems and vibrate a lot, make adjustments at the "delays" of your code. It is important that the servos have time to get to a certain point before receiving a new command. Also worth checking out if the servos are digital or analog, as though they are mechanically similar, the digital works with a frequency of 300Hz while the analog, 50Hz. The standard Arduino library "Servo.h
" was developed for analog servos and can be modified if necessary, for a better functioning with digital servos.
The above drawing shows the complete circuit.
Step 5: The codeThe project is not complicated, but it has many variables. The most prudent is to clearly define them and leave the remarks on a unique file:
ArmDefine.h
This file also should set the minimum, maximum and initial servo's angles. The code included in this tutorial, has two sets of parameters for the robotic arms that I tested in my project (of course only a group of constants should be used):
// MeArm 4-DOF
#define minGrip 15
#define minBase 0
#define minShou 60
#define minElbw 60
#define maxGrip 45
#define maxBase 170
#define maxShou 180
#define maxElbw 150
#define midGrip 30
#define midBase 87
#define midShou 138
#define midElbw 100
/* SS 3-DOF
#define minGrip 75
#define minBase 5
#define minShou 5
#define minElbw 0
#define maxGrip 125
#define maxBase 150
#define maxShou 155
#define maxElbw 0
#define midGrip 100
#define midBase 90
#define midShou 90
#define midElbw 0
*/
Each type of arm has a different set of parameters and it is important that you find the right for yours. What I suggest is that initially the potentiometers (pots) remain at its midpoint and the Mapping of the PWM outputs are set to the default values: Max = 255
, Min = 0
and Mid = 126
( "#defines
" above). Then, start varying the pots (one by one) and follow in the Serial Monitor (or LCD) what should be the minimum and maximum values where the arm works properly. Those will be the final values to be used for the settings (change my original values at ArmDefine.h)
.
For ”recording" the sets of coordinates (or steps) that the robot should play, I will use data arrays:
int gripPosition[100];
int basePosition[100];
int shouPosition[100];
int elbwPosition[100];
int positionIndex = 0; // Index to be used at position array used for recorded tasks
Note that I'm not keeping the "stored" position and at the end of the "robot" program, the index is back to zero and the robot will wait for the recording of a new sequence (the program is lost). Alternatively, you could keep these data arrays in the Arduino EEPROM, for example. Doing that, the program would be executed again or even you could have more than one stored program.
Step 6: The program logicThe main block ("Loop") is really quite simple:
Check if a command to execute the "program" (sequence of steps) was used.
- If so, run it.
- Otherwise, the "program" is not complete and still must write new steps.
- If a “new position” is defined, add it to the program.
- First, checks for messages arriving at the serial buffer, from the Android device.
- Next, verifies if the control mode is "Local" or "Remote" (the default is Local).
- Back to the beginning and perform step 1 again.
void loop ()
{
checkBTcmd ();
defineLocalRemote () ;
execTaskCmd = digitalRead (execTaskPin);
if (execTaskCmd == || HIGH command == "runon")
{
RunProgram () ;
}
else recArmPosition () ;
command = "";
}
The function checkBTcmd() assembles a string using the individuals characters that arrives from the BT module. This string is passed to the variable "command".
The function defineLocalRemote() considers the variable "command" checking whether one command to change the mode to remote is received or vice versa. The alarm command is also analyzed here. For the program logic, if the "Alarm" is triggered in the Android device, the arm must necessarily go to the Remote mode.
The function RunProgram() performs the preparations, turning LEDs on / off, etc and especially invoking the function: ExecuteTask(). The latter is the function that contains the execution’s logic of the sequence of steps. The function increases the "positionIndex" sending the position data to arm one by one using the tool: armPosition(grip, base, shoulder, elbow) .
Finally, the function that really command the servos and writes the "steps" is the recArmPosition(). Depending on receiving the Android command, this function will define the positioning of the servos that can be through the pots, or through the "sliders" of Android app. With each position’s change, this function sends the coordinates to the servos using the armPosition
function (grip, base, shoulder, elbow). The reading of the real position of the pots or sliders and the corresponding activation of servos occurs by the time the command "SAVE" or "PROGRAM" is triggered. At that moment, the arrays’ position index is incremented and the step stored.
To simplify the understanding, all the code was based on its specific functions. The "Setup
", "Loop
" and the functions described above are virtually all in the file: MJRoBot_Arm_Robot_Task_Prgm.ino
The more general functions such as read BT command: void checkBTcmd(); sound generator: void beep (int pin, int freq, long ms) and debouncing: boolean debounce (int pin); are on file: General_Functions.ino
An important fact: as the Arduino executes instructions based on a clock of 16Mhz, it is expected that the control buttons are read hundreds or even thousands of times per second, hence it is important to make a "debouncing" button that sets the recording step.
The fourth and final file is: Arm_Ctrl_and_Display.ino
In this file are the potentiometer's reading functions: bool readPotenciometers(); reading of Android sliders: bool readSliders(); placement of servos: void armPosition (int gripp, int basee, int shoulder, elbow int). The other functions included in the file are for data display on the LCD, Serial Monitor, alarms, etc.
The video shows the robotic arm 4DOF "meArm" being programmed remotely through the the Android app.
The complete source code for the project can be found at GITHUB:
https://github.com/Mjrovai/MJRoBot-Programmed-Arm
or here:
Step 7: ConclusionAs always, I hope this project can help others find their way in the exciting world of Electronics, Robotics and IoT! For more projects, please visit my blog: MJRoBot.org
Saludos from the south of the world! See you at my next tutorial!
Thank you
Marcelo
Comments