物联网开发笔记(56)- 使用Micropython开发ESP32开发板之手机蓝牙控制舵机

news2024/9/23 3:26:06

一、目的

        这一节我们学习如何使用我们的ESP32开发板来实现通过蓝牙控制接在ESP32开发板上的舵机。

二、环境

        ESP32 + MG90S舵机 + Thonny IDE + 几根杜邦线 + 手机

        舵机的链接方法见第54节:物联网开发笔记(54)- 使用Micropython开发ESP32开发板之控制MG90S舵机_魔都飘雪的博客-CSDN博客

三、手机APP

        这里用到的手机APP是BluefruitConnect,使用苹果手机的同学打架早Apple Store中直接搜索安装即可。安卓暂时我没找到这个APP,哪位同学有的可以评论区留言哈。。。

BluefruitConnect APP的图标是这个样子:

 安卓的同学我们使用:BLE调试助手:

 

几款常用的ble调试app(nRF Connect、BLE调试助手、LightBlue) - 知乎

四、代码

from machine import Pin
from machine import Timer  # 导入定时器
from time import sleep_ms
from machine import PWM   # 导入PWM
import time
import bluetooth  # 导入蓝牙

BLE_MSG = ""  # 定义一个变量来接收蓝牙发送来的数据

# 创建一个蓝牙类
class ESP32_BLE():
    def __init__(self, name):  # 蓝牙类的初始化
        self.led = Pin(2, Pin.OUT)  # 创建LED对象
        self.timer1 = Timer(0)  # 使用0号定时器,ESP32共有4个定时器0,1,2,3
        self.name = name  # 传入蓝牙名字
        self.ble = bluetooth.BLE()  # 创建蓝牙对象
        self.ble.active(True)  # 打开蓝牙
        self.ble.config(gap_name=name)  # 设置蓝牙的名字
        self.disconnected()  # 断开蓝牙连接
        self.ble.irq(self.ble_irq)  # 蓝牙中断
        self.register() # 蓝牙注册
        self.advertiser()

    def connected(self):
        self.led.value(1)
        self.timer1.deinit()

    def disconnected(self):        
        self.timer1.init(period=100, mode=Timer.PERIODIC, callback=lambda t: self.led.value(not self.led.value()))

    def ble_irq(self, event, data):
        global BLE_MSG
        if event == 1: #_IRQ_CENTRAL_CONNECT 手机链接了此设备
            self.connected()
        elif event == 2: #_IRQ_CENTRAL_DISCONNECT 手机断开此设备
            self.advertiser()
            self.disconnected()
        elif event == 3: #_IRQ_GATTS_WRITE 手机发送了数据 
            buffer = self.ble.gatts_read(self.rx)
            BLE_MSG = buffer.decode('UTF-8').strip()
            
    def register(self):        
        service_uuid = '6E400001-B5A3-F393-E0A9-E50E24DCCA9E'
        reader_uuid  = '6E400002-B5A3-F393-E0A9-E50E24DCCA9E'
        sender_uuid  = '6E400003-B5A3-F393-E0A9-E50E24DCCA9E'

        services = (
            (
                bluetooth.UUID(service_uuid), 
                (
                    (bluetooth.UUID(sender_uuid), bluetooth.FLAG_NOTIFY), 
                    (bluetooth.UUID(reader_uuid), bluetooth.FLAG_WRITE),
                )
            ), 
        )

        ((self.tx, self.rx,), ) = self.ble.gatts_register_services(services)

    def send(self, data):
        self.ble.gatts_notify(0, self.tx, data + '\n')

    def advertiser(self):
        name = bytes(self.name, 'UTF-8')
        adv_data = bytearray('\x02\x01\x02') + bytearray((len(name) + 1, 0x09)) + name
        self.ble.gap_advertise(100, adv_data)
        print(adv_data)
        print("\r\n")

# 创建BOOT按键中断执行函数
def buttons_irq(pin):
    led.value(not led.value())  # 翻转LED灯的状态
    print('LED is ON.' if led.value() else 'LED is OFF')  # 打印LED的状态
    ble.send('LED is ON.' if led.value() else 'LED is OFF')  # 发送LED的状态给手机


