基于arduino的ESP32上蓝牙midi音乐设备开发教程

目录

简介

开发环境

开发过程

函数介绍

相关文章


简介

首先看几个视频,大佬们做的东西,都是基于esp32。

自制卡林巴电子琴,可通过蓝牙连接手机库乐队 MIDI Boy【理科生的第一件乐器】_哔哩哔哩_bilibili

【Totoro】模仿“埙”的电子吹奏乐器_哔哩哔哩_bilibili

相关的文章如下

Python挺酷的 | 识别蓝牙MIDI(基于ESP32开发板)_python解析midi-CSDN博客

【MIDI_Boy】使用ESP32做一个炫酷的【卡林巴】【电子琴】, 可通过蓝牙MIDI连接手机库乐队_esp32 midi-CSDN博客

上面这些都是用esp32官方编译琏进行的编译,对于我这种懒汉有点不友好,现在编译器,ide五花八门,实在不想做多配环境。

下面我就用arduino的库来开发一个能实现上面功能的方法。

开发环境

esp32开发板

android手机,因为我只有android手机,ios没有验证过。

arduino2.3.2

自乐班 自乐班 - 锣钹科技 (robkoo.com)

开发过程

打开raduino,安装库中搜索“BLE-MIDI”并安装。

先这样选,后面需要手动更改,

配置开发板

如果你用了其他esp32模块,根据需要进行选择。

现在我们需要手动修改一下库,以为刚刚全部下载的依赖库中包含了多余的库。

我们到“项目文件夹地址”的目录中

我们看到一共下载了4个库,我们需要手动把ArduinoBLE文件夹删掉,因为这个库里面的东西与esp32的ble库冲突。

现在我们就准备好了全部的环境。

函数介绍

我的功能定义的比较简单,就是蓝牙能够连接上手机,然后代码能够让手机发出音乐,所以这里我就说一下必须用到的函数,额外的功能自行学习吧。

需要引用的头文件

#include <BLEMIDI_Transport.h>
#include <hardware/BLEMIDI_ESP32.h>
BLEMIDI_CREATE_DEFAULT_INSTANCE()

定义了蓝牙设备,名字是默认的“Esp32-BLE-MIDI”

#define BLEMIDI_CREATE_INSTANCE(DeviceName, Name)

如果需要定义特别的名字,可以调用上面的宏,如:BLEMIDI_CREATE_INSTANCE("MyBLEserver",MIDI)

MIDI.begin();

初始化蓝牙midi设备。

    BLEMIDI_Transport &setHandleConnected(void (*fptr)())
    {
        _connectedCallback = fptr;
        return *this;
    }

    BLEMIDI_Transport &setHandleDisconnected(void (*fptr)())
    {
        _disconnectedCallback = fptr;
        return *this;
    }

设备连接和断开回调。可以如下方法使用。

  BLEMIDI.setHandleConnected([]() {
    isConnected = true;
    digitalWrite(LED_BUILTIN, HIGH);
  });

  BLEMIDI.setHandleDisconnected([]() {
    isConnected = false;
    digitalWrite(LED_BUILTIN, LOW);
  });
void MidiInterface<Transport, Settings, Platform>::sendNoteOn(DataByte inNoteNumber,
                                                     DataByte inVelocity,
                                                     Channel inChannel)

发送信息给手机,inNoteNumber播放的音节,inVelocity音量0-100,0表示关闭,inChannel通道,对于midi音乐设备没有用到,直接写1即可。

音节的表可以看【低功耗蓝牙】④ 蓝牙MIDI协议-CSDN博客文章。

下面我贴一下我的测试代码,

#include <BLEMIDI_Transport.h>

//#include <hardware/BLEMIDI_ESP32_NimBLE.h>
#include <hardware/BLEMIDI_ESP32.h>
//#include <hardware/BLEMIDI_nRF52.h>
//#include <hardware/BLEMIDI_ArduinoBLE.h>

BLEMIDI_CREATE_DEFAULT_INSTANCE()

unsigned long t0 = millis();
bool isConnected = false;
#define LED_BUILTIN 2
#define BUTTON_PIN 0
// -----------------------------------------------------------------------------
// When BLE connected, LED will turn on (indication that connection was successful)
// When receiving a NoteOn, LED will go out, on NoteOff, light comes back on.
// This is an easy and conveniant way to show that the connection is alive and working. 
// -----------------------------------------------------------------------------
void setup()
{
  MIDI.begin();
  Serial.begin(9600);

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  digitalWrite(LED_BUILTIN, LOW);

  BLEMIDI.setHandleConnected([]() {
    isConnected = true;
    digitalWrite(LED_BUILTIN, HIGH);
  });

  BLEMIDI.setHandleDisconnected([]() {
    isConnected = false;
    digitalWrite(LED_BUILTIN, LOW);
  });

  MIDI.setHandleNoteOn([](byte channel, byte note, byte velocity) {
    digitalWrite(LED_BUILTIN, LOW);
  });
  MIDI.setHandleNoteOff([](byte channel, byte note, byte velocity) {
    digitalWrite(LED_BUILTIN, HIGH);
  });
}

// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void loop()
{
  // MIDI.read();
  int buttonState = digitalRead(BUTTON_PIN);
  if ((buttonState == LOW) && isConnected) {
    Serial.printf("123\n");
    MIDI.sendNoteOn (60, 100, 1);
    delay(500);
    MIDI.sendNoteOn (70, 100, 1);
    delay(5000);
    MIDI.sendNoteOn (60, 0, 1);
    MIDI.sendNoteOn (70, 0, 1);
  }
  delay(10);
}

下载完成后手机上打开自乐班软件,找到“设备管理”,“其他MIDI”,“BLE MIDI设备”,点击“Esp32-BLE-MIDI”,连接完成后名字后面会有一个小黄点。

代码功能就是连接设备后开发板上的蓝灯亮起,断开连接蓝灯熄灭,按下boot按键手机会发出声音。

这个软件很强大,很多种乐器可以选择,而且我发现那些按一下发一声的乐器,比如钢琴,你调用一次,就会响较短的一声,当你选择那些能够持续发声的,比如口琴,笛子这种,发声会持续,直到调用音量为0才停止。

相关文章

【低功耗蓝牙】④ 蓝牙MIDI协议-CSDN博客

最全midi常用表 - 豆丁网 (docin.com)

【BLE MIDI】开发 BLE MIDI 硬件电子乐器设备需要遵循的相关规范 ( 资料收集 )-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

win11电脑驱动怎么更新,windows11更新驱动

驱动是指计算机里软件的程序,硬件的运作离不开驱动的支持,因为驱动就是使得硬件和电脑系统沟通的桥梁。既然驱动如此重要,那么不装肯定不行,如果有问题,也要及时地修复和更新。最近,有位win11用户,想要了解win11电脑驱动怎么更新?接下来,教程会带来两种更新win11驱动的…

vscode i18n Ally插件配置项

.vscode文件&#xff1a; {"i18n-ally.localesPaths": ["src/lang"], //显示语言&#xff0c; 这里也可以设置显示英文为en,// 如下须要手动配置"i18n-ally.keystyle": "nested", // 翻译路径格式 (翻译后变量格式 nested&#xff1a…

[C++初阶]类和对象(一)

1.面向过程和面向对象的区分 我们之前都是用C语言写的代码,我们知道C语言是一个面向过程的语言,但是现在我们学的时C,我们都知道C是一种面向对象的语言,那么什么叫面向过程?什么叫面向对象呢? 这里我们来举个例子: 比如我们是开饭店的&#xff0c;客人点了一道菜&#xff0c…

开源模型应用落地-LangChain试炼-CPU调用QWen1.5(一)

一、前言 尽管现在的大语言模型已经非常强大&#xff0c;可以解决许多问题&#xff0c;但在处理复杂情况时&#xff0c;仍然需要进行多个步骤或整合不同的流程才能达到最终的目标。然而&#xff0c;现在可以利用langchain来使得模型的应用变得更加直接和简单。 通过langchain框…

什么是T型槽铸铁平板中内应力——河北北重厂家

T型槽铸铁平板中的内应力指的是平板内部受到的内部力&#xff0c;包括拉应力和剪应力。在T型槽铸铁平板使用过程中&#xff0c;由于自身重量、外力加载等原因&#xff0c;会产生内部应力。这些内应力是平板内部各部分之间的相互作用力&#xff0c;使得平板各部分受到不同的拉伸…

C++ 为什么不能在构造函数中调用虚函数

最近在Clion编辑器中看到构造函数中调用虚函数提示&#xff1a; Do not invoke virtual member functions from constructor 这里记录一下为什么不能在构造函数中调用虚函数。 #include <iostream> #include <string>using namespace std;class BaseClass {publi…

大模型时代:普通人该如何获利?

随着科技的飞速发展&#xff0c;我们正处在一个大模型的时代。所谓大模型&#xff0c;就是指那些拥有数十亿、甚至千亿参数的深度学习模型。这些大模型的出现&#xff0c;不仅推动了人工智能技术的进步&#xff0c;也为普通人创造了众多的获利机会。那么&#xff0c;在这个大模…

【Java开发指南 | 第六篇】Java成员变量(实例变量)、 类变量(静态变量)

