×

MIDI合并器构建

消耗积分:0 | 格式:zip | 大小:0.88 MB | 2022-10-18

分享资料个

描述

这个概念

这个项目的诞生与我的ARKeytar MIDI 控制器的开发密切相关。在我构建 ARKeytar 之后,我意识到我想扩展它在音乐表达方面的能力。此外,我需要通过 MIDI 接口将生成的 MIDI 消息发送到我的键盘合成器或我的 PC,以控制 VST 合成器。

为了在连接整个设置的同时更改 MIDI 路由,我决定构建一个 MIDI 合并器,它还可以管理表情踏板和开关踏板。

工作原则

由于需要管理两个串行端口(两个 MIDI 输入和两个 MIDI 输出),因此选择了 Arduino Mega 板,因为与 Arduino Uno 不同,它能够管理多个串行端口。

这个想法是让 ARKeytar MIDI 控制器和我的键盘合成器连接到合并器的 MIDI 输入,而两个 MIDI 输出直接指向键盘合成器和音频-MIDI 接口。通过两个具有三个位置的 SPDT(单刀双掷)开关,可以告诉 Arduino 两个 MIDI 输入中的每一个的目标 MIDI 输出端口。

MIDI 输入 1 可以发送到 MIDI 输出之一或两者,而 MIDI 输入 2 可以发送到 MIDI 输出之一或不发送。MIDI 输入 2 的路由包括不转发生成的消息的可能性,因为连接的键盘只能用于控制其内部声音,而不是控制某些 VST 软件。现在,只需移动两个开关,我就可以配置我的 MIDI 设备的路由。

dscf7710_(grandi)_hUHJYRzovg.png?auto=compress%2Cformat&w=740&h=555&fit=max

六个 SPDT 开关控制 MIDI 路由以及踏板设置。

合并的后面板还提供了两个插孔端口。其中之一可用于连接开关踏板。另一个可以同时处理表情踏板或开关踏板。可以通过顶部面板上的开关来选择行为,该开关会更改踏板所连接的 Arduino 引脚的配置。

dscf7708_(grandi)_ODobFA7J4v.png?auto=compress%2Cformat&w=740&h=555&fit=max

两个用于表情和开关踏板的插孔。

将踏板用作简单开关时,数字引脚 D2 设置为 INPUT_PULLUP。否则,将其设置为状态为 HIGH 的输出。在这种情况下,立体声插孔中心引脚的电压值通过模拟引脚 A4 上的analogRead() 读取。其余引脚始终连接到 GND。

gestione_pedali_Lm3LjLUPpq.png?auto=compress%2Cformat&w=740&h=555&fit=max

专用开关更改数字引脚 2 的模式以适应两种可能的踏板类型:输出 HIGH 将表情踏板用作电位器,而 INPUT_PULLUP 将延音踏板用作开关。

读取踏板状态后,如果发生更改,则会生成 MIDI 消息。可以对控制更改目标进行编程,并且可以使用顶部面板上的开关为每个踏板选择目标 MIDI 输出端口。Arduino 将路由的传入消息与踏板动作后生成的消息合并在一起。

存在一个额外的开关来添加一些可以通过在 Arduino IDE 中编辑代码来分配的通用设置。出于同样的原因,存在数字编码器。此外,可以使用三个单块开关生成附加的 MIDI 消息,例如程序更改消息。

所有开关都使用一对移位寄存器连接到 Arduino。这主要用于简化前面板和拧在底座上的 Arduino Mega 之间的连接。以这种方式使用的通道数量减少了。

合并还提供了三个 LED,用于分析传入 MIDI 消息的类型。绿色和红色 LED 分别由音符开和音符关信息激活,而蓝色 LED 由弯音信息(这是 ARKeytar 发送的大部分 MIDI 信息)和控制更改信息触发。

dscf7705_(grandi)_ckmapQvuWi.png?auto=compress%2Cformat&w=740&h=555&fit=max

编码器和根据传入 MIDI 消息类型闪烁的三个 LED。绿色表示打开,橙色表示关闭,蓝色表示弯音和控制变化信息。

