質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

mbedでMP3モジュールへシリアル通信

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 5,470

score 43

前提・実現したいこと

mbedでGrove MP3モジュール v2へシリアル通信をして、
mp3を再生したいと思ってプログラミングをしているのですが、どのように信号を送ればいいのかわかりません。
そのモジュールに使われているMP3チップはKT403Aという名前で、
マニュアルや、個人のサイトを見てみましたが、わかりませんでした。

「7E FF 06 0F 00 63 FF EF」と送るとSDカード内の「255(適当な名前)」というファイル名の音声ファイルが再生されるようなのですが…

#include "mbed.h"

Serial mp3(USBTX, USBRX);
int main() {
    mp3.baud(9600);
    mp3.printf("ここに数字か何かを入れるのだろうけども、書式がわからない");
}

補足

  1. シリアル通信の書式についていろいろ調べてみましたが、全て文字の送り方でした…
  2. モジュール自体はArduino用のようですが、秋月の店員さん曰く使えるそうです。ケーブルの配線はちゃんとしました。

更新 17/07/03

コードはμvisionで書いており、通信にはTera Termを使っています

以下のコードで行ってみましたが音声が再生されず、~と出てきます。なぜでしょうか。検索してもわかりませんでした。検索の方法が悪かったのかもしれませんが…

なお、以下のコードは、コマンド0F(フォルダーとトラック番号を指定して再生)で、01フォルダの01ファイルを再生しようとしています。

#include "mbed.h"
#include "stdint.h"
Serial mp3(P1_7, P1_6);//P1_7はtx,P1_6rxです。
int main() {
    int idx;
    mp3.baud(9600);
    uint8_t send_data[] =  {0x7E, 0xFF, 0x06, 0x0f, 0x00, 0x01, 0x01, 0xEF};
    for(idx = 0; idx < sizeof(send_data); idx++) {
        mp3.putc(send_data[idx]);
    }

}

更新 17/07/03 20:59

配線はTX同士、RX同士でつないでます。もしやそこがダメだったのでしょうか。
同じ名前同士でつないでおけばいいかなと思ってました。
雄と雌的な接続の考え方の方だったならばつなぎ替えます。こんな間違いをやらかすぐらいには初心者です。

マイコンは仕様的にピン接続?につないでいるときはUSB側とは不通になるそうなのですけども…詳しくは知りません。

更新 17/07/03 22:03

TXをRXにRXをTXに接続しました。前回よりノイズが減ったように感じられますが、相変わらず~と出てきます。

更新 17/07/10 15:43

nullbot氏の提言を試すため教授にmbed互換基盤の仕様を聞いたところ、
「シリアルで送るとPCにもモジュールにも信号が行く」とのことなのでモジュールはどうやら信号を受信できているようです。しかしそうなるとどうして再生されないのか…

更新 17/07/18 00:42

ozwk氏の案

MP3モジュールのTxはどこにも結線せず
MP3モジュールのRxはmbedのTxに結線

を試してみましたが変化はありませんでした。
あと、

MP3モジュールのリセットをmbedの適当なGPIOに接続し、
mbedのプログラムでMP3モジュールにコマンド送る前にMP3モジュールのリセットかけて
適当な時間待ってからコマンド送信するように変更

の方はモジュールのリセット部分がどこか掴めず試せずにいます。

モジュールの生存確認を友人氏のmbedを借りて行いました。両方とも同じコードで同じ反応。
これは生か死か。

再生デバイスの選択コマンドも使ってみましたが音沙汰なし。

#include "mbed.h"
#include "stdint.h"
Serial mp3(P1_7, P1_6);
int main() {
    int idx;
    mp3.baud(9600);
    uint8_t set_device[]    = {0x7E, 0xFF, 0x06, 0x09, 0x00, 0x00, 0x02, 0xEF};//準備
    uint8_t set_music[]    = {0x7E, 0xFF, 0x06, 0x0f, 0x00, 0x01, 0x01, 0xEF};//再生
        wait(1);
        for(idx = 0; idx <sizeof(set_device); idx++) {
                mp3.putc(set_device[idx]);
        }        
        wait(1);
        for(idx = 0; idx <sizeof(set_music); idx++) {
                mp3.putc(set_music[idx]);
        }

}

17/07/18 補足

MP3のサンプリングレートが対応ということはないと思います。

・ファイルシステム:FAT16/FAT32
・オーディオフォーマット:MP3、WAV、WMA
・SDカード最大対応容量:32GB
・サンプルレート(KHz):8/11.025/12/16/22.05/24/32/44.1/48

これだけの幅ならまず外れないと思いますし...

mbed←→MP3モジュール のケーブルをもう一度点検しましたが、やはり間違っていません。過去の間違い(TXRX)は修正済みです。

17/08/04 追記

