勝手な電子工作・・

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

入眠タイマー付きMP3プレーヤーの製作(その3)

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

まさかこの単純な記事を3回にわたって書くとは思いませんでした。

前々回、前回からの続きですが、写真のような本番機をチョコッと作り試していましたら、なかなかいい感じなので書くことにしました。SN比も音質もとても良く、目的通りで眠りつくのも早い^^; ので、これが役立つ人がおられるかも。

操作部分は電源スイッチと、音量ダウンボタン、音量アップボタンのたった3つです。枕元近くに置くので、電源スイッチはトグルスイッチよりはスライドスイッチのほうが安全でよいでしょうね。

最初のうちは試しにマイクロSDに英語のセンテンスを沢山収容し、きっとこれならすぐに眠くなるだろうとやってみました。ところが30分たってもしっかり聞いてしまって眠くなりませんでした^^;。そこでタイマースイッチの15分を追加、設定が15分、30分、45分、60分、75分、90分、105分の7通りできるようにしました。

手直しした最終的なプログラムはこの記事の最後につけておきます。

この回路は「その2」と殆ど同じですが次です。

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



スリープタイマーがセットされていることを知らせるLED(緑)は、なるべく暗く点灯するようにRを大きめに設定してあります。

数日後から内容を入れ替えて、英語ではなく眠くなる音楽を選んで適当に入れてみました。ファイル名の順番に自動演奏されます。タイマーが来たら曲の途中でも音量がぐっと下がり、その曲が終わったら停止します。停止すると所用電流は小さいので、とくにパワーオフはしません。朝起きたらオフればよいわけで。

タイマーを45分にセットしていましたが、眠くなる音楽の場合はそんなに長い必要はありませんでした。30分で十分になりました^^;

単純な工作なのでどう作っても大丈夫でしょうが、以下、この場合の製作についてダラダラと書かせていただきます(といっても短いですが)。

基板は、50mmx50mmで次のようにデザイン(Top view=部品面から)。例によってはんだ用のランドなどは面倒なので省略し、早く作るのが優先でして^^

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

ソフトで変換した銅箔面の切削図(ツールパス)は次です。

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

毎度ですが、長年大事に使っているCNCルータでさっさと削ります。

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

次ができあがりの銅箔面。今回は比較的大きいので、アースはループを作らないようにしました。

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

表(部品面)は次です。

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


単純ですから、はんだ付けはすぐに終わりました。

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

きたないはんだ付けではありますが、一応電源を試験してとくに何も問題はない感じ。

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

ということで、使うスピーカーに見合うケースに組みこみました。秋月の次のケースです。

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

このケースは重く頑丈で箱鳴りの心配がない感じ。蓋もきっちりしまるのを選びました。容積は287mlあるので、ここで使っている小型フルレンジスピーカーなら、このほぼ密閉ボックスで問題が全くない感じです。

思いのほか大音量となるので、プログラムの最初で音量を実に15段階も下げてからスタートするようにしました。その分だけスタートが遅いですが、まあ入眠用ですからね^^

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

上の写真では、タイマーは30分にセットしてあります。

ついでですが、こういう基板をネジ穴なく取り付けるのに、次の「貼り付けボス」を使うとたいへん簡単で便利です。

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

この部品はケースにしっかり固定されますし、大きすぎる場合はニッパーで好きなように切れますので自由自在。

今回のマイコンの分担機能は単純なので、8ピンPICを使ってごく小さい基板でもできそうですね。回路のバリエーションも色々考えられますし。そして、近頃の超小型フルレンジスピーカーを使えばごく小さな箱でもできるわけです。そのうちにやってみます。

最後に、今回の製作に合わせた更新済プログラムをつけておきます。

 

/********************************************************
   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.
   Revisions:
     V02: Changed all pin assignments.     Feb.1,2021
     V02b: Added 15min timer switch        Feb.7,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 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(ledG, OUTPUT);
  digitalWrite(ledG, HIGH); // show that I waked-up
  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 volue
  }
  setTmr();   // check and set sleep-timer
  delay(50);
}

/******************************
     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.
}

// *** 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.