读者可订阅专栏&#xff1a;Java开发指南 |【CSDN秋说】 文章目录 成员变量&#xff08;实例变量&#xff09;类变量&#xff08;静态变量&#xff09;定义方式静态变量的使用场景 成员变量&#xff08;实例变量&#xff09; 成员变量声明在一个类中&#xff0c;但在方法、构造…

GAMS104 现代游戏引擎 2

渲染的难点可以分为一下三部分&#xff1a;如何计算入射光线、如何考虑材质以及如何实现全局光照。 渲染的难点之一在于阴影&#xff0c;或者说是光的可见性。如何做出合适的阴影效果远比想象中要难得多&#xff0c;在实践中往往需要通过大量的技巧才能实现符合人认知的阴影效…

AI数字人对话之RealChar框架源码解读

零.功能介绍 与虚拟角色(非形象)进行文本或语音会话 体验地址:RealChar. 代码库:GitHub - Shaunwei/RealChar: 🎙️🤖Create, Customize and Talk to your AI Character/Companion in Realtime (All in One Codebase!). Have a natural seamless conversation with AI…

3.3 Ax=b 的完全解

一、Ax b 在求解 A x 0 A\boldsymbol x\boldsymbol 0 Ax0 时&#xff0c;我们将其转化成 R x 0 R\boldsymbol x\boldsymbol 0 Rx0&#xff0c;将自由变量赋予特殊值&#xff08;1 或 0&#xff09;&#xff0c;主元变量即可通过回代求出。这个过程中我们没有关注右侧的 …

基于SpringBoot+Vue的在线教育系统(源码+文档+包运行)

一.系统概述 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了在线教育系统的开发全过程。通过分析在线教育系统管理的不足&#xff0c;创建了一个计算机管理在线教育系统的方案。文章介绍了在线教育系统的系统分析部…

Python基于Django的微博热搜、微博舆论可视化系统

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

【SLAM】在Win10上实现Nerf-Pytorch【GPU版】

文章目录 ReadMe安装依赖运行下载两个示例数据集:lego和fern训练一个低分辨率的Lego NeRF:训练一个低分辨率蕨类植物NeRF:更多数据集预训练模型可复现实现1、下载nerf-pytorch工程2、安装依赖3、下载数据4、运行lego NeRF:ReadMe Github链接 NeRF (神经辐射场)是一种在合成…

UE5 C++ 创建3DWidgete 血条 再造成伤害

一&#xff0e;创建 二&#xff0e;&#xff35;&#xff29;里声明变量 创建类 public:UPROPERTY(EditAnywhere,BlueprintReadWrite,Category "MyWidget")float CurrentHealth 100.0f;UPROPERTY(EditAnywhere,BlueprintReadWrite,Category "MyWidget"…

代码随想录算法训练营DAY24|C++回溯算法Part.1|回溯算法理论基础、77.组合、组合问题的剪枝操作

文章目录 回溯算法如何理解回溯算法回溯法模版回溯算法模版框架 77.组合树形结构回溯三部曲伪代码CPP代码实现 组合问题的剪枝操作 回溯算法 如何理解回溯算法 回溯法解决的问题都可以抽象为树形结构。 因为回溯法解决的都是在集合中递归查找子集&#xff0c;集合的大小就构成…

mysql面试题 二

超键、候选键、主键、外键分别是什么&#xff1f; 超键&#xff1a;在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以为作为一个超键&#xff0c;多个属性组合在一起也可以作为一个超键。超键包含候选键和主键。候选键&#xff1a;是最小超键&#xff0c;即没…

【Altium Designer 20 笔记】PCB板框

Altium Designer中设置PCB板框 PCB板框位于Mechanical1层 点击放置中的线条或使用其他绘图工具来绘制板框, 可以绘制矩形、圆形或其他形状的板框,确保板框是闭合的 注意&#xff1a;在绘制板框时&#xff0c;确保线条的起点和终点相连&#xff0c;形成一个闭合的图形。 快捷键D…

【C++航海王:追寻罗杰的编程之路】异常——错误处理方式之一

目录 引言 1 -> C语言传统的处理错误的方式 2 -> C异常概念 3 -> 异常的使用 3.1 -> 异常的抛出和捕获 3.2 -> 异常的重新抛出 3.3 -> 异常规范 4 -> 自定义异常体系 5 -> C标准库的异常体系 6 -> 异常的优缺点 引言 在C编程中&#xff…

C++ | Leetcode C++题解之第32题最长有效括号

题目&#xff1a; 题解&#xff1a; class Solution { public:int longestValidParentheses(string s) {int left 0, right 0, maxlength 0;for (int i 0; i < s.length(); i) {if (s[i] () {left;} else {right;}if (left right) {maxlength max(maxlength, 2 * ri…