外出自粛でとかく運動不足。夜寝つきにくいことがあります。自作のスリープタイマー付きのMP3プレーヤーを使い始めてからは、30分のタイマーでつけておけば早く快適に眠れます。.夜中に目覚めても、また演奏を始めればOKです^^
つまり、思いのほか役にたっています!そして、家族のリクエストで追加を作りました。こちらは場所をとらないように、小サイズにカッコよく(?)まとめました(自画自賛)。自分用のは大きくて不格好のままでいいのですが^^;。3月はなにかと時間がとりにくい月ですが、週末が来たのでやっと記事に書きます。
「眠るための音楽」とか「快適に眠りにつく曲」とか「睡眠を誘う音楽」とか、適当な言葉でYouTubeを検索してみれば、そのための曲は今やてんこ盛りです^^; 今、世界中で需要が高いのでしょうかね。その中から自分に合いそうで、ダウンロード可能なものを選んでMP3にします。
ところで、市販のMP3プレーヤーにはスリープタイマー付きが未だに見当たらないよう(また、スピーカー付きのMP3プレーヤーはどれも充電タイプで、不精者には面倒)ですがどうなんでしょう?よって自作したわけで、これまでの記事に書いたDFPlayer miniという廉価なマイクロSDのMP3デコーダモジュールを、Arduino(ATmega328p)で動かしています。ところが、この小さなモジュールはシリアル通信でコントロールする場合ノイズが載りやすいため、それを避けて勝手な方法で動かしています。経緯は前の記事に書いたとおりです(右のカテゴリー欄のDFPlayer miniで前の3記事がご覧になれます)。
今回は最近の超小型スピーカーで、今年製の30㎜径3Wフルレンジを使いました。といってもAliExpressで2個で百円ほどでした^^; これに合わせてケースは次の小さくてカッコよい透明ケース。
かつて百均で入手したものですがなかなか丈夫で精密に、しっかりできています。さすがに本物の日本製。今でも同じものがあるかどうかわかりませんが(ネットで同等品を探したところ、形は少し違いますが、よさそうなのはちなみに1個200円ほどで見当たります)。
今回はどうせ作ならと、使っていなかったピンを曲のNext(Forward)とPrevious(Bakward)ボタンとして使える(使わなくてもよい)ようにしました。この記事の最後に掲げるプログラムもそのように改善しておきました。この製作ではそのプログラムを使っていますが、それらのボタンはつけていません。そのうちに別のに生かせるかと。そもそも長押し・短押しを使い分けるのは面倒ですから、必要とする場合は専用ボタンにするほうがいいですからね。
これに合わせて基板も、少しだけ模様替えしました。左下のところ。
今後の追加作成のために、まとめて3枚をCNCルーターで削りました。
30分ほどで3枚が削れました。銅箔面は次。
今回の生基板は、ベークライト(=紙フェノール樹脂)の材料がいかにも「私の原料は紙でした」という感じなのですが、こういう用途には特に問題ないですね^^;
ケースを次のように加工しました。小さなスピーカーを透明ケースに直接接着すると糊(ホットボンド)が見えて恰好わるそうですから、別に厚めの樹脂でバッフル板を作ってそれにとりつけることにしました。そうすると穴あけの手間はケースに加えてほぼ二重にかかりますがね^^;
そして組みあがりの基板をケースの底にとりつけたのが次。
そして組んでみたところが次です。まだゴミだらけですが。
ゴミやバリなどをとって下の写真が出来上がり。
今回も操作ボタンは電源と音声ボリュームの-と+だけで単純です。タイマーの設定や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.