0代码,不用app Arduino esp32cam 远程控制Web Server视频小车

使用 ESP32-CAM 构建 Wi-Fi 遥控汽车机器人。您将能够使用Web服务器控制机器人,该服务器显示机器人"看到"的视频流。您可以远程控制您的机器人,即使它不在你的视线范围内。ESP32-CAM 将使用 Arduino IDE 进行编程。

电路板兼容性:此项目需要 4 个 GPIO 来控制直流电机。因此,您可以使用任何带有 4 个可用 GPIO 的 ESP32 相机板,如 ESP32-CAM Ai-Thinker  

项目概况

在开始项目之前,我们将重点介绍用于构建机器人的最重要功能和组件。

无线网络

机器人将使用您的 ESP32-CAM 通过 Wi-Fi 进行控制。我们将创建一个基于Web的界面来控制机器人,可以在本地网络内的任何设备中访问。

该网页还显示了机器人"看到"的视频流。为了获得良好的视频流效果,我们建议使用带外部天线。

机器人控制

Web 服务器有 5 个控件:"前进"、"向后"、"向左"、"向右""停止"

只要您按下按钮,机器人就会移动。当您松开任何按钮时,机器人就会停止。但是,我们包含了"停止"按钮,如果您释放按钮时 ESP32 未收到停止命令,该按钮非常有用。

智能机器人底盘套件

我们将使用智能机器人底盘套件。您可以在大多数在线商店中找到它。该套件的价格约为10美元,并且易于组装 - 观看此视频,了解如何组装机器人底盘套件。

您可以使用任何其他机箱套件,只要它带有两个直流电机即可。

L298N 电机驱动器

控制直流电机的方法有很多种。我们将使用L298N电机驱动器,它提供了一种简单的方法来控制2个直流电机的速度和方向。

为了保持电路简单,我们将使用相同的电源为机器人(电机)和 ESP32 供电。我们使用了移动电源/便携式充电器(就像用于为智能手机充电的充电器一样),效果很好。

 

 注意:电机消耗大量电流,因此,如果您觉得机器人无法正常移动,则可能需要为电机使用外部电源。这意味着您需要两种不同的电源。一个用于为直流电机供电,另一个用于为 ESP32 供电。

部件
对于此项目,我们将使用以下部分:

ESP32-CAM AI-Thinker(安信可原装性能有保障),价格较贵,不带外置天线

ESP32-CAM模块带外置天线,第三方,较实惠
L298N 电机驱动器
机器人汽车底盘套件
移动电源其他5V电源

