用儿童合成器制作MIDI键盘

图片

有一天,回到家中,在入口处的垃圾槽附近,我看到了一个旧的儿童玩具合成器。过去了,因为从垃圾箱中拿走垃圾是“有罪的”,但我内心想把它拖到那儿。我已经深夜了,大约2点钟,我决定看看她是否还站在那儿。是的,她还在那里!从外观上看,她完全健康整洁,所以没有吱吱作响的感觉,以免带走她。所以是的,我带了她。

我一直想为自己准备一架钢琴,我不是专业音乐家,而是沉迷于-为什么不呢?买东西“为了宠爱”我被“蟾蜍勒死了”,在这里-一个免费的玩具。当我从垃圾箱中拿走它时,我什至没有想到要把它当作儿童玩具使用,我立即想到:“哦……尝试制作MIDI键盘的好基础。”
由于我已经具有与专业键盘和MIDI键盘进行通信的经验,因此我立即了解了我的想法的所有缺点。也就是说,玩具实际上将仍然是玩具。在此基础上,将不可能实现击键的功能。 “轻巧”的塑料按键本身也不完整,无法进行有价值的操作。

首先,将玩具合成器“拧到”螺丝上,将所有塑料用肥皂清洗干净。主板和按键的触点组也要清洗。

拆卸后,人们对为什么将其丢弃有了一个了解。玩具(我不知道为什么:不时,由于中国部件的质量或操作困难),其次:内置扬声器散开,其次:它们的连接器损坏了,插在了耳机插孔中,所以几乎没有办法拉它。可能是在玩具停止使用内置扬声器播放后,他们将其与耳机配合使用,然后在断开连接器后,将其扔掉了。

在内部,玩具合成器由通过电缆回路互连的三个板组成。负责产生声音和其他事物的中央委员会立即从其他两个委员会中解散出来,并搁置了下来。在另外两个板上,有玩具前面板上的按钮和钢琴键本身的触点。我将PBS连接器焊接到了它们,特别是因为板上的孔距仅为2.54 mm。





在那之后,我花了几个小时来绘制带有按键的这些板的示意图。事实证明,该方案是一个简单的矩阵键盘。



在黄色圆圈中的图片中,数字是“水平”触点的编号,按键上的数字是键盘板上PBS-13连接器中“垂直”触点的编号。







在那之后,所有这些都扔进了一个角落,并撒了一年灰尘。然后,自我隔离的时期开始了……开始变得无聊,我想用自己的双手去做些事情,尤其是因为无处可去,而且这是不可能的……

最后,我决定尝试至少完成一点这个玩具。 Arduino板被用作控制器的基础,并且由于键链的数量大于Arduino UNO引脚的数量,我决定使用移位寄存器74HC595和74HC165。结果,我们得到了这样的方案。



该电路最初是在无焊面包板上组装的。为了测试电路的可操作性(在任何地方的连接中没有错误),开发了一个测试程序,该程序显示一切似乎正常。测试程序的算法很简单:打开移位输出芯片的输出之一,并在按下键的同时从移位输入芯片中读取一个周期的值。乍一看,没有什么预示着麻烦……而且一切似乎都很好……



接下来的几天,我慢慢地进行“作业”,即将电路板的所有组件小心地焊接到面包板上。我从自己家的地方收集了所有东西。他将Arduino NANO作为控制板。



板子之间的这种“三明治”是由于以下事实:玩具的两个板子(一个带有按钮,第二个带有键盘)位于不同的位置,在焊接之前,我曾想过:“是否可以通过某种方式将其连接在一起我在家中看起来差不多的组件是什么?”因此,事实证明,这种通过连接器互连的两块板的设计。从我的角度来看,对于家庭选项,当我们处于自我隔离状态时,结果非常好。我所要做的就是切开面包板,并稍微修改玩具主体,以便您可以将USB电缆连接到Arduino板上。



当我完成测试程序时,就意识到设备不能完全按照我的要求工作。该算法很简单:考虑到74HC165芯片输入的状态,打开74HC595芯片的每个输出,并将结果写入单独的变量中。总共74HC595的5个输出连接到了键盘,因此在这次轮询之后,最终我得到了40位(5 * 8)数据。一串40位的字符串输出到控制台,并按下了按键以查看设备如何处理多个按键的同时击键。



这是问题浮出水面的地方:如果您按下一个键,一切都很好,但是当您尝试同时按下两个以上的键时,出现了无法预测将要读取的内容的情况。使用一种组合,结果可能是正确的,而使用另一种组合,结果可能是完全不可预测的。问题在于没有考虑该方案的功能。同时按下多个键时,不仅关闭了键盘扫描的多个垂直方向(这是允许的),而且可以通过键关闭多条水平线(绝对不允许)。您可以在此处阅读有关此问题及其解决方法的更多信息

