我正在使用树莓派 B+ 和 Arduino Mega 制作一个仿生射击画廊。总体来说,进展顺利,但有一个细节需要注意。我无法保持电机运动与声音同步。
例如,假设我有一个会说话的猪。当你击中目标,猪就会说:“嘿,孩子!小心你把枪指向的地方!你要把你的眼睛刺瞎了!”或类似的话。问题是,让猪运动的电机无法跟上音频的速度。它们会落后,与音频不同步。例程越长,它们落后的程度就越大。而且,这种落后的程度并不是一致的。它似乎取决于计算机在当时做了什么。例如,在我程序运行的同时运行 Audacity 时,相比仅运行我的程序时,延迟明显更大。我还注意到,使用 IDLE 运行程序和从终端运行程序之间存在轻微的延迟差异。
有些目标对同步的敏感度高于其他目标,例如,如果我有一个随着咻咻声飞向目标的火箭,那么电机稍快或稍慢地移动实际上不是问题,但如果嘴部动作相差十分之一秒以上,看起来就会非常糟糕。
为了控制电机,我使用了一个腌渍的元组列表,每个元组包含 0:发送位置信号后例程开始的时间(以毫秒为单位)、1:发送信号的电机的编号以及 2:电机的位置。主程序循环遍历所有目标,并让每个目标有机会查看是否到了发送下一个电机位置命令的时候。
2. 解决方案
2.1 当前程序的改进方法
考虑到当前程序的局限性,你可以尝试以下方法来改进同步性能:
- 优化代码:检查代码中是否存在任何可能导致延迟的低效或不必要的操作。例如,确保你不会在循环中执行任何耗时的操作,并且你使用的数据结构是高效的。
- 减少其他程序的干扰:确保在运行你的程序时没有其他程序在后台运行,尤其是那些可能占用大量 CPU 或内存的程序。这可以帮助减少延迟并提高同步性能。
- 调整音频设置:尝试调整音频设置,例如缓冲区大小和采样率,看看这是否会对同步产生影响。有时,调整这些设置可以减少延迟并提高同步性能。
2.2 使用 FFT 分析的解决方案
如果以上方法无法解决同步问题,那么你可以考虑使用快速傅里叶变换 (FFT) 分析来检测电机控制信号中的特定频率。你可以按照以下步骤实现此解决方案:
- 构建输入电路:你需要构建一个电路来将树莓派中的音频信号转换为 Arduino 可以读取的 0-5V 信号。你可以使用运放来放大信号并将其转换为所需的电压范围。
- 设置 FFT 库:在 Arduino 中设置 FFT 库,以便能够分析输入信号中的频率。这通常涉及设置采样率和 FFT 大小等参数。
- 检测电机控制信号中的频率:使用 FFT 库分析输入信号并检测电机控制信号中的特定频率。你可以使用频率滤波器来隔离特定的频率范围并检测是否存在这些频率。
- 控制电机:当检测到电机控制信号中的特定频率时,你可以使用 Arduino 发送 PWM 信号来控制电机。这将使电机以与音频同步的方式移动。
2.3 其他注意事项
在使用 FFT 分析解决方案时,还有一些注意事项需要考虑:
- 计算资源:FFT 分析可能需要大量的计算资源,因此你需要确保 Arduino 有足够的处理能力来执行此任务。
- 频率选择:你需要选择合适的频率来代表电机控制信号。这个频率应该足够高,以便能够与音频信号区分开来,但又不能太高,以至于难以检测。
- 延迟:FFT 分析可能会引入一些延迟,这可能会影响同步性能。你需要仔细选择 FFT 分析的参数以尽量减少延迟。