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

本文主要是介绍【MIDI_Boy】使用ESP32做一个炫酷的【卡林巴】【电子琴】, 可通过蓝牙MIDI连接手机库乐队,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

摘要

本项目主要使用ESP32模块作为主控,通过蓝牙MIDI协议连接手机,配合手机APP(库乐队等),实现了一个电子琴。

渲染图如下:

MIDI Boy 渲染图

演示视频

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



设计思路

卡林巴琴

本设计以真实的卡林巴琴为参考,采用下图所示的鼠标按键代替卡林巴琴的金属弹片,使用蜂鸣器作为发生元器件。

鼠标按键

蜂鸣器

仅仅采用蜂鸣器作为发声元器件,其表现力可能不会太好。所以本项目采用ESP32模块作为主控,利用其蓝牙功能连接手机,通过与手机的互动增强其表现力。

ESP32模块

ESP32是一颗功能强大的物联网芯片,可同时支持WiFi和蓝牙功能,20+可用GPIO,运行频率最高可达240MHz,可以采用C语言ArdiunoMicroPython等方式进行开发。



硬件设计

为了模拟真实的卡林巴琴的手感,设计硬件之前首先测量了上图所示的17键的卡林巴琴的尺寸键距 , 最终确定尺寸141mm*88mm,键距 7.6mm。

除了按键和蜂鸣器外,还使用了CH340串口芯片用于烧录程序,若干WS2812彩灯烘托音乐氛围。

完整原理图如下:

MIDI Boy原理图
MIDI原理图

PCB布局参考:

在这里插入图片描述

为了追求美观,将所有的线路都安排在了PCB板的背面。

另外,还是为了美观,将USB接口放置到了天线的下方,这种设计会影响无线信号,大家不要模仿哦!


硬件开源地址: https://oshwhub.com/Dr.Zhang/midi_boy



软件设计


前文提到,ESP32有多种开发方式,我这里采用了MicroPython的开发方式,其优点是开发环境搭建起来比较简单,代码量也不较少,目前程序并不完善,核心代码如下:

from machine import Pin, Timer
from time import sleep_ms
import ubluetooth
from esp32 import raw_temperatureclass BLE():def __init__(self, name):self.name = nameself.ble = ubluetooth.BLE()self.ble.active(True)self.led = Pin(14, Pin.OUT)self.timer1 = Timer(0)self.timer2 = Timer(1)self.disconnected()self.ble.irq(self.ble_irq)self.register()self.advertiser()self.isConnected = Falsedef connected(self):self.timer1.deinit()self.timer2.deinit()def disconnected(self):self.timer1.init(period=1000, mode=Timer.PERIODIC, callback=lambda t: self.led(1))sleep_ms(200)self.timer2.init(period=1000, mode=Timer.PERIODIC, callback=lambda t: self.led(0))def ble_irq(self, event, data): # 蓝牙事件处理if event == 1: # Central disconnectedself.isConnected = Trueself.connected()self.led(1)elif event == 2: # Central disconnectedself.isConnected = Falseself.advertiser()self.disconnected()elif event == 4: # New message receivedbuffer = self.ble.gatts_read(self.midi)message = buffer.decode('UTF-8')[:-1]print(message)if received == 'blue_led':blue_led.value(not blue_led.value())def register(self): # 注册MIDI蓝牙服务MIDI_SERVER_UUID = ubluetooth.UUID('03B80E5A-EDE8-4B33-A751-6CE34EC4C700')MIDI_CHAR_UUID   = (ubluetooth.UUID('7772E5DB-3868-4112-A1A9-F2669D106BF3'), ubluetooth.FLAG_READ | ubluetooth.FLAG_WRITE | ubluetooth.FLAG_NOTIFY , )BLE_MIDI_SERVER = (MIDI_SERVER_UUID, (MIDI_CHAR_UUID , ) , )SERVICES = (BLE_MIDI_SERVER, )((self.midi,), ) = self.ble.gatts_register_services(SERVICES)def send(self, data):if self.isConnected :self.ble.gatts_notify(0, self.midi, data)def advertiser(self): # 设置广播及扫描响应数据name = bytes(self.name, 'UTF-8')self.ble.gap_advertise(100, adv_data = b'\x02\x01\x05' + bytearray((len(name) + 1, 0x09)) + name ,  resp_data = b'\x11\x07\x00\xC7\xC4\x4E\xE3\x6C\x51\xA7\x33\x4B\xE8\xEd\x5A\x0E\xB8\x03')ble = BLE("ESP32")k_d6 = Pin(32, Pin.IN, Pin.PULL_UP)
k_b5 = Pin(33, Pin.IN, Pin.PULL_UP)
k_g5 = Pin(25, Pin.IN, Pin.PULL_UP)
k_e5 = Pin(26, Pin.IN, Pin.PULL_UP)
k_c5 = Pin(27, Pin.IN, Pin.PULL_UP)
k_a4 = Pin(12, Pin.IN, Pin.PULL_UP)
k_f4 = Pin(13, Pin.IN, Pin.PULL_UP)
k_d4 = Pin(15, Pin.IN, Pin.PULL_UP)k_c4 = Pin(4,  Pin.IN, Pin.PULL_UP)k_e4 = Pin(16, Pin.IN, Pin.PULL_UP)
k_g4 = Pin(17, Pin.IN, Pin.PULL_UP)
k_b4 = Pin(5,  Pin.IN, Pin.PULL_UP)
k_d5 = Pin(18, Pin.IN, Pin.PULL_UP)
k_f5 = Pin(19, Pin.IN, Pin.PULL_UP)
k_a5 = Pin(21, Pin.IN, Pin.PULL_UP)
k_c6 = Pin(22, Pin.IN, Pin.PULL_UP)
k_e6 = Pin(23, Pin.IN, Pin.PULL_UP)key_pin_list   = [k_c4,k_d4,k_e4,k_f4,k_g4,k_a4,k_b4,k_c5,k_d5,k_e5,k_f5,k_g5,k_a5,k_b5,k_c6,k_d6,k_e6]
key_name_list  = ['k_c4','k_d4','k_e4','k_f4','k_g4','k_a4','k_b4','k_c5','k_d5','k_e5','k_f5','k_g5','k_a5','k_b5','k_c6','k_d6','k_e6']
key_value_last = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
key_value_now  = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]midi_start = 0x48 #C4键的音高# 与C4相比的音程查
midi_inve  = [0,2,4,5,7,9,11,12,14,16,17,19,21,23,24,26,28]while True :for i in range(17):key_value_now[i] = key_pin_list[i].value()if not key_value_last[i] == key_value_now[i] :if key_value_now[i] == 0:print("on_" + key_name_list[i])ble.send(bytearray([0x80, 0x80, 0x90, midi_start + midi_inve[i] , 0x63]))else :print("off_" + key_name_list[i])ble.send(bytearray([0x80, 0x80, 0x80, midi_start + midi_inve[i] , 0x00]))key_value_last[i] = key_value_now[i]sleep_ms(10)