MP3モジュールへのシリアル通信ですけども実はこれ大学のロボット製作チャレンジで音声を流したく質問した物なのです。しかしそれの期限がもう過ぎてしまったのでこれはあきらめて音声再生無しで実装しました。

期限までに実装できずに終わってしまったのですが、この質問はどうしておけばいいでしょうかね?
後日頑張って解決するまで取っておくか、それとも…

なお、ozwkさんの助言

電源5Vにしてみるとか
ソフトウェアシリアルのライブラリ使ってMP3モジュールと通信するとか

は後日試行の予定です。

17/08/04 追記2

電圧足りてないぞこれ。今の今まで気付かなんだ。もしや…このせいでは。
要5.0VDC
出3.3VDC
別電源から引っ張ってくるか...?
ほかの出力端子3.3VDCと直列につないで6.6VDCにして抵抗噛まして5VDCにするって邪道ですかね

17/09/18 終焉

皆様お久しぶりです。マシンが手元にある環境に戻ってまいりましたので、さっそくモジュールの電源の5V化を行いました。
無事鳴りました。

mbed本体とつなぐケーブルの電源部を切り、別途用意した5V電源(単3エネループx4直列)につないで、
「更新 17/07/03」のコードを実行したところ、何事もなかったように鳴りました。

助言をいただいた皆様本当にありがとうございました。今度からはしっかりと抜かりなく仕様書を読みます。

20/10/29 追記

ラズパイ経由で改めてこのモジュールを使用しようと思ったので、古くなったリンクの更新とともに参考サイト追加
http://www.ne.jp/asahi/shared/o-family/ElecRoom/AVRMCOM/MP3module/MP3module.html

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ozwk

    2017/07/10 16:11

    とりあえずTeratermに~が出るのはその接続だと特に不思議ではないです。mbedが送信している{0x7E,...}の0x7EはAsciiコードで~ですので。

    キャンセル

  • yumetodo

    2017/09/23 03:18

    解決お疲れ様です、が、そういうことは回答欄に書き込んで解決済みにしたほうがいいです、はたから見て解決しているかわからないので

    キャンセル

  • Kazumori102

    2017/09/23 09:13

    なるほど。

    キャンセル

回答 3

+4

Serialクラスでどうやってバイナリデータを送るかってことですよね。
ドキュメント日本語
ドキュメント英語

日本語と英語で内容が全く違う・・・。

serial.putc()を使ってください。serial.writeも使えそうですが、比較的新しいAPIのようで、デバイスによってはサポートされないとのコメントを見かけました。

uint8_t send_data[] = {0x7E,0xFF,0x06,0x0F,0x00,0x63,0xFF,0xEF};

int idx;
for(idx = 0; idx < sizeof(send_data); idx++) {
    mp3.putc(send_data[idx]);
}

2017/7/3 追記

回路図をみるとLPC1114の47番ピン(PIO1_7)はLPC1114側から見てTXD, 46番ピン(PIO1_6)はLPC1114側から見てRXDです。
Grove UARTは1番ピンがGroveモジュール側からみてRX, 2番ピンがGroveモジュール側からみてTXです。

問題はLPC1114にはUART用のコネクタが出ていますが、謎のUSBシリアル変換ICとwired orになっていることです。
UARTはバス接続は出来ないので基本的に一対一で接続する必要がありますが、この基板ではジャンパなどで切り離せるような設計にはなっておらず、USBシリアルICを物理的に切り離すことができません。よってUARTポートが2つある基板に買い換えるのが良いかと思います。(無理にパターンカットすると書き込めなくなってしまいますし。)

もしかしたらUARTシリアルのICにTX,RXをハイインピーダンスにする機能があり回路的に切り離せるのかもしれませんが、ICの型番すらわからないためなんとも言えません。

もう一つ可能性があるとすれば入力ポートは一般的にハイインピーダンスなのでUSBシリアル変換のICのRXとGrove MP3モジュールのRXだけはwired orでもいけるかもしれません。(LPC1114側から一方的にデータを送りつけるだけなら大丈夫かもしれない)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/04 08:36

    データシートが置いてあるので
    UART<->USB変換は多分FT231Xっぽいですね

    キャンセル

  • 2017/07/04 10:17

    > ozwkさん
    ドキュメントありがとうございます。

    > Kazumori102さん
    FT231XのドキュメントのP23にreset時はUARTのIOはトライステートだと書かれているのでFT231XのRESETピンをlowにしてやれば回路的に切り離すことができ、LPC1114とGroveモジュールが一対一で接続できます。

    ただし回路図上はFT231Xはresetピンに#RESETというラベルだけ貼られていてLPC1114やスイッチなどに接続されていないように見えます。なのでは結局1対1で接続するに基板の改造が必要です。

    キャンセル

  • 2017/09/23 09:13

    解決しました。ご協力ありがとうございました

    キャンセル

checkベストアンサー

+2

Arduinoですが、公式Wikiによれば叩くためのライブラリとして

