基于ESP32—CAM物联网WIFI小车

news2024/12/24 9:03:36

一.功能概述

        摄像头的画面可以实时的传输到,点灯科技APP的手机端,这样可以实时查看周围环境的状况,灯光不足,画面不清晰时可以打开灯光照明。手机端有左转、右转、前进、后退、停止的按钮。可以根据自己需要,来控制小车。手机APP端还设有模式切换的按钮,可以根据需要进行避障和手动模式的切换。

二、项目模块

小车套件,舵机、esp32-cam、稳压模块、电机驱动模块、超声波模块、开光按钮

三、代码演示

#define BLINKER_WIFI
#include <Blinker.h>
#include "ESP32_CAM_SERVER.h"

#define LED 4
#define DriveLeft_A   13         //控制左轮转动方向
#define DriveLeft_B   15
#define DriveRight_A  14        //控制右轮转动方向
#define DriveRight_B  2
#define ServoPin 12  //舵机的引脚
#define Echo     3  //超声波echo
#define Trig     1  //超声波trig

const char* ssid = "nova7";         //wifi账号
const char* password = "66666666";  //wifi密码
char auth[] = "5e3ebc64737f";
int modeflag;
int Wave_len_R;
int Wave_len_L;
bool setup_camera = false;//摄像头默认不开启


BlinkerButton Button1("GoForward"); //前进按键
BlinkerButton Button2("GoBack");    //后退按键
BlinkerButton Button3("Left");      //左转按键
BlinkerButton Button4("Right");     //右转按键
BlinkerButton Button5("Stop");      //停车按键
BlinkerButton Button6("led");       //led灯
BlinkerButton Button7("mode");      //模式切换按钮
BlinkerSlider Slider1("duoji");     //舵机滑块

//****定义运动函数***********************************//
void Go_Forward( )       // 前进 
{
  digitalWrite(DriveLeft_A, HIGH);
  digitalWrite(DriveRight_A, HIGH);

  digitalWrite(DriveLeft_B, LOW); 
  digitalWrite(DriveRight_B, LOW);
}

void Go_Back( )         //后退  
{ 
  digitalWrite(DriveLeft_A, LOW);
  digitalWrite(DriveRight_A, LOW); 

  digitalWrite(DriveLeft_B, HIGH);
  digitalWrite(DriveRight_B, HIGH);
}
void Stop_Car( )       //停止
{
  digitalWrite(DriveLeft_A, LOW);
  digitalWrite(DriveLeft_B, LOW);
  digitalWrite(DriveRight_A, LOW);
  digitalWrite(DriveRight_B, LOW);
}

void Turn_Left( )// 左转
{
    digitalWrite(DriveLeft_A, LOW);
    digitalWrite(DriveRight_A, HIGH);//左轮后退

    digitalWrite(DriveLeft_B, HIGH);//右轮前进
    digitalWrite(DriveRight_B, LOW);
}

void Turn_Right( )// 右转 
{
    digitalWrite(DriveLeft_A, HIGH);//左轮前进
    digitalWrite(DriveRight_A, LOW);

    digitalWrite(DriveLeft_B, LOW);
    digitalWrite(DriveRight_B, HIGH);//右轮后退

}

//超声波计算距离函数
long getTime() 
{
  digitalWrite(Trig, HIGH);
  delayMicroseconds(10);            //发送10us的高电平 让超声波工作
  digitalWrite(Trig, LOW);
  return pulseIn(Echo, HIGH);       //返回接收到高电平时的时间
}

//舵机的旋转函数
void Myservo(int angle)
{
  for (int i = 0; i < 5; i++) {
    int pulsewidth = (angle * 11) + 500;        //将角度转化为500-2480的脉宽值
    digitalWrite(ServoPin, HIGH);               //将舵机接口电平至高
    delayMicroseconds(pulsewidth);              //延时脉宽值的微秒数
    digitalWrite(ServoPin, LOW);                //将舵机接口电平至低
    delayMicroseconds(20000 - pulsewidth);      //延时脉宽值的微秒数
  }
  delay(10);
}


void button1_callback(const String & state)                 //定义前进按钮
{
  BLINKER_LOG("get button state: ", state);
  if (state == "press" || state == "tap") {                 //判断按键是否被按下
    Go_Forward();    
  }
  else if (state == "pressup") {                            //判断按键是否松开
    Stop_Car( );
  }
}

void button2_callback(const String & state)                 //定义后退按钮
{
  BLINKER_LOG("get button state: ", state);
  if (state == "press" || state == "tap") {         //判断按键是否按下 或者按下但没有松手
    Go_Back( );
  }
  else if (state == "pressup") {
    Stop_Car( );
  }
}

