【嵌入式设备】蓝牙鼠标遥控器

今天讲的这个产品也是刚开发的

主要就是可以遥控你的设备,进行一些自动化的操作流程,不需要再一个一个去单独进行操作,举个最简单的例子,比如你需要拨打一个电话号,你是不是需要一个一个数字去按,最终按下这个电话号的所有数字,那这个产品就是帮你简化这个步骤,按一下,他自己把剩下的数字都按下了。

当然我这个例子就是非常简单的,你可以自己设置更繁琐复杂的逻辑动作。

新开发的产品~蓝牙鼠标遥控器(多设备设定多个逻辑动作,自动化操作)

这里我就先展示一下刚举得例子,我写的一个代码

配置文件

{"bluetooth_name": "xxx","phone_number": "17349297033","keypad_coordinates": {"1": [95, 478], "2": [270, 480], "3": [445, 470],"4": [89, 567], "5": [270, 567], "6": [446, 570],"7": [89, 650], "8": [270, 664], "9": [445, 670],"*": [89, 750], "0": [270, 764], "#": [445, 770]},"dial_button": [260, 835],"hangup_button": [400, 700]}

信号接收

#ASK_433MHz_Receiver.pyfrom machine import Pin, Timer
import time# 配置 GPIO 引脚用于接收 433MHz 射频信号
_ASK_MIN_BYTE_LEN_ = 3                  #   byte
_ASK_MAX_BYTE_LEN_ = 3                  #   byte
_ASK_MIN_NEW_FRAM_DETECT_TIME_ = 5000   #   us
_ASK_TOLERANCE_ = 0.9                   #   脉冲宽度容忍度asklen =  (_ASK_MAX_BYTE_LEN_ * 16 + 1)   #完整aks数据位长度
datalen_max = (_ASK_MAX_BYTE_LEN_*8)      #射频最大数据位长度
datalen_min = (_ASK_MIN_BYTE_LEN_*8)      #射频最小数据位长度
detect_begin = False                      #是否接收到射频开始信号
detect_end = False                        #aks射频数据是否接收完成# 定义用于存储脉冲的时间长度列表
buffer_int = []ask_time = 0#中断处理器
def irq_handler(pin):global buffer_int,ask_time,detect_begin,detect_end# print(f"中断触发,pin值: {pin.value()}")tackus = time.ticks_us()   # 当前时间戳(微秒)if not detect_end:dt = time.ticks_diff(tackus,ask_time)  # 计算脉冲间隔if not detect_begin:if dt > _ASK_MIN_NEW_FRAM_DETECT_TIME_ and pin.value():detect_begin = True   buffer_int = []     # 清空缓冲区# print("开始接收数据包...")else:if dt > _ASK_MIN_NEW_FRAM_DETECT_TIME_ and pin.value():if len(buffer_int) == asklen:detect_end = True# print("数据包接收完成:", buffer_int)  # 打印接收到的脉冲时间else:detect_begin = False  # 重新开始检测buffer_int = []else:buffer_int.append(dt)# 记录脉冲时间# print(f"脉冲时间: {dt} 微秒")  # 打印每次记录的脉冲间隔ask_time = tackus  # 获取当前的微秒时间#初始化射频接收引脚
def ask_init(pin):rf_pin = Pin(pin, Pin.IN)  # 假设接收模块连接到 GPIO16rf_pin.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=irq_handler)#解码逻辑def decodeData(buffer):# buffer_time = buffer[0] + buffer[1]buffer_time_high = [0,0]buffer_time_low = [0,0]if buffer[0] >buffer[1]:buffer_time_high[0] = buffer[0] - int(_ASK_TOLERANCE_ * buffer[0])buffer_time_high[1] = buffer[0] + int(_ASK_TOLERANCE_ * buffer[0])buffer_time_low[0] = buffer[1] -  int(_ASK_TOLERANCE_ * buffer[1])buffer_time_low[1] = buffer[1] +  int(_ASK_TOLERANCE_ * buffer[1])elif buffer[0] < buffer[1]:buffer_time_high[0] = buffer[1] - int(_ASK_TOLERANCE_ * buffer[1])buffer_time_high[1] = buffer[1] + int(_ASK_TOLERANCE_ * buffer[1])buffer_time_low[0] =  buffer[0] - int(_ASK_TOLERANCE_ * buffer[0])buffer_time_low[1] =  buffer[0] + int(_ASK_TOLERANCE_ * buffer[0])else:return Nonedata_bit = 0 data_byte = [0,0,0]i = 0index = len(buffer)while(i < index - 1):if buffer[i] > buffer_time_low[0] and buffer[i] < buffer_time_low[1] and buffer[i+1] > buffer_time_high[0] and buffer[i+1] < buffer_time_high[1]: data_bit += 1elif buffer[i+1] > buffer_time_low[0] and buffer[i+1] < buffer_time_low[1] and buffer[i] > buffer_time_high[0] and buffer[i] < buffer_time_high[1]:data_byte[data_bit // 8] |= 0x80 >> (data_bit % 8)# data_byte[data_bit // 8] = data_byte[data_bit // 8] | 0x80 >> (data_bit % 8)data_bit += 1else:breaki +=2if data_bit % 8 != 0:return Noneif data_bit > datalen_max or data_bit < datalen_min:return Nonereturn data_bytedef reciveData():global detect_begin,detect_end,buffer_intif detect_end:dat = decodeData(buffer_int)detect_end = Falsedetect_begin = Falsereturn datreturn None
#初始化射频接收引脚并进入循环
#每当检测到完整数据包时,调用解码函数并输出结果def main():global detect_begin,detect_end,buffer_intask_init(16)while True:time.sleep_ms(1)  # 主循环继续运行if detect_end:print(len(buffer_int),buffer_int)dat = decodeData(buffer_int)if dat:print('data:%02x%02x%02x'%(dat[0],dat[1],dat[2]))detect_end = Falsedetect_begin = Falsetime.sleep_ms(100)if __name__ == '__main__':main()

