用两台TFmini Plus实现 PPT切换

2023-05-16

1. PPT自动切换模块简介

本模块利用北醒公司两台TFmini Plus、Arduino DUE板、一个低功率红外激光指向灯、两个LED指示灯、一个单向开关、一个双向开关和连接线结合设计。
系统作用:通过检测人的手势,操作PPT的上一页、下一页切换。

2. 试验设备及接线

2.1 实验设备

  • Benewake TFmini Plus 标品
    图2.1 TFmini Plus
    TFmini Plus(如图2.1所示),详细参数见TFmini Plus使用说明;
    本模块用来检测人的手势,当手或者手臂扫过时,测距状态发生改变。

  • Arduino DUE板
    图2.2 Arduino DUE
    本模块使用DUE板检测雷达1和雷达2的测距状态,并利用自带的USB通信实现HID功能。
    Arduino DUE板(如图2.2所示),详细介绍和学习,请参考以下两个网站:
    中文社区:http://www.arduino.cn/;
    英文官网:http://www.arduino.cc/。

  • 激光指示灯
    图2.3 红外激光指示灯
    如图2.3所示,为红外激光指示灯,用来指示雷达的工作方向和大致区域。
    具体说明参考:https://m.tb.cn/h.eml6WNY?sm=032032

  • LED灯
    图2.4功能指示灯
    如图2.4所示,为LED灯,用来指示模块功能状态:绿灯为功能开启,红灯为功能关闭。

  • 单向开关
    图2.5 单向开关
    如图2.5所示,为单向开关,用来控制红外激光指示灯的打开和关闭。

  • 双向开关

图2.6 双向开关

  • 电脑
    图2.7 电脑
    如图2.7所示,作为该系统的上位机,用来编写程序并上传到DUE板,并为模块供电。
  • 连接线
    图2.8 连接线
    如图2.8所示,为杜邦线和USB数据线。
    杜邦线——用于TFmini Plus与UNO板连接;
    USB数据线——用于DUE板与电脑连接、供电。

2.2 接线

图2.9 系统接线图
如图2.9所示,为PPT切换模块的接线图,接线需要注意一下几个方面:
(1) TFmini Plus供电电压为5V,直接连接Arduino DUE板的5V和GND,其他雷达需查阅产品规格书,确保供电正常;
(2) 雷达1(RX,TX)连接DUE板的(TX3,RX3); 雷达2(RX,TX)连接DUE板的(TX1,RX1);
(3) 功能指示灯连接23,25引脚,通过检测开关状态,对应功能指示灯的关闭和打开。当功能打开时,绿灯亮起;功能关闭时,红灯亮起;

3. PPT切换原理及注意事项

  • 注意事项
    (1) TFmini Plus的采样率最大为1000,手臂挥动速度不应太大;
    (2) 手臂挥动速度不应过小,即触发时间符合正常操作;
    (3) 可以实现人一般速度走过,不触发PPT切换。
  • 程序流程图
    图3.1 系统工作流程图

4. 系统程序编写

#include <Keyboard.h>
/****************************************************************
定义引脚功能,控制引脚为27,29,显示引脚为23,25
*****************************************************************/
#define ON 23
#define OFF 25
#define LED_ON 27
#define LED_OFF 29
char left  = KEY_LEFT_ARROW; 
char right  = KEY_RIGHT_ARROW;
const int HEADER=0x59;//数据包帧头
/****************************************************************
定义模块功能初始状态参数
*****************************************************************/
bool receiveok1=false;
bool receiveok2=false;
bool status_complete1=false;
bool status_complete2=true;
/****************************************************************
变量DELAY可以控制模块的延迟时间,用以滤除人行走带来的误操作
*****************************************************************/
int DELAY=180;
int distance1=0;
int distance2=0;
int DISTANCE1=1200;
int DISTANCE2=1200;
int threshold=0;
unsigned long tim[2]={0};
int period=0;
/****************************************************************
声明函数,雷达数据获取函数和采集环境距离阈值函数
*****************************************************************/
int TFminione(void);
int TFminitwo(void);
int lidar_average(void);





