极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 22322|回复: 9

遥控Arduino播放音乐

[复制链接]
发表于 2013-8-29 17:48:07 | 显示全部楼层 |阅读模式
本帖最后由 迷你强 于 2013-8-30 22:37 编辑

  没玩几天Arduino(mega328),手头也没什么模块,看了论坛里那篇Arduino播放音乐的教程后跟着做出来了(http://www.geek-workshop.com/for ... thread&tid=2611),还不错,但是缺点很明显,必须用电脑连串口输入文件名和命令,于是就改改程序加进IR接收,让板子可以摆脱电脑独立受遥控控制播放音乐,并不难,但是很实用,贴出来
分享一下。
  SD卡的接线参照“Workshop Team”的上面那篇帖子,红外接收管脚可自定义,我设的D5脚。

  代码当然是根据MostFunctionDemo.ino改的,库函数用word打开各种看不懂啊,不过关键地方改对就行。



  1. //This is used for play music on SD card under the control of IR remote;
  2. #include <SimpleSDAudio.h>
  3. #include<IRremote.h>

  4. int RECV_PIN = 5;   //红外线接收器OUTPUT端接在pin 5
  5. IRrecv irrecv(RECV_PIN);   // 定义IRrecv 对象来接收红外线信号
  6. decode_results results;   //解码结果放在decode_results构造的对象results里

  7. // Callback target, prints output to serial
  8. void DirCallback(char *buf) {
  9. Serial.println(buf);
  10. }

  11. char AudioFileName[16];

  12. // Create static buffer
  13. #define BIGBUFSIZE (2*512)      // bigger than 2*512 is often only possible on Arduino megas!
  14. uint8_t bigbuf[BIGBUFSIZE];

  15. // helper function to determine free ram at runtime
  16. int freeRam () {
  17.   extern int __heap_start, *__brkval;
  18.   int v;
  19.   return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
  20. }

  21. void setup()
  22. {
  23. // Open serial communications and wait for port to open:
  24.    Serial.begin(9600);
  25.    irrecv.enableIRIn();          //启动红外解码
  26.    //while (!Serial) {
  27.    // wait for serial port to connect. Needed for Leonardo only
  28.    //}

  29.   Serial.print(F("Free Ram: "));
  30.   Serial.println(freeRam());
  31.   
  32.   // Setting the buffer manually for more flexibility
  33.   SdPlay.setWorkBuffer(bigbuf, BIGBUFSIZE);
  34.   
  35.   Serial.print(F("\nInitializing SimpleSDAudio V" SSDA_VERSIONSTRING " ..."));  
  36.   
  37.   // If your SD card CS-Pin is not at Pin 4, enable and adapt the following line:
  38.   //SdPlay.setSDCSPin(10);
  39.   
  40.   // Select between SSDA_MODE_FULLRATE or SSDA_MODE_HALFRATE (62.5kHz or 31.25kHz)
  41.   // and the output modes SSDA_MODE_MONO_BRIDGE, SSDA_MODE_MONO or SSDA_MODE_STEREO
  42.   if (!SdPlay.init(SSDA_MODE_FULLRATE | SSDA_MODE_MONO)) {
  43.     Serial.println(F("initialization failed. Things to check:"));
  44.     Serial.println(F("* is a card is inserted?"));
  45.     Serial.println(F("* Is your wiring correct?"));
  46.     Serial.println(F("* maybe you need to change the chipSelect pin to match your shield or module?"));
  47.     Serial.print(F("Error code: "));
  48.     Serial.println(SdPlay.getLastError());
  49.     while(1);
  50.   } else
  51.   {
  52.     Serial.println(F("Wiring is correct and a card is present."));
  53.   }
  54. }


  55. void loop(void) {
  56.   uint8_t count=0,flag=0;//unsigned int,c will transfered one by one
  57.   char d[9]={'B','E','T','H','.','A','F','M'};////////////////////////////1
  58.   char e[13]={'M','A','D','W','O','R','L','D','.','A','F','M','\0'};/////2
  59.   char f[13]={'B','L','U','E','B','I','~','1','.','A','F','M','\0'};/////////3
  60.   char a[13]="";
  61.   char g[13]={'M','E','M','O','R','I','E','S','.','A','F','M','\0'};///////4

  62. //Add here;
  63.   Serial.println(F("Files on card:"));
  64.   SdPlay.dir(&DirCallback);

  65. //ReEnter:
  66.   Serial.println(F("\r\nEnter filename (send newline after input):"));
  67. while(1)
  68. {/////////////small loop in big loop;
  69.   count=0;
  70.   if(flag==2){for(int i=0;i<13;i++){ AudioFileName[count++]=e[i];}count=0;}
  71.   if(flag==3){for(int i=0;i<13;i++){ AudioFileName[count++]=f[i];}count=0;}
  72.   if(flag==4){for(int i=0;i<9;i++){ AudioFileName[count++]=d[i];}count=0;}
  73.   if(flag==5){for(int i=0;i<13;i++){ AudioFileName[count++]=g[i];}count=0;}
  74. //Add here;
  75.   Serial.print(F("Looking for file... "));
  76.   if(!SdPlay.setFile(AudioFileName)) //judging file name according to filename
  77.   {
  78.     Serial.println(F(" not found on card! Error code: "));
  79.     Serial.println(SdPlay.getLastError());
  80. //goto ReEnter;
  81.   }
  82.   else {
  83.    Serial.println(F("found."));
  84.   }
  85.   
  86.   Serial.println(F("Press s for stop, p for play, h for pause, f to select new file, d for deinit, v to view status."));
  87.   flag = 1;  
  88.   while(flag==1) {
  89.     SdPlay.worker();
  90.    if (irrecv.decode(&results))  {
  91.     switch(results.value) {
  92.     case 0xFF30CF:
  93.            count=0;
  94.            for(int i=0;i<13;i++){ AudioFileName[count++]=a[i];}
  95.            count=0;
  96.            flag=2;/////////1
  97.            break;
  98.     case 0xFF18E7:
  99.            count=0;
  100.            for(int i=0;i<13;i++){ AudioFileName[count++]=a[i];}
  101.            count=0;
  102.            flag=3;
  103.            break;///////////2
  104.     case 0xFF7A85:
  105.            count=0;
  106.            for(int i=0;i<13;i++){ AudioFileName[count++]=a[i];}
  107.            count=0;
  108.            flag=4;
  109.            break;///////////3
  110.     case 0xFF10EF:
  111.            count=0;
  112.            for(int i=0;i<13;i++){ AudioFileName[count++]=a[i];}
  113.            count=0;
  114.            flag=5;
  115.            break;///////////4
  116.            
  117. //Add here;
  118.     case 0xFFE21D:           
  119.            SdPlay.stop();
  120.            Serial.println(F("Stopped."));
  121.            break;
  122.     case 0xFF22DD:           
  123.            SdPlay.play();
  124.            Serial.println(F("Play."));
  125.            break;
  126.     case 0xFFE01F:
  127.            SdPlay.pause();
  128.            Serial.println(F("Pause."));
  129.            break;
  130.     case 0xFFA25D:
  131.            SdPlay.deInit();
  132.            Serial.println(F("SdPlay deinitialized. You can now safely remove card. System halted."));
  133.            while(1) ;
  134.            break;
  135.      case 0xFFB04F:
  136.            flag = 0;
  137.            count=0;
  138.            for(int i=0;i<13;i++){ AudioFileName[count++]=a[i];}
  139.            count=0;
  140.            break;
  141.      case 0xFF629D:
  142.            Serial.print(F("Status: isStopped="));
  143.            Serial.print(SdPlay.isStopped());
  144.            Serial.print(F(", isPlaying="));
  145.            Serial.print(SdPlay.isPlaying());
  146.            Serial.print(F(", isPaused="));
  147.            Serial.print(SdPlay.isPaused());
  148.            Serial.print(F(", isUnderrunOccured="));
  149.            Serial.print(SdPlay.isUnderrunOccured());
  150.            Serial.print(F(", getLastError="));
  151.            Serial.println(SdPlay.getLastError());
  152.            Serial.print(F("Free RAM: "));
  153.            Serial.println(freeRam());
  154.            break;         
  155.       }   
  156.       irrecv.resume();
  157.     }
  158.   }  
  159. }
  160. }
复制代码

  该程序中有三处打头为//Add here,那三个地方是要增加歌曲或者修改歌曲名称时用到的,对应上面几行复制再改参数就行。
添加歌曲名时注意,AudioFileName的歌曲名都被自动改为大写字母、无空格、不超过12个字符(除去.afm,只有8个)的字符串,而且,不支持字符“’”,会产生错误。由于害怕里面很多库函数对AudioFileName长度有限制,就没有改长它,短了又不知道是什么歌曲,所以就没管它。SD卡中存储的afm文件显示到串口调试器里的名字才是我们需要的。
下载到板子上之后连上电池拔掉USB,然后按1,2,3等数字键选择歌曲,然后按播放键(键码不用多说了哈)就有开始播放了,
其他功能键可以自己设置,我设置的功能键在连USB时按下板子上TX灯会闪,串口调试器上也会出单词,什么功能一目了然。
有必要的朋友可以再加一个液晶显示模块显示歌名状态等。这个作品的缺点是,AFM格式文件制作有点麻烦,还比较大,然后歌曲多了的话几个数字键不够用(再进一步修改程序使其能接收两三位数字来选择歌曲即可)。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2013-8-30 18:57:07 | 显示全部楼层
受教了,很好, 支持下
回复 支持 反对

使用道具 举报

发表于 2013-8-30 19:22:00 | 显示全部楼层
引入#include <SimpleSDAudio.h> 后就报错啊,楼主有遇到这个问题么?
回复 支持 反对

使用道具 举报

发表于 2013-8-30 21:12:10 来自手机 | 显示全部楼层
zjgaoli888 发表于 2013-8-30 19:22
引入#include  后就报错啊,楼主有遇到这个问题么?

你是1.5.2的IDE吧,只有1.0.3以下才能用此库!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-31 11:49:27 | 显示全部楼层
zjgaoli888 发表于 2013-8-30 19:22
引入#include  后就报错啊,楼主有遇到这个问题么?

我的IDE是1.0.5的,没有遇到你说的问题,你的SimpleSDAudio.h放在library里了吗?最好先用只有一个音乐文件的MostFuctionDemo测试一下。
回复 支持 反对

使用道具 举报

发表于 2013-9-21 20:36:15 | 显示全部楼层
不行啊     这句有错啊   1.01的ide,
IRrecv irrecv(RECV_PIN);   // 定义IRrecv 对象来接收红外线信号
错在irrecv' was not declared in this scope
求教啊!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-9-21 22:27:24 | 显示全部楼层
whmn 发表于 2013-9-21 20:36
不行啊     这句有错啊   1.01的ide,
IRrecv irrecv(RECV_PIN);   // 定义IRrecv 对象来接收红外线信号
...

换1.0.5的试下吧。上次我用9v电源插uno结果板子和1602液晶全烧了,bootloader也刷不了,SD卡换了板子再也读不出来,但是里面文件都是好的,所以可能存在兼容性问题,只能您自己搞了,爱莫能助啊
回复 支持 反对

使用道具 举报

发表于 2014-4-5 21:05:38 | 显示全部楼层
whmn 发表于 2013-9-21 20:36
不行啊     这句有错啊   1.01的ide,
IRrecv irrecv(RECV_PIN);   // 定义IRrecv 对象来接收红外线信号
...

因为你少了一个红外接受的库。论坛精华教程里有
回复 支持 反对

使用道具 举报

发表于 2015-5-7 08:31:38 | 显示全部楼层
楼主 可以分享一下一个按键控制音乐播放的代码么 求指点
回复 支持 反对

使用道具 举报

发表于 2015-5-8 19:57:53 | 显示全部楼层
大神 能指点一下只用一个按键控制音乐播放么
回复 支持 反对

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-28 23:26 , Processed in 0.047815 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表