main.py

import json
import time
from machine import Timer
import uartUtil
import touchTool
import ASK_433MHz_Receiver
from ASK_433MHz_Receiver import ask_init, decodeData# 全局变量
tcount = 0
config = {}
devname = "fengmm521"  # 默认蓝牙名称
phone_number_coords = []# 文件是否存在
def isExists(pth):try:f = open(pth, 'rb')f.close()return Trueexcept Exception:return False# 读取 JSON 文件中的配置
def load_config():global config, devname, phone_number_coordswith open("config.json", "r") as f:config = json.load(f)# 从 JSON 文件中读取蓝牙名称devname = config.get("bluetooth_name", "xxx")# 将电话号码转换为坐标列表phone_number = config.get("phone_number", "")keypad = config["keypad_coordinates"]phone_number_coords = [keypad[digit] for digit in phone_number]# 从文件读取设备蓝牙名
def initDeviceName():global devnameprint("初始化设备...")load_config()if isExists('config.json'):with open('config.json', 'r') as f:config = json.load(f)devname = config.get("bluetooth_name", devname)  # 从配置文件中读取蓝牙名称print(f"蓝牙设备名称: {devname}")# 点击屏幕上的某个坐标
def click(coord):x, y = coordtouchTool.moveTo(x, y, True)time.sleep_ms(100)  # 点击延迟touchTool.moveTo(x, y, False)# 遥控按键事件处理
def handle_remote_command(command):print(f"处理命令: {command}")  # 检查命令是否正确if command == 1:# 模拟拨号:依次点击号码的坐标for coord in phone_number_coords:print(f"点击坐标: {coord}")  # 确认每个号码对应的坐标click(coord)elif command == 2:# 点击拨号按钮print("拨号")click(config["dial_button"])elif command == 3:print("挂断")# 点击挂断按钮click(config["hangup_button"])# 主函数
def main():print("start")initDeviceName()                 #设备设备名称print("device name:%s"%(devname))uartUtil.start()                 #初始化串口接收数据touchTool.set_screenWH(540,960)   #设置手机分辨率touchTool.start(devname)          time.sleep(1)                    #等3秒,手动配对成功,这个时间根据不同手机决定print("start and connect")ask_init(16)  # 初始化 433MHz 接收引脚print("开始监听遥控信号...")while True:time.sleep_ms(100)  # 保持主循环运行dat = ASK_433MHz_Receiver.reciveData()if dat:print(dat)if dat[2] == 120:#1handle_remote_command(1)elif dat[2] == 116:#1handle_remote_command(2)elif dat[2] == 124:#1handle_remote_command(3)if __name__ == "__main__":main()

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

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

