It is often said that robots may rule the world one day. And with the convenience and ease of making robots today within our private homes, we may not be too far away. In essence, each robotic project adds a new insight into the world of mechatronics. As such, the following article presents a simple way to control a robotic arm with an XBOX 360 wireless controller. This project was inspired by Barrett Anderies’ RC car controlled by a PS3 controller.
Table of Contents
ToggleRequirements
To build this project you will need:
- Arduino Uno ($23.25)
- USB host shield for Arduino Uno ($15.99)
- XBOX 360 controller ($16.00)
- XBOX 360 Wireless adapter ($17.49)
If you do not have a robotic arm already:
SOFTWARE:
- Autodesk Inventor 2014
- Arduino IDE
- USB Host Shield Library
- Final Code uses XBOXRECV
Optional software: Fritzing: circuit drawing software
MECHANICAL:
- Breadboard [400 pt]
- Standard Servo
ELECTRICAL:
- Jumper wires
- Power source : 3000 mAh or higher, 7Volts or higher : preferably a NiMH Venom battery as shown in the photos
- Jumper Wires
- Electrical Tape
STEP 1 :Important parts to buy first
Xbox controller with adapter, Arduino UNO (with cable), USB host shield for Arduino UNO, a servo and wires are the core parts you should order right away. The reasoning; you want to make sure your Xbox controller, adapter, USB host shield, and Arduino all talk to each other nicely.
STEP 2 : Putting everything together
Buy the core material. The arrival date for some of these parts can vary; there is a joke in the engineering design community in which you buy what you need first and then you design later.
1. Connect Arduino USB host shield to Arduino UNO
2. Xbox 360 adapter to USB jack on the shield
Warning: Make sure to not force the pins down, gently wiggle USB host shield until pins are completely covered
NOTE: make sure it’s a Microsoft adapter
3. Yellow/ White wire of servo to digital pin 2
NOTE: The pins on the shield are the same as the Arduino pins that are directly below
4. Black/ Brown wire of servo to GND
5. Red / Orange wire of servo to 5V
6. GND from Arduino to GND rail
7. V_in from Arduino to Red rail
Your wiring should look like this:
8. Connect Out + [ of Regulator] to Red Rail
9. Connect Out – [of Regulator] to GND rail
10. Strip the other end of alligator clip (that came with battery charger) like so:
WARNING: make sure the wires cannot touch when in the terminal as shown (I used electrical tape).
VERY IMPORTANT:
The Regulator steps down the voltage so that the Arduino board and servos can work.The “Out” side of the regulator should read 4.8 – 6 Volts (depending on your servo). I have mine set at 5.5 V and it works well. – Do not just connect the regulator without turning the golden potentiometer (gold circle with arrow above it) to this voltage.
a. Connect red alligator clip to battery
b. Connect other end to In +
c. Connect black alligator clip to black battery
d. Connect other end to In –
If you wired everything right you should see the following:
STEP 3: Code
In order for your Xbox controller and adapter to talk to the USB shield and the Arduino, you will need to download the USB host shield library found here: https://github.com/felis/USB_Host_Shield_2.0 simply click “download zip” on right hand side.
NOTE : you can probably find other websites with the similar examples, just make sure you get the XBOXRECV, as this is the Xbox 360 wireless library needed.
Don’t know how to place new libraries in the Arduino IDE? Go here: Libraries
I have included many versions of the code as well as the final code. Barrett Anderies helped develop a PS3 code that has much smoother controls than that previous attempts. The previous attempts are to illustrate other possible routes to accomplish the same task; it’s a good idea to look over the commenting and approaches to broaden your perspective.
Six servo controller(Xbox360 Wireless)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
|
// Six servo controller(Xbox360 Wireless)
// Barrett Anderies
// May 25, 2014
// Modified by Sergei Dines
// August 3, 2014
#include
#include
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include
#endif
#define LOOPTIME 25 //Define the delay between timed loop cycles.
//Define where each servo is attahed//
#define SERVO1 2 // Left/Right Trigger : Base Joint
#define SERVO2 3 // RightHat Y : Elbow Joint
#define SERVO3 4 // LeftHat Y : CLAW 1
#define SERVO4 5 // LeftHat Y : CLAW 2
#define SERVO5 6 // LeftHat X : Swivel
#define SERVO6 7 // RightHatX : Spin Claw
#define SERVO1_INIT 90 //Define initial servo position(initial Condition) & (initiates when “start” button pressed).
#define SERVO2_INIT 90
#define SERVO3_INIT 90
#define SERVO4_INIT 90
#define SERVO5_INIT 90
#define SERVO6_INIT 90
#define SERVO1_STEP 8 //Step Value for L/R Tripper [Base Joint]
//Define step size for servos controlled by D-pad (larger is faster).
#define SERVO2_RATE 4/32000
//Note: Org SERVO2_STEP 10
//Define rate for servos controller by sticks (larger is faster).
#define SERVO3_RATE 5/32000
#define SERVO4_RATE 5/32000
#define SERVO5_RATE 2/32000
#define SERVO6_RATE 4/32000
#define SERVO1_DIRECTION 1 //Set to -1 to reverse servo direction.
#define SERVO2_DIRECTION 1 //Set to -1 to reverse servo direction.
#define SERVO3_DIRECTION -1 //Set to -1 to reverse servo direction. CLAW 1
#define SERVO4_DIRECTION 1 //Set to -1 to reverse servo direction. CLAW 2
#define SERVO5_DIRECTION 1 //Set to -1 to reverse servo direction.
#define SERVO6_DIRECTION 1 //Set to -1 to reverse servo direction.
#define SERVO1_MIN 2 //Define minimum servo angles.
#define SERVO2_MIN 2
#define SERVO3_MIN 2 //EDIT*** : Claw – Change Value to avoid collision
#define SERVO4_MIN 2 //EDIT*** : Claw – Change Value to avoid collision
#define SERVO5_MIN 2
#define SERVO6_MIN 2
#define SERVO1_MAX 178 //Define maximum servo angles.
#define SERVO2_MAX 178
#define SERVO3_MAX 178 // EDIT*** : Claw – Change Value to avoid collision
#define SERVO4_MAX 178 // EDIT*** : Claw – Change Value to avoid collision
#define SERVO5_MAX 178
#define SERVO6_MAX 178
#define STICK_CENTER 0 //Value from controller when sticks are centered (127 for PS3 controller, 0 for xbox controller)
#define DEADZONE 7500 //Deadzone to prevent unwanted movement. Defined as 7500 for Xbox360 Controller
//================================ Global Variables ================================//
USB Usb; //USBHub Hub1(&Usb); // Some dongles have a hub inside. Try this is your dongle isn’t working.
XBOXRECV Xbox(&Usb);
Servo servo1; //Instantiate servo variables
Servo servo2;
Servo servo3;
Servo servo4;
Servo servo5;
Servo servo6;
unsigned long previousTime = 0; //for loop timing
int s1 = SERVO1_INIT; //Define variables to store servo positions and set to initial positions
int s2 = SERVO2_INIT;
int s3 = SERVO3_INIT;
int s4 = SERVO4_INIT;
int s5 = SERVO5_INIT;
int s6 = SERVO6_INIT;
//================================ Setup ================================//
void setup() //setup loop
{
Serial.begin(115200);
while (!Serial); // Wait for serial port to connect – used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
if (Usb.Init() == –1) {
Serial.print(F(“rnOSC did not start”));
while (1); //halt
}
Serial.print(F(“rnXbox Wireless Receiver Initiated”));
servo1.detach(); //Initially All Servos Disabled // Waiting for Button to Initialize [ requirement of MAKE course]
servo2.detach();
servo3.detach();
servo4.detach();
servo5.detach();
servo6.detach();
}
//================================ Loop ================================//
void loop() { //Primary runtime loop
Usb.Task(); //Task USB
if(Xbox.XboxReceiverConnected || Xbox.Xbox360Connected) {
for(uint8_t i=0;i<4;i++) { if(Xbox.Xbox360Connected[i]) { //This loop executes only when Xbox 360 controller is connected if(millis() – previousTime > LOOPTIME) {
//Start of timed
if(Xbox.getButtonClick(i,L2)) { //Base Joint Servo PIN2
s1 = s1 + SERVO1_STEP*SERVO1_DIRECTION;
}
else if(Xbox.getButtonClick(i,R2)) {
s1 = s1 – SERVO1_STEP*SERVO1_DIRECTION;
}
if(s1 > SERVO1_MAX) s1 = SERVO1_MAX;
if(s1 < SERVO1_MIN) s1 = SERVO1_MIN; if (Xbox.getAnalogHat(i,RightHatY) > STICK_CENTER + DEADZONE || Xbox.getAnalogHat(i,RightHatY) < STICK_CENTER – DEADZONE) { // Elbow Joint PIN3 //s2 = s2 + (Xbox.getAnalogHat(i,RightHatY) – STICK_CENTER)*SERVO2_RATE*SERVO2_DIRECTION; } if(s2 > SERVO2_MAX) s2 = SERVO2_MAX;
if(s2 < SERVO2_MIN) s2 = SERVO2_MIN; if (Xbox.getAnalogHat(i,LeftHatY) > STICK_CENTER + DEADZONE || Xbox.getAnalogHat(i,LeftHatY) < STICK_CENTER – DEADZONE) { //Servo3 CLAW 1 PIN4 s3 = s3 + (Xbox.getAnalogHat(i,LeftHatY) – STICK_CENTER)*SERVO3_RATE*SERVO3_DIRECTION; } if(s3 > SERVO3_MAX) s3 = SERVO3_MAX;
if(s3 < SERVO3_MIN) s3 = SERVO3_MIN; if (Xbox.getAnalogHat(i,LeftHatY) > STICK_CENTER + DEADZONE || Xbox.getAnalogHat(i,LeftHatY) < STICK_CENTER – DEADZONE) { //Servo4 CLAW 2 Pin5 s4 = s4 + (Xbox.getAnalogHat(i,LeftHatY) – STICK_CENTER)*SERVO4_RATE*SERVO4_DIRECTION; } if(s4 > SERVO4_MAX) s4 = SERVO4_MAX;
if(s4 < SERVO4_MIN) s4 = SERVO4_MIN; if (Xbox.getAnalogHat(i,LeftHatX) > STICK_CENTER + DEADZONE || Xbox.getAnalogHat(i,LeftHatX) < STICK_CENTER – DEADZONE) { //Servo5 Swivel Pin6 s5 = s5 + (Xbox.getAnalogHat(i,LeftHatX) – STICK_CENTER)*SERVO5_RATE*SERVO5_DIRECTION; } if(s5 > SERVO5_MAX) s5 = SERVO5_MAX;
if(s5 < SERVO3_MIN) s5 = SERVO5_MIN; if (Xbox.getAnalogHat(i,RightHatX) > STICK_CENTER + DEADZONE || Xbox.getAnalogHat(i,RightHatX) < STICK_CENTER – DEADZONE) { //Servo6 Spin Claw Pin7 s6 = s6 + (Xbox.getAnalogHat(i,RightHatX) – STICK_CENTER)*SERVO6_RATE*SERVO6_DIRECTION; } if(s6 > SERVO6_MAX) s6 = SERVO6_MAX;
if(s6 < SERVO6_MIN) s6 = SERVO6_MIN;
Serial.print(” s1 = “); //Debug information about servo positions. Uncomment when you are determining servo limits.
Serial.print(s1);
Serial.print(” s2 = “);
Serial.print(s2);
Serial.print(” s3 = “);
Serial.print(s3);
Serial.print(” s4 = “);
Serial.print(s4);
Serial.print(” s5 = “);
Serial.print(s5);
Serial.print(” s6 = “);
Serial.println(s6);
if(Xbox.getButtonClick(i,B)) { // Safety Release
// Detaches all servos – waiting for button to re-engage
servo1.detach();
servo2.detach();
servo3.detach();
servo4.detach();
servo5.detach();
servo6.detach();
}
//Safety Restore
//Also : Initializing Button : creative way to start robot
if(Xbox.getButtonClick(i,A)) {
servo1.attach(2);
servo2.attach(3);
servo3.attach(4);
servo4.attach(5);
servo5.attach(6);
servo6.attach(7);
if(Xbox.getButtonClick(i,START)) { //Reset ALL Servos to initial positions when “start” button is pressed
s1 = SERVO1_INIT;
s2 = SERVO2_INIT;
s3 = SERVO3_INIT;
s4 = SERVO4_INIT;
s5 = SERVO5_INIT;
s6 = SERVO6_INIT;
}
//Following are re-programmable detach buttons for other applications
//Note : Does not have to be limited to just servos
//I.e. could attach, detach led when servo is attached, detached
if(Xbox.getButtonClick(i,X)) //Detach Base Joint
{
servo1.detach();
}
if(Xbox.getButtonClick(i,Y)) { //Detach Elbow Joint
servo2.detach();
}
if(Xbox.getButtonClick(i,UP)) { //Detach Claw 1
servo3.detach();
}
if(Xbox.getButtonClick(i,DOWN)) { //Detach Claw 2
servo4.detach();
}
if(Xbox.getButtonClick(i,RIGHT)) { //Detach Swivel
servo5.detach();
}
if(Xbox.getButtonClick(i,LEFT)) { //Detach Spin Claw
servo6.detach();
}
previousTime = millis(); //save time at end of loop
} //Timed loop
servo1.write(s1); //Write to servos.
servo2.write(s2);
servo3.write(s3);
servo4.write(s4);
servo5.write(s5);
servo6.write(s6);
}
}
}
}
}
|
Incremental control of Servo(s) Using Xbox 360 Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
//Name : Sergei Dines
//Date : 8/6/2014
//Purpose : Incremental control of Servo(s) Using Xbox 360 Controller
#include
#ifdef dobogusinclude
#include<
#endif
#include
//above 5 lines from org
USB Usb;
XBOXRECV Xbox(&Usb);
Servo servo1;
int var1; //retrieves xbox analog values right
int var2; //maps xbox analog to servo values right
int var3; // incremental control
void setup()
{
Serial.begin(115200);
while(!Serial); // wait for serial port to connect
if (Usb.Init() == –1) {
Serial.print(F(“rn0SC did not start”));
while (1); //halt
}
Serial.print(F(“rnXbox Wireless Receiver Library Iniated”));
pinMode(9, OUTPUT);
servo1.attach(9);
}
void loop()
{
Usb.Task();
for (uint8_t i = 0; i < 4; i++) {
if (Xbox.Xbox360Connected[i]) {
//by definition from orginal code
if (Xbox.getAnalogHat(i,LeftHatX)){ //Original Defintion
var1 =Xbox.getAnalogHat(i,LeftHatX); //Var1 gets the org. def
var2 = map(var1, 0, 255, 0, 79); //Var2 converts this code to a useable servo control
servo1.write(var2);
}
Serial.print(F(“LeftHatX: “));
Serial.print(Xbox.getAnalogHat(i,LeftHatX));
Serial.print(“t”);
/*This Code Completes the Objective to move the servo to a specific location and hold it there
but here are the issues :
1] Control too sensitive
2] Jittering occurs
3] No speed control
4] Must move joystick slowly to output accurate movements
*/
}
}
}
|
The code, by default, will output:
NOTE: you must press A to start the robot by the default code
Start-Stop Functions | |
A | Starts Robot |
B | Safety Stop |
Button | Digital Pin |
LT, RT | 2 |
Right Hat Y | 3 |
Left Hat Y | 4 |
Left Hat Y | 5 |
Left Hat X | 6 |
Right Hat X | 7 |
STEP 4 [Optional]: Build Complete AXIOM ARM or your own robotic arm
If you want to design a robotic arm from start to finish, then the following mechanical parts may be mechanical parts useful: download mechanical parts
1. Download Autodesk Inventor 2014
- Go to: Autodesk to create a free profile
- NOTE: When prompted, the material content library is useful but not necessary
2. Download AXIOM ARM Inventor Parts
3. The claws are ready to be 3D printed as is
However: the servo brackets may need adjustments. Amazon has a great servo bracket kit for $90, if you do not plan on designing and modifying the brackets parts;
Parts:
- Polycase
- Toggle Switch w/ Blue Light
- 3D printed Parts
- Buy SainSmart 17DOF Biped Black Educational Robot Kit
- Or : 3D print parts (parts available below)
- Rubber bands
Everything stays the same, the only difference is your circuit will look something like this:
ABOUT SERGEI DINES:
Sergei Dines is a mechanical engineer senior at USF, in FL. His interests include product design and robotics. He states, “going through the design process from scratch is very rewarding; it makes you think how everything is associated and forces you to ask help and connect with like-minded robotic enthusiasts”.
He would like to personally thank Barrett Anderies, Dr. Schlaf [USF], and Anthony Rose [USF] for their expertise.