/****************************************************************
引脚功能定义,初始化;
串口初始化;
采集周边环境,确定模块工作阈值;
*****************************************************************/
void setup() 
{
  pinMode(ON,INPUT);
  pinMode(OFF,INPUT);
  pinMode(LED_ON,OUTPUT);
  pinMode(LED_OFF,OUTPUT);
  digitalWrite(ON,HIGH);
  digitalWrite(OFF,HIGH);
  digitalWrite(LED_ON,LOW);
  digitalWrite(LED_OFF,LOW);  
  Serial1.begin(115200);//设置TFmini1与arduino的串口波特率
  Serial2.begin(115200);//设置TFmini2与arduino的串口波特率
  Serial3.begin(115200);//设置电脑与arduino的串口波特率
  int threshold1=lidar_average();
  threshold=threshold1-100;
  Serial3.print("threshold=");
  Serial3.println(threshold);
}
/****************************************************************
首先,判断功能开关状态;
然后,对雷达测距状态进行判断;
如果满足判断条件,执行对应操作;
*****************************************************************/
void loop() 
{
       if(digitalRead(ON)==LOW)//控制开关打开
       {                          
           digitalWrite(ON,HIGH);
           digitalWrite(LED_OFF,LOW);
           digitalWrite(LED_ON,HIGH);
           Keyboard.begin();
           receiveok1=false;
           receiveok2=false; 
           distance1 =  TFminione();
           distance2 =  TFminitwo(); 
           if(receiveok1 & receiveok2)
           {           
              if(DISTANCE1>threshold  & distance1<=threshold  & distance2>threshold)
              { 
                   tim[0]=millis();
                   DISTANCE1=distance1;
                   DISTANCE2=distance2;
                   while(true)
                   {
                      receiveok1=false;
                      receiveok2=false;
                      distance1 =  TFminione();
                      distance2 =  TFminitwo(); 
                      if(receiveok1 & receiveok2)
                      {
                          tim[1]=millis();
                          period=tim[1]-tim[0];
                          if(DISTANCE2>threshold  & distance2<=threshold )
                          {
                              DISTANCE1=distance1;
                              DISTANCE2=distance2;
                              while(true)
                              {
                                  receiveok1=false;
                                  receiveok2=false;
                                  distance1 =  TFminione();
                                  distance2 =  TFminitwo(); 
                                  if(receiveok1 & receiveok2)
                                  { 
                                      tim[1]=millis();
                                      period=tim[1]-tim[0];
                                      if(distance2>threshold & distance1>threshold )
                                      {
                                         tim[1]=millis();
                                         period=tim[1]-tim[0];
                                         if(period<DELAY)
                                         {
                                             Keyboard.write(right);
                                             status_complete1=true;  
                                             break; 
                                         }
                                         else
                                         {
                                            status_complete1=true;
                                            break;           
                                         }
                                      }
                                      else if(period>DELAY)
                                      {
                                         status_complete1=true;
                                         break;
                                      }
                                      else
                                      {
                                          DISTANCE1=distance1;
                                          DISTANCE2=distance2;
                                      }        
                                  }
                              }                                        
                          }
                          else if(status_complete1)
                          {
                              status_complete1=false;
                              break;   
                          }
                          else if(period>DELAY)
                          {
                              break;
                          }
                          else
                          {
                              DISTANCE1=distance1;
                              DISTANCE2=distance2;
                          }
                      }    
                   }
              }
              else if(DISTANCE2>threshold  & distance2<=threshold  & distance1>threshold)
              { 
                   tim[0]=millis();
                   DISTANCE1=distance1;
                   DISTANCE2=distance2;
                   while(true)
                   {
                      receiveok1=false;
                      receiveok2=false;
                      distance1 =  TFminione();
                      distance2 =  TFminitwo(); 
                      if(receiveok1 & receiveok2)
                      {
                          tim[1]=millis();
                          period=tim[1]-tim[0];
                          if(DISTANCE1>threshold  & distance1<=threshold )
                          {
                              DISTANCE1=distance1;
                              DISTANCE2=distance2;
                              while(true)
                              {
                                  receiveok1=false;
                                  receiveok2=false;
                                  distance1 =  TFminione();
                                  distance2 =  TFminitwo(); 
                                  if(receiveok1 & receiveok2)
                                  { 
                                      tim[1]=millis();
                                      period=tim[1]-tim[0];
                                      if(distance1>threshold & distance2>threshold )
                                      {
                                         tim[1]=millis();
                                         period=tim[1]-tim[0];
                                         if(period<DELAY)
                                         {
                                             Keyboard.write(left);
                                             status_complete2=true;  
                                             break; 
                                         }
                                         else
                                         {
                                            status_complete2=true;
                                            break;           
                                         }
                                      }
                                      else if(period>DELAY)
                                      {
                                         status_complete2=true;
                                         break;
                                      }
                                      else
                                      {
                                          DISTANCE1=distance1;
                                          DISTANCE2=distance2;
                                      }        
                                  }
                              }                                        
                          }
                          else if(status_complete2)
                          {
                              status_complete2=false;
                              break;   
                          }
                          else if(period>DELAY)
                          {
                              break;
                          }
                          else
                          {
                              DISTANCE1=distance1;
                              DISTANCE2=distance2;
                          }
                      }    
                   }
              }
              else
              {
                 DISTANCE1=distance1;
                 DISTANCE2=distance2; 
              }
              Keyboard.end();
           }                 
       }
 
       else if(digitalRead(OFF)==LOW)
       {              
            digitalWrite(OFF,HIGH);
            digitalWrite(LED_OFF,HIGH);
            digitalWrite(LED_ON,LOW);
       }
       else
       {
          delay(1);
       }
}



