完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
一、前言 1.1 项目由来 前些天,在b站上看到有人分享单片机模拟NS手柄,在《精灵宝可梦》、《异度之刃》等游戏中实现自动操作的视频。我是个有着多年“鼓龄”的太鼓达人玩家,于是产生想法,将该方案用于自动完成太鼓达人曲目,实现类似TAS的效果。经过一周的实验,取得了一定的成果:开发板通过USB TypeB转TypeC转接线连接至Switch游戏机的USB接口上,系统能够在操作者手动给出曲目开始信号(按下按键模块上的特定按键)的情况下,自动完成鬼难度6星的一首曲目,获得了“全良”的成绩,验证了方案的可行性。展示视频如下: [自制] 单片机模拟Switch控制器_半自动完成太鼓达人曲目《恋》_20200224 备用链接 下面将简单介绍我的完成过程 1.2 前期调研工作 项目参考了以下链接中的内容: “当单片机取代橡皮筋——解放双手,放飞双眼,我的宝可梦自动化成果” “在 Switch上使用 Arduino Uno R3 开发板模拟连续 A 键” 此类项目基本是基于:https://github.com/progmem/Switch-Fightstick 二次开发而成。其中,单片机模拟USB功能的实现,主要依靠LUFA开源框架的使用,它可以让AVR单片机模拟成想要的USB设备。移植工作并不复杂,初始化函数无需自己修改;只需要自行编写业务代码即可。 1.3 测试曲目选择 测试曲目的选择方面:
二、项目实现 2.1 硬件平台 硬件平台为ARDUINO UNO R3开发板。特别要指出的是,此次开发中使用的是开发板上用作USB接口芯片的ATmega16U2(下图中红框圈出),并不是常规情况下用来开发的核心芯片ATMEGA328P。为避免干扰,减少功耗,可以将其从开发板上去除(下图中绿框圈出)。 通过研究硬件原理图可以发现,板子上的TX、RX两颗LED是连接在ATmega16上的,可供我们使用,项目中将用它来指示演奏音符的种类(鼓心、鼓边);同时,开发板上还提供了一些排针,连接至单片机的IO口上。我们将用来连接外部按键模块,用于输入。开发板原理图中ATMEGA16U2相关部分如下: 完成搭建的测试系统如图所示: 2.2 工具链及开发环境 单片机程序的编译环境为WinAVR-20100110,在windows和Linux下均可使用。为开发方便,本项目选择在Windows系统下进行开发。 本工程没有现成的集成开发环境(如Keil、Visual Studio等)可以使用,必须手写makefile,通过终端执行make指令进行编译。 于是,本项目的软件开发工作选择宇宙第一的文本编辑器——微软Visual Studio Code进行。不但代码编辑、makefile编辑非常方便,还自带终端,可以随时进行生成(make)、清理(clean)等操作,如下图。 项目进行make(生成)操作后,会生成用于执行的hex文件。下载hex文件使用Flip软件,通过USB线连接开发板和电脑,之后手动短接单片机的RESET引脚和GND(地)(如下图),待系统将设备枚举成功后,再进行下载,如下图。 2.3 软件实现 2.3.1 软件流程设计 拟定软件工作流程如下:
2.3.2 音符时长标定 ·音符和休止符 曲目的完成,实际上就是按照谱面演奏音符和休止符。具体到该项目,进行设计如下:
我们在只使用B键用于输出“咚”音色,只使用A键用于输出“咔”音色的情况下,要完成一次完整、无误判的按键信号输出动作,需要进行以下步骤(以输出一次B键为例): HID_Task(B); USB_USBTask(); _delay_ms(10); _delay_ms(10); HID_Task(PAUSE); USB_USBTask(); _delay_ms(10); _delay_ms(10); 首先调用一次HID_Task(B)及USB_USBTask()函数进行输出,之后延时20毫秒;之后调用HID_Task(PAUSE)及 USB_USBTask()输出一个“PAUSE”信号,再延时20毫秒。总共需要40毫秒左右。 ·使用逻辑分析仪进行音符时长标定 在明确了上述信息后,我们就可以对曲目中使用的音符、休止符进行标定了。曲目速度为BPM158,4/4拍。经过计算,得到如下结果:
逻辑分析仪通过杜邦线,连接至单片机的IO口。测量时可以先将该IO口拉低,然后进行待测操作,之后再将IO口拉高。低电平的持续时间即为待测操作占用的时间。IO口翻转占用的时间为微秒级别,忽略不计。下图为测量上个章节提到的“单次按键输出”操作的结果图。从波形中可以看出,低电平(待测操作)持续时间为40.0733毫秒。 经过测试,我们可以得到各音符、休止符演奏时的实际时间,如下表所示(单位 毫秒)。我们根据测量结果,首先对部分延时的毫秒数进行修正,并记录下修正完毕依然残留的误差。 2.3.3 曲谱数据建立及演奏函数设计 进行如下设计:用16位整数(unsigned short int)组成的数组来描述曲目。 数字“1”表示演奏“咚”音色,数字2表示演奏“咔”音色,数字“5”表示曲目结束。其余数字则表示延时相应的毫秒数,如378表示将会调用_delay_ms()函数延时378毫秒。 为方便编码,设计宏定义如下: //休止符#define R4 (378) #define R8 (189)#define R16 (95)#define R32 (47) //演奏音符 1为演奏don 2为演奏ka #define PLAY_DON 1#define PLAY_KA 2#define HITDUR (40)#define D4 PLAY_DON,(R4-HITDUR+1) //修正#define D8 PLAY_DON,(R8-HITDUR)#define D16 PLAY_DON,(R16-HITDUR)#define D32 PLAY_DON,(R32-HITDUR)#define K4 PLAY_KA,(R4-HITDUR) #define K8 PLAY_KA,(R8-HITDUR)#define K16 PLAY_KA,(R16-HITDUR) 曲目方面,图片格式的曲谱可以在太鼓达人wiki上获得,如图所示: 以前四小节为例,图中所示为: 在乐理上表示的意义为(谱例中普通符头为表示“咚” ×型符头表示“咔”,由于例程中没有给出左手上下左右按键的输出方法,所以大音符简化为同音色小音符处理): 按照前述宏定义,则前四小节编码为: const unsigned short music[] PROGMEM = { //M1 D4, K4, D4, K4, //M2 D4, K4, D8, K16,K16,K8, D8, //M3 D4, D4, D8, K8, K8, D8, //M4 R8, D4, D4, K8, K16,K16,K16,K16, 代码中为方便查看,以小节为单位分行编写。依次类推,完成整首曲目的编码。要注意的是,由于单片机的内存空间极其有限(仅512Byte),所以该数组不能像普通变量一样放在RAM中,而必须存放在FLASH中。数组定义时需要加入PROGMEM宏进行标志。 演奏函数设计为:在遇到结束标志之前,从数组中依次取出数字,判断数字并做出相应的动作。代码如下: void play(void){ unsigned short i = 0; while(1) { if( pgm_read_word(&music) == PLAY_DON) { PLAY_DON_B(); //通过B键演奏“咚”音色 } else if(pgm_read_word(&music)== PLAY_KA ) { PLAY_KA_A(); //通过A键演奏“咔”音色 } else if (pgm_read_word(&music) == MUS_END) { break; } else { _delay_ms(pgm_read_word(&music)); } i++; }//while(1)}//play() 为了访问FLASH中的数组数据,必须使用pgm_read_word()函数。相应的音色演奏函数如下(以PLAY_DON_B()函数为例): void PLAY_DON_B(void){ RXLED_ON; HID_Task(B); USB_USBTask(); _delay_ms(10); _delay_ms(10); HID_Task(PAUSE); USB_USBTask(); _delay_ms(10); _delay_ms(10); RXLED_OFF;} 在演奏时,通过宏定义RXLED_ON、RXLED_OFF,操作IO口,使用了LED进行指示。演奏“咚”时,使用的是RXLED;相应的,在PLAY_KA_A()函数中,使用的是TXLED。 2.3.4 时间误差补偿 由于选择的最小时间单位为仅为毫秒,误差会随着演奏过程不断积累,导致后半段演奏出现问题。所以,应当统计各段落的误差,进行补偿。 曲目中各音符单独导致的误差是已知的,我们将各个片段的音符进行统计,计算总误差,再拟定各段落中补偿修正的毫秒数,将累计残余误差控制在1毫秒以内。如下表所示(单位 毫秒): 例如,前8小节中,经过统计,按照现有程序演奏完后,会比实际时间多出3.19毫秒。为了尽可能减少误差,就需要在8小节中平均的分配出用于补偿的-3毫秒。补偿时尽量选择时长较长的休止符。完成补偿的前八小节编码如下: const unsigned short music[] PROGMEM = { //M1 D4, K4, D4, K4, //M2 D4, K4, D8, K16,K16,K8, D8, //M3 D4, D4, D8, K8, K8, D8, //M4 R8, D4, D4, K8, K16,K16,K16,K16, //M5 D4, R4-2, R8, D4, R8, //M6 D4, R8, D4, R8, K4, //M7 D4, R4-1, R8, D4, R8, //M8 D4, R8, D4, R8, K4, 以此类推,完成整首曲目的误差修正。 2.3 实验验证 完成开发后进行验证实验。先在游戏的“曲目选择”中,将光标放到待选曲目上,连接开发板和Switch游戏机,待USB设备枚举完成后,按动按键模块上的SW1,代替Switch的A键,进行曲目和难度确定。进入曲目后,在合适的时机,手动按动SW4按键,启动输出流程。经过测试,只要首个音符能够抓出“良”,那么整首曲目基本可以保证全良。测试成绩如图所示: 理论上,只要单片机存储空间足够,使用该系统可以全良《太鼓达人Switch版》上任意一首曲目。 三、后记 后续可以改进的点(咕咕咕):
欢迎交流 联系方式 gurn@tju.edu.cn 617442575@qq.com |
|
|
|
只有小组成员才能发言,加入小组>>
2514 浏览 0 评论
1086浏览 2评论
701浏览 1评论
454浏览 0评论
194浏览 0评论
334浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-23 08:17 , Processed in 1.265779 second(s), Total 82, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号