No Code AI(肉寇)AI自動化兩日精通|實體6小時+線上6小時
|

用Ameba打造WiFi控制的MP3 Player

   

作者:賴桑

為了讓Ameba能廣泛運用,我hack了十幾年前市面上常見的MP3 Player,進一步將MP3 Player改裝成:可藉由WiFi進行點歌的裝置;這樣的系統除了可以運用在娛樂上,也能用於家庭監控與防盜上,而且價格只要幾百元台幣就可以取得這樣的模組,既簡單又方便。

使用材料

  • Grove – Serial MP3 Player
  • Grove – LCD RGB Backlight
  • MicroSD卡一片(如果電腦沒辦法直接讀取,請添購讀卡機)
  • 杜邦跳線
  • 圓形針頭跳線 (公-公)

構型說明

用Ameba打造WiFi控制的MP3 Player構型

用Ameba打造WiFi控制的MP3 Player構型

Ameba操作說明

Ameba操作說明

所有模組都用Ameba的5V,與GND直流電力,另外,建議在5V對GND間,掛接一個電解質電容穩壓,以免有時USB供電不穩,發生掉電Brown-out的現象。

原始程式碼


#include
#include
#include "rgb_lcd.h"
#include "WiFiServer1.h"

#define mp3  Serial1

#define PORT 5000

char ssid[] = "AndroidAP1B3F";     // the name of your network
char pwd[] = "t101419008";        //The password of your AP
int status = WL_IDLE_STATUS;     // the Wifi radio's status

WiFiServer1 server(PORT);
WiFiClient1 client;

int playIndex = 1;
int volumn = 0x0E;
int playMode = 1;

rgb_lcd lcd;

const int colorR = 0;
const int colorG = 0;
const int colorB = 128;

void setup() {
  // put your setup code here, to run once:
  mp3.begin(9600);
  mp3.setTimeout(500);

  Serial.begin(9600);
  delay(100);
  if (true ==SetPlayMode(0x01))
    Serial.println("Set The Play Mode to 0x01, Single Loop Mode.");
  else
    Serial.println("Playmode Set Error");

  PauseOnOffCurrentMusic();

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);  
  lcd.setRGB(colorR, colorG, colorB);
  lcd.print("Ameba MP3 player");
 
  status = WiFi1.begin(ssid, pwd);
  if ( status != WL_CONNECTED) {
    lcd.print("    No WiFi     ");
    // don't do anything else:
    while(true);
  }
  else {
    delay(3000);
    IPAddress ip = WiFi1.localIP();
    lcd.setCursor(0, 1);
    lcd.print("S");      //Show server IP
    lcd.print(ip);
    server.begin();
  }

  delay(1000);
}

char buffer[3];

void loop() {
  // put your main code here, to run repeatedly:
  // check the network connection once every 10 seconds:
  // listen for incoming clients
  int n;

  client = server.available();
 
  if(client)
  {
    lcd.setCursor(0, 0);
    lcd.print("C               ");
    lcd.setCursor(1, 0);
    lcd.print(client.get_address());
    lcd.setRGB(128, 128, 0);
 
    if(client.available())
    {
      n = client.read((uint8_t*)(&buffer[0]), sizeof(buffer));
      n = server.write(buffer, n);
      Serial.println(buffer);
     
      switch(buffer[0])
      {
        case 'P':
        case 'p':
          playIndex = buffer[1] - 0x30;
          SetMusicPlay(highByte(playIndex), lowByte(playIndex));
          delay(1000);
          break;
        case 'M':
        case 'm':
          playMode = buffer[1] - 0x30;
          SetPlayMode(playMode);
          delay(1000);
          break;
        case '+':
          volumn++;
          SetVolume(volumn);
          break;
        case '-':
          volumn--;
          SetVolume(volumn);
          break;
      }
      buffer[0] = buffer[1] = buffer[2] = 0;
     
      client.stop();
    }
  }
}

//Set the music index to play, the index is decided by the input sequence
//of the music;
//hbyte: the high byte of the index;
//lbyte: the low byte of the index;
boolean SetMusicPlay(uint8_t hbyte,uint8_t lbyte)
{
    mp3.write(0x7E);
    mp3.write(0x04);
    mp3.write(0xA0);
    mp3.write(hbyte);
    mp3.write(lbyte);
    mp3.write(0x7E);
    delay(10);
    while(mp3.available())
    {
        if (0xA0==mp3.read())
        return true;
        else
        return false;
    }
}
// Pause on/off  the current music
boolean PauseOnOffCurrentMusic(void)
{
    mp3.write(0x7E);
    mp3.write(0x02);
    mp3.write(0xA3);
    mp3.write(0x7E);
    delay(10);
    while(mp3.available())
    {
        if (0xA3==mp3.read())
        return true;
        else
        return false;
    }
}
 
//Set the volume, the range is 0x00 to 0x1F
boolean SetVolume(uint8_t volume)
{
    mp3.write(0x7E);
    mp3.write(0x03);
    mp3.write(0xA7);
    mp3.write(volume);
    mp3.write(0x7E);
    delay(10);
    while(mp3.available())
    {
        if (0xA7==mp3.read())
        return true;
        else
        return false;
    }
}
 
boolean SetPlayMode(uint8_t playmode)
{
    if (((playmode==0x00)|(playmode==0x01)|(playmode==0x02)|(playmode==0x03))==false)
    {
        Serial.println("PlayMode Parameter Error! ");
        return false;
    }
    mp3.write(0x7E);
    mp3.write(0x03);
    mp3.write(0xA9);
    mp3.write(playmode);
    mp3.write(0x7E);
    delay(10);
    while(mp3.available())
    {
        if (0xA9==mp3.read())
        return true;
        else
        return false;
    }
}

基本解說

Grove LCD RGB Backlight與Ameba間,透過I2C通訊,而Grove Serial MP3 player與Ameba間,是以Serial通訊;另外,Serial MP3 player上面主要是一個WT5001的晶片,WT5001這枚晶片就是當年MP3 player風行一時的時代,常被用於MP3 player的主晶片,同時也具有SPI以及SD卡的存取功能。

程式一開始以Serial1 來跟Grove Serial MP3 Player建立通訊管道,並且以protocal跟WT5001進行溝通;系統會先以Single Mode的方式撥出SD卡上的一首歌曲,當系統登入WiFi後,會於LCD上顯示目前取得的IP,目前程式固定埠號為5000;當使用者透過像是Telnet等終端服務登入Ameba後,就可以輸入對應的字元、字串,控制MP3 player的歌曲撥出效果。

結語

透過「無線通訊控制音效撥出」這樣的功能本來就常見於目前日常生活的娛樂設備上,這次運用Ameba打造的WiFi控制MP3 Player,只要所錄製的MP3檔案具有警示音效,就能在出門的時候當作警示器,甚至用於電話上語音留言的撥出。

而Ameba的下一代版本,據瑞昱半導體表示,將會特別強調影音串流管理效果,事實上,由於Ameba是以ARM Cortex系列為基礎進行開發的,這效果相信是可以辦到的!我個人非常期待新一代具有影音串流管理效果的Ameba,到時候當然也會想辦法到手,寫寫開箱文與大家分享。

賴建宏

訂閱MakerPRO知識充電報

與40000位開發者一同掌握科技創新的技術資訊!

Author: 賴建宏

社群稱號為「賴桑」的他,以電子電機的背景,熱衷於OSHW的應用開發與實作。取得台北科技大學電子所博士學位,目前主推「農林漁牧大業」計畫的迷你型魚菜共生系統開發。

Share This Post On
468 ad

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *