입사한지 얼마되지 않은 나는 출근해서 8시 30분 땡! 되면 요즘 강조되는 TBM 활동으로 국민체조를 틀어 사무실 직원 전체가 모두 자리에서 일어나 국민체조를 진행한다. 이게 은근히 귀찮고 무엇보다 휴가때는 다른 분들께 부탁드려야 해서 번거롭기도 해서 ESP32를 활용해 자동화를 하고 싶다는 욕심이 생겼다.
1. 수동이었던 과거 방법
- 출근하여 노트북과 블루투스 스피커를 켠다.
- 노트북 소리를 무음으로 설정하고 스피커는 최대 음량으로 다이얼을 돌려준다.
- 국민체조 영상을 틀고 정지해둔다.
- 8시 30분이 되면 영상을 재생한다.
2. 실패한 자동화 계획
1) 계획
- ESP32 모듈과 DFplayer mini를 이용해 스피커에 연결하고 집에 있는 홈어시스턴트 서버 자동화로 8시 30분에 재생한다.
2) 방법
(1) 음원 편집
- 영상에서 음원을 추출한다(Audacity)
- 음원 음량을 키워주고 불필요한 소리를 제거한다.
- micoSD카드에 음원을 담아두고 DFPlayer mini 모듈에 넣어준다.
(2) 이어폰 단자 추출 및 배선
- 다이소에서 이어폰, 충전 케이블 젠더를 구매한다.
- 모듈을 부수어 3.5파이 이어폰 암젠더를 분리한다.
- 폭풍 납땜을 진행한다.
- ESP32의 TX2 – DFplayer mini RX(ESP32는 3.3v라 저항연결이 따로 필요 없다.
- ESP32의 RX2 – DFplayer mini TX
- ESP32 GND – DFplayer mini GND(그림상 오른쪽, 듣기로는 그래야 잡음이 없음)
- ESP32 VIN(USB 연결시 5v 출력) – DFplayer mini VCC(그림상 왼쪽 위)
- 3.5파이 4극 이어폰 기준으로 이어폰 암젠더를 대조하면서 포인트 찾고 DAC_L,R 연결
(3) ESP32 아두이노 코드
#include "DFRobotDFPlayerMini.h"
#include <WiFi.h>
#include <PubSubClient.h>
// Create the Player object
DFRobotDFPlayerMini player;
const char *ssid = "";
const char *password = "";
const char* ID = "speaker"; // Name of our device, must be unique
const char* TOPIC = "office/Speaker/Status";
const char* INTOPIC = "office/Speaker/Set";
const char* mqttUser = "";
const char* mqttPassword = "";
const char* broker = "";
char messages[50];
WiFiClient wclient;
PubSubClient client(wclient);
// Connect to WiFi network
void setup_wifi() {
Serial.print("\nConnecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
if (WiFi.status() != WL_CONNECTED) {
return;
}
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
client.setServer(broker, 1883);
client.setCallback(callback);
reconnect();
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Received messages: ");
Serial.print(INTOPIC);
String msg = "";
for(int i=0; i<length; i++){
Serial.println((char)payload[i]);
msg += (char)payload[i];
}
Serial.println(msg);
if (msg == "play") {
player.play(1);
delay(100);
}
// Reconnect to client
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(ID, mqttUser, mqttPassword)) {
Serial.println("connected");
Serial.print("Publishing to: ");
Serial.println(TOPIC);
Serial.println('\n');
client.subscribe(INTOPIC);
GetReq(api);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println("\n try again in 5 seconds");
// Wait 5 seconds before retrying
//delay(5000);
}
}
}
void setup() {
// Init USB serial port for debugging
Serial.begin(115200);
// Init serial port for DFPlayer Mini
Serial2.begin(9600); //ESP32의 Tx Rx 시리얼 통신 연결
pinMode(5, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
delay(1000);
//delay(1000);
//Start communication with DFPlayer Mini
if (player.begin(Serial2)) {
Serial.println("OK");
//Set volume to maximum (0 to 30).
player.volume(0);
// Play the first MP3 file on the SD card
//player.play(1);
} else {
Serial.println("Connecting to DFPlayer Mini failed!");
player.reset();
player.readState();
}
if (player.available()) {
printDetail(player.readType(), player.read()); //Print the detail message from DFPlayer to handle different errors and states.
}
delay(100);
setup_wifi(); // Connect to network
client.setServer(broker, 1883);
client.setCallback(callback);
}
void loop() {
Serial.print(sec);
if (WiFi.status() != WL_CONNECTED) {
delay(10);
Serial.println("와이파이 연결중 ");
wifiC = false;
if (WiFi.status() == WL_CONNECTED) {
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
}
if (WiFi.status() == WL_CONNECTED && wifiC == false) {
Serial.println();
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
}
client.loop();
if (player.available()) {
printDetail(player.readType(), player.read()); //Print the detail message from DFPlayer to handle different errors and states.
}
int value = Serial.parseInt();
if (value == 1){
player.volume(29);
player.play(1);
} else if (value == 2) {
player.pause();
player.volume(0);
} else if (value == 3){
player.volume(29);
player.start();
Serial.println("3");
} else if (value == 4){
player.volume(29);
player.start();
}
}
void printDetail(uint8_t type, int value){
switch (type) {
case TimeOut:
Serial.println(F("Time Out!"));
break;
case WrongStack:
Serial.println(F("Stack Wrong!"));
break;
case DFPlayerCardInserted:
Serial.println(F("Card Inserted!"));
break;
case DFPlayerCardRemoved:
Serial.println(F("Card Removed!"));
break;
case DFPlayerCardOnline:
Serial.println(F("Card Online!"));
break;
case DFPlayerUSBInserted:
Serial.println("USB Inserted!");
break;
case DFPlayerUSBRemoved:
Serial.println("USB Removed!");
break;
case DFPlayerPlayFinished:
Serial.print(F("Number:"));
Serial.print(value);
player.volume(0);
Serial.println(F(" Play Finished!"));
snprintf(messages, 75, "%ld", 3);
client.publish(TOPIC, messages);
snprintf(messages, 75, "%ld", 0);
client.publish(TOPIC, messages);
break;
case DFPlayerError:
Serial.print(F("DFPlayerError:"));
switch (value) {
case Busy:
Serial.println(F("Card not found"));
break;
case Sleeping:
Serial.println(F("Sleeping"));
break;
case SerialWrongStack:
Serial.println(F("Get Wrong Stack"));
break;
case CheckSumNotMatch:
Serial.println(F("Check Sum Not Match"));
break;
case FileIndexOut:
Serial.println(F("File Index Out of Bound"));
break;
case FileMismatch:
Serial.println(F("Cannot Find File"));
break;
case Advertise:
Serial.println(F("In Advertise"));
break;
default:
break;
}
break;
default:
break;
}
}
라이브러리는 알아서 설치하시길… ㅈㅅ합니다.
3. 블루투스 스피커 넣은 후
블루투스 스피커에 넣어 블루투스 스피커의 전원 끌어와 연결하고 이어폰 단자도 직접납땜으로 연결함
!! AUX 연결 인식은 블루투스 스피커 이어폰 단자 끝 GND 양 옆 을 서로 연결하여야 인식함. !!
혹시나 왜 인식이 안되냐 하시는 분은 참고 하시길 사진을 잊어보리고 안 찍었다.. 엄청 고민하느라…
며칠은 잘 작동했다…
4. 문제 – 어느순간 DFPlayer mini 작동 통신을 안함…
다음번에는 성공한 설계로 돌아오겠습니다. 지금은 성공했거든요 ㅎㅎ
같이 보면 좋은 글