大数跨境
0
0

玩+ | 国外老爸的硬核礼物,DIY一款木制收音机给孩子

玩+ | 国外老爸的硬核礼物,DIY一款木制收音机给孩子 DF创客社区
2019-05-30
3
导读:儿童节主动营业的爸爸才是好爸爸!哈哈哈

 

一起成为技术颜控


这个项目的作者是 Jiří Praus,他的初心是,制作一个适合您孩子使用的小巧方便的收音机。让他们播放自己喜欢的歌曲或童话故事。这一切都集中在木盒子里面!



使用硬件

  • Arduino Nano R3

  • DFPlayer Mini 播放器模块


起源

当我第一眼看到Horbert收音机时,我就立刻想为我2岁的女儿制作出类似的东西。但是我希望让它变得更加小巧和方便。也许需要在那里放置一些灯。我们确实也是这么做的。收音机在您手中可以变得更加小巧。它包含7个颜色按钮、小巧而强大的扬声器,以及MP3播放器,能够播放SD卡中的歌曲或童话故事。最后但同样重要的是,它在表壳周围设有彩虹LED,以创造出漂亮的环境光,能在睡前童话故事中作为夜灯使用。





木箱

我希望让箱子变成木制的。它看起来不错,我喜欢用木头工作。幸运的是,同时,我的朋友给我带来了一把激光切割机切割胶合板。它太棒了!各种形状都能够在几秒钟内切割完毕,而且精确度极高!图形文件附在本文底部。


尺寸:90x140x35mm




表壳采用4毫米胶合板并切割成8个部分。前后板、四个侧板、电池和扬声器盖。首先,我将四个侧板粘在一起形成整个框架。我还使用了其它一些木头对角落进行加固,因为我希望它们在最后是圆形的,所以我需要在那里增加一些材料才能将角落向下钻一点。




在我粘贴前面部分前,我在前板和框架之间嵌入一层薄薄的有机玻璃。这将允许我稍后连接LED,以便在收音机周围创建漂亮的闪亮环。某些额外的设计触感触动了我。我使用4mm有机玻璃,将其切成粗糙的形状以适应整个框架。有机玻璃使用超级胶水粘在框架和前板上。不必担心重叠的有机玻璃,它将最终打磨成型。



环境彩虹灯

为了在黑暗环境下增加额外的炫酷效果,我在表壳周围增加了4个RGB LED。先前插入的有机玻璃将允许发射的光在壳体周围扩散。我使用了菊链式标准可寻址WS2818 RGB LED。木箱的每个角落都分布了一个LED灯。




首先,使用万能胶将这些微型LED粘合到有机玻璃顶部角落。不要忘记标记引脚1,否则您将无法正确连接它们-请参阅永久标记所做的微型黑色标记。其次,将它们粘连在一起。我采用的工具是0.3mm铜线和透明绝缘材料。


VCC到VCC

GND至GND

OUT到下一个LED的IN



完成木箱制作

在将背板粘贴到位之前,在框架一侧切割小孔以适合Arduino Nano USB端口、MP3播放器SD卡插槽和电源开关。我决定将它们放置在收音机左侧。我使用小刀和方形文件,切割出精确的孔洞。保证这些孔洞尽量少,并且尽可能地隐藏。





现在是时候将背板粘合到位,并打造收音机最终形状了。利用万能胶套装后,我使用台式砂光机塑造圆角,并对所有表面进行清理。为了保护边缘,我还给它们打了一点点万能胶。保护从RGB LED出来的电线,以防止在打磨时损坏绝缘层。




最后一步是将扬声器盖环粘在扬声器孔上。它将使扬声器保持在原位。作为最后的保护措施,我已经涂了4层清漆。



扬声器盖网

为了避免人员好奇损坏扬声器,我希望在扬声器孔上放置一些网状物。但是由于我没有3D打印机,而且我没有其他任何合适的工具,我只好通过将1mm黄铜棒焊接成网状物来创建这种网状物。



事实证明它很完美。它非常坚固。没有什么能够穿透这层网,而且它也看起来很漂亮。为了隐藏焊点,我喷了白色漆。使用万能胶将扬声器盖粘在收音机中。


收音机里面

收音机核心是我最喜欢的Arduino Nano板。它能够读取7个按钮的状态,控制DFPlayer迷你MP3播放器,以及可寻址RGB LED。DFPlayer是一款小巧的MP3播放器,内置SD卡插槽和声音放大器,能够对高达3W的扬声器进行处理。我使用了一个功率为0.5W的8欧扬声器。



