■作るもの
特定のICカードをかざしたら、そのICカードのIDに紐づくアルバムの曲を流すようにしたい。
幼児(3歳児)が直感的にわかるように、色んなイラストのICカードを用意し、それぞれに流す曲を変えられる音楽プレイヤーを作りたい。
- アンパンマンのイラスト →アンパンマンの曲が流れる
- ピカチュウのイラスト →ポケモンの曲が流れる
- ミッキーのイラスト →ディズニー曲が流れる
仕様:
- 電源:乾電池3本(単4×3)
- マイコン: Atmega328-pu(内部クロック動作)をArduino互換機として使う。
- RFIDリーダ: RC522※
- mp3プレイヤ: DFplayer mini (一応、互換品でも動く)
- 基盤:Kicadでプリント基板を設計し、PCB Wayで発注。
- スケッチの書き込み:Atemega328のRX,TXはUSBシリアル変換ケーブルを経由し、スケッチの書き込みを行う。
試作
いったん、PCB設計をする前にブレッドボードを使って挙動を確認する。
DFplayerのRXは、1kΩ等の抵抗を接続していないとノイズが入るため、注意したい。
また、DFpalyerは音量があまり大きくなければ3.3Vで動作することも確認したが、今後、大きい音を出すことも想定して、乾電池3本の電圧(4.5V程度)で動作させたい。
(単三電池2本の場合は3.3Vに昇圧して、DFplayerのソフトウェアシリアル経由で音量を低めにすれば音はでる。)

配線がグチャグチャなので、PCBにしないと色々とストレスが沸きそう・・・・。
回路図の作成
今回、初めてのPCB設計だった。
youtubeの動画を参考にしたりしてKicadを使って、回路図を書いてみる。
RC522はSPI接続(SS:D10, RST:D9)。DFPlayerはソフトウェアシリアル(TX:D2,RX:D4)をAtmega328の所定のPinに接続する。
特に、マイコンのRX,TX端子と、USBシリアル変換に接続する端子については間違えないようにしたい。(それぞれRX→TX, TX→RXにつながるように)
また、モバイルバッテリーからの給電ができるようにしたい。モバイルバッテリーは一定時間(30秒程度)の電流が流れていないと、給電を止めてしまうので、定期的に50mA程度電流を流す仕組みとしている(マイコンのデジタルピン(D7)をトランジスタのベースにつなぎ、ベース電流に流れたら、トランジスタのコレクタにつないだ抵抗に電流が流れるようにする)。
 
PCBの設計
回路図の設計が完了したら、いよいよPCBの設計に入る。
kicadに事前に登録したフットプリントを使って、パーツの設置場所を整える

パーツの設置、配線が終わったら3Dビューで表示することで、設計したもののイメージも表示できる。

プリント基板の発注
Kicadで設計したガーバーデータをPCB Wayにアップロードし発注。
キャンペーンをしていたので、5枚で5ドルだった。(30mm×70mm)
輸送コストがOCSで13ドル・・・。 (基板のコストよりも高い)
 
パーツ実装後のイメージ
個人的に、初めてにしては満足のいく仕上がりになった。
なにより、ゴチャとした配線が無くなるのが素晴らしい。
強いて言えば3端子レギュレータの足がPCBの穴に入りづらかった。この辺のフットプリントの考慮をもうちょっとしておくべきだった。

このピンソケットにRC522のピンヘッダを接続するイメージ。
■コード例
それぞれのイラストカードが書かれたICカードは、それぞれ固有のID(UID)がある。コード上ではUID1~4に応じた値が決まっているので、それをSPI接続により、マイコンが読み取り、UIDに応じた音楽をならせばよい。
#include "Arduino.h"
#include "SoftwareSerial.h"
#include <DFPlayer.h>
#include <SPI.h>
#include <MFRC522.h>
#define UID1 "xx xx xx xx" // 取得した識別子を記述
#define UID2 "xx xx xx xx" // 取得した識別子を記述
#define UID3 "xx xx xx xx" // 取得した識別子を記述
#define UID4 "xx xx xx xx" // 取得した識別子を記述
#define RST_PIN 9          // Configurable, see typical pin layout above
#define SS_PIN 10         // Configurable, see typical pin layout above
#define MP3_RX_PIN              2     //GPIO2 to DFPlayer Mini TX
#define MP3_TX_PIN              4     //GPIO4 to DFPlayer Mini RX
#define MP3_SERIAL_SPEED        9600  //DFPlayer Mini suport only 9600-baud
#define MP3_SERIAL_BUFFER_SIZE  32    //software serial buffer size in bytes, to send 8-bytes you need 11-bytes buffer (start byte+8-data bytes+parity-byte+stop-byte=11-bytes)
#define MP3_SERIAL_TIMEOUT      350   //average DFPlayer response timeout for GD3200B chip 350msec..500msec
// IO6をRX, IO7をTXとしてアサイン
SoftwareSerial mp3Serial(2, 4); 
DFPlayer       mp3;
MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
MFRC522::MIFARE_Key key;
void setup() {
 digitalWrite(8, HIGH);
 delay(4); 
 // mySoftwareSerial.begin(9600); //dfplayer initialization
  Serial.begin(115200);//Initailze Serial Communication
  
  //while (!Serial);    // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
  SPI.begin();      // Init SPI bus
  
  mfrc522.PCD_Init();   // Init MFRC522
  delay(4);       // Optional delay. Some board do need more time after init to be ready, see Readme
  mfrc522.PCD_DumpVersionToSerial();  // Show details of PCD - MFRC522 Card Reader details
  Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
  mp3Serial.begin(9600);
  mp3.begin(mp3Serial, MP3_SERIAL_TIMEOUT, DFPLAYER_HW_247A, false); //"DFPLAYER_HW_247A" see NOTE, false=no feedback from module after the command
  mp3.setVolume(8);                      //0..30, module persists volume on power failure
    
  dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
}
void loop() {
  //Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  //Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
       return;
  }
 String strBuf[mfrc522.uid.size];
    for (byte i = 0; i < mfrc522.uid.size; i++) {
      strBuf[i] =  String(mfrc522.uid.uidByte[i], HEX);
      if (strBuf[i].length() == 1) {
        strBuf[i] = "0" + strBuf[i];
      }
    }
    String strUID = strBuf[0] + " " + strBuf[1] + " " + strBuf[2] + " " + strBuf[3];
    if ( strUID.equalsIgnoreCase(UID1) ) {
      Serial.println("Detect UID1 Card");
      Serial.println(strUID);
      mp3.playTrack(1);    
    } else if ( strUID.equalsIgnoreCase(UID2) ) {
      Serial.println("Detect UID2 Card");
      Serial.println(strUID);
      mp3.playTrack(2);    
    } else if ( strUID.equalsIgnoreCase(UID3) ) {
      Serial.println("Detect UID3 Tag");
      Serial.println(strUID);
      mp3.playTrack(3);       
    } else if ( strUID.equalsIgnoreCase(UID4) ) {
      Serial.println("Detect UID4 Tag");
      Serial.println(strUID);
       mp3.playTrack(4);   
    } else {
      Serial.println("error!");
      Serial.println(strUID);
    }
}
/*Helper routien to dump a byte array as hex values to Serial.*/
void dump_byte_array(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  
}
}
参考にしたURL
