Stránka 1 z 1

Kukačky na ESP32, DFPlayer, TM1637

Napsal: 06 dub 2024, 09:23
od buchar
Ahoj kamarádi, chci vás požádat o pomoc s konstrukcí kukaček.
Původní konstrukce, kterou jsem s úspěchem dokončil je tady [url]
https://www.youtube.com/watch?v=TgJOAbc ... d&index=14[/url] .
Ta mi ale nevyhovovala, protože nelze nastavit čas manuálně. Čas se u každých takových hodin za nějakou dobu předbíhá nebo je o něco pozadu.
A když je změna času na zimní nebo na letní, tak tady to nenastavíte.
Proto jsem se rozhodl migrovat na ESP32 a načítat čas z NTP. Po pár víkendech se mi to podařilo s pomocí kamaráda a zdejšího uživatele "hafca" rozchodit.
Musel jsem na ESP32 program trochu upravit, ptorože jak víte, UNO/NANO se chová trochu jinak.
Hodiny běží a DFPlayer hraje, jenže nepřetržitě přehrává dvě zakukání. Už mě nenapadá co bych mohl udělat. Proto se obracím na vás zkušenější.



Kód: Vybrat vše

#include <WiFi.h>
#include "time.h"
#include "sntp.h"
#include "TM1637Display.h"
#include "HardwareSerial.h"
#include "DFRobotDFPlayerMini.h"

TM1637Display display(17,16);                      // TX2, RX2
HardwareSerial MySerial(1);

DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

int hrs, mins, sec;

const char* ssid       = "netis"; //netis  //Vitek 3 2.4 GHz
const char* password   = "krasnoludek"; //krasnoludek //BHD8RL3TRL

const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.nist.gov";
const long  gmtOffset_sec = 3600;
const int   daylightOffset_sec = 3600;

const char* time_zone = "CET-1CEST,M3.5.0,M10.5.0/3";  // TimeZone rule for Europe/Prague including daylight adjustment rules (optional)
                                                       // PSTR("CET-1CEST,M3.5.0,M10.5.0/3")

void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("No time available (yet)");
    return;
  }
  Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
  //display.clear();
  display.setBrightness(3);
  int hrs = timeinfo.tm_hour;
  int mins = timeinfo.tm_min;
  int sec = timeinfo.tm_sec;
  int time = hrs*100 + mins;
  display.showNumberDecEx(time, 0b11100000);
  delay(1000);
  display.showNumberDec(time);
  delay(1000);
}

// Callback function (get's called when time adjusts via NTP)
void timeavailable(struct timeval *t)
{
  Serial.println("Got time adjustment from NTP!");
  printLocalTime();
}

void setup()
{
  MySerial.begin(9600, SERIAL_8N1, 5, 4); // TX, RX
  Serial.begin(115200);
 
  Serial.println();
  Serial.println(F("Zkouška DFPlayer ... (může to trvat 3-5 sekund)"));

  if (!myDFPlayer.begin(MySerial)) {                //Připojování k softwaru Serial pro komunikaci s mp3.

    Serial.println(F("1.Zkontrolujte připojení k přehrávači!"));
    Serial.println(F("2.Vložte nebo zkontrolujte kartu!"));
    while(true){
      delay(0);                                             // Kód pro kompatibilitu s ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.setTimeOut(500);                               //Set serial communictaion time out 500ms 
   
    myDFPlayer.volume(25);                                  // nastavte hlasitost od 0 do 30
    delay(5000);
    myDFPlayer.EQ(DFPLAYER_EQ_BASS);                        // Ekvalizér BASS

  // set notification call-back function
  sntp_set_time_sync_notification_cb( timeavailable );

  /**
   * NTP server address could be aquired via DHCP,
   *
   * NOTE: This call should be made BEFORE esp32 aquires IP address via DHCP,
   * otherwise SNTP option 42 would be rejected by default.
   * NOTE: configTime() function call if made AFTER DHCP-client run
   * will OVERRIDE aquired NTP server address
   */
  sntp_servermode_dhcp(1);    // (optional)

  /**
   * This will set configured ntp servers and constant TimeZone/daylightOffset
   * should be OK if your time zone does not need to adjust daylightOffset twice a year,
   * in such a case time adjustment won't be handled automagicaly.
   */
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1, ntpServer2);

  /**
   * A more convenient approach to handle TimeZones with daylightOffset
   * would be to specify a environmnet variable with TimeZone definition including daylight adjustmnet rules.
   * A list of rules for your zone could be obtained from https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h
   */
  //configTzTime(time_zone, ntpServer1, ntpServer2);

  //connect to WiFi
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }
  Serial.println(" CONNECTED");
  myDFPlayer.volume(20);

}