按钮

首先,创建按钮平台。收音机包含7个可编程按钮,总共焊接到一小块穿孔板上。最初我希望每个按钮都采用不同的颜色,以播放7种不同的歌曲。但是它看起来并不好看,所以我决定用一个黑色按钮来改变音量,用黄色、蓝色和红色对来选择3组歌曲的上一首或下一首歌。每个按钮连接到Arduino的一个数字引脚,它们都通过1Kohm电阻接地。



按钮的穿孔板间距并非标准和友好,因此我不得不将它们放入壳体的孔洞中,并使用自由形式技术将它们与一块黄铜棒焊接在一起。现在当按钮布局固定后,是时候将它倒挂到穿孔板上,并为每个按钮添加7根电线。最后,我为共同的接地点焊接了第8根电线。



整体组装

现在,当您已经完成所有零件制作后,就可以结束这项工作了。我首先焊接了Arduino Nano、DFPlayer、按钮、扬声器、RGB LED、电池和收音机外部的所有电线,因为一旦插入它们,机箱内就没有足够空间。它还允许我在所有组件不可逆地粘在内部之前测试外壳电子设备。



首先,我使用Mamut Glue将Arduino Nano、DFPlayer和开/关开关插入并粘贴到表壳中。 Mamut Glue让我拥有更多的时间,精确地将板材放在里面,并且将来会更好地保持它们,因为它是灵活可调的。接下来是扬声器盖网底部再次安装Mamut Glue的扬声器。最后的环节是按钮和电池组。电池组位于背面孔洞中,方便轻松更换电池。后来我用一节9V电池更换了4xAA电池。它的重量更轻。



大功告成!我们来编程吧!


播放歌曲!

我只是使用了DFPlayer网站的示例,并添加了一些代码来读取按钮,并对我的Ever Blooming Mechanical Tulip(“永不凋谢的机械郁金香”)项目的LED进行控制。代码非常简单。这简直不像是我做出来的,但是它却非常有效。



它要求SD卡包含3个名为01、02、03的文件夹,以对应每种颜色。每个文件夹中最多可包含255首歌曲,名为001.mp3到255.mp3。我宁愿将文件夹命名为红色、蓝色和黄色,但DFPlayer不支持。


DFPlayer使用非常方便。它通过串行通信,并具有超级棒的音乐库,具有各种功能读取和控制播放器的状态。我只会添加对人可读的文件夹和文件名的功能支持。


代码