if __name__ == "__main__":
    ble = ESP32_BLE("ESP32BLE")  # 定义蓝牙的名字为ESP32BLE

    # 检测boot按键
    but = Pin(0, Pin.IN)  # 创建BOOT按键对象,GPIO脚为0
    # 创建BOOT按键的中断,中断出发模式设置为下降沿触发,触发对象为buttons_irq
    but.irq(trigger=Pin.IRQ_FALLING, handler=buttons_irq)  

    # 控制蓝色led
    led = Pin(2, Pin.OUT)  # 创建LED对象
    
    # 控制舵机
    p15 = PWM(Pin(15))  # 创建舵机对象
    p15.freq(50)  # PWM的频率为59HZ
    duty_num = 1638  # 定义一个变量,设置舵机的角度为0度
    p15.duty_u16(1638)

    # 0度    p15.duty_u16(1638)
    # 45度   p15.duty_u16(3276)
    # 90度   p15.duty_u16(4915)
    # 135度  p15.duty_u16(6553)
    # 180度  p15.duty_u16(8192)

    # 下面ESP32按照蓝牙接收到的数据进行判断,执行响应的动作
    while True:
        if BLE_MSG == 'read_LED':
            print(BLE_MSG)  # 打印接收到的信息
            BLE_MSG = ""
            print('LED is ON.' if led.value() else 'LED is OFF')
            ble.send('LED is ON.' if led.value() else 'LED is OFF')
        elif BLE_MSG:
            print("接收到的信息:>>%s<<" % BLE_MSG)  # 打印接收到的信息
            if BLE_MSG == "!B11:":  # 按下app上数字1
                duty_num += 100
                if duty_num > 8192:
                    duty_num = 8192
                print(duty_num)
                p15.duty_u16(duty_num)
            elif BLE_MSG == "!B219":  # 按下app上数字2
                duty_num -= 100
                if duty_num < 1638:
                    duty_num = 1638
                print(duty_num)
                p15.duty_u16(duty_num)
            elif BLE_MSG == "!B318":  # 按下app上数字3
                duty_num += 300
                if duty_num > 8192:
                    duty_num = 8192
                print(duty_num)
                p15.duty_u16(duty_num)
            elif BLE_MSG == "!B417":  # 按下app上数字4
                duty_num -= 300
                if duty_num < 1638:
                    duty_num = 1638
                print(duty_num)
                p15.duty_u16(duty_num)
            elif BLE_MSG == "!B516":  # 按下app上up键
                p15.duty_u16(4915)  # 90度
                duty_num = 4915
            elif BLE_MSG == "!B615":  # 按下app上down键
                p15.duty_u16(3276)  # 45度
                duty_num = 3276
            elif BLE_MSG == "!B714":  # 按下app上left键
                p15.duty_u16(8192)  # 180度
                duty_num = 8192
            elif BLE_MSG == "!B813":  # 按下app上right键
                p15.duty_u16(1638)  # 0度
                duty_num = 1638
            BLE_MSG = ""
        sleep_ms(100)
        '''
        此处,讲解一下手机蓝牙发送的按键的指令,针对苹果手机APP:
        按钮1,2,3,4,上,下,左,右分别对应指令的第三位“!Bxxx”
        z指令!Bxxx,前两位是固定格式,第三位是按钮的ID,按钮1到4的ID就是1到4. 按钮上下左右对应的ID是5到8.
        比如:按钮5对应的指令就是!B5xx。指令的第四为指的是按钮是按下还是释放,按下是1,释放是0.
        '''

五、苹果手机APP操作

        大家下载完成后,按照图片中操作即可,注意先运行程序哈:

 

 分别按1,2,3,4,上,下,左,右,BOOT键后Thonny IDE打印如下:

 五、安卓手机APP操作

         操作可参考如下图片,注意先运行程序哈:

BLE调试助手界面:

 

 

 

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

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

相关文章

Win11的两个实用技巧系列之电脑死机解决办法

目录 Win11电脑突然死机卡住不动?Win11电脑死机屏幕静止 方法一&#xff1a; 方法二&#xff1a; sfc包括有以下命令&#xff1a; 方法三&#xff1a; 点击拿去 Win11电脑突然死机卡住不动?Win11电脑死机屏幕静止 在使用Win11系统时&#xff0c;很多用户经常会遇到自己…

12月3日下午:thinkphp框架中的视图以及模型剩余部分

回忆知识&#xff1a; dump()与halt()方法 dump()&#xff1a;输出内容后不会终止脚本&#xff0c;会继续向下执行 halt()&#xff1a;输出内容后会终止脚本&#xff0c;结束程序 //dump()和halt()public function haltTest(){$result \db(demo)->where(id,,1)->select…

【Qt记录】Windows 窗口层级(Z-order)

功能&#xff1a;软件有一个提示弹窗&#xff0c;希望让他永远在最上面&#xff0c;保证该窗口在任何情况下不会被遮挡。 由上面的问题就查找对应的api找到了SetWindowPos()。 在说这个函数之前&#xff0c;先了解以下概念&#xff1a; Z-order&#xff08;Z顺序&#xff09…

6. SpringBoot 整合 RabbitMQ

二八佳人体似酥&#xff0c;腰间仗剑斩愚夫。虽然不见人头落&#xff0c;暗里教君骨髓枯。 创建一个 普通的 Spring Boot Web 项目 整合 RabbitMQ pom.xml 添加依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-st…

【云原生】一文带你吃透FlexManager数据传入华为云IOT

文章目录一、华为云设备接入服务1、创建设备接入基础版2、创建产品实例3、在产品下创建设备实例二、FlexManager部署一、华为云设备接入服务 设备接入服务&#xff08;IoTDA&#xff09;是华为云的物联网平台&#xff0c;提供海量设备连接上云、设备和云端双向消息通信、批量设…

【Linux】守护进程

文章目录任务管理进程组作业会话任务管理操作相关操作守护进程创建守护进程daemon函数创建守护进程所谓的项目部署任务管理 进程组 进程组是一个或多个进程的集合。每个进程除了有一个进程ID之外&#xff0c;还属于一个进程组。 每个进程组有一个唯一的进程组ID。每个进程组都…