我选择了该问题的“基本解决方案”,即:我决定键盘上的每个键都会有一个二极管。

在我的脑海中,我已经开始思考如何切割板上的走线并将SMD外壳中的二极管放在间隙中。我爬进储藏室,发现在SMD外壳中根本没有那么多二极管(别忘了我们所有人都坐在自我隔离的环境中,不太可能去商店购买无线电组件-因为这些绝对不是必需品)。有点不高兴,我决定更仔细地看一下电路板:有可能在某些轨道上放置输出二极管(我也有一些)。然后我看到每个键都有一个跳线(电路板是单面的),并且制作了电路,因此您可以放一个二极管代替这个跳线。我立刻想到-您甚至不需要削减任何东西,您只需要放置输出二极管,而不是到处都安装跳线即可。我也没有这么多输出二极管。我脑海中闪过一个念头:“也许是LED吗?”电路工作在+ 5V电压下,如果您将电压降最小的红色LED(在LED之间)放置,那么最后应该有一个逻辑电平来进行正确的确定:是否按下该键。



考虑到这一点,我再次爬进股票,并尽可能地抓住红色的LED。键盘上的按键数正好一样!我认为,这是一个信号,并焊接了多个LED而不是跳线进行测试。测试结果表明该解决方案正在工作。之后,我焊接了其余的LED而不是跳线。测试程序显示您可以同时按下至少所有按键,并且所有按键都可以正确读取。



我决定不将二极管放在玩具上的其他按钮上,因为不太可能一次将它们压成几块。而且,在程序中我还没有点击这些按钮的处理。好吧,我还没有决定如何使用它们。

现在该弄清楚如何使该设备作为MIDI键盘出现在计算机上以及需要以哪种格式发送数据了。

在互联网上找到的信息告诉我,可以很容易地从Arduino中制作MIDI键盘,只需将固件倒入其中,这将使计算机将其视为不是MIDI键盘,而是COM端口。最初,我受此决定的指导,而不是特别关注如何执行它。

现在,当我走近他并仔细阅读它时,我意识到我的Arduino NANO开发板不适合该解决方案,因为它具有基于CH340芯片的COM端口。要使用上面的链接中的固件,只有那些USB端口已经在控制器上(例如:AtMega32u4)或不在FT232RL类型转换芯片等上通过COM端口进行通信,而是在AtMega微控制器上进行通信的卡才适用。因此,开发板上的固件必须将MIDI格式的数据发送到COM端口,并且在计算机上,您将必须安装和配置将拦截该数据并将其传输到虚拟MIDI端口的软件。
读取按键和生成MIDI命令的算法如下:



Arduino NANO控制器的程序现在看起来像这样。
//    +5V
//   ST_CP  74HC595
#define latchPin      11
//   SH_CP  74HC595
#define clockPin      13
//   DS  74HC595
#define dataPin       12

//     +5V
#define latchPin_IN   9
#define clockPin_IN   10
#define dataPin_IN    8

// ,       1-16    
#define BUT_OUT0      7
#define BUT_OUT1      6
#define BUT_OUT2      5
#define BUT_OUT3      4

byte but_out[4] = {BUT_OUT0, BUT_OUT1, BUT_OUT2, BUT_OUT3};
//       
byte kbd_in[5] = {0, 0, 0, 0, 0};
byte kbd_in_new[5] = {0, 0, 0, 0, 0};

//       
byte btn_in[4] = {0, 0, 0, 0};
byte btn_in_new[4] = {0, 0, 0, 0};

//  3  -   (1 - , 0 - )
byte kbd_out = 0b11100000;

//  
void init_electronics() {
  //  ,   +5V
  //  OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

  //  ,   +5V
  pinMode(latchPin_IN, OUTPUT);
  pinMode(clockPin_IN, OUTPUT);
  pinMode(dataPin_IN, INPUT);

  //          
  for (byte i = 0; i < 4; i++) pinMode(but_out[i], OUTPUT);
}

//      74HC595
void write_5V(byte a) {
    digitalWrite(latchPin, LOW);
    //    dataPin
    shiftOut(dataPin, clockPin, MSBFIRST, a); 
     //"" ,      
    digitalWrite(latchPin, HIGH); 
}

void read_5V(byte *btn, byte *kbd) {
  digitalWrite(clockPin_IN, HIGH);
  digitalWrite(latchPin_IN, LOW);
  digitalWrite(latchPin_IN, HIGH);
  
  //    -    
  *btn = shiftIn(dataPin_IN, clockPin_IN, LSBFIRST);
  
  //    -    
  *kbd = shiftIn(dataPin_IN, clockPin_IN, LSBFIRST);
}

