This shows you the differences between two versions of the page.
|
iothings:proiecte:2022:proiect_costin_vasile [2023/01/19 21:45] costin.vasile1003 |
iothings:proiecte:2022:proiect_costin_vasile [2023/01/19 23:59] (current) costin.vasile1003 |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== WiFi-controlled surveillance system ====== | ====== WiFi-controlled surveillance system ====== | ||
| **Student: ** Costin-Emanuel Vasile (ACES) | **Student: ** Costin-Emanuel Vasile (ACES) | ||
| + | |||
| + | All the materials, including the source code and presentation, are [[https://drive.google.com/file/d/151IeY4q_suLt7SAYGVkuXzN0IbmFm5n2/view?usp=sharing|here]] | ||
| ===== 1. Project overview ===== | ===== 1. Project overview ===== | ||
| Line 41: | Line 43: | ||
| ===== 3. Software ===== | ===== 3. Software ===== | ||
| - | TODO | + | The starting point of this project was the official ESP32-CAM webserver example which can be found [[https://github.com/espressif/arduino-esp32/tree/master/libraries/ESP32/examples/Camera/CameraWebServer|in this repository]], which I simplified and changed to fit the needs of the project. |
| + | |||
| + | The main functions that the module has to do are the following: | ||
| + | * Connect to WiFi to be accessible from local network | ||
| + | * Host a web platform to provide access to the video stream and movement controls | ||
| + | * Drive the motors according to the commands received from the user through the web platform | ||
| + | |||
| + | The updates I added to the initial code are detailed below. | ||
| + | |||
| + | == Simple HTML index == | ||
| + | From the initial HTML index I removed all the controls available and kept only the video stream and flashlight controlls. On top of this I added the code for the five buttons: | ||
| + | * Added the buttons in the body of the HTML: | ||
| + | <code html> | ||
| + | <button id="drive_stop" style="float:left;" title="">Stop</button> | ||
| + | <button id="drive_front" style="float:left;" title="">Front</button> | ||
| + | <button id="drive_back" style="float:left;" title="">Back</button> | ||
| + | <button id="drive_left" style="float:left;" title="">Left</button> | ||
| + | <button id="drive_right" style="float:left;" title="">Right</button> | ||
| + | </code> | ||
| + | * Added the behavior of the buttons in the <script> side of the HTML index: | ||
| + | |||
| + | <code javascript> | ||
| + | const driveStopButton = document.getElementById('drive_stop') | ||
| + | const driveFrontButton = document.getElementById('drive_front') | ||
| + | const driveBackButton = document.getElementById('drive_back') | ||
| + | const driveLeftButton = document.getElementById('drive_left') | ||
| + | const driveRightButton = document.getElementById('drive_right') | ||
| + | |||
| + | driveStopButton.onclick = () => { | ||
| + | var xhr = new XMLHttpRequest(); | ||
| + | xhr.open('post', 'http://192.168.0.128/?direction=stop', true); | ||
| + | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); | ||
| + | xhr.send(); | ||
| + | } | ||
| + | driveFrontButton.onclick = () => { | ||
| + | var xhr = new XMLHttpRequest(); | ||
| + | xhr.open('post', 'http://192.168.0.128/?direction=front', true); | ||
| + | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); | ||
| + | xhr.send(); | ||
| + | } | ||
| + | driveBackButton.onclick = () => { | ||
| + | var xhr = new XMLHttpRequest(); | ||
| + | xhr.open('post', 'http://192.168.0.128/?direction=back', true); | ||
| + | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); | ||
| + | xhr.send(); | ||
| + | } | ||
| + | driveLeftButton.onclick = () => { | ||
| + | var xhr = new XMLHttpRequest(); | ||
| + | xhr.open('post', 'http://192.168.0.128/?direction=left', true); | ||
| + | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); | ||
| + | xhr.send(); | ||
| + | } | ||
| + | driveRightButton.onclick = () => { | ||
| + | var xhr = new XMLHttpRequest(); | ||
| + | xhr.open('post', 'http://192.168.0.128/?direction=right', true); | ||
| + | xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); | ||
| + | xhr.send(); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | == Camera server == | ||
| + | For the server configuration I declared and registered a new URI handler as follows: | ||
| + | <code cpp> | ||
| + | httpd_uri_t direction_index_uri = { | ||
| + | .uri = "/", | ||
| + | .method = HTTP_POST, | ||
| + | .handler = direction_index_handler, | ||
| + | .user_ctx = NULL | ||
| + | }; | ||
| + | |||
| + | httpd_register_uri_handler(camera_httpd, &direction_index_uri); | ||
| + | </code> | ||
| + | |||
| + | The handler registers the following function used to answer to the requests: | ||
| + | <code cpp> | ||
| + | static esp_err_t direction_index_handler(httpd_req_t *req){ | ||
| + | char* buf; | ||
| + | size_t buf_len; | ||
| + | char dir[32] = {0,}; | ||
| + | |||
| + | buf_len = httpd_req_get_url_query_len(req) + 1; | ||
| + | if (buf_len > 1) { | ||
| + | buf = (char*)malloc(buf_len); | ||
| + | if(!buf){ | ||
| + | httpd_resp_send_500(req); | ||
| + | return ESP_FAIL; | ||
| + | } | ||
| + | if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) { | ||
| + | if (httpd_query_key_value(buf, "direction", dir, sizeof(dir)) == ESP_OK) { | ||
| + | } else { | ||
| + | free(buf); | ||
| + | httpd_resp_send_404(req); | ||
| + | return ESP_FAIL; | ||
| + | } | ||
| + | } else { | ||
| + | free(buf); | ||
| + | httpd_resp_send_404(req); | ||
| + | return ESP_FAIL; | ||
| + | } | ||
| + | free(buf); | ||
| + | } | ||
| + | |||
| + | Serial.print("New movement request: "); Serial.println(dir); | ||
| + | drive(dir); | ||
| + | return ESP_OK; | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | The function above calls the method below which I implemented to drive the motors using the H-bridge module. It sends a PWM signal to the module by calling the built-in Arduino method called ledcWrite. | ||
| + | |||
| + | The pin used to control each side of the H-bridge was mapped to a different PWM output of the ESP32-CAM board. This PWM output represents the first argument of the ledcWrite function, the second being the duty-cycle (where 0 means 0% and 255 means 100% duty-cycle). | ||
| + | |||
| + | <code cpp> | ||
| + | void drive(char* dir){ | ||
| + | ledcWrite(0, 0); | ||
| + | ledcWrite(1, 0); | ||
| + | ledcWrite(2, 0); | ||
| + | ledcWrite(3, 0); | ||
| + | |||
| + | if(strcmp(dir, "right") == 0){ | ||
| + | ledcWrite(0, 150); | ||
| + | ledcWrite(1, 0); | ||
| + | ledcWrite(2, 150); | ||
| + | ledcWrite(3, 0); | ||
| + | } | ||
| + | else if(strcmp(dir, "left") == 0){ | ||
| + | ledcWrite(0, 0); | ||
| + | ledcWrite(1, 150); | ||
| + | ledcWrite(2, 0); | ||
| + | ledcWrite(3, 150); | ||
| + | } | ||
| + | else if(strcmp(dir, "back") == 0) { | ||
| + | ledcWrite(0, 0); | ||
| + | ledcWrite(1, 170); | ||
| + | ledcWrite(2, 170); | ||
| + | ledcWrite(3, 0); | ||
| + | } | ||
| + | else if(strcmp(dir, "front") == 0) { | ||
| + | ledcWrite(0, 170); | ||
| + | ledcWrite(1, 0); | ||
| + | ledcWrite(2, 0); | ||
| + | ledcWrite(3, 170); | ||
| + | } | ||
| + | } | ||
| + | </code> | ||
| ===== 4. Results and demonstration ===== | ===== 4. Results and demonstration ===== | ||
| - | TODO | + | I uploaded a demonstrative video [[https://www.youtube.com/shorts/r5RtWcMs1yU|here]]. |
| + | |||
| + | Below are some images with the final prototype of the car. | ||
| + | == Front view == | ||
| + | {{ :iothings:proiecte:2022:front_costin.jpeg?300 |}} | ||
| + | |||
| + | == Side view == | ||
| + | {{ :iothings:proiecte:2022:side_costin.jpeg?300 |}} | ||
| + | |||
| + | == Back view == | ||
| + | {{ :iothings:proiecte:2022:back_costin.jpeg?300 |}} | ||
| + | |||
| + | == Bottom view == | ||
| + | {{ :iothings:proiecte:2022:below_view_costin.jpeg?300 |}} | ||
| + | |||
| + | == Web platform == | ||
| + | {{ :iothings:proiecte:2022:web_platform_costin.png?300 |}} | ||
| + | |||
| + | ===== 5. Resources ===== | ||
| + | [[https://github.com/easytarget/esp32-cam-webserver]] | ||
| + | |||
| + | [[https://github.com/espressif/arduino-esp32/tree/master/libraries/ESP32/examples/Camera/CameraWebServer]] | ||
| + | |||
| + | [[https://randomnerdtutorials.com/esp32-cam-car-robot-web-server/]] | ||
| + | |||
| + | [[https://www.optimusdigital.ro/ro/]] | ||