があります。これはArduinoのSoftwareSerial::write(),SoftwareSerial::available(),SoftwareSerial::read()のみで実装されています。

mbedでこれに相当するのはStream::write(),Serial::readable(),Stream::read()かと思います(StreamSerialのbase class)。ただしStream::write()SoftwareSerial::write()とちがい長さを指定できるので、MP3Player_KT403A.cppの実装のように何度もwrite()を呼び出す必要はないでしょう。

つまり上述ライブラリをパクればいいと思います。Stream::write()には上記ライブラリで渡していたバイナリ列をそっくりそのまま含むstd::uint8_t型配列を指定すればいいと思います。

・・・まあここまで書いて何ですが、私は組み込み開発って一回もやったこと無いんですけどね。でもArduinoとmbedの実装読む限りではそうだと思います。

ref:

 追記

うーん、本当に書き換えはほぼCの範囲なんだけどなぁ・・・

void SpecifyfolderPlay(uint8_t folder, uint8_t index)
{
    mp3.write(0x7E);
    mp3.write(0xFF);
    mp3.write(0x06);
    mp3.write(0x0F);
    mp3.write(uint8_t(0x00));
    mp3.write(uint8_t(folder));
    mp3.write(uint8_t(index));
    mp3.write(0xEF);
    delay(10);
//  return true;
}

例えばこんな関数がありますが、

#include "mbed.h"
#include <cstdint>

template <class T, size_t N>
constexpr size_t size(const T (&)[N]) noexcept { return N; }

using uint8_t = std::uint8_t;

void SpecifyfolderPlay(uint8_t folder, uint8_t index)
{
    const uint8_t out[] = { 0x7E, 0xFF, 0x06, 0x00, folder, index, 0xEF };
    mp3.write(reinterpret_cast<const char*>(out), size(out));
    wait_ms(10);
}

こんな感じになるんじゃないですかね~、あくまでイメージですが。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/01 23:18

    素早く詳細な回答をしていただきありがとうございました。

    実は私はまだCしか習っていないのでちょっとC++の書き方はちんぷんかんぷんなのです。もしよろしかったら紹介していただいた関数の使い方をコメントアウトで詳細を説明しつつコードを書いていただいたりできませんでしょうか?お手数掛けます。

    キャンセル

  • 2017/07/01 23:20

    え、無理です。組み込み開発の開発環境を持っていませんので。
    http://qiita.com/yumetodo/items/e49a673afd9a3ecb81a8
    http://qiita.com/yumetodo/items/b0ff58617f2733d4ffa1
    この辺を見て勉強してください。

    キャンセル

  • 2017/07/01 23:21 編集

    C++そのものについての質問であればTwitter: @yumetodoに投げていただければ回答しますが、上記ライブラリの置き換えと言うのはほとんどCの範疇ですのでこれくらいできないで組み込み開発とか言われてもちょっと・・・となります。

    キャンセル

  • 2017/09/23 09:13

    解決しました。ご協力ありがとうございました

    キャンセル

+2

MP3モジュールのTxはどこにも結線せず
MP3モジュールのRxはmbedのTxに結線

これでもダメなら
MP3モジュールのリセットをmbedの適当なGPIOに接続し、
mbedのプログラムでMP3モジュールにコマンド送る前にMP3モジュールのリセットかけて
適当な時間待ってからコマンド送信するように変更してみてください。

初期のころのT/RXの結線間違いや
UART変換モジュールのTxとMP3モジュールのTxを決戦したことで
端子ショートして死んだ可能性もあるので、
本当はシリアル2つ持ってるマイコンボードかなんかで
MP3モジュールの生存確認から始めたほうがいいんですが。

あとT/RXの結線間違いからして
他をちゃんと接続できているかも怪しいですし。


上で色々書きましたが、

「7E FF 06 0F 00 63 FF EF」と送るとSDカード内の「255(適当な名前)」というファイル名の音声ファイルが再生されるようなのですが… 

とありますがデータシート読む限りこれはフォルダ63のファイル255の再生です。
フォルダ63あります?

あと再生デバイスの選択コマンドも存在して、
デフォルトがSDカードかどうか不明なので
そこら辺ちゃんと設定した方がいいと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/18 11:28 編集

    電源5Vにしてみるとか

    ソフトウェアシリアルのライブラリ使って
    MP3モジュールと通信するとか

    キャンセル

  • 2017/08/04 16:47

    > ほかの出力端子3.3VDCと直列につないで6.6VDCにして抵抗噛まして5VDCにするって邪道ですかね

    邪道も何も、
    > 3.3VDCと直列につないで
    どうやって?

    > 抵抗噛まして5VDC
    無理です。分圧点から電流を引き出す時点で電圧変わってしまいます。

    キャンセル

  • 2017/09/23 09:13

    解決しました。ご協力ありがとうございました

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る