├── Diagrams └── Robot Arm.png ├── LICENSE ├── README.md └── Robot_Arm └── Robot_Arm.ino /Diagrams/Robot Arm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/un0038998/RobotArm/caa31a2f4c87e73991e78a2724bdf2d39747f97c/Diagrams/Robot Arm.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Ujwal Nandanwar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RobotArm 2 | This repository contains code and diagram for Robot Arm using esp32 controlled using smartphone 3 | -------------------------------------------------------------------------------- /Robot_Arm/Robot_Arm.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | struct ServoPins 11 | { 12 | Servo servo; 13 | int servoPin; 14 | String servoName; 15 | int initialPosition; 16 | }; 17 | std::vector servoPins = 18 | { 19 | { Servo(), 27 , "Base", 90}, 20 | { Servo(), 26 , "Shoulder", 90}, 21 | { Servo(), 25 , "Elbow", 90}, 22 | { Servo(), 33 , "Gripper", 90}, 23 | }; 24 | 25 | struct RecordedStep 26 | { 27 | int servoIndex; 28 | int value; 29 | int delayInStep; 30 | }; 31 | std::vector recordedSteps; 32 | 33 | bool recordSteps = false; 34 | bool playRecordedSteps = false; 35 | 36 | unsigned long previousTimeInMilli = millis(); 37 | 38 | const char* ssid = "RobotArm"; 39 | const char* password = "12345678"; 40 | 41 | AsyncWebServer server(80); 42 | AsyncWebSocket wsRobotArmInput("/RobotArmInput"); 43 | 44 | const char* htmlHomePage PROGMEM = R"HTMLHOMEPAGE( 45 | 46 | 47 | 48 | 49 | 105 | 106 | 107 | 108 | 109 |

Hash Include Electronics

110 |

Robot Arm Control

