10541| 15
|
“神笔马良”是如何炼成的 |
本帖最后由 robo027 于 2017-9-4 00:14 编辑 很久很久以前,有个孩子名字叫马良。他梦想能成为一名艺术家,但家里很贫苦,仅仅靠他砍柴、割草换来的钱过日子。他从小喜欢音乐,可是他没有电子琴也没有架子鼓,他仅仅只有一台破电脑一些电子零件和一支毛笔。然而这些阻碍并没有终止他对梦想的追求,于是,他拿起毛笔,在纸上画了一架电子琴,配合一些所学到的电子硬件软件的相关知识。弄出了这么个玩意儿: 不光如此他还试着去画了一套架子鼓,也玩了起来: 他实现了自己的梦想。马良也因此一画成名,当上总经理,出任CEO,迎娶白富美,走上人生巅峰。 我们从小就看过《神笔马良》的动画,也曾梦想有一支马良的”神笔“。 在今天,科技让我们拉近了与梦想的距离。Arduino控制器+导电墨水就可以实现这个梦想。 下面让我来做一个Touchboard的大致介绍和midi玩法教学,一旦你掌握了,其实这块板也差不多弄明白怎么玩了。 购买链接在这https://www.dfrobot.com.cn/goods-1176.htm 拿到板子后我的建议还是先到官网大致看看。虽然全英文的,但我们有翻译器嘛不是。 这块板也可以说是集成了数字音乐模块VS1053,电容触摸模块MPR121的Arduino Leonardo,非常漂亮精致。而且可以用全能来形容它。 大致有以下几个功能: 除了可以胜任Arduino所有功能。 还可以当MakeyMakey玩,用触摸的方式发送键盘信号。然后用键盘信号去操作电脑里的游戏,音乐软件等。这个就不多介绍了。 另外它还支持内存卡里音频文件的读取,你可以录一段声音或是放一首歌曲或是找一些乐器的采样声音用GOLDwave转成MP3,然后按"TARCK000.mp3,TARC001.mp3...”的格式命名放到卡的根文件,这样接块电池插上耳机或音箱,用导电漆在纸上或墙上画一些有创意的画和线连到相应的键位(E0,E1...)就可以了,这样用手摸画就可以发出相应的声音从而可以完成很多互动表演。 VS1053芯片里还内置了一些MIDI音色可选,连内存卡都不用,接上音箱,直接通过修改代码调用相应的乐器就可以演奏了。 它还可以发出MIDI信号,比如把我之前的MIDI鼓机升级成涂鸦鼓机结合Ableton Live或IOS/OSX上的GarageBand玩出更多花样。 因为导电墨水会因为自身浓度,干湿度、涂抹环境,涂抹距离、厚度等诸多因素,导致阻值不同。继而影响操作,所以他并不是一套代码就能通吃的。 会带来接下来我着重讲讲怎么调试: 首先我们需要在官网上下载一个类似补丁的东西 windows点此 Mac点此 下好后直接安装,注意在选择安装盘符的时候必须选择ArduinoIDE对应的文件夹。装好后运行IDE你就会发现IDE有一些变化: 在工具---开发板的子菜单里你会发现多了两个可以选择的名称,一个是串口通信,另外一个是USBmidi通信。在这里需要说明的是除了你要用它来发送MIDI信号给电脑或手机选择第二个,其他的例程基本上都使用第一个板。 接下来看例程: 点开文件----项目文件夹,我用midi_interface_generic做个示范,先翻译了部分注释: [mw_shl_code=csharp,true]//*******************************************************************************/ // compiler error handling //*******************************************************************************/ // compiler error handling #include "Compiler_Errors.h" #include <MPR121.h> #include <Wire.h> #include "Midi_object.h" MIDIEvent e; #define numElectrodes 12 midi_object_t MIDIobjects[numElectrodes]; //创建一个要使用的MIDI对象数组(每个电极一个) void setup() { Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT); MPR121.begin(0x5C); MPR121.setInterruptPin(4); // ************************* // Proximity (CC) electrodes // ************************* //将电极0设置为连接到控制器102的代理映射控制器 MIDIobjects[0].type = MIDI_CONTROL; MIDIobjects[0].controllerNumber = 102; // 102..119在MIDI规范中未定义 MIDIobjects[0].inputMin = 520; // note than inputMin这里大于inputMax //这意味着你的手越接近传感器 //输出值越高 //反转映射,使inputMax大于inputMin MIDIobjects[0].inputMax = 480; // inputMin和inputMax之间的距离越远 //传感器工作范围越大 // the larger of a range the sensor will work over MIDIobjects[0].outputMin = 0; //控制器的最小输出 - 最小有效值为0 MIDIobjects[0].outputMax = 127; //控制器的最大输出 - 最大有效值为127 //将电极1设置为连接到控制器103的原始映射控制器 MIDIobjects[1].type = MIDI_CONTROL; MIDIobjects[1].controllerNumber = 103; MIDIobjects[1].inputMin = 520; MIDIobjects[1].inputMax = 480; MIDIobjects[1].outputMin = 0; MIDIobjects[1].outputMax = 127; //将电极2设置为连接到控制器104的代理映射控制器 MIDIobjects[2].type = MIDI_CONTROL; MIDIobjects[2].controllerNumber = 104; MIDIobjects[2].inputMin = 520; MIDIobjects[2].inputMax = 480; MIDIobjects[2].outputMin = 0; MIDIobjects[2].outputMax = 127; // set up electrode 3 as a proxmity mapped controller attached to controller 105 MIDIobjects[3].type = MIDI_CONTROL; MIDIobjects[3].controllerNumber = 105; MIDIobjects[3].inputMin = 520; MIDIobjects[3].inputMax = 480; MIDIobjects[3].outputMin = 0; MIDIobjects[3].outputMax = 127; // set up electrode 4 as a proxmity mapped controller attached to controller 106 MIDIobjects[4].type = MIDI_CONTROL; MIDIobjects[4].controllerNumber = 106; MIDIobjects[4].inputMin = 730; MIDIobjects[4].inputMax = 710; MIDIobjects[4].outputMin = 0; MIDIobjects[4].outputMax = 127; // set up electrode 5 as a proxmity mapped controller attached to controller 107 // MIDIobjects[5].type = MIDI_CONTROL; //MIDIobjects[5].controllerNumber = 107; // MIDIobjects[5].inputMin = 520; //MIDIobjects[5].inputMax = 480; // MIDIobjects[5].outputMin = 0; // MIDIobjects[5].outputMax = 127; // set up electrode 6 as a proxmity mapped controller attached to controller 108 // MIDIobjects[6].type = MIDI_CONTROL; // MIDIobjects[6].controllerNumber = 108; //MIDIobjects[6].inputMin = 520; // MIDIobjects[6].inputMax = 480; // MIDIobjects[6].outputMin = 0; // MIDIobjects[6].outputMax = 127; // set up electrode 7 as a proxmity mapped controller attached to controller 109 // MIDIobjects[7].type = MIDI_CONTROL; //MIDIobjects[7].controllerNumber = 109; //MIDIobjects[7].inputMin = 520; // MIDIobjects[7].inputMax = 480; // MIDIobjects[7].outputMin = 0; //MIDIobjects[7].outputMax = 127; // set up electrode 8 as a proxmity mapped controller attached to controller 110 //MIDIobjects[8].type = MIDI_CONTROL; //MIDIobjects[8].controllerNumber = 110; //MIDIobjects[8].inputMin = 520; // MIDIobjects[8].inputMax = 480; // MIDIobjects[8].outputMin = 0; // MIDIobjects[8].outputMax = 127; // set up electrode 9 as a proxmity mapped controller attached to controller 111 // MIDIobjects[9].type = MIDI_CONTROL; //MIDIobjects[9].controllerNumber = 111; // MIDIobjects[9].inputMin = 520; //MIDIobjects[9].inputMax = 480; // MIDIobjects[9].outputMin = 0; // MIDIobjects[9].outputMax = 127; // set up electrode 10 as a proxmity mapped controller attached to controller 112 // MIDIobjects[10].type = MIDI_CONTROL; //MIDIobjects[10].controllerNumber = 112; // MIDIobjects[10].inputMin = 520; //MIDIobjects[10].inputMax = 480; //MIDIobjects[10].outputMin = 0; //MIDIobjects[10].outputMax = 127; // set up electrode 11 as a proxmity mapped controller attached to controller 113 // MIDIobjects[11].type = MIDI_CONTROL; // MIDIobjects[11].controllerNumber = 113; // MIDIobjects[11].inputMin = 520; // MIDIobjects[11].inputMax = 480; // MIDIobjects[11].outputMin = 0; // MIDIobjects[11].outputMax = 127; // *********************** //触摸(注)电极 // *********************** //如果要将电极配置为音符输出(而不是接近) // CC)你需要做以下两件事情: // // 1.取消注释下面的部分 // // 2.完全注释“接近(CC)电极”部分。这确保 //这两个部分不会相互干扰。 // //您也可以在两者之间选择,例如具有电极0作为 //接近电极和电极1作为触摸电极。你这样做: // // 1.在“接近(CC)电极”中注释与电极1相关的线 // section - 这是以“MIDIobjects [1]”开头的六行 // // 2.取消注释“触摸(注)电极”中与电极1相关的线条 //部分 - 这是下面的4行,以“MIDIobjects [1]”开头 // //要记住的重要事情是,您不能有两个活动的部分 //相同的电极。 // // set up electrode 0 as a touch sensitive key attached to note 60 // MIDIobjects[0].type = MIDI_NOTE; // MIDIobjects[0].noteNumber = 60; // middle C // MIDIobjects[0].touchThreshold = 50; // always make sure that the touch threshold is // MIDIobjects[0].2releaseThreshold = 2; // larger than the release threshold - larger values // // are less sensitive (and more robust) // // // set up electrode 1 as a touch sensitive key attached to note 61 // MIDIobjects[1].type = MIDI_NOTE; // MIDIobjects[1].noteNumber = 61; // MIDIobjects[1].touchThreshold = 50; // MIDIobjects[1].releaseThreshold = 20; // // // set up electrode 2 as a touch sensitive key attached to note 62 // MIDIobjects[2].type = MIDI_NOTE; // MIDIobjects[2].noteNumber = 62; // MIDIobjects[2].touchThreshold = 50; // MIDIobjects[2].releaseThreshold = 20; // // // set up electrode 3 as a touch sensitive key attached to note 63 // MIDIobjects[3].type = MIDI_NOTE; // MIDIobjects[3].noteNumber = 63; // MIDIobjects[3].touchThreshold = 50; // MIDIobjects[3].releaseThreshold = 20; // // // set up electrode 4 as a touch sensitive key attached to note 64 // MIDIobjects[4].type = MIDI_NOTE; // MIDIobjects[4].noteNumber = 64; // MIDIobjects[4].touchThreshold = 50; // MIDIobjects[4].releaseThreshold = 20; // // // set up electrode 5 as a touch sensitive key attached to note 65 MIDIobjects[5].type = MIDI_NOTE; MIDIobjects[5].noteNumber = 65; MIDIobjects[5].touchThreshold = 50; MIDIobjects[5].releaseThreshold = 20; // set up electrode 6 as a touch sensitive key attached to note 66 MIDIobjects[6].type = MIDI_NOTE; MIDIobjects[6].noteNumber = 66; MIDIobjects[6].touchThreshold = 50; MIDIobjects[6].releaseThreshold = 20; // // set up electrode 7 as a touch sensitive key attached to note 67 MIDIobjects[7].type = MIDI_NOTE; MIDIobjects[7].noteNumber = 67; MIDIobjects[7].touchThreshold = 50; MIDIobjects[7].releaseThreshold = 20; // // // set up electrode 8 as a touch sensitive key attached to note 68 MIDIobjects[8].type = MIDI_NOTE; MIDIobjects[8].noteNumber = 68; MIDIobjects[8].touchThreshold = 50; MIDIobjects[8].releaseThreshold = 20; // // // set up electrode 9 as a touch sensitive key attached to note 69 MIDIobjects[9].type = MIDI_NOTE; MIDIobjects[9].noteNumber = 69; MIDIobjects[9].touchThreshold = 50; MIDIobjects[9].releaseThreshold = 20; // // // set up electrode 10 as a touch sensitive key attached to note 70 MIDIobjects[10].type = MIDI_NOTE; MIDIobjects[10].noteNumber = 70; MIDIobjects[10].touchThreshold = 50; MIDIobjects[10].releaseThreshold = 20; // // // set up electrode 11 as a touch sensitive key attached to note 71 MIDIobjects[11].type = MIDI_NOTE; MIDIobjects[11].noteNumber = 71; MIDIobjects[11].touchThreshold = 50; MIDIobjects[11].releaseThreshold = 20; //设置要求它的电极的触发和释放阈值 for(int i=0; i<numElectrodes; i++){ if(MIDIobjects.type == MIDI_NOTE){ MPR121.setTouchThreshold(i, MIDIobjects.touchThreshold); MPR121.setReleaseThreshold(i, MIDIobjects.releaseThreshold); } } // start with fresh data MPR121.updateAll(); } void loop() { //检查笔记电极 if(MPR121.touchStatusChanged()){ MPR121.updateTouchData(); for(int i=0; i<numElectrodes; i++){ if(MIDIobjects.type==MIDI_NOTE){ //如果这是一个笔记型对象... e.type = 0x08; e.m2 = MIDIobjects.noteNumber; //设置笔记号码 e.m3 = 127; //最大音量 if(MPR121.isNewTouch(i)){ //如果我们有新的触摸,打开板载LED和 //发送一个“note on”消息,并附上适当的注释集 digitalWrite(LED_BUILTIN, HIGH); e.m1 = 0x90; } else if(MPR121.isNewRelease(i)){ //如果我们有一个新的版本,关闭板载LED和 //发送“note off”消息 digitalWrite(LED_BUILTIN, LOW); e.m1 = 0x80; } else { //设置一个标志来做任何事情 e.m1 = 0x00; } //只需要发送USB MIDI消息即可 if(e.m1 != 0x00){ MIDIUSB.write(e); } } } } MPR121.updateFilteredData(); //现在检查控制器电极 for(int i=0; i<numElectrodes; i++){ if(MIDIobjects.type==MIDI_CONTROL){ //如果我们有一个控件类型的对象... Serial.print("E"); Serial.print(i); Serial.print(":"); //这会打印一些串行调试数据,以方便映射 Serial.println(MPR121.getFilteredData(i)); //例如E11:567表示E11的值为567(这是输入数据) //从输入中输出正确映射的值 e.m3 = (unsigned char)constrain(map(MPR121.getFilteredData(i), MIDIobjects.inputMin, MIDIobjects.inputMax, MIDIobjects.outputMin, MIDIobjects.outputMax), 0, 127); if(e.m3!=MIDIobjects.lastOutput){ //如果自上次更改以来,只输出一个新的控制器值 MIDIobjects.lastOutput=e.m3; e.type = 0x08; e.m1 = 0xB0; // control change message e.m2 = MIDIobjects.controllerNumber; //选择正确的控制器编号 - 应使用数字 //在102到119之间,除非你知道你在做什么 MIDIUSB.write(e); } } } //刷新USB缓冲区,以确保发送所有音符 MIDIUSB.flush(); delay(10); // 10ms延迟给USB MIDI目标时间赶上 } [/mw_shl_code] 翻译的部分因为用的谷歌有的语句不通,但不影响理解,看完就差不多知道怎么去调试了。 我截取了两段关系到每个按键灵敏程度以及发出的MIDI信号是数字还是模拟(数字信号--开关--琴键,模拟信号--阀值--旋钮) 数字信号: MIDIobjects[11].type = MIDI_NOTE; MIDIobjects[11].noteNumber = 36; //这里是指发出去的MIDI信号的CC值,在我MIDI鼓机那篇文章中我有讲过) MIDIobjects[11].touchThreshold = 40; MIDIobjects[11].releaseThreshold = 20; //这里的40和20是指一个触发的区间,数值越小意味着越灵敏,相当于你的手可以拿开的更远,实现空中打鼓就是把他们改成个位数行了。 模拟信号: MIDIobjects[11].type = MIDI_CONTROL; MIDIobjects[11].controllerNumber = 112; //CC值,在CC信号的表中102-119是没有被定义的,也就是说你可以自己定义 Live界面上的功能映射。 MIDIobjects[11].inputMin = 755; MIDIobjects[11].inputMax = 770; //这个和上面数字信号触发的区间差不多,但是需要去调试,没调试有可能根本触发不了旋钮。怎么调试下面讲解 MIDIobjects[11].outputMin = 0; MIDIobjects[11].outputMax = 127; 调试的过程: 无非就是打开串口通信的窗口,然后看一看里面跳动的数值,然后你用手指从画上某个类旋钮功能键的可变区域范围内来回刷,观察最大和最小读数,(一定要结合项目每个按键去调试)取一个高效的区间。填到上面的nputMin 和inputMax 里面即可。这样调试下来,这块板才算真正的适配到了项目中。 材料的话就墨水笔,和纸,木板,塑料板,等等反正不导电的都可以当作画板。这块板玩的就是墨水与创意。 MP3的玩法不能同时按下多个按键,家庭的墙面装饰,英语课,音乐课什么的增添一些艺术感和科技感。因为这时候他可能要被挂在墙上。所以能简化尽量简化。(一个板一个音箱即可) MIDI玩法就比较多元化了,不管是电脑,手机,室内室外都可以被支持,而且还可以同时发出去多个按键的CC值,尤其配合GarageBandAPP就相当于一部万能乐器了。真正实现画什么乐器就玩什么乐器。我开篇胡编滥造的神笔马良的段子,就源自于此。最后我想说好的音乐其实不在于用多名贵的乐器去演奏,而在于我们怎么去玩。 最后想说一下这个导电漆 我觉得价格确实偏高了。最开始用铅笔啊,石墨粉+各种胶,不是没用就是达不到理想效果,以至于让我不得不把我的工作间变成了化学实验室。翻阅了大量的资料,做了大量的尝试,当然前期也吸进去了不少毒气。进过一次医院,最终找到了我认为比官网的漆还要好的材料,第一,水性,快干。第二环保且无味,第三,可以灌进笔里画,第四,导电性不输。第五成本降低。后面的就不接着说了。我真的只是介绍这块板子来的。 好了就介绍到这里,如果有任何需要纠正的或我没有说清楚的地方请帮我及时指出。如果还需要这块板其他例程的讲解也可以下方留言,第一时间回复,谢谢大家。 |
我在以前听过一期《闲白电台》的节目,里面提到过一种乐器叫“特雷门琴”,其实我觉得这个板最好玩也是最厉害的地方在于他竟然可以做“特雷门琴”(例程里的MIDI_Theremin) 科普一下”特雷门琴“是世界上唯一一种不需要身体接触的电子乐器。原理是利用两个感应人体与大地的分布电容的LC 振荡器工作单元分别产生震荡的频率与大小变化而工作。圆形天线是用来调节音量的,手越靠近,声音越小。垂直的天线用来调节频率,手越靠近,音调越高。演奏的关键是了解双手的位置与所发出的音符之间的关系。 想想就很难,以至于全世界一共有20位特雷门琴演奏家。想走向世界的话可以先做一个练练。 明天出个视频 |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed