BoBo | NPC | 创造力: | 帖子: | 发消息 | 串个门 | 加好友 | 打招呼
2021-3-19 18:54:58 [显示全部楼层]
7735浏览
查看: 7735|回复: 6

DIY语音相册 -使用Firebeetle M0主板来制作一款语音相册

[复制链接]

DIY语音相册
-使用Firebeetle M0主板来制作一款语音相册

最近一直在琢磨做一个特别的礼物。看到朋友购买实体相册送人,我想是否能够在实体相册上做一些创新呢,例如增加一些互动?
我翻看着相册里面的相片,相片往往让我回想起过往岁月的点点滴滴,往往令人感动的不是变化的事物,而是那些被相片定格的不变的瞬间。
每一个瞬间都有一段故事,为什么我们不让照片自己来讲述这段故事呢?
于是制作语音相册的想法一直在我脑海中回荡。自从看到了DFRobot推出的Firebeetle M0主板,我突然发现这个主板恰恰好能够实现我的想法。

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图1


我先来说说为什么恰恰好。Firebeetle M0主板的主芯片使用了一款ATSAMD21G18 ARM Cortex M0+ 高性能32位处理器,而且还带一路数模转换DAC,这意味着我可以通过MCU软件解析音频文件,并播放出声音。

在主板上还集成了16MB SPI Flash,可以虚拟出一个12MB的U盘用于存储数据。也就是我可以通过USB将音频文件直接存储到Flash中。我算了一下存储单声道WAV文件大概可以存储5分钟,够讲几段故事了。

在加上必要的GPIO作为按钮的输入,一个Firebeetle M0主板可以完成我的这个作品。

以下是Firebeetle M0主板的详细介绍


我购买了一本漂亮的16寸自粘式覆膜相册,封面是印象派画家柴尔德·哈萨姆的海边。
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图2


选用的部件

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图5


部件清单:
1. FIT0625 带开关两节7号电池盒(安装一对7号电池) 1只
7. 16寸自粘式覆膜相册 1本

准备的工具:
2.     KIT0077 基础焊接工具套装(里面包含了焊接所需的烙铁、钳子、镊子等)  1套
3.     FIT0641 USB Type- C线 1条
4.     双面胶 1卷
5.     电脑  1台


所用到的软件:
1.  Arduino IDE 编程环境
2.  Audacity音频转换软件
3.  voice_album.ino 代码


制作步骤:
一、安装Arduino IDE和Firebeetle M0主板SDK,并测试开发环境
使用Firebeetle M0主板之前,首先需要下载并安装Arduino IDE开发环境,测试Firebeetle M0主板。
Arduino官方下载最新版本的IDE开发环境。


IDE安装好以后,打开IDE,然后下载安装Firebeetle M0主板的SDK
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图4

点击File -> Preferences
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图6

1.Preferences界面点击Additional Boards Manager URLs最左边的窗口图标,将弹出输入URL的窗口。
2.将下面的链接地址复制到新弹出的对话框中
3.点击OK将保存Firebeetle M0主板SDK的URL地址
4.点击Preferences界面的OK按钮保存配置



点击Tools -> Board -> Boards Manager
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图7


此时可以看到Firebeetle SAMD Board这个SDK,点击Install安装SDK

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图8


装好以后我们就可以在Board界面看到Firebeetle M0主板的选项,我们选择Firebeetle M0

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图9


通过USB线将Firebeetle M0主板连接到电脑,此时可看到操作系统发现了一个新的COM口,我们在Port菜单选择新的这个COM口。

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图10


为了验证主板是否可以工作,我们先来运行一个简单的板上13脚LED闪烁的例子程序。

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图11

点击左上角的箭头按钮,LED闪烁程序将会编译后烧写到主板。烧写过程中主板上的13脚LED灯快速闪烁,当IDE左下角显示Done uploading说明程序下载完成。

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图12

可以看到主板上13脚的绿色LED灯按照亮一秒灭一秒的节奏闪烁,说明主板是好的,开发环境我们也搭好了。

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图17


二、使用电烙铁焊接硬件
将音频功放、喇叭和5个按钮焊接在一起,按钮的连线15厘米左右

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图3

连线示意图



DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图14




三、挑选照片,讲述照片背后的故事,准备音频文件
我们挑选出照片,准备好我们想讲的故事。用手机录制5个故事的音频文件,需要注意的是声音需要大声一些,这样可以提高信噪比。
如果检查没有问题,我们将这些文件传输到PC上,它们一般是.m4a文件,我们对文件进行重命名。因为5个按键在程序里面的编号是从按键0到按键4,所以我们文件的命名也是从0到4。
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图13


这些文件是压缩后的双声道,我们需要转换为Firebeetle M0主板能够软件音频解码的WAV单声道文件。
我们使用Audacity这个开源免费的音频软件将m4a文件转换为单声道WAV文件。
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图16


Audacity软件安装完成后,我们还需要去下载一个免费的ffmpeg-win-2.2.2.exe插件
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图15


ffmpeg-win-2.2.2.exe安装好后,在Audacity软件点击菜单Edit ->Preferences
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图19


点击Libraries ->FFmpegLibrary -> Location
选择FFmpeg安装的路径点击 OK

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图18

点击Audacity软件File -> Open打开刚才录音的0.m4a文件
点击音轨上方的下拉按钮,选择 Split Stereoto Mono 分离出单声道
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图20


点击一个声道的Mute按钮对这个声道进行静音,Project Rate选择44100Hz
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图22

点击File -> Export ->Export as WAV,导出WAV文件
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图23


Encoding选择Unsigned 8-bit PCM格式,保存0.wav文件
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图21

按照以上方法将其他4个.m4a文件转换为.wav文件


将Firebeetle M0主板通过USB线连接到电脑,双击侧面的RST按钮,此时主板上的RGB灯变成绿色,电脑也将弹出一个U盘,将准备好的5个.wav文件拷贝到这个U盘。拷贝的速度比通常的U盘慢,需要耐心等待。

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图26

拷贝完成后,我们单击RST按钮,进入到编程模式。


四、下载语音相册的代码到Firebeetle M0主板
此时打开Arduino IDE,点击Sketch -> Include Library -> Add .ZIP Librar选择附件代码文件中的AudioZero.zip音频库,此时成功加入了音频库

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图24




点击Arduino IDE 的File -> Open
打开voice_album.ino,点击Ipload按钮将语音相册的程序下载到Firebeetle M0主板
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图25