/****************************************************************
雷达1采集环境距离函数
*****************************************************************/
int TFminione(void) 
{
  int dist=0;//雷达实测距离值
  int check;//校验数值存放
  int uart[9]={0};//存放雷达测量的数据
  int i=0;
  if (Serial1.available())//查看串口是否有数据输入
  {
    if(Serial1.read()==HEADER)//判断数据包帧头0x59
    {
      uart[0]=HEADER;
      if(Serial1.read()==HEADER)//判断数据包帧头0x59
      {
        uart[1]=HEADER;
        for(i=2;i<9;i++)//存储数据到数组
        {
          uart[i]=Serial1.read();
        } 
        check=uart[0]+uart[1]+uart[2]+uart[3]+uart[4]+uart[5]+uart[6]+uart[7];
        if(uart[8]==(check&0xff))//按照协议对收到的数据进行校验
        {
          dist=uart[2]+uart[3]*256;//计算距离值
          receiveok1=true;
          return(dist);
        }
      }
    }
  }
  else
  {
      delay(1);  
  }
}
/****************************************************************
雷达2采集环境距离函数
*****************************************************************/
int TFminitwo(void) 
{
  int dist=0;//雷达实测距离值
  int check;//校验数值存放
  int uart[9]={0};//存放雷达测量的数据
  int i=0;
  if (Serial2.available())//查看串口是否有数据输入
  {
    if(Serial2.read()==HEADER)//判断数据包帧头0x59
    {
      uart[0]=HEADER;
      if(Serial2.read()==HEADER)//判断数据包帧头0x59
      {
        uart[1]=HEADER;
        for(i=2;i<9;i++)//存储数据到数组
        {
          uart[i]=Serial2.read();
        } 
        check=uart[0]+uart[1]+uart[2]+uart[3]+uart[4]+uart[5]+uart[6]+uart[7];
        if(uart[8]==(check&0xff))//按照协议对收到的数据进行校验
        {
          dist=uart[2]+uart[3]*256;//计算距离值
          receiveok2=true;
          return(dist);     
        }
      }
    }
  }
  else
  {
      delay(1);  
  }
}
int lidar_average(void)
{
  int i=0;
  int sum=0;
  int average=0;
  int temp[100]={0};
  while(true)
  {
    distance1=TFminione();
    if(receiveok1)
    {
        temp[i]=distance1;
        Serial3.println(distance1);
        i++;
        if(i>=100)
        {
          for(i=0;i<100;i++)
          {
            sum+=temp[i];
          }
          average=sum/100;
          Serial3.print("average=");
          Serial3.print(average);
          Serial3.print('\t');
          i=0;
          sum=0;
          return(average);
          delay(1);
          break;
        }
    }
    receiveok1=false;
  }
}
 