void loop()
{/*
  while (MySerial.available()>0) {
    uint8_t byteFromSerial = MySerial.read();
  }*/
 
  delay(500);
  printLocalTime();     // it will take some time to sync time :)


//*********Odbijeni zvonu po 15ti minutách**********

   if((mins == 15) && (sec == 0))

   myDFPlayer.volume(5);
   myDFPlayer.play(15);                                // přehrát soubor 0015.mp3
   delay(1000);
}

   if((mins == 30) && (sec == 0))

   myDFPlayer.volume(5);
   myDFPlayer.play(13);                                // přehrát soubor 0013.mp3
   delay(1000);
}
   if((mins == 45) && (sec == 0))

   myDFPlayer.volume(5);
   myDFPlayer.play(14);                                // přehrát soubor 0014.mp3
   delay(1000);
}
//****************************************************

//*********** V celou hodinu kukacka kuká ************

   if ((mins == 0) && (sec == 0)) {
   switch (hrs)                                   // Každou hodinu zakuká kukačka
 {   
   case 1:
   myDFPlayer.volume(5);
   myDFPlayer.play(1);                                // přehrát soubor 0001.mp3
   delay(1000);
   break;
   
   case 13:
   myDFPlayer.volume(10);
   myDFPlayer.play(1);
   delay(1000);
   break;
   
   case 2:
   myDFPlayer.volume(5);
   myDFPlayer.play(2);                                // přehrát soubor 0002.mp3
   delay(1000);
   break;
   
   case 14:
   myDFPlayer.volume(10);
   myDFPlayer.play(2);                               
   delay(1000);
   break;
   
   case 3:
   myDFPlayer.volume(5);
   myDFPlayer.play(3);                                // přehrát soubor 0003.mp3
   delay(1000);
   break;
   
   case 15:
   myDFPlayer.volume(10);
   myDFPlayer.play(3);                               
   delay(1000);
   break;
   
   case 4:
   myDFPlayer.volume(5);
   myDFPlayer.play(4);                                // přehrát soubor 0004.mp3
   delay(1000);
   break;
   
   case 16:
   myDFPlayer.volume(10);
   myDFPlayer.play(4);                               
   delay(1000);
   break;

   case 5:
   myDFPlayer.volume(5);
   myDFPlayer.play(5);                                 // přehrát soubor 0005.mp3
   delay(1000);
   break;
   
   case 17:
   myDFPlayer.volume(10);
   myDFPlayer.play(5);                                 
   delay(1000);
   break;
   
   case 6:
   myDFPlayer.volume(5);
   myDFPlayer.play(6);                                 // přehrát soubor 0006.mp3   
   delay(1000);
   break;
   
   case 18:
   myDFPlayer.volume(10);
   myDFPlayer.play(6);                                   
   delay(1000);
   break;

   case 7:
   myDFPlayer.volume(10);
   myDFPlayer.play(7);                                 // přehrát soubor 0007.mp3
   delay(1000);
   break;
   
   case 19:
   myDFPlayer.volume(10);
   myDFPlayer.play(7);                                 
   delay(1000);
   break;

   case 8:
   myDFPlayer.volume(10);
   myDFPlayer.play(8);                                 // přehrát soubor 0008.mp3
   delay(1000);
   break;
   
   case 20:
   myDFPlayer.volume(10);
   myDFPlayer.play(8);                                 
   delay(1000);
   break;
 
   case 9:
   myDFPlayer.volume(10);
   myDFPlayer.play(9);                                 // přehrát soubor 0009.mp3
   delay(1000);
   break;
   
   case 21:
   myDFPlayer.volume(10);
   myDFPlayer.play(9);                                 
   delay(1000);
   break;

   case 10:
   myDFPlayer.volume(10);
   myDFPlayer.play(10);                                // přehrát soubor 0010.mp3
   delay(1000);
   break;
   
   case 22:
   myDFPlayer.volume(5);
   myDFPlayer.play(10);                               
   delay(1000);
   break;
   
   case 11:
   myDFPlayer.volume(10);
   myDFPlayer.play(11);                                // přehrát soubor 0011.mp3
   delay(1000);
   break;
   
   case 23:
   myDFPlayer.volume(5);
   myDFPlayer.play(11);                               
   delay(1000);
   break;
   
   case 12:
   myDFPlayer.volume(10);
   myDFPlayer.play(12);                                 // přehrát soubor 0012.mp3
   delay(1000);
   break;
   
   case 0:
   myDFPlayer.volume(5);
   myDFPlayer.play(12);                                 
   delay(1000);
   break;
 
   default:
   {  }
  }                 
 }
