
开源协议
:Public Domain
描述
项目说明
这个装置能够帮助你的键盘实现各种音效,从麻将音到芝加哥打字机。
开源协议
Public Domain
项目相关功能
将这个设备连接在USB键盘和主机之间,键盘按下后设备会发出声音从而实现各式各样的“打字音效”。
项目属性
本项目为首次公开,为本人原创项目。项目未曾在别的比赛中获奖。
项目进度
已完成
设计原理
使用 ESP32-S3 作为 USB Host ,将解析后的数据通过串口发送给Ch9326,CH9326是一款HID转串口免驱芯片。它支持双向数据传输,用于接收串口数据,并按照HID类设备规范,将数据打包通过USB口上传给计算机,或者从计算机接收符合HID类设备的USB数据包,并从串口进行发送。通过提供的上位机软件,用户也可自行配置芯片的VID、PID,以及各种字符串描述符。芯片是 SOP16 封装,容易焊接;此外,解析后的数据还会发送给 DFRobot 的Fermion: DF1201S DFPlayer PRO MP3播放器模块【参考1】。这是一款MP3播放模块支持arduino、AT指令、板载按键和AD按键四种控制方式。通过板载按键即使在没有微控制器的情况下也能进行音乐播放和切换。模块搭载了128MB的存储空间,通过USB线即可很容易的将音乐拷贝到模块中。

软件说明
代码基于 ESP32 Arduino 环境开发。重要部分解释如下:
1. keyboard_transfer_cb() 函数中解析USB键盘数据。解析后的数据会和上一次收到的数据(keypressOld)进行比较,这样做是为了避免重复输出已经按下的按键;如果新出现的数据没有出现在上一次的数据中,那么就将这个数据加入到SoundBuffer中:
void keyboard_transfer_cb(usb_transfer_t *transfer)
{
if (Device_Handle == transfer->device_handle) {
isKeyboardPolling = false;
if (transfer->status == 0) {
if (transfer->actual_num_bytes == 8) {
uint8_t *const p = transfer->data_buffer;
ESP_LOGI("", "HID report: %02x %02x %02x %02x %02x %02x %02x %02x",
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
// USB Host 解析得到的数据,传输给 Ch9326
memcpy(&keypress[5], p, transfer->actual_num_bytes);
SendData((byte*)keypress, sizeof(keypress));
//检查数据
for (int i = 2; i < 8; i++) {
if (p[i] != 0) {
// 在之前的 Buffer 中搜索
boolean Found = false;
for (int j = 2; j < 8; j++) {
if (p[i] == keypressOld[j]) {
Found = true;
break;
}
}
// 如果没有找到,那么就把数据放入 SoundBuffer
if (Found == false) {
Serial.print("Put");
Serial.print(p[i]);
Serial.println("into buffer");
SoundBuffer[IndexTail] = p[i];
IndexTail = (IndexTail + 1) % SOUNDBUFSIZE;
}
}
}
memcpy(keypressOld, p, 8);
}
else {
ESP_LOGI("", "Keyboard boot hid transfer too short or long");
}
}
else {
ESP_LOGI("", "transfer->status %d", transfer->status);
}
}
}
2.在主函数中有一个检查当前队列的动作,如果队列不为空那么就播放队列中的数据。比如,下面的 0x14就是 HID 定义的“q”按键。代码的意思就是如果收到的 q 键,那么就对 MP3 模块发送播放 /mj/1b.wav 的命令,这样对应的声音就会在喇叭中播放出来
// 首先检查队列是否为空
if (IndexTail != IndexHeader) {
char NameBuffer[100];
switch (SoundBuffer[IndexHeader]) {
// 饼
case 0x14: // 'Q'
sprintf(NameBuffer, "%s1b.wav\r\n", PlayFile);
Serial.print(NameBuffer);
Serial1.print(NameBuffer);
break;
case 0x1A: // 'W'
sprintf(NameBuffer, "%s2b.wav\r\n", PlayFile);
Serial.print(NameBuffer);
Serial1.print(NameBuffer);
break;
实物展示

设计注意事项
其他
B站:
参考:
1. https://www.dfrobot.com.cn/goods-3046.html
设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程知识产权声明&复刻说明
本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。
请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。


评论