CTFShow re2 (RC4

参考&#xff1a;CTFSHOW re2 本文&#xff1a;跟着大佬的博客一步一步做CTFShow re2的记录 IDA分析 有个比较函数 re一下 s "DH~mqqvqxB^||zllJq~jkwpmvez{" s1 for i in s:s1 chr(ord(i) ^ 0x1f) print(s1)得到 再四处看看 跟进sub_401028 四个sub点进去看看…

禅道登录-调用API方式

禅道提供了API机制方便于大家和其他的系统进行集成&#xff0c;API机制也都是基于http协议的&#xff0c;返回的数据以json格式存储。禅道的API都是需要先登录后才能进行接口调用&#xff08;登录返回的cookie需要在之后的每次请求中携带用于验证身份信息&#xff09;。网上关于…

DNS中有哪些值得学习的优秀设计

为什么要有DNS 如果我们想要访问某度&#xff0c;你可以在浏览器上的搜索栏里输入112.80.248.76这个IP地址&#xff0c;直达页面。 通过IP访问网页 这样的行为&#xff0c;合法&#xff0c;但有病。 大部分人&#xff0c;连自己对象的电话号码都记不住&#xff0c;又怎么可能…

shell脚本受限执行

shell 中运行的脚本或脚本的个代码断会禁用一些正常 shell 中可以执行的命令.这是限制脚本用户的权限和最小化运行脚本导致的破坏的安全措施.受限的内容包括&#xff1a;使用 cd 命令更改工作目录. 更改环境变量$PATH, $SHELL, $BASH_ENV,或$ENV 的值. 读或更改 shell 环境选项…

ARM 反汇编工具objdump的使用简介

一、反汇编的原理 & 为什么要反汇编 arm-linux-objdump -D led.elf > led_elf.dis-D, --disassemble-all Display assembler contents of all sectionsobjdump 是 gcc 工具链中的反汇编工具&#xff0c;作用是由编译链接好的 elf 格式的可执行程序反过来得到汇编源代…

【期末大作业】基于HTML+CSS+JavaScript网上订餐系统(23个页面)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

26-38-javajvm-类加载器子系统

26-javajvm-类加载器子系统&#xff1a; 1.内存结构概述 2.类加载子系统 2.1 类加载器子系统的作用 1&#xff09;、类加载器子系统负责从文件系统或者网络中加载Class文件&#xff0c;class文件在文件开头有特定的文件标识。 2&#xff09;、ClassLoader只负责class文件的加…

常用的shell命令

常用的shell命令 1、ls命令 功能&#xff1a;显示文件和目录的信息 ls 以默认方式显示当前目录文件列表 ls -a 显示所有文件包括隐藏文件 ls -l 显示文件属性&#xff0c;包括大小&#xff0c;日期&#xff0c;符号连接&#xff0c;是否可读写及是否可执行 ls -lh 显示文件的…

1547_AURIX_TC275_CPU子系统_数据存储接口

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) 这个可以对比PMI来看一下&#xff0c;相比于PMI&#xff0c;DMI的结构简单很多。 1. 之前在看cache以及其对指令读取速度影响的时候&#xff0c;可能弄错了一个概念。如果cache不命中&…

【JavaEE】认识多线程(一)

✨哈喽&#xff0c;进来的小伙伴们&#xff0c;你们好耶&#xff01;✨ &#x1f6f0;️&#x1f6f0;️系列专栏:【JavaEE】 ✈️✈️本篇内容:了解多线程(初阶) &#x1f680;&#x1f680;代码存放仓库gitee&#xff1a;JavaEE初阶代码存放&#xff01; ⛵⛵作者简介&#x…

单变量微积分重点(2)

泰勒公式 用柯西定理证明 拉格朗日余项 麦克劳林展开式&#xff1a; 皮亚诺余项的泰勒公式&#xff1a; 弧长的微分 注意s(t)需要在后面证明&#xff08;定积分的知识&#xff09; 不定积分&#xff1a; 注意&#xff0c;不同的积分方法经常会得到不同的结果&#xff0c;但它们…

IDEA如何配置 Gradle 及 Gradle 安装过程(详细版)

IDEA如何配置 Gradle&#xff08;详细版&#xff09; 一、安装 Gradle 1、下载 Gradle 安装包 官网下载链接&#xff1a;https://gradle.org/releases/ 2、下载后解压 3、文件夹如图所示 二、环境变量配置 1、点击我的电脑->属性->高级系统设置->环境变量 2、新建&…

[附源码]JAVA毕业设计抗击新冠疫情专题宣传网站(系统+LW)

[附源码]JAVA毕业设计抗击新冠疫情专题宣传网站&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 …

JSP+MySQL绿色环境保护网站的设计于实现

环保已经是当前中国的一个基本国策,国家领导人和各地政府也制定了一系列相关的政策来号召全民积极的参加到环保事业中来,为了能够更好的响应多家的号召我们开发了本JSP&#xff1a;MySQL&#xff1a;SSH 绿色环保网站,希望更多的人能够积极的参加到环保事业中来,本网站通过环境…