参考代码:
  1. // voice album project
  2. //
  3. #include <UD.h>
  4. #include <SPI.h>
  5. //Here is an example of audioZero https://www.arduino.cc/en/Tutorial/SimpleAudioPlayerZero
  6. #include <AudioZero.h>
  7. // D12口低电平将关闭PAM8403音频功放
  8. // When D12 is low level will turn off pam8403 audio amplifier
  9. const byte nShoutdown = 12;
  10. // D32 pin for SPI Flash CS pin
  11. const byte flashCS = 32;
  12. // 5个按钮的编号对应到Firebeetle M0 Pin
  13. // The numbers of the five button correspond to firebeetle M0 pin
  14. // Button  number      :| 0 | 1 | 2 | 3 | 4 |
  15. // Firebeetle M0    Pin:| D0| D1| D3| D5| D6|
  16. // 记录按钮按下的时刻
  17. // Record the time when the button is pressed
  18. volatile unsigned long triggertime = 0;
  19. // 去抖期的时长 (毫秒)
  20. // Duration of dithering (mS)
  21. volatile unsigned long delta = 500;   
  22. volatile boolean buttonStatus[5] = {0};
  23. volatile byte soundNumber = 0;
  24. volatile boolean startPlay = 0;
  25. String title = String(".wav");
  26. // 播放控制
  27. // Playback control
  28. void controlPlay(void) {
  29.   volatile byte i = 0;
  30.   // 如果有按钮按下将停止音频播放
  31.   // If a button is pressed, the audio will stop playing
  32.   AudioZero.stop();
  33.   Serial.println("stop ");
  34.   // 如果没有播放过这个音频,此时就播放按钮对应的这个音频
  35.   // If the audio has not been played, the audio corresponding to the button will be played at this time
  36.   if (0 == buttonStatus[soundNumber]) {
  37.     title = String(".wav");
  38.     title =  soundNumber + title;
  39.     startPlay = 1;
  40.     for (i = 0; i < 5; i++) {
  41.       buttonStatus[i] = 0;
  42.     }
  43.     buttonStatus[soundNumber] = 1;
  44.   }
  45.   else {
  46.     buttonStatus[soundNumber] = 0;
  47.   }
  48. }
  49. // 读取5个按钮的值,按钮的编号对应到Firebeetle M0 Pin如下
  50. // Read the values of the five buttons. The button numbers correspond to firebeetle M0 pin as follows
  51. // Button  number      :| 0 | 1 | 2 | 3 | 4 |
  52. // Firebeetle M0    Pin:| D0| D1| D3| D5| D6|
  53. void readButton(void) {
  54.   // 如果第二次按钮中断间隔时间大于消除抖动时间,说明是一次正常的按键动作
  55.   // If the interval between the second button interruption is greater than the time to eliminate jitter, it is a normal key action
  56.   if (millis() - triggertime > delta) {
  57.     triggertime = millis();
  58.     // 读取D0引脚的电平,如果是按钮0按下调用控制播放功能
  59.     // Read the level of D0 pin, if it is the button 0, press it to call the control playback function
  60.     if (digitalRead(0) == 0) {
  61.       soundNumber = 0;
  62.       controlPlay();
  63.       return;
  64.     }
  65.     // 读取D1引脚的电平,如果是按钮1按下调用控制播放功能
  66.     // Read the level of D1 pin, if it is the button 1, press it to call the control playback function
  67.     if (digitalRead(1) == 0) {
  68.       soundNumber = 1;
  69.       controlPlay();
  70.       return;
  71.     }
  72.     // 读取D3引脚的电平,如果是按钮2按下调用控制播放功能
  73.     // Read the level of D3 pin, if it is the button 2, press it to call the control playback function
  74.     if (digitalRead(3) == 0) {
  75.       soundNumber = 2;
  76.       controlPlay();
  77.       return;
  78.     }
  79.     // 读取D5引脚的电平,如果是按钮3按下调用控制播放功能
  80.     // Read the level of D5 pin, if it is the button 3, press it to call the control playback function
  81.     if (digitalRead(5) == 0) {
  82.       soundNumber = 3;
  83.       controlPlay();
  84.       return;
  85.     }
  86.     // 读取D6引脚的电平,如果是按钮4按下调用控制播放功能
  87.     // Read the level of D6 pin, if it is the button 4, press it to call the control playback function
  88.     if (digitalRead(6) == 0) {
  89.       soundNumber = 4;
  90.       controlPlay();
  91.       return;
  92.     }
  93.   }
  94. }
  95. // 初始化设置函数,程序从这里开始
  96. // Initialization setting function, the program starts from here
  97. void setup()
  98. {
  99.   // 设置音频功放关闭控制脚为输出
  100.   // Set the audio amplifier off control pin as output
  101.   pinMode(nShoutdown, OUTPUT);
  102.   // 关闭音频功放
  103.   // Audio power amplifier off
  104.   digitalWrite(nShoutdown, LOW);
  105.   // 设置5个按钮接口为输入,并且上拉使能,按钮的编号对应到Firebeetle M0 Pin如下
  106.   // The numbers of the five button correspond to firebeetle M0 pin
  107.   // Button  number      :| 0 | 1 | 2 | 3 | 4 |
  108.   // Firebeetle M0    Pin:| D0| D1| D3| D5| D6|
  109.   // 设置| D0| D1| D3| D5| D6|为输入中断
  110.   // Set | D0 | D1 | D3 | D5 | D6 | as input interrupt
  111.   pinMode(0, INPUT_PULLUP);
  112.   attachInterrupt(digitalPinToInterrupt(0), readButton, FALLING );
  113.   pinMode(1, INPUT_PULLUP);
  114.   attachInterrupt(digitalPinToInterrupt(1), readButton, FALLING );
  115.   pinMode(3, INPUT_PULLUP);
  116.   attachInterrupt(digitalPinToInterrupt(3), readButton, FALLING );
  117.   pinMode(5, INPUT_PULLUP);
  118.   attachInterrupt(digitalPinToInterrupt(5), readButton, FALLING );
  119.   pinMode(6, INPUT_PULLUP);
  120.   attachInterrupt(digitalPinToInterrupt(6), readButton, FALLING );
  121.   Serial.begin(115200);
  122.   Serial.print("Initializing SD card...");
  123.   //D32 pin for SPI Flash CS pin
  124.   if (!UD.begin(flashCS)) {
  125.     Serial.println(" failed!");
  126.     while (true);
  127.   }
  128.   Serial.println(" done.");
  129.   // 44100kHz mono sample rate
  130.   AudioZero.begin(44100);
  131. }
  132. // 程序主循环
  133. // Program main loop
  134. void loop ()
  135. {
  136.   byte flag = 0;
  137.   // 如果startPlay标志置位,控制播放
  138.   // If the startplay flag is set, the playback is controlled
  139.   if (1 == startPlay) {
  140.     startPlay = 0;
  141.     // 按照音频文件名读取文件
  142.     // Read audio file name according to
  143.     UDFile myFile = UD.open(title);
  144.     if (!myFile) {
  145.       // if the file didn't open, print an error and stop
  146.       Serial.println("error opening .wav file");
  147.     }
  148.     else {
  149.       // 开启音频功放
  150.       // Turn on audio amplifier
  151.       digitalWrite(nShoutdown, HIGH);
  152.       Serial.print("Playing ");
  153.       Serial.println(soundNumber);
  154.       // 返回byte: false:音频播放完毕; true:音频播放过程中中断停止
  155.       // Return byte: false: audio playback finished; true: interrupt stop during audio playback
  156.       // until the file is not finished
  157.       flag = AudioZero.play(myFile);
  158.       if (false == flag) {
  159.         buttonStatus[soundNumber] = 0;
  160.       }
  161.       Serial.println("End of file. Thank you for listening!");
  162.       // 播放完毕关闭音频功放
  163.       // Turn off the audio amplifier after playing
  164.       digitalWrite(nShoutdown, LOW);
  165.     }
  166.   }
  167. }
