Introduction: The Punishment: a 3DOF Writing Robot Arm
created by Rabih Koussa & Niki Kentroti
The project was conducted in the framework of the ICD seminar: Computational Design and Digital Fabrication in the International Master of Science Programme: ITECH
Introduction
‘The Punishment’ is a three degrees of freedom writing robot arm whose output and actions are determined by the availability of light.
Concept
For the "Useless Machine" assignment of the seminar, we integrated in our project the concept of eternal useless effort, as it is described in the myth of Sisyphus.
According to Greek mythology, Sisyphus received eternal punishment for supposedly cheating Death. As a result of his arrogant belief that his cleverness surpassed even that of Zeus, he was condemned to roll a boulder up a hill in Tartarus. When he reached the top of the hill, the boulder would roll back down, consigning Sisyphus to an eternity of useless efforts.
Our “Useless Machine” consists of a robot system that is executing repeatedly the same task, with its efforts constantly being erased.
Unlike a typical Greek hero who stoically accepts their fate, we programmed a 3 DOF robot arm to operate with the assistance of an accomplice in two different modes. An integrated Photoresistor in its circuit informs the robot's actions. When the light is on, the robot arm compliantly executes its eternal punishment by writing the same text repeatedly. However, when the light is off, the robot arm switches to a non-compliant mode, attempting to outsmart its punisher and regain its freedom by writing a different text.
Step 1: List of Parts
1. Electronics
1.1. Basics
Breadboard
Jumper Wires
10K Ohm Resistor (x3)
9V Battery
1.2. Sensors
Phototransistor (Ambient light detector Photosensitive sensor)
1.3. Motor-Related
Servo Motor MG996R Micro Digital (x3)
DC Motor
L293D H-bridge Motor Driver
1.4. Actuators
Pushbuttons (x2)
2. Mechanics
wood sheet 220x140x4 mm (writing board)
wood board 290x470x6mm (base)
Screws 20x5mm, 10x5mm, bolts M5, washers M5
Screws 10x2mm
Threaded rod (x2) 200x8mm & 230x8mm
Bolt M8
threaded rod 60x6mm (x8)
Bolts M6 (x16)
Bearing 8x22x7 mm (x4)
Non-permanent marker
Acetate sheet transparent 0.3mm DIN A3
Step 2: Tools
- Allen key
- Screw driver
- Power drill
- Electronics soldering iron kit
Step 3: System Logic
3.General Description
3.1. Robotic arm and eraser system logic
As a general description of the system's logic, the robotic arm operates in two different modes based on the values received by the light sensor and a predefined threshold that distinguishes between the modes. If there is sufficient light according to the threshold, the robotic arm executes a specific movement to repeatedly write a certain text. After each completion of writing, an eraser system is activated to erase the text, and the robotic arm proceeds to rewrite the same text. If there is insufficient light, the robotic arm performs a different movement to write a different text, and the eraser system is activated in the same manner.
3.2. Writing motion implementation logic
The automated movement of the robotic arm requires the implementation of inverse kinematics. The robot root is positioned to the origin of the cartesian coordinate system. To determine the motion of the robot to a desired position, letters are first translated into points with x, y, and z coordinates. These coordinates are then processed and organized into arrays, which are imported into the Arduino code for calculating the movement of the robotic arm.
Step 4: Robot Design
4.Design, Fabrication and assembly of parts
The robotic arm body as well as the parts related to the eraser system where 3D printed. Mechanical parts, such as screws, bolts and washers were used to connect the joints of the robot. A single bolt and three bearings were used in the eraser system.
4.1.Base of the robotic arm
The robotic arm is attached to a circular plate, underneath of which the servo motor of the first axis of rotation is attached and screwed with a designed piece to the base plate. A rectangular cutout of the circular plate ensures stability while the robot is in movement.
In the circular plate, two holders designed for the two servo motors of the second and third axis of rotation are screwed to ensure that the servo motors are fixed in the right position.
4.2.Robotic arm parts
The first robotic arm corresponding to the second axis of rotation, is designed in two pieces to facilitate the 3D printing process and screwed together after printing.
The second arm, is designed in three pieces. One connected to the first arm, forming a joint. There is also an extension to the piece so that it can be attached to the TCP calibration mechanism. The remaining two pieces are connected to the first piece and to each other with a joint. One of them is finally attached to the motor corresponding to the third axis of rotation.
4.3.TCP calibration mechanism
This system is rotating passively, following the position of the robot. It ensures that the Tool center point (TCP) always meetS the writing area at a 90 degrees angle. It is designed in three pieces and consists of two linear elements and a right-angle element connecting the two and is connected to the base, the joint of the second arm and the pen holder end effector.
Please find attached the corresponding stl. files.
4.4. Writing area and base
A wooden board measuring 290x470x6mm is used as the base. The 3D printed servo motor holder for the first axis of rotation is screwed onto the board. The 3D printed rectangular cutout of the circular base of the robot arm is positioned 5.5cm above the base using a 6mm threaded rod and 6M bolts. A wooden sheet measuring 220x140x4mm is used as the writing surface of the robotic arm and is placed on the assembly in the same manner.
Alternatively, the same set up can be accomplished without the use of mechanical parts, by cutting the wooden sheet as shown in the file wooden_base.stl provided.
4.5. Servo Motors Calibration
Defining the home position of the robot involves configuring the robot's motors and components. All of the servo motors are set to 90 degrees and the two arms of the robot are placed in a 90-degree configuration in relation to each other and attached to the second and third axis servo motors, that are placed at the circular base. Finally, the base is attached to the first axis servo motor. The process requires careful attention to detail to ensure that everything is properly aligned and configured.
Step 5: Assembling the Electronics
5. Electronics Assembly:
5.1. Servos:
Base servo (first axis of rotation):
Signal wire: D9 Digital Pulse Width Modulation (PWM) pin
power wire: external supply
ground wire: external supply and Arduino's Ground (GND) pin
Arm 1 servo (second axis of rotation):
Signal wire: D10 Digital Pulse Width Modulation (PWM) pin
power wire: external supply
ground wire: external supply and Arduino's Ground (GND) pin
Arm 2 servo (third axis of rotation):
Signal wire: D10 Digital Pulse Width Modulation (PWM) pin
power wire: external supply
ground wire: external supply and Arduino's Ground (GND) pin
5.2. DC Motor
H-Bridge: (Numbering of pins based on L293D H-bridge Motor Driver datasheet)
1. Enable 1 &2 pin: 5V Arduino pin
2. Input 1 pin: D12: General purpose digital I/O pin
3. Output 1 pin: DC motor positive terminal
4. Ground pin: Arduino's Ground (GND) pin
5. Ground pin: Arduino's Ground (GND) pin
6. Output 2 pin: DC motor negative terminal
7. Input 1 pin: D8: General purpose digital I/O pin
8. Vcc 2 pin: External supply
16. Vcc 1 pin: 5V Arduino pin
13. Ground pin: External supply and Arduino's Ground (GND) pin
12. Ground pin: External supply and Arduino's Ground (GND) pin
5.3. Sensor
Collector terminal of the phototransistor:
connected in series with a 10K Ohm resistor to the Arduino's Ground (GND) pin and to the A0 analog input Arduino's pin.
Emitter terminal of the phototransistor: 5V Arduino pin
5.4. Pushbuttons
Pushbutton 1:
Leg 1 of the pushbutton: 10K ohm resistor connected to the ground pin (GND) on the Arduino board
Leg2 of the pushbutton: D2 - Interrupt 0: Interrupt 0 (INT0) Arduino pin
Pushbutton 2:
Leg 1 of the pushbutton: 10K ohm resistor connected to the ground pin (GND) on the Arduino board
Leg2 of the pushbutton: D3 - Interrupt 1: Interrupt 1 (INT1) Arduino pin
Step 6: Code
The project's digital workflow is devided in two parts:
Part 1: a grasshopper definition providing lists of x,y,z coordinates that are imported to the Arduino code
Please find the respective file in the following google drive link: "ThePunishment_GH-TextToPoints.gh"
Part 2: the Arduino code
Description of the Arduino code:
Libraries used:
Servo.h: allows the use of servo motors with Arduino.
math.h: provides mathematical functions such as trigonometric functions.
ExcelDataReader.h: provides functions to read values from an Excel file.
Constants and global variables:
lightSensorPin: the analog pin connected to the light sensor.
lightsen_thres: the threshold value for the light sensor reading, which is used to determine whether there is enough light for the robot to write.
baseservo_pin, arm1servo_pin, and arm2servo_pin: the digital pins connected to the three servo motors that control the robotic arm.
baseservo, arm1servo, and arm2servo: the Servo objects that represent the three servo motors.
arm_length: the length of the arm in millimeters.
buttonPin1 and buttonPin2: the digital pins connected to two buttons used for erasing.
motorPin1 and motorPin2: the digital pins connected to a DC motor that controls the eraser.
Functions description:
homePosition(): moves the three servo motors to their home position, which is when they are all set to 90 degrees.
inverseKinematics(double x, double y, double z): uses inverse kinematics to calculate the angles required to move the robotic arm to a specified position. The function takes as arguments the x, y, and z coordinates of the points that the TCP should move to. For the inverse kinematics calculations, a trigonometric approach is used as shown in figure 1.
setup(): initializes the pins and objects used in the code, reads values from an Excel file, and sets the DC motor direction to rotate in one direction.
loop(): Sequence of actions in loop function:
First, the light sensor reading is obtained by using the analogRead() function. If the reading is greater than a certain threshold, the robot arm moves to write text by calling the inverseKinematics() function. The function takes three arguments: the x, y, and z coordinates of the point to which the arm should move. These coordinates are obtained from pre-defined lists of coordinates for text1, which is read from an Excel file using the ExcelDataReader library. After completing the writing of text1, the homePosition() function is called to move the arm back to its home position.
Next, the code checks if a button (buttonPin2). If the button is pressed, the DC motor connected to motorPin1 and motorPin2 is set to move in the opposite direction, which pulls the eraser across the writing surface. When the first button is pushed (buttonPin1) the DC motor stops.
If the reading is not greater than a certain threshold, the exact same sequence of actions is performed. The coordinates, however, are obtained from pre-defined lists of coordinates for text2 in this case, which is also read from an Excel file using the ExcelDataReader library.
The full Arduino code:
#include <Servo.h>
#include <math.h>
#include <ExcelDataReader.h>
///// All global variables /////
// Define pin of light sensor
const int lightSensorPin = A0;
// Define lightSensorReading threshold
const int lightsen_thres=300;
// Define global variables for the servo pins
const int baseservo_pin = 9;
const int arm1servo_pin = 10;
const int arm2servo_pin = 11;
// Define global variables for the Servo objects
Servo baseservo;
Servo arm1servo;
Servo arm2servo;
// Define the arm length
const double arm_length = 105;
////Define pins for two buttons and two pins for the DC motor
//buttons
const int buttonPin1 = 2; // Button 1 connected to digital pin 2
const int buttonPin2 = 3; // Button 2 connected to digital pin 3
//dc motor pins
const int motorPin1 = 8; // DC motor connected to digital pin 8
const int motorPin2 = 12; // DC motor connected to digital pin 12
///set up for lists
// Define number of points first text1, number of rows imported from excel
const int num_list1=93;
// Define number of points first text2, number of rows imported from excel
const int num_list2=70;
//lists of x,y,z text1
double x_values_text1[num_list1];
double y_values_text1[num_list1];
double z_values_text1[num_list1];
//lists of x,y,z text2
double x_values_text2[num_list2];
double y_values_text2[num_list2];
double z_values_text2[num_list2];
// Define function to return to home position
void homePosition() {
baseservo.write(90);
arm1servo.write(90);
arm2servo.write(90);
}
// Define inverse kinematics function
void inverseKinematics(double x, double y, double z) {
double b = atan2(y,x) * (180 / 3.1415); // base angle
double l = sqrt(x*x + y*y);
double h = sqrt (l*l + z*z);
double phi = atan(z/l) * (180 / 3.1415);
double theta = acos((h/2)/arm_length) * (180 / 3.1415);
double a1 = 188 - (phi + theta); // angle for first part of the arm
double a2 = 101 + (phi - theta); // angle for second part of the arm
// Move the servos to the calculated angles
baseservo.write(b);
arm1servo.write(a1);
arm2servo.write(a2);
delay(50);
}
void setup() {
baseservo.attach(baseservo_pin);
arm1servo.attach(arm1servo_pin);
arm2servo.attach(arm2servo_pin);
pinMode(buttonPin1, INPUT_PULLUP); // Set button 1 as input with internal pull-up resistor
pinMode(buttonPin2, INPUT_PULLUP); // Set button 2 as input with internal pull-up resistor
pinMode(motorPin1, OUTPUT); // Set motor pin 1 as output
pinMode(motorPin2, OUTPUT); // Set motor pin 2 as output
// text1, read each column from the Excel file for text1 and assing the values to the x_values_text1, y_values_text1 and z_values_text1
ExcelDataReader excel("coordinates_1.xlsx");
excel.readColumn(1, x_values_text1, num_list1);
excel.readColumn(2, y_values_text1, num_list1);
excel.readColumn(3, z_values_text1, num_list1);
// text2, read each column from the Excel file for text2 and assing the values to the x_values_text2, y_values_text2 and z_values_text2
ExcelDataReader excel2("coordinates_2.xlsx");
excel2.readColumn(1, x_values_text2, num_list2);
excel2.readColumn(2, y_values_text2, num_list2);
excel2.readColumn(3, z_values_text2, num_list2);
// step 1: robot is at home position
homePosition();
// DC motor direction is defined
// Rotate the motor in one direction
digitalWrite(motorPin1, HIGH);
digitalWrite(motorPin2, LOW);
}
void loop() {
int lightSensorReading = 0;
lightSensorReading = analogRead(lightSensorPin); //reads the value from the sensor
//Serial.print(lightSensorReading);
if(lightSensorReading > lightsen_thres){ //when there is light
for (int i = 0; i < sizeof(x_values_text1) / sizeof(x_values_text1[0]); i++) {
inverseKinematics(x_values_text1[i], y_values_text1[i], z_values_text1[i]);
}
//gets the robot to home position after completing the writing
homePosition();
/////////////START ERASER///////////////
if (digitalRead(buttonPin2) == LOW) {
// Reverse the direction of the motor
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, HIGH);
// Wait for the motor to hit button 1
while (digitalRead(buttonPin1) == HIGH) {
delay(10);
}
// Reverse the direction of the motor
digitalWrite(motorPin1, HIGH);
digitalWrite(motorPin2, LOW);
// Wait for the motor to hit button 2
while (digitalRead(buttonPin2) == HIGH) {
delay(10);
}
// Reverse the direction of the motor
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, HIGH);
// Wait for 1 second
delay(500);
// Stop the motor
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, LOW);
}
}
/////////////// STOP OF ERASER////////////////
else{
//Gets the robot to home position when there is no light.
homePosition();
//Robot starts writing text2
for (int i = 0; i < sizeof(x_values_text2) / sizeof(x_values_text2[0]); i++) {
inverseKinematics(x_values_text2[i], y_values_text2[i], z_values_text2[i]);
}
//gets the robot to home position after completing the writing of text2
homePosition();
/////////////START ERASER///////////////
if (digitalRead(buttonPin2) == LOW) {
// Reverse the direction of the motor
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, HIGH);
// Wait for the motor to hit button 1
while (digitalRead(buttonPin1) == HIGH) {
delay(10);
}
// Reverse the direction of the motor
digitalWrite(motorPin1, HIGH);
digitalWrite(motorPin2, LOW);
// Wait for the motor to hit button 2
while (digitalRead(buttonPin2) == HIGH) {
delay(10);
}
// Reverse the direction of the motor
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, HIGH);
// Wait for 1 second
delay(500);
// Stop the motor
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, LOW);
}
}
/////////////// STOP OF ERASER////////////////
}
Attachments
Step 7: References
- Olivares-Méndez, M. A., Dávila-Martínez, D. M., & Salazar-Desachy, D. (2017). Inverse Kinematics Solution for a 3DOF Robotic Structure using Denavit-Hartenberg Convention.
- M. A. Arshad, H. A. Rahim, and M. A. Othman. (2015). Inverse Kinematics Solution for a Three Degree of Freedom Robotic Arm Using Denavit-Hartenberg Convention. Procedia Computer Science, 76, 261-267. doi: 10.1016/j.procs.2015.12.290
- V. Singh, V. Kumar, and A. Kumar. (2016). Kinematics Analysis of 3 DOF Robotic Arm Using Denavit-Hartenberg Convention. International Conference on Advances in Computing, Communications and Informatics (ICACCI). doi: 10.1109/ICACCI.2016.7732364
- roTechnic. (n.d.). InverseKinematicArm: Inverse Kinematics for robotic arms in Arduino. GitHub. Retrieved May, 2023, from https://github.com/Technic/InverseKinematicArm.
- Kim, H., & Cho, Y. (2016). Kinematics and Control of Robot Manipulators. Springer
- Brown, S. (2019). Arduino Robotics (2nd ed.). Packt Publishing.
- Monk, S. (2015). The Maker's Guide to the Zombie Apocalypse: Defend Your Base with Simple Circuits, Arduino, and Raspberry Pi. No Starch Press.
- Bruton, J. (2019, May 21). How Robots Use Maths to Move. YouTube. https://www.youtube.com/watch?v=IN8tjTk8ExI
- (2021, June 29). Send Data from Excel to Arduino Using Data Streamer. YouTube. https://www.youtube.com/watch?v=umBarmiCWEo
Step 8: Closing Remarks:
Thank you for visiting this Instructables tutorial. As this is our first Instructables tutorial and also our first Arduino project (still under development), we would appreciate any feedback you may have.
List of links to some of projects conducted by other students as part of the Computational Design and Digital Fabrication seminar:
Emotion Aid by Clara Blum & Mohammad Jafari
Miss Fortune Teller by Luiza Longo, Ceren Tüfek, Ali Zolfaghari
Robotic Kukko With Thermal Vision by Matthias Hornung, Otto Lindstam, Kalaivanan Amudhan
Useless Mirror by Simon Joller, Hamed Behmanesh & Seyedehgelareh Sanei
The above mentioned projects are only few of the projects conducted in the framework of the seminar. There are many other equally interesting and worth exploring projects.