//*******************************************************

}

Napsal: 06 dub 2024, 12:27
od asdf
Ty tam máš globální proměnné hrs, mins a sec, podle kterých pouštíš ty mp3. Jenže do nich nikde nic nepíšeš. V té funkci printLocalTime() máš deklarované lokální hrs, mins a sec, které ty globální překryjí. Takže bych tu funkci printLocalTime() předělal takhle:

Kód: Vybrat vše

void printLocalTime()
{
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    Serial.println("No time available (yet)");
    return;
  }
  Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
  //display.clear();
  display.setBrightness(3);
  hrs = timeinfo.tm_hour;
  mins = timeinfo.tm_min;
  sec = timeinfo.tm_sec;
  int time = hrs*100 + mins;
  display.showNumberDecEx(time, 0b11100000);
  delay(1000);
  display.showNumberDec(time);
  delay(1000);
}
Stejně si ale myslím, že to bude kukat jen někdy (bude to vynechávat).

Napsal: 06 dub 2024, 14:34
od buchar
Díky za rychlou reakci "asdf". Hned to vyzkouším.

Napsal: 06 dub 2024, 15:03
od buchar
Tak jsem to stihl pár minut před 15:00. Už to nehraje nepřetržitě. Počkal jsem si tedy na celou, ale nezakukalo to. Bylo ticho.

Napsal: 06 dub 2024, 15:17
od asdf
To mě nepřekvapuje. Ty totiž v té funkci printLocalTime() máš dva příkazy delay(1000), takže skončí až za dvě sekundy. Takže každé dvě sekundy se koukne, jestli má kukat. Takže když máš smůlu, tak se koukne v 59 a pak až 01 sekund, takže nezakuká.

Takže bych obě ty zpoždění v printLocalTime() zkrátil na třeba delay(100). Pak by to mělo kukat pokaždé.

Zase ale bude asi rychleji blikat dvojtečka, nebo co to má dělat. Každopádně bych to zkusil.

Napsal: 06 dub 2024, 15:22
od buchar
Samozřejmě delay zkusím upravit, ale chci ti říct, že teď v 15:15h se ozval jeden gong tak jak má.

Napsal: 06 dub 2024, 18:05
od buchar
Tak to funguje jak má. Od 15:45h do 18:00h, kdy to sleduji, to oznámilo každou čtvrthodinu i celou hodinu tak jak má. Moc dík "asdf"!!!
Ještě mám ale jeden dotaz. Když odpojím ESP32 od napájení a pak zase připojím, tak musím zmáčknout RST na ESP, aby se to rozběhlo. Jak to udělat, aby se hodiny rozběhly hned a sami po připojení napájení?


PS: Omlouvám se. Teď už to funguje i po připojení napájení.
Ještě jedno veliký dík!!!