111 | 112 | 113 | 114 | 115 | 116 | 117 | 122 | 123 | 124 | 125 | 126 | 131 | 132 | 133 | 134 | 135 | 140 | 141 | 142 | 143 | 144 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 |
Gripper: 118 |
119 | 120 |
121 |
Elbow: 127 |
128 | 129 |
130 |
Shoulder: 136 |
137 | 138 |
139 |
Base: 145 |
146 | 147 |
148 |
Record:
Play:
163 | 164 | 232 | 233 | 234 | )HTMLHOMEPAGE"; 235 | 236 | void handleRoot(AsyncWebServerRequest *request) 237 | { 238 | request->send_P(200, "text/html", htmlHomePage); 239 | } 240 | 241 | void handleNotFound(AsyncWebServerRequest *request) 242 | { 243 | request->send(404, "text/plain", "File Not Found"); 244 | } 245 | 246 | void onRobotArmInputWebSocketEvent(AsyncWebSocket *server, 247 | AsyncWebSocketClient *client, 248 | AwsEventType type, 249 | void *arg, 250 | uint8_t *data, 251 | size_t len) 252 | { 253 | switch (type) 254 | { 255 | case WS_EVT_CONNECT: 256 | Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str()); 257 | sendCurrentRobotArmState(); 258 | break; 259 | case WS_EVT_DISCONNECT: 260 | Serial.printf("WebSocket client #%u disconnected\n", client->id()); 261 | break; 262 | case WS_EVT_DATA: 263 | AwsFrameInfo *info; 264 | info = (AwsFrameInfo*)arg; 265 | if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) 266 | { 267 | std::string myData = ""; 268 | myData.assign((char *)data, len); 269 | std::istringstream ss(myData); 270 | std::string key, value; 271 | std::getline(ss, key, ','); 272 | std::getline(ss, value, ','); 273 | Serial.printf("Key [%s] Value[%s]\n", key.c_str(), value.c_str()); 274 | int valueInt = atoi(value.c_str()); 275 | 276 | if (key == "Record") 277 | { 278 | recordSteps = valueInt; 279 | if (recordSteps) 280 | { 281 | recordedSteps.clear(); 282 | previousTimeInMilli = millis(); 283 | } 284 | } 285 | else if (key == "Play") 286 | { 287 | playRecordedSteps = valueInt; 288 | } 289 | else if (key == "Base") 290 | { 291 | writeServoValues(0, valueInt); 292 | } 293 | else if (key == "Shoulder") 294 | { 295 | writeServoValues(1, valueInt); 296 | } 297 | else if (key == "Elbow") 298 | { 299 | writeServoValues(2, valueInt); 300 | } 301 | else if (key == "Gripper") 302 | { 303 | writeServoValues(3, valueInt); 304 | } 305 | 306 | } 307 | break; 308 | case WS_EVT_PONG: 309 | case WS_EVT_ERROR: 310 | break; 311 | default: 312 | break; 313 | } 314 | } 315 | 316 | void sendCurrentRobotArmState() 317 | { 318 | for (int i = 0; i < servoPins.size(); i++) 319 | { 320 | wsRobotArmInput.textAll(servoPins[i].servoName + "," + servoPins[i].servo.read()); 321 | } 322 | wsRobotArmInput.textAll(String("Record,") + (recordSteps ? "ON" : "OFF")); 323 | wsRobotArmInput.textAll(String("Play,") + (playRecordedSteps ? "ON" : "OFF")); 324 | } 325 | 326 | void writeServoValues(int servoIndex, int value) 327 | { 328 | if (recordSteps) 329 | { 330 | RecordedStep recordedStep; 331 | if (recordedSteps.size() == 0) // We will first record initial position of all servos. 332 | { 333 | for (int i = 0; i < servoPins.size(); i++) 334 | { 335 | recordedStep.servoIndex = i; 336 | recordedStep.value = servoPins[i].servo.read(); 337 | recordedStep.delayInStep = 0; 338 | recordedSteps.push_back(recordedStep); 339 | } 340 | } 341 | unsigned long currentTime = millis(); 342 | recordedStep.servoIndex = servoIndex; 343 | recordedStep.value = value; 344 | recordedStep.delayInStep = currentTime - previousTimeInMilli; 345 | recordedSteps.push_back(recordedStep); 346 | previousTimeInMilli = currentTime; 347 | } 348 | servoPins[servoIndex].servo.write(value); 349 | } 350 | 351 | void playRecordedRobotArmSteps() 352 | { 353 | if (recordedSteps.size() == 0) 354 | { 355 | return; 356 | } 357 | //This is to move servo to initial position slowly. First 4 steps are initial position 358 | for (int i = 0; i < 4 && playRecordedSteps; i++) 359 | { 360 | RecordedStep &recordedStep = recordedSteps[i]; 361 | int currentServoPosition = servoPins[recordedStep.servoIndex].servo.read(); 362 | while (currentServoPosition != recordedStep.value && playRecordedSteps) 363 | { 364 | currentServoPosition = (currentServoPosition > recordedStep.value ? currentServoPosition - 1 : currentServoPosition + 1); 365 | servoPins[recordedStep.servoIndex].servo.write(currentServoPosition); 366 | wsRobotArmInput.textAll(servoPins[recordedStep.servoIndex].servoName + "," + currentServoPosition); 367 | delay(50); 368 | } 369 | } 370 | delay(2000); // Delay before starting the actual steps. 371 | 372 | for (int i = 4; i < recordedSteps.size() && playRecordedSteps ; i++) 373 | { 374 | RecordedStep &recordedStep = recordedSteps[i]; 375 | delay(recordedStep.delayInStep); 376 | servoPins[recordedStep.servoIndex].servo.write(recordedStep.value); 377 | wsRobotArmInput.textAll(servoPins[recordedStep.servoIndex].servoName + "," + recordedStep.value); 378 | } 379 | } 380 | 381 | void setUpPinModes() 382 | { 383 | for (int i = 0; i < servoPins.size(); i++) 384 | { 385 | servoPins[i].servo.attach(servoPins[i].servoPin); 386 | servoPins[i].servo.write(servoPins[i].initialPosition); 387 | } 388 | } 389 | 390 | 391 | void setup(void) 392 | { 393 | setUpPinModes(); 394 | Serial.begin(115200); 395 | 396 | WiFi.softAP(ssid, password); 397 | IPAddress IP = WiFi.softAPIP(); 398 | Serial.print("AP IP address: "); 399 | Serial.println(IP); 400 | 401 | server.on("/", HTTP_GET, handleRoot); 402 | server.onNotFound(handleNotFound); 403 | 404 | wsRobotArmInput.onEvent(onRobotArmInputWebSocketEvent); 405 | server.addHandler(&wsRobotArmInput); 406 | 407 | server.begin(); 408 | Serial.println("HTTP server started"); 409 | 410 | } 411 | 412 | void loop() 413 | { 414 | wsRobotArmInput.cleanupClients(); 415 | if (playRecordedSteps) 416 | { 417 | playRecordedRobotArmSteps(); 418 | } 419 | } 420 | --------------------------------------------------------------------------------