5. 使用说明

  • 工作流程图
  1. 模块上电;
  2. 系统自适应实际场景,采集距离信息,设定模块工作阈值;
  3. 打开PPT切换功能开关;
  4. 打开激光指示灯,大致调整模块工作区域,然后关闭激光指示灯;
  5. 手掌或者手臂通过模块,从上到下或者从下到上,依次经过两个雷达,当离开工作区域后,PPT进行切换(上一页或者下一页);
  6. 重复步骤4;
  7. 模块断电。
  • 实际结构图
    在这里插入图片描述
    在这里插入图片描述
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用两台TFmini Plus实现 PPT切换 的相关文章

  • 论文写作踩坑-Wiley杂志投稿-Latex模板使用Windows-Stix-fontinstaller安装Wiley stix-fonts字体出错

    投稿Wiley相关的杂志 xff0c 其LaTeX模板和elsevier及IEEE旗下杂志LaTeX模板不相同 xff0c 其中比较明显的区别是需要安装 特殊字体 xff0c 如果不安装要求的字体会报如下错 xff1a 在百度上可以查到的资
  • LaTex修改参考文献的颜色-BiBTeX-包括参考文献的序号颜色

    1 正文添加 xff1a 复制粘贴即可 xff0c 只需修改 文献1 xff0c 文献2 变成你自己的 usepackage xcolor usepackage xpatch makeatletter def changeBibColor
  • 自动化领域(控制领域)主要期刊汇总整理(SCI和EI)

    目录 IEEE旗下 Elsevier旗下 Springer旗下 Taylor amp Francis Online Wiley Online Library 国内期刊 IEEE旗下 IEEE Transactions on Automati
  • PCL点云分割算法及其测试代码-分割平面

    目录 nbsp 1 平台 2 PCD文件读取 3 算法 4 测试代码及注释 5 测试结果 1 平台 PCL1 8 0 VS2015 Win10 具体配置可以参照链接
  • 点云PCL入门基础

    目录 点云对象的声明 转换关系 示例 输入输出保存点云数据 点云对象的声明 pcl PointCloud lt pcl PointXYZ gt cloud 点云对象 pcl PointCloud lt pcl PointXYZ gt Ptr
  • 源自中国顶级开源软件再下一城!向量数据库公司Zilliz完成6000万美元B+轮融资

    中国开源届再次迎来一个好消息 xff01 北京时间 8 月 25 日 xff0c 向量数据库公司 Zilliz 宣布完成 6000 万美元的新 笔融资 xff0c 成功将其 B 轮融资规模进 步扩 1 03 亿美元 该笔融资由沙特阿美 xf
  • 耗散性、无源性、正实性

    耗散性和作为其特例的无源性概念广泛存在于物理学 应用数学以及力学等领域 研究耗散性和无源性理论的主要出发点在于他们运用基于能量多输入输出描述给出了控制系统分析和设计的新框架 xff0c 对系统控制的诸多方面都起到了很大的推动作用 不仅在控制
  • python学习笔记之tkinter中的label

    from tkinter import longtext 61 39 39 39 多行 文本 39 39 39 master 61 Tk master title 34 label学习 34 w0 61 Label master text
  • python做数据拟合

    项目中有涉及趋势预测的工作 xff0c 整理一下这3种拟合方法 xff1a 1 线性拟合 使用math import math def linefit x y N 61 float len x sx sy sxx syy sxy 61 0
  • 关于VS编译的程序内存分配只能用1.5~2G上限的优化方案

    关于VS编译的程序 内存分配只能用1 5 2G上限的优化方案 遇到的问题是这样的 xff1a 电脑内存32G xff0c VS2012编译的一个程序 xff0c 在程序运行过程中 xff0c 一旦程序的内存使用达到1 5G xff0c 就会
  • 对称矩阵及正定性

    对称阵是非常重要的矩阵 xff0c 对于实对称矩阵 xff0c 其特征值也为实数 xff0c 且特征向量是垂直的 注意这里的垂直是指 xff1a 如果特征值互不相同 xff0c 那么每个特征值对应的特征向量是在一条线上 xff0c 那些线之
  • C++变量前面加下划线的含义

    参考C 43 43 变量前面加下划线的含义 云 43 社区 腾讯云 C 43 43 变量前面加下划线和不加下划线都不会影响对变量的定义 xff0c 只是风格问题 xff0c 更喜欢将成员变量或者私有成员变量的前面加上下划线 以表示该变量是某
  • 对PX4参数THR_MDL_FAC的理解

    对参数THR MDL FAC的理解 home wp src PX Firmware src lib mixer module mixer module hpp 这里引入了参数THR MDL FAC的使用 DEFINE PARAMETERS
  • TX2安装ubuntu18,ROS

    设备 TX2 8G版本 ubuntu18 04笔记本一台 重要提示 请看完全文再安装 xff01 本文不是手把手教你安装类型教程 给TX2刷系统 看看我的参考博客1吧 最好参考最新的博客 xff0c 现在官网的新版本都不是这样 JetPac
  • px4的PWM是如何输出的

    如果有io芯片 xff0c 且使用了io作为输出PWM的设备 则fmu将mixer传输给io xff0c io进行混控计算并输出PWM xff0c 将pwm结果传递回fmu xff0c 此时无app订阅acuator outpus xff0
  • PX4的mix文件是怎么被使用的呢?

    启动 怎么到启动这里的就不说了 2 作为MIXER FILE被mixer load的 src systemcmds mixer mixer cpp实现mixer load Mixer load调用函数 xff1a load const ch
  • 诚迈科技发布OpenHarmony发行版鸿诚志远HongZOS

    2022年11月3日 xff0c 诚迈科技在东莞松山湖举办 鸿雁于飞 至诚志远 开源鸿蒙 诚迈科技HongZOS发布会 xff0c 发布基于OpenHarmony的商业发行版鸿诚志远 xff08 HongZOS xff09 xff0c 并推
  • PX4阅读开发小技巧

    1 基操 本文件搜索 全局搜索 后退 前进 ctrl 43 p xff0c 搜索文件名 右键 xff0c 书签功能 ctrl 43 单击 F12 xff0c 转到定义 大纲视图 vscode的Open Folder插件搜索文件夹名 2 利用
  • 一种基于接触性检查的全方位空中操作平台

    这里写自定义目录标题 摘要简介相关工作系统描述控制架构A 系统模型B 外部力估计C Interaction Control Selective Impedance 交互作用控制 xff1a 选择性阻抗D Surface Normal and
  • PX4的代码测试

    PX4的代码测试 写完代码总要测试一下吧 xff0c 自己先测试一下 xff0c 怎么用Test呢 xff1f 官方关于测试的概括说明 xff1a Platform Testing and Continuous Integration PX