void button3_callback(const String & state)                  //定义左转按钮
{
  BLINKER_LOG("get button state: ", state);
  if (state == "press" || state == "tap") {
    Turn_Left( );
    delay(100);
    Stop_Car( );
  }
  else if (state == "pressup") {
    Stop_Car( );
  }
}

void button4_callback(const String & state)                  //定义右转按钮
{
  BLINKER_LOG("get button state: ", state);
  if (state == "press" || state == "tap") {
    Turn_Right( );
    delay(100);
    Stop_Car( );
  }
  else if (state == "pressup") {
    Stop_Car( );
  }
}

void button5_callback(const String & state)                  //定义停止按钮
{
  BLINKER_LOG("get button state: ", state);

  Stop_Car( );
}

// 按下LED按键即会执行该函数
void button6_callback(const String & state)                  //定义LED灯开关按钮
{
  BLINKER_LOG("get button state: ", state);
  digitalWrite(LED, !digitalRead(LED));

}

// // 切换模式的按键
void button7_callback(const String & state)                  
{
  BLINKER_LOG("get button state: ", state);
  if(state=="on")
  {
      modeflag = 1;
      Button7.print("on");
      Blinker.notify("开启避障模式");    
      Stop_Car();  
  }
  else if(state == "off") 
  {
    modeflag = 0;
    Button7.print("off");
    Blinker.notify("遥控模式");
    Stop_Car();
  }
  Blinker.vibrate();  //手机震动

} 
//滑动滑块就要执行的函数
void slider1_callback(int32_t value)
{
    int val = value;
    Myservo(val);   //转动多少度
}

//反馈点灯科技平台的状态
void dataRead(const String & data)
{
    BLINKER_LOG("Blinker readString: ", data);

    Blinker.vibrate();
    
    uint32_t BlinkerTime = millis();
    
    Blinker.print("millis", BlinkerTime);
}

void setup()
{
    // //超声波的初始化
    pinMode(Trig,OUTPUT);
    pinMode(Echo,INPUT);
    //led灯的初始化
    pinMode(LED,OUTPUT);
    digitalWrite(LED,LOW);
    pinMode(ServoPin,OUTPUT);
    Myservo(90);    
     //小车电机引脚设置
    pinMode(DriveLeft_A, OUTPUT);         
    pinMode(DriveLeft_B, OUTPUT);
    pinMode(DriveRight_A, OUTPUT);
    pinMode(DriveRight_B, OUTPUT);
    // Serial.begin(115200);
    //esp32-cam的连接到点灯科技平台
    BLINKER_DEBUG.stream(Serial);//点灯科技串口的debug
    Blinker.begin(auth,ssid,password);//通过wifi,密钥,密码连接平台
    Blinker.attachData(dataRead);//反馈点灯科技的状态


 //**********注册App按钮对应动作函数********************************//
    Button1.attach(button1_callback);
    Button2.attach(button2_callback);
    Button3.attach(button3_callback);
    Button4.attach(button4_callback);
    Button5.attach(button5_callback);
    Button6.attach(button6_callback);//起到关联处理按键控制函数的作用
    Button7.attach(button7_callback);//模式切换按键的关联
    Slider1.attach(slider1_callback);//滑块的关联函数
}

void loop()
{
    Blinker.run();//连接点灯科技
    int Wave_len = 0;
    if(modeflag == 0)
    {
        //获取超声波的数据
        Wave_len =  getTime()/58;
        if((Wave_len > 1) && (Wave_len < 25))
        {
            Stop_Car();             //停车
            digitalWrite(LED,HIGH);//开灯
            Go_Back();             //后退
            delay(100);
            Stop_Car();         //停车
            digitalWrite(LED,LOW);//关灯
        }
    }
    //避障模式
    else if(modeflag == 1)
    {
        Go_Forward();
        //获取超声波的数据
        Wave_len =  getTime()/58;
        if((Wave_len > 1) && (Wave_len < 25))
        {
            Stop_Car();             //停车
            digitalWrite(LED,HIGH);//开灯
            Wave_len =  getTime()/58;
            if(Wave_len >1 && Wave_len <15)
            {
                digitalWrite(LED,HIGH);//开灯
                Go_Back();             //后退
                delay(100);
                Stop_Car();         //停车
                digitalWrite(LED,LOW);//关灯
            }
            else
            {
                Stop_Car();
                Myservo(135);
                Wave_len_L =  getTime()/58;
                delay(1000);
                Myservo(45);
                Wave_len_R = getTime()/58;
                delay(1000);
                Myservo(90);
                delay(100);
                if(Wave_len_R >= Wave_len_L)//右边的距离大于左边
                {
                    
                    do{
                        Turn_Right();
                        delay(100);
                        Wave_len_R =  getTime()/58;
                    }while((Wave_len_R > 1) && (Wave_len_R < 25));
                }
                else if(Wave_len_R < Wave_len_L)
                {
                    do
                    {
                        Turn_Left();
                        delay(100);
                        Wave_len_L =  getTime()/58;
                    }while((Wave_len_L > 1) && (Wave_len_L <25));
                }
            }

        }
       
    }

    if (Blinker.connected() && !setup_camera)
    {
        setupCamera();
        setup_camera = true;
        Blinker.printObject("video", "{\"str\":\"mjpg\",\"url\":\"http://"+ WiFi.localIP().toString() + "\"}");
    }
}