#include "Arduino.h"#include "SoftwareSerial.h"#include "DFRobotDFPlayerMini.h"#include <Adafruit_NeoPixel.h>#define BUTTON_1 A2 // yellow left#define BUTTON_2 A1 // yellow right#define BUTTON_3 A3 // red left#define BUTTON_4 A0 // red right#define BUTTON_5 A4 // blue left#define BUTTON_6 2 // blue right#define BUTTON_7 3 // black#define BUTTONS_COUNT 7#define BUTTON_RELEASED 0#define BUTTON_PRESSED 1#define BUTTON_HANDLED 2byte buttonPins[] = {BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4, BUTTON_5, BUTTON_6, BUTTON_7};byte buttonState[] = {0, 0, 0, 0, 0, 0, 0};#define NEOPIXEL_PIN 9#define RED 0#define GREEN 1#define BLUE 2float currentRGB[] = {0, 0, 0};float changeRGB[] = {0, 0, 0};byte newRGB[] = {0, 0, 0};Adafruit_NeoPixel pixels = Adafruit_NeoPixel(4, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ400);SoftwareSerial playerSerial(7, 6); // RX, TXDFRobotDFPlayerMini player;#define FOLDER_RED 0#define FOLDER_BLUE 1#define FOLDER_YELLOW 2byte currentSong[] = {0, 0, 0}; // 1 to size of folderbyte folderSizes[] = {0, 0, 0};byte volume = 5;byte lightIntensity = 0;void setup() {  randomSeed(analogRead(A7));  playerSerial.begin(9600);  Serial.begin(115200);  pixels.begin();  pixelsUnifiedColor(0);  for (int i = 0; i < BUTTONS_COUNT; i++) {    pinMode(buttonPins, INPUT_PULLUP);    buttonState = BUTTON_RELEASED;  }     Serial.println();  Serial.println(F("DFRobot DFPlayer Mini Demo"));  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));     if (!player.begin(playerSerial)) {  //Use softwareSerial to communicate with mp3.    Serial.println(F("Unable to begin:"));    Serial.println(F("1.Please recheck the connection!"));    Serial.println(F("2.Please insert the SD card!"));    while(true);  }  Serial.println(F("DFPlayer Mini online."));  //player.EQ(DFPLAYER_EQ_ROCK);  player.outputDevice(DFPLAYER_DEVICE_SD);  player.volume(volume);  //player.play(1);  folderSizes[FOLDER_RED] = player.readFileCountsInFolder(FOLDER_RED + 1);  folderSizes[FOLDER_BLUE] = player.readFileCountsInFolder(FOLDER_BLUE + 1);  folderSizes[FOLDER_YELLOW] = player.readFileCountsInFolder(FOLDER_YELLOW + 1);  Serial.println(F("Radio ready."));}void loop() {   if (player.available()) {    printDetail(player.readType(), player.read()); //Print the detail message from DFPlayer to handle different errors and states.  }  readButtons();  crossFade();  delay(15);}void readButtons() {  for (int i = 0; i < BUTTONS_COUNT; i++) {    if (digitalRead(buttonPins) == HIGH) {      buttonState = BUTTON_RELEASED;    }    else if (buttonState == BUTTON_RELEASED) {      buttonState = BUTTON_PRESSED;    }  }  if (buttonState[0] == BUTTON_PRESSED) { // yellow left    buttonState[0] = BUTTON_HANDLED;    playNextInFolder(FOLDER_YELLOW);  }  else if (buttonState[1] == BUTTON_PRESSED) { // yellow right    buttonState[1] = BUTTON_HANDLED;    playPreviousInFolder(FOLDER_YELLOW);  }  else if (buttonState[2] == BUTTON_PRESSED) { // red left    buttonState[2] = BUTTON_HANDLED;    playNextInFolder(FOLDER_RED);  }  else if (buttonState[3] == BUTTON_PRESSED) { // red right    buttonState[3] = BUTTON_HANDLED;    playPreviousInFolder(FOLDER_RED);  }  else if (buttonState[4] == BUTTON_PRESSED) { // blue left    buttonState[4] = BUTTON_HANDLED;    playNextInFolder(FOLDER_BLUE);  }  else if (buttonState[5] == BUTTON_PRESSED) { // blue right    buttonState[5] = BUTTON_HANDLED;    playPreviousInFolder(FOLDER_BLUE);  }  else if (buttonState[6] == BUTTON_PRESSED) { // black    volume = volume >= 15 ? 5 : volume + 5;    player.volume(volume);    buttonState[6] = BUTTON_HANDLED;  }}void playNextInFolder(byte folder) {  currentSong[folder]++;  if (currentSong[folder] > folderSizes[folder]) {    currentSong[folder] = 1;  }  player.playFolder(folder + 1, currentSong[folder]);}void playPreviousInFolder(byte folder) {  currentSong[folder]--;  if (currentSong[folder] <= 0) {    currentSong[folder] = folderSizes[folder];  }  player.playFolder(folder + 1, currentSong[folder]);}void printDetail(uint8_t type, int value){  switch (type) {    case TimeOut:      Serial.println(F("Time Out!"));      break;    case WrongStack:      Serial.println(F("Stack Wrong!"));      break;    case DFPlayerCardInserted:      Serial.println(F("Card Inserted!"));      break;    case DFPlayerCardRemoved:      Serial.println(F("Card Removed!"));      break;    case DFPlayerCardOnline:      Serial.println(F("Card Online!"));      break;    case DFPlayerPlayFinished:      Serial.print(F("Number:"));      Serial.print(value);      Serial.println(F(" Play Finished!"));      break;    case DFPlayerError:      Serial.print(F("DFPlayerError:"));      switch (value) {        case Busy:          Serial.println(F("Card not found"));          break;        case Sleeping:          Serial.println(F("Sleeping"));          break;        case SerialWrongStack:          Serial.println(F("Get Wrong Stack"));          break;        case CheckSumNotMatch:          Serial.println(F("Check Sum Not Match"));          break;        case FileIndexOut:          Serial.println(F("File Index Out of Bound"));          break;        case FileMismatch:          Serial.println(F("Cannot Find File"));          break;        case Advertise:          Serial.println(F("In Advertise"));          break;        default:          break;      }      break;    default:      break;  }}void prepareCrossFade(byte red, byte green, byte blue, unsigned int duration) {  float rchange = red - currentRGB[RED];  float gchange = green - currentRGB[GREEN];  float bchange = blue - currentRGB[BLUE];  changeRGB[RED] = rchange / (float) duration;  changeRGB[GREEN] = gchange / (float) duration;  changeRGB[BLUE] = bchange / (float) duration;  newRGB[RED] = red;  newRGB[GREEN] = green;  newRGB[BLUE] = blue;  Serial.print(newRGB[RED]);  Serial.print(" ");  Serial.print(newRGB[GREEN]);  Serial.print(" ");  Serial.print(newRGB[BLUE]);  Serial.print(" (");  Serial.print(changeRGB[RED]);  Serial.print(" ");  Serial.print(changeRGB[GREEN]);  Serial.print(" ");  Serial.print(changeRGB[BLUE]);  Serial.println(")");}boolean crossFade() {  if (currentRGB[RED] == newRGB[RED] && currentRGB[GREEN] == newRGB[GREEN] && currentRGB[BLUE] == newRGB[BLUE]) {    return true;  }  for (byte i = 0; i < 3; i++) {    if (changeRGB > 0 && currentRGB < newRGB) {      currentRGB = currentRGB + changeRGB;    }    else if (changeRGB < 0 && currentRGB > newRGB) {      currentRGB = currentRGB + changeRGB;    }    else {      currentRGB = newRGB;    }  }  pixelsUnifiedColor(pixels.Color(currentRGB[RED], currentRGB[GREEN], currentRGB[BLUE]));  return false;}void pixelsUnifiedColor(uint32_t color) {  for (unsigned int i = 0; i < pixels.numPixels(); i++) {    pixels.setPixelColor(i, color);  }  pixels.show();}void rainbow(int j) {  uint16_t i;  byte num = pixels.numPixels() - 1;  pixels.setPixelColor(pixels.numPixels() - 1, 100, 100, 100);  for (i = 0; i < num; i++) {    pixels.setPixelColor(i, colorWheel(((i * 256 / num) + j) & 255));  }  pixels.show();}uint32_t colorWheel(byte wheelPos) {  // Input a value 0 to 255 to get a color value.  // The colours are a transition r - g - b - back to r.  wheelPos = 255 - wheelPos;  if (wheelPos < 85) {    return pixels.Color(255 - wheelPos * 3, 0, wheelPos * 3);  }  if (wheelPos < 170) {    wheelPos -= 85;    return pixels.Color(0, wheelPos * 3, 255 - wheelPos * 3);  }  wheelPos -= 170;  return pixels.Color(wheelPos * 3, 255 - wheelPos * 3, 0);}



