まさかこの単純な記事を3回にわたって書くとは思いませんでした。
前々回、前回からの続きですが、写真のような本番機をチョコッと作り試していましたら、なかなかいい感じなので書くことにしました。SN比も音質もとても良く、目的通りで眠りつくのも早い^^; ので、これが役立つ人がおられるかも。
操作部分は電源スイッチと、音量ダウンボタン、音量アップボタンのたった3つです。枕元近くに置くので、電源スイッチはトグルスイッチよりはスライドスイッチのほうが安全でよいでしょうね。
最初のうちは試しにマイクロSDに英語のセンテンスを沢山収容し、きっとこれならすぐに眠くなるだろうとやってみました。ところが30分たってもしっかり聞いてしまって眠くなりませんでした^^;。そこでタイマースイッチの15分を追加、設定が15分、30分、45分、60分、75分、90分、105分の7通りできるようにしました。
手直しした最終的なプログラムはこの記事の最後につけておきます。
この回路は「その2」と殆ど同じですが次です。
スリープタイマーがセットされていることを知らせるLED(緑)は、なるべく暗く点灯するようにRを大きめに設定してあります。
数日後から内容を入れ替えて、英語ではなく眠くなる音楽を選んで適当に入れてみました。ファイル名の順番に自動演奏されます。タイマーが来たら曲の途中でも音量がぐっと下がり、その曲が終わったら停止します。停止すると所用電流は小さいので、とくにパワーオフはしません。朝起きたらオフればよいわけで。
タイマーを45分にセットしていましたが、眠くなる音楽の場合はそんなに長い必要はありませんでした。30分で十分になりました^^;
単純な工作なのでどう作っても大丈夫でしょうが、以下、この場合の製作についてダラダラと書かせていただきます(といっても短いですが)。
基板は、50mmx50mmで次のようにデザイン(Top view=部品面から)。例によってはんだ用のランドなどは面倒なので省略し、早く作るのが優先でして^^
ソフトで変換した銅箔面の切削図(ツールパス)は次です。
毎度ですが、長年大事に使っているCNCルータでさっさと削ります。
次ができあがりの銅箔面。今回は比較的大きいので、アースはループを作らないようにしました。
表(部品面)は次です。
単純ですから、はんだ付けはすぐに終わりました。
きたないはんだ付けではありますが、一応電源を試験してとくに何も問題はない感じ。
ということで、使うスピーカーに見合うケースに組みこみました。秋月の次のケースです。
このケースは重く頑丈で箱鳴りの心配がない感じ。蓋もきっちりしまるのを選びました。容積は287mlあるので、ここで使っている小型フルレンジスピーカーなら、このほぼ密閉ボックスで問題が全くない感じです。
思いのほか大音量となるので、プログラムの最初で音量を実に15段階も下げてからスタートするようにしました。その分だけスタートが遅いですが、まあ入眠用ですからね^^
上の写真では、タイマーは30分にセットしてあります。
ついでですが、こういう基板をネジ穴なく取り付けるのに、次の「貼り付けボス」を使うとたいへん簡単で便利です。
この部品はケースにしっかり固定されますし、大きすぎる場合はニッパーで好きなように切れますので自由自在。
今回のマイコンの分担機能は単純なので、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.