四、视频演示

视频地址:https://live.csdn.net/v/382534?spm=1001.2014.3001.5501icon-default.png?t=N7T8https://live.csdn.net/v/382534?spm=1001.2014.3001.5501

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1634340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

变革 Perplexica:AI驱动的问答搜索引擎

Perplexica是一个开源的人工智能搜索工具&#xff0c;也可以说是一款人工智能搜索引擎&#xff0c;它深入互联网以找到答案。受Perplexity AI启发&#xff0c;它是一个开源选择&#xff0c;不仅可以搜索网络&#xff0c;还能理解您的问题。它使用先进的机器学习算法&#xff0c…

【doghead】修改abseil-cpp 构造worker成功

台式机 13900k 的wsl2 ubuntu22.04 环境root@DESKTOP-1723CM1:/mnt/d/XTRANS/thunderbolt/ayame/zhb-bifrost/Bifrost-202403/worker/build# uname -a Linux DESKTOP-1723CM1 5.15.146.1-microsoft-standard-WSL2 #1 SMP Thu Jan 11 04:09:03 UTC 2024 x86_64 x86_64 x86_64 GN…

电商技术揭秘四十:电商智能风控系统决策引擎浅析

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘二十八&#xff1a;安全与合规性保障 电商技术揭秘二十九&#xff1a;电商法律合规浅析 电商技术揭秘三十&#xff1a;知识产权保…

Grafana页面嵌入自建Web应用页面

目录 一、应用场景 二、实现方式 1、修改Grafana配置文件 2、获取监控页面url 3、隐藏左侧和顶部菜单 一、应用场景 需要将Grafana监控页面嵌入自建Web应用页面&#xff0c;使Grafana监控页面成为自建Web应用的一部分。 二、实现方式 总体思路&#xff1a;修改Grafana配…

嵌入式移植7Z解压缩(纯C)

本文分享一个纯C语言编写的7Z解压缩代码库&#xff0c;本代码库的主要目的是在嵌入式环境下使用7z解压缩文件&#xff0c;可以将升级包通过7z进行压缩&#xff0c;然后发送给设备&#xff0c;减小和设备传输过程中的文件大小&#xff0c;进而达到传输大文件的目的。 下载链接 …

[CUDA 学习笔记] GEMM 优化: 双缓冲 (Prefetch) 和 Bank Conflict 解决

GEMM 优化: 双缓冲 (Prefetch) 和 Bank Conflict 解决 前言 本文主要是对 深入浅出GPU优化系列&#xff1a;GEMM优化&#xff08;一&#xff09; - 知乎, 深入浅出GPU优化系列&#xff1a;GEMM优化&#xff08;二&#xff09; - 知乎 以及 深入浅出GPU优化系列&#xff1a;GE…

Python数组类+AI插件

目录 规划实现初始化插入删除查找 AI插件单测注释调优建议 小结 规划 先想清楚都写哪些&#xff0c;然后再动手操作 用Python写了一个简单数组类&#xff0c;首先思考下都写哪些功能&#xff1a; 插入删除查找用插件做单元测试和写注释 目的只是实现一个简单的数组类&#x…

React + 项目(从基础到实战) -- 第十期

目标 学会react 状态管理工具 使用redux管理用户状态 Context 跨层级传递,不像props层层传递类似于Vue的provide/inject用于:切换主题颜色,切换语言 useReducer useState 的替代方案 简化版的redux MobX 1. MobX 介绍 MobX 中文文档 声明式的修改数据 , 像vue state ac…

数据结构-AVL树