*欢迎转发朋友圈。如需转载,请注明出处和原作者。


项目干货戳这里

图像识别:教PIXY识别物体 | 萌兔sudo化身语音助手

LED全彩手表 | 美队护盾我收下了! | Arduino混合饮料机

脱机音质赞爆的电子钢琴 | 自制指纹箱

Makerspace NFC组件管理系统 

 “时间”嵌入玻璃窗 | “多喝水”提醒器

纸箱机器人cos苏大强 | 魔法书隔空翻页的魔法书 

激光切割中国象棋 | 永恒郁金香 | 太阳能板追太阳 

LED爱心灯 | 【必收藏】2018年精选项目大全!

NFC门禁 |  micro:bit荷兰风车

GameBuino游戏机 织风音乐交互艺术装置

 美到窒息的LED雪花 | 抖音兔兔帽+肌电传感器

 漂移雪橇 最轻薄树莓派魔镜 | 陀螺仪另类玩法

 巨型弹珠机 | 机械翅膀 | 音乐留声机 

 MIDI控制自动弹钢琴 | mini热带温室 | 无线蓝牙机械键盘 

变脸娃娃 给lcd触摸屏做了个soulmate……

 属于理工男的梦幻立方体  |  木质留声机

动态像素眼镜 复古ComputeModule 3

磁悬浮盆景 | LED项链

吃币机器人 | 骨骼追踪抛物预判垃圾桶 | 弹球机



美的作品,值得拥有一个 “在看”

【声明】内容源于网络
0
0
DF创客社区
我们是专注于创新和开源硬件开发的公司——DFRobot成立的创客社区,无论你是资深创客还是小白,这里都有你的一席之地。一个人玩自己的项目,你只是寂寞宅;一群人看你玩项目,你就是技术牛!快来分享你的项目吧!
内容 1282
粉丝 0
DF创客社区 我们是专注于创新和开源硬件开发的公司——DFRobot成立的创客社区,无论你是资深创客还是小白,这里都有你的一席之地。一个人玩自己的项目,你只是寂寞宅;一群人看你玩项目,你就是技术牛!快来分享你的项目吧!
总阅读2.1k
粉丝0
内容1.3k