相关文章

如果有100万条消息堆积在MQ怎么解决

当 RabbitMQ 中有 100 万条消息堆积时&#xff0c;意味着消息处理速度已经明显落后于消息产生的速度。如果不及时解决&#xff0c;可能会导致系统负载过重、消息处理延迟加剧&#xff0c;甚至系统崩溃。为了解决这种大规模消息堆积问题&#xff0c;可以采取以下几种措施&#x…

如何在Matlab界面中添加日期选择器?

在Matlab界面中添加日期选择器&#xff0c;可以让用户通过图形界面方便地选择日期。Matlab提供了uidatepicker函数&#xff0c;允许用户在App Designer设计的GUI中添加日期选择器组件。以下是如何在Matlab界面中添加日期选择器的详细步骤&#xff1a; 1. 使用App Designer添加…

重写QObjiet虚函数timerEvent()启动定时器

重写QObjiet虚函数timerEvent()启动定时器是一个常见的方法&#xff0c;它允许在Qt应用程序中实现定时功能。下面是一个简单的例子&#xff0c;展示了如何重写timerEvent()并启动定时器&#xff1a; 首先&#xff0c;创建一个继承自QObject的类&#xff0c;并在该类中重写time…

基于springboot+微信小程序校园自助打印管理系统(打印1)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于springboot微信小程序校园自助打印管理系统实现了管理员、店长和用户。管理员实现了用户管理、店长管理、打印店管理、打印服务管理、服务类型管理、预约打印管理和系统管理。店长实现…

vue3中报has no default export错误

原因 在同时使用Vetur和Volar插件的Vue2与Vue3项目中&#xff0c;遇到Module has no default export错误。通过在VSCode设置中将vetur.validation.script设为false&#xff0c;可以消除该报错&#xff0c;不影响实际运行。 解决办法 "vetur.validation.script": fa…

【Linux线程】Linux线程编程基础:概念、创建与管理

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;Linux “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀Linux多线程 &#x1f4d2;1. 线程概念&#x1f4dc;2. 进程VS线程&#x1f4da;3. 线程控制…

算法魅力-双指针的实战

目录 1.双指针的介绍 1. 左右指针&#xff08;对撞指针&#xff09; 2. 快慢指针 2.题目练习讲解 2.1 移动零 算法思路 代码展示 画图效果效果 2.2 复写零 算法思路 代码展示 2.3 快乐数 算法思路 代码展示 2.4 盛最多水的容器 算法思路 代码展示 结束语 1.双指针的…

Python项目引入其他项目作为子模块

Python子模块引入 背景&#xff0c;项目A为主项目&#xff0c;项目B为封装的通用逻辑&#xff08;可被多个项目使用&#xff09;。项目A和项目B都是独立更新的&#xff0c;两者互不影响只有引用关系 项目A子模块设置 设置子模块信息 创建.gitmodules文件&#xff0c;写入子…

大模型带来新安全机遇

当前网络空间安全面临攻击隐蔽难发现、数据泄露风险高和违法信息审核难等挑战。大模型展现出强大的信息理解、知识抽取、意图和任务编排等能力&#xff0c;为网络空间安全瓶颈问题提供了新的解决思路和方法。与此同时&#xff0c;大模型发展也催生了恶意软件自动生成、深度伪造…

架构师之路-学渣到学霸历程-22

NFS文件共享服务器 今天开始了云计算-SRE架构师的第二个阶段&#xff0c; 第二阶段就是服务阶段了&#xff1b;第一个分享的就是NFS服务&#xff1b; 文件共享服务&#xff1b; 早上就了解一下NFS原理&#xff1b; 1、NFS文件共享服务器 NFS&#xff1a;就是network file sy…

