MP3 дверной звонок
- Войдите на сайт для отправки комментариев
Чт, 19/08/2021 - 09:40
MP3 эвонок на Wemos D1 Mini и DFPlayer Mini с беспроводной WI-FI кнопкой на ESP8266-01
Все звуковые файлы должны лежать в папке «mp3» на TF карте в следующем формате: «0001.mp3», «0002.mp3», «0003.mp3» и т.д.
Приемник слушает порт по которому приходит состояние кнопки и если есть нажатие, то проигрывается мелодия. Пока мелодия воспроизводится на нажатие кнопки приемник не реагирует. После проигрывания, при следующем нажатии будет проигрываться следующая мелодия.
Геркон с нормально разомкнутыми контактами ставится на дверь для останова воспроизведения при ее открывании.

Скетч приемника:
#include <ESP8266WiFi.h> #include <WiFiUdp.h> #include <DFPlayer_Mini_Mp3.h> #include <SoftwareSerial.h> #define BAUD_RATE 9600 SoftwareSerial swSer(D5, D6, false, 256); // d5-Rx d6-Tx int vol = 15; boolean in_zvonok; #define reed_switch D1 // Геркон двери //***************Изменить для себя ************************* const char* host = "esp07_Zvonok"; const char* SSIDDAT = "........"; const char* PASSSIDDAT = "........"; //*********************************************************** unsigned int localUdpPort = 1855; char incomingPacket[255]; char replyPacekt[] = "Hi there! Got the message :-)"; // "Привет! Сообщение получено :-)" IPAddress local_IP(192, 168, 8, 1); IPAddress gateway(192, 168, 8, 1); IPAddress subnet(255, 255, 255, 0); WiFiUDP Udp; //================================================== /* Для двери */ void Stop_Muzik() { interrupts(); mp3_stop (); } //=================================================== void setup() { Serial.begin(BAUD_RATE); swSer.begin(BAUD_RATE); pinMode(D7, INPUT); pinMode(reed_switch, INPUT); mp3_set_serial(swSer); delay(10); mp3_set_volume (vol); delay (10); mp3_set_EQ (5); // Эквалайзер WiFi.hostname(host); WiFi.mode( WIFI_AP); Serial.println(""); Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!"); Serial.println(""); Serial.println(WiFi.softAP(SSIDDAT, PASSSIDDAT) ? "Ready" : "Failed!"); delay(1000); Serial.println(""); Serial.printf("Stations connected = %d\n", WiFi.softAPgetStationNum()); Serial.print("Soft-AP IP address = "); Serial.print(WiFi.softAPIP()); Serial.println(""); Serial.printf("MAC address = %s\n", WiFi.softAPmacAddress().c_str()); // "MAC-адрес = " Udp.begin(localUdpPort); Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort); noInterrupts(); attachInterrupt(reed_switch, Stop_Muzik, CHANGE); interrupts(); } //########################################### void loop() { int packetSize = Udp.parsePacket(); if (packetSize) { // Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort()); // "Получено %d байт от %s, порт %d%" int len = Udp.read(incomingPacket, 255); if (len > 0) { incomingPacket[len] = 0; } in_zvonok = atoi(incomingPacket); // отправляем ответ на IP-адрес и порт, с которых пришел пакет: Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(replyPacekt); Udp.endPacket(); } //================================================ bool Busy = (digitalRead (D7)); // boolean play_state = in_zvonok; if (Busy == HIGH) { // Низкий означает идет воспроизведение, высокий означает нет if (in_zvonok == HIGH) { // if (play_state == HIGH) { delay (10); in_zvonok = 0; mp3_next (); // mp3_random_play (); // Воспроизвести в случайном порядке. } } else in_zvonok = 0; // delay(1000); }В скетче ошибка (в функции Stop_Muzik) из-за которой система будет иногда подвисать без видимых причин. Виновата в этом будет, по установившейся в российском ардуино-сообществе традиции, "китайскость модулей" (ну, а кто ещё может быть виноват?) :-)))
Такой ошибки не знаю. В процессе отладки все работало штатно, без каких либо глюков.
Подвисание возможны из-за слишком длинного провода (было такое на другой конструкции), наведенные помехи.
Такой ошибки не знаю.
Так подумайте. Я же Вам даже сказал где именно она.
Я, конечно, могу всё объяснить (скажите, объясню, мне не трудно), но я всегда предпочитаю только дать намёк и оставить человеку шанс дойти самому, это гораздо приятнее и полезнее.
Далее кнопка:
#include <ESP8266WiFi.h> #include <WiFiUdp.h> //#define button 2 // Кнопка звонка volatile boolean flag = true; // флаг нажатой кнопки //***********Изменить на свои *********************** const char* host = "esp01_Button"; const char* AP_SSID = "........"; const char* AP_PASS = "........"; //*************************************************** char buff[255]; int packetSize; unsigned int localUdpPort = 1855; IPAddress ip_esp07_Zvonok (192, 168, 8, 1); // IP адрес первого модуля IPAddress ipClient(192, 168, 8, 3); IPAddress Subnet(255, 255, 255, 0); WiFiUDP Udp; //======================================================= void handover() { itoa(flag, buff, 10); int packetSize = Udp.parsePacket(); if (!packetSize) { Udp.beginPacket(ip_esp07_Zvonok, localUdpPort); Udp.write(buff); Udp.endPacket(); delay(25); } } //===================================================== void setup() { WiFi.hostname(host); WiFi.mode( WIFI_STA); // Serial.printf("Connecting to %s ", AP_SSID); WiFi.begin(AP_SSID, AP_PASS); while (WiFi.status() != WL_CONNECTED) { delay(500); // Serial.print("."); } // Serial.println(" connected"); WiFi.config(ipClient, ip_esp07_Zvonok, Subnet); Udp.begin(localUdpPort); // Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort); handover(); // Serial.println("передали и спать"); ESP.deepSleep(0); } //============================================= void loop() { // delay(1000); }Спасибо за подсказку. Буду разбираться сам.
Разбирайтесь, удачи. Но, если что, предложение "объяснить" остаётся в силе, обращайтесь.
В скетче ошибка (в функции Stop_Muzik) из-за которой система будет иногда подвисать без видимых причин. Виновата в этом будет, по установившейся в российском ардуино-сообществе традиции, "китайскость модулей" (ну, а кто ещё может быть виноват?) :-)))
Думаю дребезг контакта геркона. Тогда так конечно не вариант. Позже исправлю программу, сейчас на работе, немного некогда.
Ну, не только, но и дребезг тоже. В общем случае, программа зависнет, если функция будет вызвана менее, чем через 50 мс после того, как вызывалась она же (как раз дребезг) или любая другая функция, которая шлёт команды проигрывателю (см. функцию mp3_send_cmd на предмет почему так). Исправить - там всего одну строчку добавить - просто разрешить прерывания перед вызовом mp3_stop - тогда всё будет нормально.
Ну, не только, но и дребезг тоже. В общем случае, программа зависнет, если функция будет вызвана менее, чем через 50 мс после того, как вызывалась она же (как раз дребезг) или любая другая функция, которая шлёт команды проигрывателю (см. функцию mp3_send_cmd на предмет почему так). Исправить - там всего одну строчку добавить - просто разрешить прерывания перед вызовом mp3_stop - тогда всё будет нормально.
Спасибо за объяснения, я хотел перед mp3_stop запретить прерывание, а по Busy разрешить.
Скетч подправил.
Если Вы поправили в посте №1, то так, как сейчас - неправильно. Вы не разрешили прерывания, а просто отключили дальнейший вызов обработчика. В каких-то ситуациях это может не помочь. Надо просто разрешить там прерывания (sei() или interruts() ) и больше ничего мудрить не нужно.
Поясните, зачем в функции обработки прерываний разрешать то что и так будет разрешено.
Поясните, зачем в функции обработки прерываний разрешать то что и так будет разрешено.
Кем и когда оно будет разрешено? В момент входа в обработчик прерывания запрещены. Вы в этом обработчике что делаете? Вызываете mp3_stop. А mp3_stop, в свою очередь, вызывает mp3_send_cmd. Прерывания всё ещё запрещены, ибо их никто не разрешал, так ведь? А Вы эту mp3_send_cmd видели? Я ведь Вам советовал посмотреть на неё. Она начинается вот так:
void mp3_send_cmd (uint8_t cmd, uint16_t high_arg, uint16_t low_arg) { unsigned long d = abs(millis() - _last_call); if (d < 50) { delay(50 - d); } ...А delay устроен вот так:
void delay(unsigned long ms) { uint32_t start = micros(); while (ms > 0) { yield(); while ( ms > 0 && (micros() - start) >= 1000) { ms--; start += 1000; } } }Что имеем? Если, по каким-то причинам (например, из-за дребезга геркона, обработки которого ни в схеме, ни в программе нет), mp3_stop будет вызвана менее, чем через 50мс после последнего вызова (её же или любой другой функции, вызывающей mp3_send_cmd), то delay превратится в вечное ожидание, т.к. прерывания запрещены, а значение, возвращаемое micros(), при закрытых прерываниях изменяться не будет.
Необходимо разрешить прерывания перед вызовом mp3_stop. Сразу "наведённых помех" станет меньше, да и модули станут менее китайскими :-)
Огромная благодарность Вам за разъяснения, скетч поправил. Думаю еще параллельно геркону поставить конденсатор 0,01 мкф от дребезга.
Зачем нужен звонок если есть домофон?
Зачем нужен звонок если есть домофон?
Свой дом. До калитки метров 12.
И постоянно к калитке бегаете открывать/закрывать/заряжать?
На калитку электрозамок надо,вот к чему я...
Свои так заходят, чужие звонят, геркон стоит на входной двери в дом, питание кнопки от аккумуляторов с ноутбука через DC-DC понижающий/повышающий преобразователь. И не нужно никакого электрозамка. Цель уйти от любых проводов до калитки.
Звонка с использованием ip-стека тут ещё не было. Дальше дело за SSL/TSL, полагаю...
Нет, это я не потяну, но в курятнике WI-FI поставил для управления освещением... рассвет\закат...
А мне вот непонятно, зачем дверному звонку больше одной мелодии?
Мне всегда казалось, что звук дверного звонка должен быть таким, который невозможно перепутать с каким-либо другим звуком (например, от проигрывателя или телевизора).
Мне нравится, каждый раз разная мелодия. А когда надоест легко перезалить другие мелодии. Можно записать какие нибудь прикольные звуки, да и звучание вполне приемлемого качества.
Свой дом.
И что? У меня тоже. Домофону-то это как может помешать? Неужели Вам приятно бежать на улицу каждому калитку открывать, особенно зимой?
В такую погоду свои дома сидят, телевизор смотрют. Только чужие шастают...
Мне нравится, каждый раз разная мелодия. А когда надоест легко перезалить другие мелодии. Можно записать какие нибудь прикольные звуки, да и звучание вполне приемлемого качества.
Вам нравится на каждую новую мелодию, доносящуюся из радиоприемника, бежать и открывать калитку?
Как избежать путаницы, если и по содержанию, и по качеству звук дверного замка не будет отличаться от звука музыкального центра?
Вам нравится на каждую новую мелодию, доносящуюся из радиоприемника, бежать и открывать калитку?
Как избежать путаницы, если и по содержанию, и по качеству звук дверного замка не будет отличаться от звука музыкального центра?
Глупости не говорите, если вы не отличаете, мои какие проблемы.
Домофон даже и не думаю ставить. Не вижу такой необходимости.
Изменил схему.