void setup() {
  init_electronics();
  write_5V(kbd_out);
  Serial.begin(115200);
}

//       ,   
void read_kbd_and_btn_state(byte *btn, byte *kbd) {
 byte tmp;
  for (byte i = 0; i < 5; i++) {
    write_5V(kbd_out | (1 << i));
    read_5V(&tmp, &kbd[i]);
  }
}

void noteOn(int cmd, int pitch, int velocity) {
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
}

//     num  ,   
// 0 -  0,  0
// 1 -  0,  1
// 2 -  1,  1
// 3 -  1,  0
byte compare_bit(byte old_state, byte new_state, byte num) {
  byte tmp_old, tmp_new;
  tmp_old = (old_state >> num) & 1;
  tmp_new = (new_state >> num) & 1;
  if ((tmp_old == 0) && (tmp_new == 0)) return 0;
  if ((tmp_old == 0) && (tmp_new == 1)) return 1;
  if ((tmp_old == 1) && (tmp_new == 1)) return 2; 
  if ((tmp_old == 1) && (tmp_new == 0)) return 3;  
}

void loop() {
  read_kbd_and_btn_state(btn_in_new, kbd_in_new);
  for (byte i = 0; i < 5; i++) {
    for (byte j = 0; j < 8; j++) {
      switch (compare_bit(kbd_in[i], kbd_in_new[i], 7 - j)) {
        //  
        case 1: noteOn(0x90, 0x1D + (8 * i + j), 0x7F);
                break;
        //  
        case 2: //noteOn(0x00, 0x1D + (8 * i + j), 0x7F);
                break;
        //  
        case 3: noteOn(0x90, 0x1D + (8 * i + j), 0x00);
                break;
      }
    }
    kbd_in[i] = kbd_in_new[i];
  }
} 


详细绘制如何使用MIDI数据是没有意义的,因为可以在此处读取

我将更详细地介绍计算机软件和遇到的问题。仅由于缺少该软件的常规文档,出现了问题。因此,为了使计算机能够从诸如我的设备之类的设备成功接收MIDI数据,您将需要两个程序:loopMIDISerial-Midi Converter。对于串行MIDI转换器,如果计算机上尚未安装Java,则还需要安装Java。

我们启动loopMIDI程序并创建两个虚拟端口。我称它们为Arduino IN和Arduino OUT。该程序将是虚拟MIDI设备。



接下来,运行Serial-MIDI Converter,在启动时,我们将进行设置过程。不幸的是,您每次启动时都必须执行此操作,但这并不是很可怕,它实际上是通过键盘上的四个击键来完成的。 COM端口号可能不同;连接Arduino NANO板时,它会出现在计算机上。端口速度在Arduino NANO固件中设置。红色箭头表示我的设置,所有设置均适用于我。



实际上,设置过程已经完成,您已经可以使用某些软件,可以通过接受设备的击键来播放声音。在软件设置中,必须选择“ Arduino_OUT”作为输入。在下图中,是配置Kontakt Player的示例。



最终,它的工作方式如下:


下一步是什么?然后一切都按我的预期进行-玩具仍然是玩具,它具有我一开始就提到的所有缺点。大概,孩子会嗡嗡作响,但是对于成年人来说,只要用普通的键盘...便宜地买任何用过的MIDI键盘会更容易,并且比这个玩具要好得多。我决定将这个玩具保持原样,但对其进行一些修改:

  1. 离开原来的情况。
  2. 放置工作扬声器并为它们制作一个放大器。
  3. 使它可以在“儿童玩具”模式下工作而无需连接计算机,也就是说,它可以播放声音。
  4. 可以连接FootSwitch(下面的钢琴上的同一踏板),以便您可以像普通乐器一样松开琴键后保持声音。
  5. , .
  6. , -, .



虽然我们大家都在“家里”,但我无法完成大多数要点,因为我只是没有家里所需的全部组件。

为了在Internet上实现第3段,找到了一个名为SamplerBox的解决方案。该项目的实质是您可以将任何MIDI键盘连接到Raspberry Pi板上,后者可以处理来自键盘的MIDI命令并播放声音或切换乐器等。仍然只能将Raspberry Pi板放入玩具主体中,而无需更换SD卡(无需拆卸外壳),配置玩具主体上的按钮以使其能够切换工具,这足以使此项目保持这种形式。

但是所有这些都会在自我隔离期结束后发生。

我希望有人会觉得我的经验有用。

All Articles