勝手な電子工作・・

勝手なオリジナル電子工作に関する記事を書きます

続・入眠用MP3プレーヤーの製作(#4)

f:id:a-tomi:20210306154203j:plain

外出自粛でとかく運動不足。夜寝つきにくいことがあります。自作のスリープタイマー付きのMP3プレーヤーを使い始めてからは、30分のタイマーでつけておけば早く快適に眠れます。.夜中に目覚めても、また演奏を始めればOKです^^

つまり、思いのほか役にたっています!そして、家族のリクエストで追加を作りました。こちらは場所をとらないように、小サイズにカッコよく(?)まとめました(自画自賛)。自分用のは大きくて不格好のままでいいのですが^^;。3月はなにかと時間がとりにくい月ですが、週末が来たのでやっと記事に書きます。

「眠るための音楽」とか「快適に眠りにつく曲」とか「睡眠を誘う音楽」とか、適当な言葉でYouTubeを検索してみれば、そのための曲は今やてんこ盛りです^^; 今、世界中で需要が高いのでしょうかね。その中から自分に合いそうで、ダウンロード可能なものを選んでMP3にします。

ところで、市販のMP3プレーヤーにはスリープタイマー付きが未だに見当たらないよう(また、スピーカー付きのMP3プレーヤーはどれも充電タイプで、不精者には面倒)ですがどうなんでしょう?よって自作したわけで、これまでの記事に書いたDFPlayer miniという廉価なマイクロSDのMP3デコーダモジュールを、Arduino(ATmega328p)で動かしています。ところが、この小さなモジュールはシリアル通信でコントロールする場合ノイズが載りやすいため、それを避けて勝手な方法で動かしています。経緯は前の記事に書いたとおりです(右のカテゴリー欄のDFPlayer miniで前の3記事がご覧になれます)。

今回は最近の超小型スピーカーで、今年製の30㎜径3Wフルレンジを使いました。といってもAliExpressで2個で百円ほどでした^^; これに合わせてケースは次の小さくてカッコよい透明ケース。

f:id:a-tomi:20210306162604j:plain

f:id:a-tomi:20210306162705j:plain

かつて百均で入手したものですがなかなか丈夫で精密に、しっかりできています。さすがに本物の日本製。今でも同じものがあるかどうかわかりませんが(ネットで同等品を探したところ、形は少し違いますが、よさそうなのはちなみに1個200円ほどで見当たります)。

今回はどうせ作ならと、使っていなかったピンを曲のNext(Forward)とPrevious(Bakward)ボタンとして使える(使わなくてもよい)ようにしました。この記事の最後に掲げるプログラムもそのように改善しておきました。この製作ではそのプログラムを使っていますが、それらのボタンはつけていません。そのうちに別のに生かせるかと。そもそも長押し・短押しを使い分けるのは面倒ですから、必要とする場合は専用ボタンにするほうがいいですからね。

f:id:a-tomi:20210306163200j:plain

これに合わせて基板も、少しだけ模様替えしました。左下のところ。

f:id:a-tomi:20210306163645j:plain

今後の追加作成のために、まとめて3枚をCNCルーターで削りました。

f:id:a-tomi:20210306163819j:plain

30分ほどで3枚が削れました。銅箔面は次。

f:id:a-tomi:20210306163942j:plain

今回の生基板は、ベークライト(=紙フェノール樹脂)の材料がいかにも「私の原料は紙でした」という感じなのですが、こういう用途には特に問題ないですね^^;

f:id:a-tomi:20210306164119j:plain

ケースを次のように加工しました。小さなスピーカーを透明ケースに直接接着すると糊(ホットボンド)が見えて恰好わるそうですから、別に厚めの樹脂でバッフル板を作ってそれにとりつけることにしました。そうすると穴あけの手間はケースに加えてほぼ二重にかかりますがね^^;

f:id:a-tomi:20210306164431j:plain

そして組みあがりの基板をケースの底にとりつけたのが次。

f:id:a-tomi:20210306164623j:plain

そして組んでみたところが次です。まだゴミだらけですが。

f:id:a-tomi:20210306164714j:plain

ゴミやバリなどをとって下の写真が出来上がり。

f:id:a-tomi:20210306164914j:plain

今回も操作ボタンは電源と音声ボリュームの-と+だけで単純です。タイマーの設定やSDカードの交換は必要がごく少ないので蓋を開けて行いますが、それで十分ですね。我ながら小さく思い通りにできてよかったと思うわけです^^;

プログラムは次のように拡張と改善をしました。とはいってもライブラリーを特に使いませんので、ArduinoーUNOでの使用量はデータもプログラムも容量の1割以下です。

/********************************************************
   DFPlayer with Sleep-timer and Volume-control,
     without using any libraries for DFPlayer-mini.
       Initial version-01 (c)Jan.30,2021 Akira Tominaga
   How to operate:
     Insert micro SD with mp3 or wav files, in playing
     sequences. Maximum 255 files x 99 folders.
     Power off & on to re-play after the timer expired.
     15,30,45,60,75,90,& 105 minutes timer available.
     Buttons are volume-up, volume-down, and optional
     skip-forward & backward.
   Revisions:
     V02: Changed all pin assignments.     Feb.1,2021
     V02b: Added 15min timer switch        Feb.7,2021
     V03: Added skip-forward & backward    Mar.1,2021
 *****************************************************:**/
#define pBusy 15        // DFP BUSY pin, H when busy
#define Tmr15 12        // +15 min for sleep-timer (V02a)
#define Tmr30 11        // +30 min for sleep-timer 
#define Tmr60 10        // +60 min for sleep-timer
uint8_t vTsv = 0;       // save-a to detect timer changes
#define vol_D 5         // volume-down button
#define vol_U 8         // volume-up button
#define Fwd 3           // Forward button   *V03 added
#define Bkw 2           // Backward button  *V03 added
#define ledG  9         // led green for sleep-timer
#define IO1 17          // DFPIO1 short-on=<<,long-on=Vol-
#define IO2 16          // DFPIO2 short-on=>>,long-on=Vol+
#define sOn 100         // time (mS) for short-on
#define lOn 850         // time (mS) for long-on
#define chatrT 100      // chattering time to avoid
#define init_vol_D 15   // init. or ending # of vol.-downs 
unsigned long slpT = 0; // elapsed timer mS (large value)
#define stopOff 0       // stop signal is off
#define stopOn 1        // stop signal is on
uint8_t stopSig = stopOff; // initialize stop signal

void setup() {          // *** Arduino setup() ***
  pinMode (IO1, OUTPUT);
  digitalWrite(IO1, LOW);
  pinMode (IO2, OUTPUT);
  digitalWrite(IO2, LOW);
  pinMode (pBusy, INPUT);
  pinMode (Tmr15, INPUT_PULLUP);
  pinMode (Tmr30, INPUT_PULLUP);
  pinMode (Tmr60, INPUT_PULLUP);
  pinMode (vol_D, INPUT_PULLUP);
  pinMode (vol_U, INPUT_PULLUP);
  pinMode (Fwd, INPUT_PULLUP);    //  *V03 added
  pinMode (Bkw, INPUT_PULLUP);    //  *V03 added
  pinMode(ledG, OUTPUT);
  digitalWrite(ledG, HIGH); // show "I am awake"
  Serial.begin(9600);
  for (uint8_t i = 0; i < init_vol_D; i++) { // vol.down
    volDown();          // lower in the beginning
  }
  digitalWrite(ledG, LOW); // LED off
  Serial.println(F("DFP start"));
  playNext();           // start 1st music
  delay(300);           // delay before loop
}

void loop() {           // *** Arduino loop ***
  if (digitalRead(pBusy) == HIGH) { // if idle
    playNext();
  }
  if (digitalRead(vol_D) == LOW) { // vol.d button?
    while (digitalRead(vol_D) == LOW) {} // -released?
    volDown();          //  then decrease volume
  }
  if (digitalRead(vol_U) == LOW) { // vol.up button?
    while (digitalRead(vol_U) == LOW) {} // released?
    volUp();             // then increase volume
  }
  if (digitalRead(Fwd) == LOW) {  // Forward button?
    while (digitalRead(Fwd) == LOW) {} // released?
    skpFwd();            // then skip to forward file
  }
  if (digitalRead(Bkw) == LOW) {  // Backward button?
    while (digitalRead(Bkw) == LOW) {} // released?
    skpFwd();            // then skip to backward file
  } 
  setTmr();   // check and set sleep-timer
  delay(10);
}

/******************************
     User defined functions
 ******************************/
// *** Volume down as fnction volDown() ***
void volDown(void) {
  digitalWrite(IO1, HIGH);
  delay(lOn);           // long IO-on
  digitalWrite(IO1, LOW);
  Serial.println(F("Vol -" ));
  delay(chatrT);        // avoid double detect.
}
// *** Volume up as function volUp() ***
void volUp(void) {
  digitalWrite(IO2, HIGH);
  delay(lOn);           // long IO2-on
  digitalWrite(IO2, LOW);
  Serial.println(F("Vol +"));
  delay(chatrT);        // avoid double detect.
}
// *** Skip forward as function skpFwd() ***
void skpFwd(void) {     // *V03 added as optional
  digitalWrite(IO2, HIGH); // to skip to forward file
  delay(sOn);           // short IO2-on
  digitalWrite(IO2, LOW); // and off
  Serial.println(F("Fwd"));
  delay(chatrT);        // avoid double detect.
}
// *** Skip backward as function skpBkw() ***
void skpBkw(void) {     // *V03 added as optional
  digitalWrite(IO1, HIGH); // to skip to backward file
  delay(sOn);           // short IO2-on
  digitalWrite(IO1, LOW); // and off
  Serial.println(F("Bkw"));
  delay(chatrT);        // avoid double detect.
}
// *** Play the next as function playNext() ***
void playNext(void) {
  if (stopSig != stopOn) { // if not stop timing,
    digitalWrite(IO2, HIGH); // then play next, by
    delay(sOn);         // setting IO2-on
    digitalWrite(IO2, LOW); // for a short time
    Serial.println(F("Next file"));
    // wait for DFP action done
    while(digitalRead(pBusy) == HIGH){} 
  } else {
    Serial.println(F("Stopped"));
    while (true) {}   // and stop here
  }
}
// *** Set sleep-timer as function setTmr() ***
void setTmr(void) {
#define noSleep 2000000000 // 2 Billion mS (23days)
  static uint8_t vTmr;  // sleep-timer value (min)
  vTmr = 0;             // initialize static vTmr
  if (digitalRead(Tmr15) == LOW) { // if Tmr15 is set
    vTmr = vTmr + 15;   // then add 15 minutes
  }
  if (digitalRead(Tmr30) == LOW) { // if Tmr30 is set
    vTmr = vTmr + 30;   // then add 30 minutes
  }
  if (digitalRead(Tmr60) == LOW) { // if Tmr60 is set
    vTmr = vTmr + 60;   // then add 60 minutes
  }
  if (vTmr != vTsv) {   // if sleep-timer changed
    vTsv = vTmr;        // save it
    Serial.print(F("Timer(min)=")); // and show it
    Serial.println(vTmr);
  }
  static unsigned long lTmr = vTmr; // convert type
  slpT = lTmr * 60 * 1000 + 10000;  // mS val.+10sec
  if (vTmr == 0) {      // if no timer set,
    slpT = noSleep;     // then set a huge value
    digitalWrite(ledG, LOW); // and timer-LED off
  }
  if (vTmr > 0) {       // if sleep-timer set
    digitalWrite(ledG, HIGH); // timer-LED on
  }
  static unsigned long pTime;
  pTime = millis();     // get passed time
  if (slpT < pTime) {   // if timer expired,
    Serial.println(F("Timer expired"));
    digitalWrite(ledG, LOW); // timer-LED off
    for (uint8_t i = 0; i < init_vol_D; i++) {
      volDown();        // minimize volume
    }                   // power-off req'd afterward
    stopSig = stopOn;   // and set stop-sign on
  }
}
// *** End of program

 

以上、とりあえずご紹介まで。眠りにくい夜の入眠のお役に立てば幸いです。

 

©2021 Akira Tominaga, All rights reserved.