极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 30021|回复: 10

急!关于使用Arduino来播放SD卡里的音乐的问题

[复制链接]
发表于 2013-6-23 00:26:31 | 显示全部楼层 |阅读模式
原帖:
http://www.geek-workshop.com/thread-2611-1-1.html
我是个刚学Arduino板的新人,学校里的老师上课都让我们自学的,所以有很多不懂的地方
上面这个很棒的实例我已经实验过,而且成功了,但是我想做进一步的改动,却不知道如何下手。
比如说,这个实验是要通过串口发送指令才能让扬声器播放音乐,要怎样才能做到不使用串口就让它播放音乐?
(最好能使用电池作为电源,而不是连接在电脑上)
另外,我还想通过添加人体感应模块实现当有人接近时播放音乐,远离时又停止播放,这个是否能实现,如果能的话要怎么做?
我是用的是arduino uno R3的板子,人体感应模块的型号是HC-SR501。
求各位大神指点。
如果真心无法实现,也希望各位提一提意见,把这个例子能改成一个带有一定交互性质的作品,谢谢大家了~
回复

使用道具 举报

发表于 2013-6-23 09:44:25 | 显示全部楼层
我想你已经试验过SD-MP3的播放程序,和人体感应模块的程序了吧,那应该对Arduino已经有所了解了。可以把两个程序拼接起来,Arduino程序分成三部分,定义,setup()和loop()部分,将2部分程序一一对应,先校验下,防止拼接过程中有失误。然后根据你的设想将人体感应到的反应,去替代通过串口发送的串口指令P。对于SD-MP3程序部分需要修改打开想播放MP3的文件,这部分可以在setup()里,也可以在loop(),接到人体感应后先打开文件再播放。两端文件没有读过,以上想法仅供参考。
回复 支持 反对

使用道具 举报

发表于 2013-6-23 09:50:43 | 显示全部楼层
这个学习后递进的想法很好,很有创意。对于摆脱USB的想法也很好,在调试过程中USB起到PC和Arduino通讯作用和供电双重作用,在程序调试完成后,程序下载了能独立正确运行了,就可以离开USB,当然Arduino需要电池供电了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-6-23 10:59:58 | 显示全部楼层
林定祥 发表于 2013-6-23 09:44
我想你已经试验过SD-MP3的播放程序,和人体感应模块的程序了吧,那应该对Arduino已经有所了解了。可以把两个 ...

谢谢你的回答,让我又多了一个新的思路,不过不精通语言是我的硬伤啊……
人体感应模块里感应到人的时候loop()部分的语句是这样的
int in = digitalRead(ledpin);
  Serial.println(in); //有人的时候输出高电平1 无人0
  delay(2000);
所以我一开始的设想是让播放音乐的部分不停地循环播放,无人时,电平低所以不会有声音,出现人时电平高,开始发声,但是这样的想法的难点就在于怎样让它不停地发出指令p(默认SD卡中只有一个文件)

你给我的想法我觉得也非常好,比我的靠谱多了的样子,但这样对我来说难点就在怎样将人体感应到的反应,去替代通过串口发送的串口指令P

其实主要还是代码的问题啊……刚接触这个只懂一些基本的语句,真心改不起来……

以下是SD卡播放音乐的代码:

#include <SimpleSDAudio.h>

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

char AudioFileName[16];

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

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

void setup()
{

// Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  
  Serial.print(F("Free Ram: "));
  Serial.println(freeRam());
  
  // Setting the buffer manually for more flexibility
  SdPlay.setWorkBuffer(bigbuf, BIGBUFSIZE);
  
  Serial.print(F("\nInitializing SimpleSDAudio V" SSDA_VERSIONSTRING " ..."));  
  
  // If your SD card CS-Pin is not at Pin 4, enable and adapt the following line:
  SdPlay.setSDCSPin(10);
  
  // Select between SSDA_MODE_FULLRATE or SSDA_MODE_HALFRATE (62.5kHz or 31.25kHz)
  // and the output modes SSDA_MODE_MONO_BRIDGE, SSDA_MODE_MONO or SSDA_MODE_STEREO
  if (!SdPlay.init(SSDA_MODE_FULLRATE| SSDA_MODE_MONO
)) {
    Serial.println(F("initialization failed. Things to check:"));
    Serial.println(F("* is a card is inserted?"));
    Serial.println(F("* Is your wiring correct?"));
    Serial.println(F("* maybe you need to change the chipSelect pin to match your shield or module?"));
    Serial.print(F("Error code: "));
    Serial.println(SdPlay.getLastError());
    while(1);
  } else {
    Serial.println(F("Wiring is correct and a card is present."));
  }
  

}


void loop(void) {

  uint8_t count=0, c, flag;
  
  Serial.println(F("Files on card:"));
  SdPlay.dir(&DirCallback);

ReEnter:
  count = 0;
  Serial.println(F("\r\nEnter filename (send newline after input):"));
  do {
    while(!Serial.available()) ;
    c = Serial.read();
    if(c > ' ') AudioFileName[count++] = c;
  } while((c != 0x0d) && (c != 0x0a) && (count < 14));
  AudioFileName[count++] = 0;
  
  Serial.print(F("Looking for file... "));
  if(!SdPlay.setFile(AudioFileName)) {
    Serial.println(F(" not found on card! Error code: "));
    Serial.println(SdPlay.getLastError());
    goto ReEnter;
  } else {
   Serial.println(F("found."));
  }   

  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."));
  flag = 1;
  
  while(flag) {
    SdPlay.worker();
    if(Serial.available()) {
      c = Serial.read();
      switch(c) {
         case 's':
           SdPlay.stop();
           Serial.println(F("Stopped."));
           break;
           
         case 'p':
           SdPlay.play();
           Serial.println(F("Play."));
           break;
           
         case 'h':
           SdPlay.pause();
           Serial.println(F("Pause."));
           break;   
   
         case 'd':
           SdPlay.deInit();
           Serial.println(F("SdPlay deinitialized. You can now safely remove card. System halted."));
           while(1) ;
           break;  
            
         case 'f':
           flag = 0;
           break;
     
         case 'v':
           Serial.print(F("Status: isStopped="));
           Serial.print(SdPlay.isStopped());
           Serial.print(F(", isPlaying="));
           Serial.print(SdPlay.isPlaying());
           Serial.print(F(", isPaused="));
           Serial.print(SdPlay.isPaused());
           Serial.print(F(", isUnderrunOccured="));
           Serial.print(SdPlay.isUnderrunOccured());
           Serial.print(F(", getLastError="));
           Serial.println(SdPlay.getLastError());
           Serial.print(F("Free RAM: "));
           Serial.println(freeRam());
           break;      
      }
    }
  }
  
  
}
回复 支持 反对

使用道具 举报

发表于 2013-6-23 13:28:55 | 显示全部楼层
你的人体传感器状态是in,而你的播放器的关键是c,原来loop中c=Serial.Read(),现在c=in就可以了,不过这个in需要有个转换,in是数字,c是字符,两边改一个与之匹配就好。至于0,1是STOP,PAUSE,PLAY就看你愿意怎么配了。试一下应该没有问题了,去实现你的愿望吧。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-6-24 08:56:29 | 显示全部楼层
林定祥 发表于 2013-6-23 13:28
你的人体传感器状态是in,而你的播放器的关键是c,原来loop中c=Serial.Read(),现在c=in就可以了,不过这个i ...

好的,谢谢,我来试试。
回复 支持 反对

使用道具 举报

发表于 2013-8-2 14:51:22 | 显示全部楼层
首先SdPlay.setFile(你要的音乐名字);,然后不断的判断in的状态,if(in==1){SdPlay.play();}这样应该就好了
回复 支持 反对

使用道具 举报

发表于 2013-8-7 12:32:30 | 显示全部楼层
whc2001 发表于 2013-8-2 14:51
首先SdPlay.setFile(你要的音乐名字);,然后不断的判断in的状态,if(in==1){SdPlay.play();}这样应该就好了

#include <SimpleSDAudio.h>

void setup()
{
  // If your SD card CS-Pin is not at Pin 4, enable and adapt the following line:
  // SdPlay.setSDCSPin(10);
  
  // Init SdPlay and set audio mode
  if (!SdPlay.init(SSDA_MODE_FULLRATE | SSDA_MODE_MONO)) {
    while(1); // Error while initialization of SD card -> stop.
  }
  
  // Select file to play
  if(!SdPlay.setFile("wb.AFM")) {
    while(1); // Error file not found -> stop.
  }   
  
  // Start playback
  SdPlay.play();
  
  // Let the worker work until playback is finished
  while(1) {
    SdPlay.worker();
  }
}


void loop(void) {
}
回复 支持 反对

使用道具 举报

发表于 2015-4-26 17:56:17 | 显示全部楼层
楼主 不知道你的这个控制音乐播放的代码弄好了么 可以分享一下么
回复 支持 反对

使用道具 举报

发表于 2015-4-26 20:55:51 | 显示全部楼层
void playSound(char * filename)
{
  
  if(!SdPlay.setFile(filename)) {
    Serial.println(F(" not found on card! Error code: "));
    Serial.println(SdPlay.getLastError());
    while(1); // loop forever
  } else {
   Serial.println(F("found."));
  }   
  int flag = 1;
  SdPlay.play();
  while(flag) {
    SdPlay.worker();
    if(SdPlay.isStopped()){
      break;
    }
  }

}
回复 支持 反对

使用道具 举报

发表于 2016-1-6 14:51:42 | 显示全部楼层
请问你的人体感应程序做好了吗? 求分享
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-8 03:32 , Processed in 0.041324 second(s), 24 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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