锂电池充电板
原型电路板(洞洞板排针

代码下载:icon-default.png?t=M1H3https://gitee.com/jun-tian/esp32-cam-wi-fi-car

#include "esp_camera.h"
#include <WiFi.h>
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "fb_gfx.h"
#include "soc/soc.h"             // disable brownout problems
#include "soc/rtc_cntl_reg.h"    // disable brownout problems
#include "esp_http_server.h"

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";//修改为你的wifi名称
const char* password = "REPLACE_WITH_YOUR_PASSWORD";//修改为你的WiFi密码

#define PART_BOUNDARY "123456789000000000000987654321"

#define CAMERA_MODEL_AI_THINKER
//#define CAMERA_MODEL_M5STACK_PSRAM
//#define CAMERA_MODEL_M5STACK_WITHOUT_PSRAM
//#define CAMERA_MODEL_M5STACK_PSRAM_B
//#define CAMERA_MODEL_WROVER_KIT

#if defined(CAMERA_MODEL_WROVER_KIT)
  #define PWDN_GPIO_NUM    -1
  #define RESET_GPIO_NUM   -1
  #define XCLK_GPIO_NUM    21
  #define SIOD_GPIO_NUM    26
  #define SIOC_GPIO_NUM    27
  
  #define Y9_GPIO_NUM      35
  #define Y8_GPIO_NUM      34
  #define Y7_GPIO_NUM      39
  #define Y6_GPIO_NUM      36
  #define Y5_GPIO_NUM      19
  #define Y4_GPIO_NUM      18
  #define Y3_GPIO_NUM       5
  #define Y2_GPIO_NUM       4
  #define VSYNC_GPIO_NUM   25
  #define HREF_GPIO_NUM    23
  #define PCLK_GPIO_NUM    22

#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
  #define PWDN_GPIO_NUM     -1
  #define RESET_GPIO_NUM    15
  #define XCLK_GPIO_NUM     27
  #define SIOD_GPIO_NUM     25
  #define SIOC_GPIO_NUM     23
  
  #define Y9_GPIO_NUM       19
  #define Y8_GPIO_NUM       36
  #define Y7_GPIO_NUM       18
  #define Y6_GPIO_NUM       39
  #define Y5_GPIO_NUM        5
  #define Y4_GPIO_NUM       34
  #define Y3_GPIO_NUM       35
  #define Y2_GPIO_NUM       32
  #define VSYNC_GPIO_NUM    22
  #define HREF_GPIO_NUM     26
  #define PCLK_GPIO_NUM     21

#elif defined(CAMERA_MODEL_M5STACK_WITHOUT_PSRAM)
  #define PWDN_GPIO_NUM     -1
  #define RESET_GPIO_NUM    15
  #define XCLK_GPIO_NUM     27
  #define SIOD_GPIO_NUM     25
  #define SIOC_GPIO_NUM     23
  
  #define Y9_GPIO_NUM       19
  #define Y8_GPIO_NUM       36
  #define Y7_GPIO_NUM       18
  #define Y6_GPIO_NUM       39
  #define Y5_GPIO_NUM        5
  #define Y4_GPIO_NUM       34
  #define Y3_GPIO_NUM       35
  #define Y2_GPIO_NUM       17
  #define VSYNC_GPIO_NUM    22
  #define HREF_GPIO_NUM     26
  #define PCLK_GPIO_NUM     21

#elif defined(CAMERA_MODEL_AI_THINKER)
  #define PWDN_GPIO_NUM     32
  #define RESET_GPIO_NUM    -1
  #define XCLK_GPIO_NUM      0
  #define SIOD_GPIO_NUM     26
  #define SIOC_GPIO_NUM     27
  
  #define Y9_GPIO_NUM       35
  #define Y8_GPIO_NUM       34
  #define Y7_GPIO_NUM       39
  #define Y6_GPIO_NUM       36
  #define Y5_GPIO_NUM       21
  #define Y4_GPIO_NUM       19
  #define Y3_GPIO_NUM       18
  #define Y2_GPIO_NUM        5
  #define VSYNC_GPIO_NUM    25
  #define HREF_GPIO_NUM     23
  #define PCLK_GPIO_NUM     22

#elif defined(CAMERA_MODEL_M5STACK_PSRAM_B)
  #define PWDN_GPIO_NUM     -1
  #define RESET_GPIO_NUM    15
  #define XCLK_GPIO_NUM     27
  #define SIOD_GPIO_NUM     22
  #define SIOC_GPIO_NUM     23
  
  #define Y9_GPIO_NUM       19
  #define Y8_GPIO_NUM       36
  #define Y7_GPIO_NUM       18
  #define Y6_GPIO_NUM       39
  #define Y5_GPIO_NUM        5
  #define Y4_GPIO_NUM       34
  #define Y3_GPIO_NUM       35
  #define Y2_GPIO_NUM       32
  #define VSYNC_GPIO_NUM    25
  #define HREF_GPIO_NUM     26
  #define PCLK_GPIO_NUM     21

#else
  #error "Camera model not selected"
#endif

#define MOTOR_1_PIN_1    14
#define MOTOR_1_PIN_2    15
#define MOTOR_2_PIN_1    13
#define MOTOR_2_PIN_2    12

static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";

httpd_handle_t camera_httpd = NULL;
httpd_handle_t stream_httpd = NULL;

插入您的网络凭据,代码应该立即工作。

const char* ssid = "REPLACE_WITH_YOUR_SSID"; 
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

代码的工作原理

让我们来看看控制机器人的相关部件。定义将控制电机的 GPIO。每个电机由两个引脚控制。

#define MOTOR_1_PIN_1 14
#define MOTOR_1_PIN_2 15
#define MOTOR_2_PIN_1 13
#define MOTOR_2_PIN_2 12

单击这些按钮时,将在其他 URL 上发出请求。

<table>
    <tr><td colspan="3" align="center"><button class="button" onmousedown="toggleCheckbox('forward');" ontouchstart="toggleCheckbox('forward');" onmouseup="toggleCheckbox('stop');" ontouchend="toggleCheckbox('stop');">Forward</button></td></tr>
    <tr><td align="center"><button class="button" onmousedown="toggleCheckbox('left');" ontouchstart="toggleCheckbox('left');" onmouseup="toggleCheckbox('stop');" ontouchend="toggleCheckbox('stop');">Left</button></td><td align="center"><button class="button" onmousedown="toggleCheckbox('stop');" ontouchstart="toggleCheckbox('stop');">Stop</button></td><td align="center"><button class="button" onmousedown="toggleCheckbox('right');" ontouchstart="toggleCheckbox('right');" onmouseup="toggleCheckbox('stop');" ontouchend="toggleCheckbox('stop');">Right</button></td></tr>
    <tr><td colspan="3" align="center"><button class="button" onmousedown="toggleCheckbox('backward');" ontouchstart="toggleCheckbox('backward');" onmouseup="toggleCheckbox('stop');" ontouchend="toggleCheckbox('stop');">Backward</button></td></tr>                   
</table>
<script>
    function toggleCheckbox(x) {
      var xhr = new XMLHttpRequest();
      xhr.open("GET", "/action?go=" + x, true);
      xhr.send();
    }
   window.onload = document.getElementById("photo").src =     window.location.href.slice(0, -1) + ":81/stream";
</script>

以下是根据所按下的按钮发出的请求:

向前:

<ESP_IP_ADDRESS>/action?go=forward

向后:

/action?go=backward

左:

/action?go=left

右:

/action?go=right

停:

/action?go=stop

当您松开按钮时,将在/action?go=stop网址。机器人只有在您按下按钮时才会移动。

处理请求

为了处理当我们收到对这些URL的请求时发生的情况,我们使用这些如果...其他语句:

<span style="background-color:#f5f2f0"><span style="color:#000000"><code class="language-c"><span style="color:#0077aa">if</span><span style="color:#999999">(</span><span style="background-color:rgba(255, 255, 255, 0.5)"><span style="color:#9a6e3a">!</span></span><span style="color:#dd4a68">strcmp</span><span style="color:#999999">(</span>variable<span style="color:#999999">,</span> <span style="color:#669900">"forward"</span><span style="color:#999999">)</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
    Serial<span style="color:#999999">.</span><span style="color:#dd4a68">println</span><span style="color:#999999">(</span><span style="color:#669900">"Forward"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_1_PIN_1<span style="color:#999999">,</span> <span style="color:#990055">1</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_1_PIN_2<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_2_PIN_1<span style="color:#999999">,</span> <span style="color:#990055">1</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
    <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_2_PIN_2<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
 <span style="color:#999999">}</span>
 <span style="color:#0077aa">else</span> <span style="color:#0077aa">if</span><span style="color:#999999">(</span><span style="background-color:rgba(255, 255, 255, 0.5)"><span style="color:#9a6e3a">!</span></span><span style="color:#dd4a68">strcmp</span><span style="color:#999999">(</span>variable<span style="color:#999999">,</span> <span style="color:#669900">"left"</span><span style="color:#999999">)</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
   Serial<span style="color:#999999">.</span><span style="color:#dd4a68">println</span><span style="color:#999999">(</span><span style="color:#669900">"Left"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_1_PIN_1<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_1_PIN_2<span style="color:#999999">,</span> <span style="color:#990055">1</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_2_PIN_1<span style="color:#999999">,</span> <span style="color:#990055">1</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_2_PIN_2<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#0077aa">else</span> <span style="color:#0077aa">if</span><span style="color:#999999">(</span><span style="background-color:rgba(255, 255, 255, 0.5)"><span style="color:#9a6e3a">!</span></span><span style="color:#dd4a68">strcmp</span><span style="color:#999999">(</span>variable<span style="color:#999999">,</span> <span style="color:#669900">"right"</span><span style="color:#999999">)</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
   Serial<span style="color:#999999">.</span><span style="color:#dd4a68">println</span><span style="color:#999999">(</span><span style="color:#669900">"Right"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_1_PIN_1<span style="color:#999999">,</span> <span style="color:#990055">1</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_1_PIN_2<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_2_PIN_1<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_2_PIN_2<span style="color:#999999">,</span> <span style="color:#990055">1</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#0077aa">else</span> <span style="color:#0077aa">if</span><span style="color:#999999">(</span><span style="background-color:rgba(255, 255, 255, 0.5)"><span style="color:#9a6e3a">!</span></span><span style="color:#dd4a68">strcmp</span><span style="color:#999999">(</span>variable<span style="color:#999999">,</span> <span style="color:#669900">"backward"</span><span style="color:#999999">)</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
   Serial<span style="color:#999999">.</span><span style="color:#dd4a68">println</span><span style="color:#999999">(</span><span style="color:#669900">"Backward"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_1_PIN_1<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_1_PIN_2<span style="color:#999999">,</span> <span style="color:#990055">1</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_2_PIN_1<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_2_PIN_2<span style="color:#999999">,</span> <span style="color:#990055">1</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#0077aa">else</span> <span style="color:#0077aa">if</span><span style="color:#999999">(</span><span style="background-color:rgba(255, 255, 255, 0.5)"><span style="color:#9a6e3a">!</span></span><span style="color:#dd4a68">strcmp</span><span style="color:#999999">(</span>variable<span style="color:#999999">,</span> <span style="color:#669900">"stop"</span><span style="color:#999999">)</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
   Serial<span style="color:#999999">.</span><span style="color:#dd4a68">println</span><span style="color:#999999">(</span><span style="color:#669900">"Stop"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_1_PIN_1<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_1_PIN_2<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_2_PIN_1<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
   <span style="color:#dd4a68">digitalWrite</span><span style="color:#999999">(</span>MOTOR_2_PIN_2<span style="color:#999999">,</span> <span style="color:#990055">0</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span></code></span></span>

测试代码

插入网络凭据后,您可以将代码上传到 ESP32-CAM 开发板。

上传后,打开串行监视器以获取其IP地址。

.

打开浏览器并键入 ESP IP 地址。类似的网页应加载:

 

按下按钮并查看串行监视器,以查看它是否正在流式传输而没有延迟,以及它是否正在接收命令而不会崩溃。

 

 如果一切正常,是时候组装电路了。

电路

组装机器人底盘后,您可以按照下一个原理图连接电路。.

首先将 ESP32-CAM 连接到电机驱动器,如原理图所示。您可以使用迷你试验板或脱衣板来放置 ESP32-CAM 并构建电路。

下表显示了 ESP32-CAM 和 L298N 电机驱动器之间的连接。

L298N 电机驱动器 ESP32-凸轮
国家警察 GPIO 14
IN2 GPIO 15
高级护士 GPIO 13
IN4 GPIO 12

 我们将所有连接组装在一个迷你条板上,如下所示。

之后,将每个电机连接到其接线端子。

注意:我们建议将0.1 uF陶瓷电容器焊接到每个电机的正极和负极,如图所示,以帮助平滑任何电压尖峰。此外,您可以将滑块开关焊接到来自移动电源的红线上。这样,您可以打开和关闭电源。

最后,使用移动电源供电,如图示意图所示。您需要剥离USB电缆。在这个例子中,ESP32-CAM和电机使用相同的电源供电,并且运行良好。

注意:电机消耗大量电流,因此,如果您觉得机器人的移动速度不够快,则可能需要为电机使用外部电源。这意味着您需要两种不同的电源。一个用于为直流电机供电,另一个用于为 ESP32 供电。您可以使用 4 AA 电池组为电机供电。当您获得机器人底盘套件时,您通常会获得一个用于4节AA电池的电池座。

您的机器人应类似于下图:

 

不要忘记,您应该将外部天线与 ESP32-CAM 配合使用,否则 Web 服务器可能会非常慢。

示范

在 ESP32-CAM IP 地址上打开浏览器,您应该能够控制您的机器人。Web服务器在笔记本电脑或智能手机上运行良好。

您一次只能在一个设备/选项卡中打开Web服务器。

结束语

在本教程中,您学习了如何使用 ESP32-CAM 构建遥控机器人,以及如何使用 Web 服务器对其进行控制。

使用 ESP32-CAM 控制直流电机与使用"常规"ESP32 控制直流电机相同。

 如果要在本地网络范围之外控制机器人,可以考虑将 ESP32-CAM 设置为接入点。这样,ESP32-CAM 就不需要连接到您的路由器,它会创建自己的 Wi-Fi 网络,附近的 Wi-Fi 设备(如智能手机)可以连接到它。

猜你喜欢

转载自blog.csdn.net/u014331212/article/details/123004208