目录 什么是 AVL 树 ASL 度量查找效率 结构体定义 平衡调整 调整类型 左旋和右旋 右旋 左旋 左、右平衡调整 左平衡调整 右平衡调整 插入数据 模拟建立 AVL 树 什么是 AVL 树 二叉排序树的形状取决于数据集&#xff0c;当二叉树的高度越小、结构越合理&#xff0c…

利用GaussDB的可观测性能力构建故障模型

D-SMART高斯专版已经开发了几个月了&#xff0c;目前主要技术问题都已经解决&#xff0c;也能够初步看到大概的面貌了。有朋友问我&#xff0c;GaussDB不已经有了TPOPS了&#xff0c;为什么你们还要开发D-SMART高斯专版呢&#xff1f; 实际上TPOPS和D-SMART虽然都可以用于Gaus…

Qt客服端开发的组件库

Qt 是一个功能丰富的跨平台 C 应用程序框架&#xff0c;它包含了许多用于不同目的的组件库。以下是一些主要的 Qt 组件库&#xff0c;这些库为开发者提供了广泛的工具和功能&#xff0c;以便构建复杂的应用程序。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&a…

前端页面单元测试最佳策略:全面涵盖逻辑、组件、流程、UI及性能优化测试,全面保障软件应用的质量

页面级别的测试要求我们从更宏观的角度审视应用&#xff0c;不仅关注单个组件的正确性&#xff0c;还要确保组件间的协作无误&#xff0c;以及用户在应用中的完整体验。通过集成测试、E2E测试和场景测试&#xff0c;我们可以更全面地覆盖应用的各种使用情况&#xff0c;提高软件…

实战干货|Spark 在袋鼠云数栈的深度探索与实践

Spark 是一个快速、通用、可扩展的大数据计算引擎&#xff0c;具有高性能、易用、容错、可以与 Hadoop 生态无缝集成、社区活跃度高等优点。在实际使用中&#xff0c;具有广泛的应用场景&#xff1a; 数据清洗和预处理&#xff1a;在大数据分析场景下&#xff0c;数据通常需要…

解决React报错Encountered two children with the same key

当我们从map()方法返回的两个或两个以上的元素具有相同的key属性时&#xff0c;会产生"Encountered two children with the same key"错误。为了解决该错误&#xff0c;为每个元素的key属性提供独一无二的值&#xff0c;或者使用索引参数。 这里有个例子来展示错误是…

学习【Mysql运维篇】这一篇就够了

运维篇 1. 日志1-1. 错误日志1-2. 二进制日志1-3. 查询日志1-4. 慢查询日志 2. 主从复制2-1. 概述2-2. 原理2-3. 搭建 3. 分库分表3-1. 介绍3-2. Mycat概述3-3. Mycat入门3-4. Mycat配置3-5. Mycat分片3-6. Mycat管理及监控 4. 读写分类 1. 日志 1-1. 错误日志 错误日志是MyS…

【hackmyvm】vivifytech靶机

渗透思路 信息收集端口扫描端口服务信息目录扫描爆破hydra--sshgit提权 信息收集 ┌──(kali㉿kali)-[~] └─$ fping -ag 192.168.9.0/24 2>/dev/null 192.168.9.119 --主机 192.168.9.164 --靶机个人习惯&#xff0c;也方便后续操作&#xff0c;将IP地址赋值给一个变…

IDEA 创建Servlet-HelloWorldServlet

servlet 1.创建空项目2.配置web项目3.配置Tomcat4.加载Tomcat包5.创建HelloWorldServlet类6.配置web.xml7.运行get与post请求 1.创建空项目 2.配置web项目 3.配置Tomcat 4.加载Tomcat包 5.创建HelloWorldServlet类 public class controller extends HttpServlet {Override//get…

【Hadoop】MapReduce (五)

MapReduce 入门案例练习 统计文件中每一个单词出现的次数(文件&#xff1a;words.txt)对IP去重(文件&#xff1a;ip.txt) 组件 序列化 - Writable 统计每一个人花费的上行流量、下行流量以及总流量(文件&#xff1a;flow.txt) 在MapReduce中&#xff0c;各个节点之间基本上…

【面试经典 150 | 图的广度优先搜索】最小基因变化

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;广搜 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行回顾…

Java使用SpringBoot和EasyExcel 实现动态数据导出实战

Java使用SpringBoot和EasyExcel 实现动态数据导出实战 1、前言2、【资源地址】3、代码示例(demo)4、目前Java实现数据导出为Excel方式5、依赖6、总结 1、前言 工作中有用到将数据导出为Excel的场景&#xff0c;在此记录下。在日常开发中&#xff0c;Excel文件处理是一项常见的…