复制代码

如果测试5个按钮按下都能够播放对应的歌曲,软件和电路部分我们就完成了,接下来我们需要将电路安装到相册里面。


五、将电路装配到相册里
相册有三颗螺丝,为了方便安装按钮,我们拆掉最下面的一个螺丝。

相册第一页
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图27


相册最后一页的螺丝,我们只需要拆掉最下面那一颗即可
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图29

我们使用镊子将按钮线穿过书轴
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图28


安装好按钮并连接好电路部分后,将相册的螺丝安装好

DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图32




使用双面胶将电池盒、Firebeetle M0主板、喇叭固定在相册上
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图30



将照片放置到相册
DIY语音相册  -使用Firebeetle M0主板来制作一款语音相册图31



至此一个DIY的语音相册就完成了。你要不要试试做一本自己的语音相册呢?



完整制作视频

AudioZero.zip

6.45 KB, 下载次数: 2428

语音库文件

voice_album_CN.zip

2.5 KB, 下载次数: 2466

相册代码

hnyzcj  版主

发表于 2021-3-20 06:27:12

回复

使用道具 举报

rzyzzxw  版主

发表于 2021-3-20 12:46:16

喜欢
回复

使用道具 举报

topdog  中级技师

发表于 2021-3-21 21:21:25

蛮好的,创意满满。
回复

使用道具 举报

TuTu  高级技师

发表于 2021-3-22 11:37:18

哇这也太棒了! 想学着做一个!
回复

使用道具 举报

oO听风Oo  学徒

发表于 2021-3-25 09:05:36

高手  厉害 牛牛牛
回复

使用道具 举报

 初级技匠

发表于 2021-4-12 11:06:31

这是高手
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail