用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的現象。

原始程式碼


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#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,到時候當然也會想辦法到手,寫寫開箱文與大家分享。

賴建宏

Author: 賴建宏

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

Share This Post On

發表