【YOLO学习】YOLOv5详解

文章目录 1. 网络结构2. 结构整体描述2.1 输入端2.2 Backbone2.3 Neck2.4 Head 3. 模块细节3.1 Focus模块3.2 SPPF3.3 Bounding Box损失函数 4. 训练策略 1. 网络结构 1. 目标检测的模型框架大体都是以下图示这样的结构&#xff1a; 2. 关于 YOLOv5 的网络结构其实网上相关的讲…

数据结构 - 队列

队列也是一种操作受限的线性数据结构&#xff0c;与栈很相似。 01定义 栈的操作受限表现为只允许在队列的一端进行元素插入操作&#xff0c;在队列的另一端只允许删除操作。这一特性可以总结为先进先出&#xff08;First In First Out&#xff0c;简称FIFO&#xff09;。这意味…

你是否真的弄懂了 OAuth 2.0?

目录 OAuth 2.0 中的基本概念 OAuth 2.0 参与方 OAuth 2.0 典型的授权流程 使用 OAuth 2.0 需要注意的安全问题 OAuth 2.0 的使用场景 小结 OAuth 2.0&#xff08;Open Authorization 2.0&#xff0c;开放授权 2.0&#xff09;是被广泛使用的一种开放的标准授权协议&…

php常用设计模式之工厂模式

引言 在日常开发中&#xff0c;我们一些业务场景需要用到发送短信通知。然而实际情况考虑到不同厂商之间的价格、实效性、可能会出现的情况等 我们的业务场景往往会接入多个短信厂商来保证我们业务的正常运行&#xff0c;而不同的短信厂商&#xff08;如阿里云短信、腾讯云短信…

[Java基础] Lambda 表达式

往期回顾 [Java基础] 流程控制 [Java基础] 运算符 [Java基础] 基本数据类型 [Java基础] Java HashMap 的数据结构和底层原理 [Java基础] 面向对象编程 [Java基础] 异常处理机制 [Java基础] 集合框架 [Java基础] 输入输出流 目录 概述 Lambda 表达式的基本语法 应用…

使用Uniapp开发微信小程序实现一个自定义的首页顶部轮播图效果?

在Uniapp中开发微信小程序&#xff0c;并实现自定义首页顶部轮播图的效果&#xff0c;可以通过使用Uniapp的组件如swiper和swiper-item来完成。这是一个常见的需求&#xff0c;下面是一个完整的示例代码&#xff0c;展示如何实现一个简单的自定义轮播图效果。 创建页面结构 首…

R语言机器学习算法实战系列(八)逻辑回归算法 (logistic regression)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍教程下载数据加载R包导入数据数据预处理数据描述数据切割构建模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC CurvePRC Curve特征的重要性保存模型总结系统信息介绍 …

MySQL数据库和表的基本操作

文章目录 一、数据库的基础知识 背景知识数据库的基本操作二、数据类型 字符串类型数值类型日期类型三、表的基本操作 创建表查看表结构查看所有表删除表 一、数据库的基础知识 背景知识 MySQL是一个客户端服务器结构的程序 主动发送数据的这一方&#xff0c;客户端(client…

“智改数转”转了什么?

万界星空科技专门针对数字化改造申报的MES系统具有显著的技术优势和实施效果&#xff0c;能够为制造型企业提供全方位、高效、可靠的数字化转型支持。项目合作可以私信或者百度上海万界星空科技官网。 “智改数转”是一个综合性的过程&#xff0c;涉及企业多个方面的转型和升…

【python实战】利用代理ip爬取Alibaba海外版数据

引言 在跨境电商的业务场景中&#xff0c;数据采集是分析市场、了解竞争对手以及优化经营策略的重要环节。然而&#xff0c;随着越来越多企业依赖数据驱动决策&#xff0c;许多跨境电商平台为了保护自身数据&#xff0c;采取了更严格的防护措施。这些平台通过屏蔽大陆IP地址或部…