构建和编程

我选择了一个坚固的铝盒作为该项目的外壳。底座尺寸为 189 毫米 x 121 毫米。盒子的厚度,不包括后来的添加是 38 毫米。为 SPDT 开关钻了六个孔,为停止踏板钻了三个孔,为 LED 钻了三个孔,为编码器钻了一个孔。

一开始,我没有在 MIDI 端口上钻孔,因为我需要与四个 MIDI 插座对齐,焊接到内部电路上。

bereal-1650213028426_ps_SaoWBGrwz6.png?auto=compress%2Cformat&w=740&h=555&fit=max

钻孔后放置元件。在这个阶段还不存在 LED 孔。

我遵循的程序是:

将所有主电路(包括 MIDI 端口)焊接到原型 PCB 板上。为了将 Mega 容纳在具有刚性连接且无需焊接的合并外壳内,使用了公排针。Mega 和 PCB 之间的空间可用于安装电路和电缆。也为该项目未来可能的扩展留下了空间。MIDI 电路与插座一起焊接在底座上,并连接到 Arduino 串行端口。

将 PCB 拧到铝壳底座上

打开四个 MIDI 端口和 Arduino USB 孔。对于 MIDI 端口,使用直径为 16 毫米的铣刀代替钻头,因为外壳壁略微倾斜,而 MIDI 插座则没有。

钻出所有需要的孔以安装开关、LED 和编码器。除了三个用于分析 MIDI 输入的 LED 外,还添加了一个 LED 来指示合并器已连接到电源并已打开。

dscf7707_(grandi)_zUtVZsGM6l.png?auto=compress%2Cformat&w=740&h=555&fit=max

迷笛端口。

由于所有开关都需要 5V 连接,以及另外 1 或 2 个数字引脚连接,我试图限制连接机箱底座和顶部面板的电缆数量。顶部面板下方放置了两个移位寄存器,因此至少电缆混乱仅限于顶部面板。这有助于保持合并基础的一些整洁。带状电缆用于连接前面板和底座。

pxl_20220425_131619739_2_(grandi)_zcTzzPF3JK.jpg?auto=compress%2Cformat&w=740&h=555&fit=max

带状电缆(灰色)将前面板(顶部)连接到底座(底部)。

我包括了编码器和单块踏板,因为我打算给它们一个功能,比如从列表中更改设置和发送程序更改消息。但是,它们目前不活跃。

除两个开关外,所有开关都连接到两个数字引脚。开关可以处于三个位置,以便当它们处于中心位置时,它们可以将 5V 提供给其中一个引脚或不提供给任何一个引脚。在这个位置,两个数字读数都是低的。如果其中之一为 HIGH,则选择相应的设置。由于连接的设计,它们永远不能同时处于 HIGH 状态。以这种方式,三种可能的状态是可能的。

尤其是:

开关 1 将 MIDI 输入 1 路由到输出 1、输出 2 或两者。

开关 2 将 MIDI 输入 2 路由到输出 1、输出 2 或无。

开关 3 选择踏板 2 的数字或模拟行为。踏板 1 始终充当开关

开关 4 将使用踏板 1 生成的 MIDI 消息路由到 MIDI 输出 1 或 2,或两者。

开关 5 将使用踏板 2 生成的 MIDI 信息路由到 MIDI 输出 1 或 2,或两者。

开关 6 当前未分配给任何功能。

相反,踏板只能位于两个位置,并连接到单个数字引脚。如果在压力时需要发送单条消息,则使用状态的变化来触发单条消息。否则,状态可用于确定应在一组两条消息中发送哪条消息,如开/关按钮。

三个踏板和编码器(及其按钮)当前未分配给任何功能。

merger_parti_rFbxyfFOk9.png?auto=compress%2Cformat&w=740&h=555&fit=max

(1) MIDI 端口,(2) 踏板插孔,(3) 带按钮的编码器,(4) MIDI 分析器 LED,(5) 路由和设置开关,(6) 单块开关,以及 (7) Mega USB 端口和电源引领。

 

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.lene-v.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'MIDI合并器构建',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.lene-v.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);