实物效果图

在这里插入图片描述

如果你喜欢改文章,欢迎点赞 评论 收藏 转发!

我是鹏老师!

这篇关于【MIDI_Boy】使用ESP32做一个炫酷的【卡林巴】【电子琴】, 可通过蓝牙MIDI连接手机库乐队的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/749380

相关文章

Python中模块graphviz使用入门

《Python中模块graphviz使用入门》graphviz是一个用于创建和操作图形的Python库,本文主要介绍了Python中模块graphviz使用入门,具有一定的参考价值,感兴趣的可以了解一... 目录1.安装2. 基本用法2.1 输出图像格式2.2 图像style设置2.3 属性2.4 子图和聚

windows和Linux使用命令行计算文件的MD5值

《windows和Linux使用命令行计算文件的MD5值》在Windows和Linux系统中,您可以使用命令行(终端或命令提示符)来计算文件的MD5值,文章介绍了在Windows和Linux/macO... 目录在Windows上:在linux或MACOS上:总结在Windows上:可以使用certuti

CentOS和Ubuntu系统使用shell脚本创建用户和设置密码

《CentOS和Ubuntu系统使用shell脚本创建用户和设置密码》在Linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设置密码,本文写了一个shell... 在linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设

Python使用Matplotlib绘制3D曲面图详解

《Python使用Matplotlib绘制3D曲面图详解》:本文主要介绍Python使用Matplotlib绘制3D曲面图,在Python中,使用Matplotlib库绘制3D曲面图可以通过mpl... 目录准备工作绘制简单的 3D 曲面图绘制 3D 曲面图添加线框和透明度控制图形视角Matplotlib

Pandas中统计汇总可视化函数plot()的使用

《Pandas中统计汇总可视化函数plot()的使用》Pandas提供了许多强大的数据处理和分析功能,其中plot()函数就是其可视化功能的一个重要组成部分,本文主要介绍了Pandas中统计汇总可视化... 目录一、plot()函数简介二、plot()函数的基本用法三、plot()函数的参数详解四、使用pl

MySQL 多表连接操作方法(INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL OUTER JOIN)

《MySQL多表连接操作方法(INNERJOIN、LEFTJOIN、RIGHTJOIN、FULLOUTERJOIN)》多表连接是一种将两个或多个表中的数据组合在一起的SQL操作,通过连接,... 目录一、 什么是多表连接?二、 mysql 支持的连接类型三、 多表连接的语法四、实战示例 数据准备五、连接的性

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

MySQL中的分组和多表连接详解

《MySQL中的分组和多表连接详解》:本文主要介绍MySQL中的分组和多表连接的相关操作,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录mysql中的分组和多表连接一、MySQL的分组(group javascriptby )二、多表连接(表连接会产生大量的数据垃圾)MySQL中的

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令