1.项目介绍
本项目是基于树莓派RP2350B微控制器和电子琴扩展版的音乐创作工具。它允许用户通过13个按键进行音乐弹奏和创作。用户可以单独按下某个按键来播放对应的音调,也可以同时按下多个按键来播放和弦。系统会确保在播放和弦时,音质不会失真。此外,项目还提供了"上"和"下"两个按键,用于对音程进行扩展,让用户可以自由地创作出更丰富的音乐。
2.硬件介绍
该项目采用了树莓派RP2350B作为核心处理单元,并搭配了电子琴扩展版。RP2350B拥有强大的处理能力和丰富的外设接口,非常适合用于音乐创作类项目。电子琴扩展版提供了13个按键和上下调音程的功能,与RP2350B完美配合,为用户提供了一个直观易用的音乐创作硬件平台。
RP2350B通过GPIO引脚与电子琴扩展版进行连接。13个按键通过数字输入引脚被检测,上下调音程的两个按键也通过数字输入引脚被监测。RP2350B的PWM输出引脚则用于驱动蜂鸣器和扬声器,实现音频播放。此外,还使用了一个模拟输入引脚来检测按键的模拟值,用以实现记忆指弹旋律并播放。整个硬件系统设计紧凑高效,充分利用了RP2350B的资源。
3.方案框图和项目设计思路
方案框图如下:
项目设计思路如下:
项目采用了基于状态机的设计思路。它利用RP2350B的数字输入引脚来检测按键状态,并根据不同的按键组合生成相应的音频波形。在音频输出方面,它采用了PWM技术来驱动蜂鸣器和扬声器,并使用复合波形生成算法来产生包含谐波成分的音质更加丰富的音频信号。
此外,项目还利用微控制器的内存资源来记录和回放用户的旋律,为音乐创作提供了更灵活的功能。整体方案设计简单明了,能够充分利用RP2350B的资源来实现所需的功能。
4.软件流程图和关键代码
软件的主要流程包括:检测按键状态、生成音频波形、播放音频、记录和回放旋律等。
关键的代码包括:使用数字输入引脚检测按键状态、根据按键频率生成正弦波和复合波形、通过PWM输出驱动扬声器和蜂鸣器、记录和回放旋律等。这些关键代码充分利用了RP2350B的功能,实现了音乐创作的核心需求。
# 采集按键的模拟输入值
def get_key_value():
count = 0
sum_value = 0
while count < 10:
sum_value += save_pin.value
count += 1
time.sleep(0.01)
avg_value = sum_value / count
return avg_value
# 判断按键
def get_key_id():
v = get_key_value()
if 56000.0 < v < 57000.0:
return 1
elif 52000.0 < v < 53000.0:
return 2
elif 45000.0 < v < 46000.0:
return 3
elif 30000.0 < v < 31000.0:
return 4
else:
return 0
# 创建一个空的列表来保存GPIO引脚
pins = []
# 配置13个GPIO引脚(例如D2到D14)
for pin_num in range(4, 19):
pin = digitalio.DigitalInOut(getattr(board, f'GP{pin_num}')) # 使用D2到D14的引脚
pin.direction = digitalio.Direction.INPUT # 设置为输入模式
pins.append(pin)
# 生成正弦波函数
def generate_sine_wave(frequency, length=8000):
sine_wave = []
for i in range(length):
sample = int(math.sin(2 * math.pi * frequency * i / length) * (2 ** 15))
sample = max(min(sample, 32767), -32768) # 限制 sample 在有效范围内
sine_wave.append(sample)
return sine_wave
# 混合多个音符的正弦波(和弦)
def mix_sine_waves(waves):
mixed_wave = [0] * len(waves[0])
for wave in waves:
for i in range(len(wave)):
mixed_wave[i] += wave[i]
mixed_wave = [int(sample / len(waves)) for sample in mixed_wave] # 正常化样本的值
return mixed_wave
if get_switch_state() == 'buzzer':
# 使用蜂鸣器输出
pwm_audio.deinit() # 先停止当前扬声器输出
pwm_audio = audiopwmio.PWMAudioOut(left_channel=board.GP20) # 重新初始化为蜂鸣器
#sine_wave = generate_sine_wave(frequency)
sine_wave = generate_complex_wave(frequency)
waves_to_play.append(sine_wave)
else: # speaker
pwm_audio.deinit() # 先停止当前蜂鸣器输出
pwm_audio = audiopwmio.PWMAudioOut(left_channel=board.GP21) # 重新初始化为扬声器
complex_wave = generate_complex_wave(frequency)
if key == 1:
print("播放已记忆旋律")
waves_to_play = []
is_playing = True
for i, frequency_list in enumerate(melody):
print(f"i: {i} ")
press_time = press_durations[i] # 获取对应的按键时间
for frequency in frequency_list:
#print(f"记忆旋律: {frequency} Hz,间隔: {press_time} 秒")
# 选择波形生成函数
if get_switch_state() == 'buzzer':
pwm_audio.deinit() # 先停止当前扬声器输出
pwm_audio = audiopwmio.PWMAudioOut(left_channel=board.GP20) # 重新初始化为蜂鸣器
#sine_wave = generate_sine_wave(frequency)
sine_wave = generate_complex_wave(frequency)
waves_to_play.append(sine_wave)
else: # speaker
pwm_audio.deinit() # 先停止当前蜂鸣器输出
pwm_audio = audiopwmio.PWMAudioOut(left_channel=board.GP21) # 重新初始化为扬声器
sine_wave = generate_complex_wave(frequency)
waves_to_play.append(sine_wave)
mixed_wave = mix_sine_waves(waves_to_play)
sample = audiocore.RawSample(array.array('h', mixed_wave), single_buffer=False)
pwm_audio.play(sample, loop=True)
5.实物功能展示
该项目可以通过13个按键进行音乐弹奏和创作。用户可以单独按下某个按键来播放对应的音调,也可以同时按下多个按键来播放和弦。系统会确保在播放和弦时,音质不会失真。同时,用户还可以通过按下"上"和"下"两个按键来对音程进行扩展。
在扬声器模式下,输出的音调信号不仅包含对应音调的单频正弦波,还会包含多次谐波成分,以提供更丰富的音质。在蜂鸣器模式下,系统会使用蜂鸣器来播放音乐。此外,该项目还支持记忆用户的指弹旋律,并可以进行回放,让用户可以轻松地重复播放自己创作的音乐。
6.遇到的难题和解决方法
在实现这个项目时,遇到一些技术难题,比如如何准确检测按键状态、如何生成高质量的音频波形、如何实现音程调整等。代码中提供了相应的解决方案,以及使用模拟输入检测按键值、采用复合波形生成技术、通过改变频率来实现音程调整等。这些解决方案充分利用了RP2350B的功能,为项目的实现提供了有效的技术支持。
7.对本次活动的心得体会
通过这个项目的开发,我对微控制器在音乐创作领域的应用有了更深入的了解。项目的设计思路和实现方式都很有意思,充分发挥了RP2350B的灵活性和多功能性。这个项目为用户提供了一个简单有趣的音乐创作平台,必将为音乐创作者带来新的灵感和创意
未来,我希望能够继续关注这种基于硬件的音乐创作工具,探索更多有趣的应用场景和创新点,为音乐创作者提供更好的支持。同时,也希望通过这样的活动,能够不断提高自己的嵌入式系统设计和开发能力,为更多有趣的项目贡献自己的力量。