随机推荐

  • CMAKE学习

    官方学习资料 系统的学习还是看官方资料为好 CMake Reference Documentation CMake 3 23 1 Documentation https cmake org cmake help latest Documen
  • QNAP威联通配置docker下的mysql外部网络访问问题

    QNAP的ContainerStation的mysql 容器默认配置是NAT网络是不行的 直接把mysql容器的网络设置改成host并重启 xff0c 就可以在外部连入了 注意需要设置容器的环境变量来配置root密码 需要配置下 MYSQL
  • Python数据可视化教程之基础篇

    点击上方 AI遇见机器学习 xff0c 选择 星标 公众号 重磅干货 xff0c 第一时间送达 开运张 作者 知乎专栏 来源 https zhuanlan zhihu com p 55642042 经过学习之后 xff0c 我总结了利用py
  • 终身学习楷模!吴恩达74岁父亲8年完成146门课

    点击上方 AI遇见机器学习 xff0c 选择 星标 公众号 重磅干货 xff0c 第一时间送达 学习真谛和乐趣在于保持敏锐的头脑 xff0c 以及发现美的能力 作者 贝爽 我们需要保持精神年轻 xff0c 保持好奇心 这是一位74岁老先生的
  • 通过CMakeLists.txt和shell脚本实现自动化编译

    这是项目的整个目录结构 span class hljs comment 此种方式配置犹如Vs中的配置一样 span span class hljs comment CMakeLists file span span class hljs k
  • MAC 安装JD-GUI

    今天升级MAC系统到最新版本 12 0 1 xff0c 然后突然发现JD GUI xff08 v 1 6 xff09 运行不了了 然后就删除重新下载新的 xff0c 发现还是不行 xff0c 在网上搜资料 xff0c 都说需要修改运行文件
  • mysql使用笔记

    创建数据库 create database database name 删除数据库 drop database database name 创建表 span class token comment 最简单的语法 span span clas
  • 华为携手去哪儿、九牧等企业,共论鸿蒙生态发展蓝图

    11月5日 xff0c 在华为开发者大会2022 xff08 Together xff09 上 xff0c 华为携手中软国际 九牧集团 深开鸿 开鸿智谷 去哪儿 鸿湖万联6家鸿蒙合作伙伴代表 xff0c 分享了基于OpenHarmony技术
  • 桌面客户端框架技术选型

    摘自 技术怪咖 欧阳森林 作为客户端的架构选型主要面临以下几个方面的需求 xff1a 1 开发速度快 xff0c 能够快速迭代 xff0c 快速试错 2 客户端能够跨平台 xff0c 同时适应Windows和Mac平台 3 用户界面友好 x
  • python金融数据爬虫与数据分析学习(一)

    本文针对以下链接进行学习 链接 爬取东方财富网上的股票信息 由于后来发现爬的都是指数基金的股票 xff0c 便转向观看其它文章 目前发现一个比较好的python开源的财经数据包接口 xff0c Tushare Tushare简介 Tusha
  • 股票基础知识

    股票基础知识 定义沪股通 深股通 港股通动态市盈率 静态市盈率 TTM市盈率量比股息率前十大股东与前十大流动股东区别 tushare可以获取的信息日线行情每日指标个股资金流向沪深港股通持股明细沪深港通每日整体资金流向每日涨跌停统计港股通十大
  • kubernetes安装部署

    k8s是一款辅助管理容器的平台 负责容器的部署 xff0c 扩缩容和负载均衡 k8s集群是有master节点和work节点组成 xff0c master 一个 是主节点 xff0c 负责管理和控制 work是工作节点 xff08 很多 xf
  • js 中set去重并转为数组

    const items 61 new Set 1 2 3 4 5 5 去重 const array1 61 items 2 转成数组
  • fast lio测试

    fast lio2代码编译及运行 编译 fast lio2仓库地址 一 安装依赖 ubuntu18 43 ros环境下 xff0c pcl和eigen可默认使用ros自带版本 xff0c 所以只需安装 livox驱动包 livox ros
  • 机器人开发常见第三方库、软件安装和使用

    写在前面 大多数情况下 xff0c 没有人比官方更懂官方 xff0c 所以编译安装 库配置及简单使用优先看官方github仓库README或者官网 xff0c 当然不排除有些博文或者教程有更好的表达方式更详细的说明cmake 编译三件套 通
  • Android UDP 通信总结 (终于从坑中爬起来了)

    2018 08 02 最近做的项目要求为 xff1a 一端为电视端 xff0c 一端为手机端 xff0c 实现电视端与手机端通过UDP进行通信 解释 xff1a 就是两个机器在同一个局域网内 xff08 即两端连接的同一个WiFi xff0
  • ES6之Promise常见面试题

    ES6 谈一谈 promise 所有的 ES6 特性你都知道吗 xff1f 如果遇到一个东西不知道是 ES6 还是 ES5 你该怎么区分它 es6的继承和es5的继承有什么区别 promise封装ajax let const的优点 es6
  • docker容器内关于pip的trick

    在运行某个文本检测算法的时候 xff0c 运行setup py脚本 xff0c 生成了dist目录 xff0c 且在此目录下生成了 dlocr 0 1 SNAPSHOT tar gz文件夹 下一步需要pip install dlocr 0
  • 用两台TFmini Plus实现PPT切换

    1 PPT自动切换模块简介 本模块利用北醒公司两台TFmini Plus Arduino DUE板 一个低功率红外激光指向灯 两个LED指示灯 一个单向开关 一个双向开关和连接线结合设计 系统作用 xff1a 通过检测人的手势 xff0c
  • 用两台TFmini Plus实现 PPT切换

    1 PPT自动切换模块简介 本模块利用北醒公司两台TFmini Plus Arduino DUE板 一个低功率红外激光指向灯 两个LED指示灯 一个单向开关 一个双向开关和连接线结合设计 系统作用 xff1a 通过检测人的手势 xff0c