Einschlaffunktion: Lautstärke ausfaden

Ich habe eben die KidzAudio Badoo Box entdeckt:

Im Grunde handelt es sich um einen Audioplayer für Kinder ohne Cloudbindung, soweit gut. Aber an den TonUINO kommt die nicht ran, da eine RFID-Funktion fehlt und man somit einzelne Hörspiele nicht direkt anwählen kann. Aber die Box hat eine interessante Funktion, die auch für den TonUINO Sinn macht:

Mit aktivierter Einschlaffunktion wird die Lautstärke über einen Zeitraum von 30 Minuten langsam auf Null runtergeregelt. Das wäre doch eine Idee für einen Modifier.

1 „Gefällt mir“

Coole Idee…

Noch besser wäre es, wenn die Hörspiele nicht direkt innerhalb 30 Minuten ausfaden, sondern die letzten 30 Minuten… Dann läuft das Hörspiel wenigstens zu Ende…

1 „Gefällt mir“

Das hat schon mal jemand umgesetzt. Ich finde es aber gerade auf die Schnelle leider nicht wieder. :sweat_smile:

@Blackmore: Dazu müsste aber bekannt sein, wie lange das Hörspiel dauert. Das geht mit der Kombination Arduino+DFPlayer aber nicht.
Würde man aber z.B. den BY8001 statt des DFPlayers benutzen, könnte man die Länge der Tracks abfragen und damit die längenabhängige Ausfade-Funktion realisieren…

Das kann mam doch in den Sleepteimer integrieren, so dass in den letzten 30% der eingstellten zeit, die aktuelle Lautstärke gleichmäßig reduziert wird, bis man nach Ablauf des timers, bei Lautstärke 0 ist und die Box aus geht.

1 „Gefällt mir“

@marco-117
Ich habe dafür ebenfalls den SleepTimer erweitert, jedoch nicht prozentual von der eingestellten Zeit sonder fix über die letzten 20s. Wenn man bei den kleinen Inkrementen über 30 Minuten ausblendet, müsste dieses logarithmisch erfolgen, da sonst eine ggf. ziemlich lange Zeit sehr, sehr wenig zu hören ist.

Ich habe das ganze einfach linear über die letzten 20s gemacht, zusätzlich habe ich das manuelle Lautstärke erhöhen während des Ausblenden deaktiviert (Kinder sind schlau :wink: ).

Wie folgt der auf die aktuelle DEV zurück portierte Code:

class SleepTimer : public Modifier {
    private:
        unsigned long sleepAtMillis = 0;
        unsigned long lastVolCheck = 0;
        uint16_t lastVolume = 0;
    public:

    void loop() {
        if (this->sleepAtMillis > 0 && millis() > this->sleepAtMillis) {
            Serial.println(F("=== SleepTimer::loop() -> SLEEP!"));
            mp3.pause();

            setStandbyTimer();
            activeModifier = NULL;
            delete this;
        }
        else {
            if (isPlaying() && this->sleepAtMillis > 0 && millis() > this->sleepAtMillis - 20000 && millis() > this->lastVolCheck + 1000) {
                if (this->lastVolume <= 0) {
                    this->lastVolume = volume;
                }
                this->lastVolCheck = millis();
                uint16_t val = this->lastVolume - map(this->lastVolCheck, this->sleepAtMillis - 20000, this->sleepAtMillis, 0, this->lastVolume);
                mp3.setVolume(val);
            }
        }
    }

    SleepTimer(uint8_t minutes) {
        Serial.println(F("=== SleepTimer()"));
        Serial.println(minutes);
        this->sleepAtMillis = millis() + minutes * 60000;
        this->lastVolCheck = millis();
    }

    uint8_t getActive() {
        Serial.println(F("== SleepTimer::getActive()"));
        return 1;
    }
};
1 „Gefällt mir“

So ganz verstehe ich den Sinn davon nicht. :thinking:Entweder ich will das Hörspiel zu Ende hören, dann ist es doof die letzten 30 Minuten zu verpassen. Oder ich möchte einschlafen, dann kann auch einfach nach x Minuten ausfaden…

Gut das du es erwähnst, das hätte ich vergessen zu beachten.

Hallo Pit
Ich habe deine Funktion für das ausfaden der Lautstärke im Schlummermodus implementiert. Allerdigs habe ich den Code noch ergänzt. Wenn der Timer für den Schlummermodus abgelaufen ist, wird ja der Standbytimer aktiviert . Wenn man aber den Standbytimer schon programmiert hat , z.B auf 15 min, dann laufen diese erst ab bevor sich der Tonuino ausschaltet. des halb habe ich zusätzlich für die Schlummerfunktion eine Zeile eingefügt, die den Standbytimer auf 1 min setzt, so dass sich der Tonuino 1 min nach ablauf des Schlummertimers ausschaltet. Im Übrigen war in deinem Code ein kleiner Fehler " setStandbyTimer(); " . Es muss setstandbyTimer(); heißen. Sonst meckert die Arduino IDE beim kompilieren.
Anbei mal mein Code der anstelle des Originalcodes für den Sleeptimer zur Anwendung kommt.

//******************************************************* Sleeptimer mit Ausfaden Lautstärke
class SleepTimer : public Modifier {
    private:
        unsigned long sleepAtMillis = 0;
        unsigned long lastVolCheck = 0;
        uint16_t lastVolume = 0;
    public:

    void loop() {
        if (this->sleepAtMillis > 0 && millis() > this->sleepAtMillis) {
            Serial.println(F("=== SleepTimer::loop() -> SLEEP!"));
            mp3.pause();
            
             mySettings.standbyTimer = 1; // Setzt den Standbytimer auf 1 min.
            
            setstandbyTimer();
            activeModifier = NULL;
            delete this;
        }
        else {
            if (isPlaying() && this->sleepAtMillis > 0 && millis() > this->sleepAtMillis - 20000 && millis() > this->lastVolCheck + 1000) {
                if (this->lastVolume <= 0) {
                    this->lastVolume = volume;
                }
                this->lastVolCheck = millis();
                uint16_t val = this->lastVolume - map(this->lastVolCheck, this->sleepAtMillis - 20000, this->sleepAtMillis, 0, this->lastVolume);
                mp3.setVolume(val);
            }
        }
    }

    SleepTimer(uint8_t minutes) {
        Serial.println(F("=== SleepTimer()"));
        Serial.println(minutes);
        this->sleepAtMillis = millis() + minutes * 60000;
        this->lastVolCheck = millis();
        // ***********************
           //if (isPlaying())
           mp3.playAdvertisement(302);  //Schlummerfunktion aktiviert.
           delay(500);
      // *********************
    }

    uint8_t getActive() {
        Serial.println(F("== SleepTimer::getActive()"));
        return 1;
    }
};
//*************************************************************************************************

Es funktioniert so wie ich es vor hatte. Ton fadet die letzten 20 Sekunden aus und eine Minute später schaltet der Tonuino ab.

4 „Gefällt mir“

Ich habe noch ein wenig experimentiert, weil ich noch nicht ganz zufrieden mit der Funktion war. Ich habe jetzt noch eine Tastensperre und eine Sperre für das Neueinlesen einer Karte eingebaut. Den Standbytimer habe ich auch noch geändert, weil mit dem aktivieren des Standbytimers die Tasten wieder freigegeben wurden und die Lautstärke wieder manuell geändert werden konnte.
Dank der zahlreichen Beiträge im Forum habe ich letztendlich eine Lösung gefunden um das zu beseitigen.
Jetzt werden mit dem aktivieren des Einschlafteimers die Tasten und deas Neueinlesen einer Karte gesperrt. Der Standbytimer schaltet nach Ablauf der Sleepfunktion innerhalb einer Sekund ab, so dass die wiederfreigabe der Tasten nicht mehr zur Geltung kommt.
Anbei die geänderten Codes für den Einschlafmodus und den Standbytimer.

        //****************** Sleeptimer mit Ausfaden Lautstärke und Tastensperre ************
        class SleepTimer : public Modifier {
          private:
            unsigned long sleepAtMillis = 0;
            unsigned long lastVolCheck = 0;
            uint16_t lastVolume = 0;
          public:

            void loop() {
              if (this->sleepAtMillis > 0 && millis() > this->sleepAtMillis) {
                Serial.println(F("=== SleepTimer::loop() -> SLEEP!"));
                mp3.pause();

                mySettings.standbyTimer = 1; // Setzt den Standbytimer auf 1.

                setstandbyTimer();
                activeModifier = NULL;
                delete this;
              }
              else {
                if (isPlaying() && this->sleepAtMillis > 0 && millis() > this->sleepAtMillis - 20000 && millis() > this->lastVolCheck + 1000) {
                  if (this->lastVolume <= 0) {
                    this->lastVolume = volume;
                  }
                  this->lastVolCheck = millis();
                  uint16_t val = this->lastVolume - map(this->lastVolCheck, this->sleepAtMillis - 20000, this->sleepAtMillis, 0, this->lastVolume);
                  mp3.setVolume(val);
                }
              }
            }

            SleepTimer(uint8_t minutes) {
              Serial.println(F("=== SleepTimer()"));
              Serial.println(minutes);
              this->sleepAtMillis = millis() + minutes * 60000;
              this->lastVolCheck = millis();
              // ***********************
              //if (isPlaying())
              mp3.playAdvertisement(302);  //Schlummerfunktion aktiviert.
              waitForTrackToFinish();
              delay(100);
              mp3.playAdvertisement(304);   //Tasten sind nun gesperrt.
               delay(300);
              // *********************
            }
            //************Tasten und NFC im Sleepmode sperren *************
            //Für Tasten die nicht gesperrt werden sollen, jeweils die 4 zugehörigen Zeilen mit // deaktivieren
            
        virtual bool handlePause() {
        Serial.println(F("== Locked::handlePause() -> LOCKED!"));    // Play/Pausetaste speren
        return true;
        }
        virtual bool handleNextButton() {
        Serial.println(F("== Locked::handleNextButton() -> LOCKED!")); // Nächster Titel sperren
        return true;
        }
        virtual bool handlePreviousButton() {
        Serial.println(F("== Locked::handlePreviousButton() -> LOCKED!")); // Vorhergehender Titel sperren
        return true;
        }
        virtual bool handleVolumeUp() {
        Serial.println(F("== Locked::handleVolumeUp() -> LOCKED!"));   // Lautertaste sperren
        return true;
        }
        virtual bool handleVolumeDown() {
        Serial.println(F("== Locked::handleVolumeDown() -> LOCKED!"));  // Leisertaste sperren
        return true;
        }
        virtual bool handleRFID(nfcTagObject *newCard) {
        Serial.println(F("== Locked::handleRFID() -> LOCKED!"));   // Neue Karte abspielen sperren
        return true;
        }

            uint8_t getActive() {
              Serial.println(F("== SleepTimer::getActive()"));
              return 1;
            }
        };

Und hier noch der Code für den Standbytimer:

//**** Funktionen für den Standby Timer (z.B. über Pololu-Switch oder Mosfet) ********************
//****************** Im Schlummermodus wird der StandbyTimer auf 1 sekunde gesetzt ***************
void setstandbyTimer() {
  Serial.println(F("=== setstandbyTimer()"));
  if (mySettings.standbyTimer != 0)
    sleepAtMillis = millis() + (mySettings.standbyTimer * 60 * 1000); // Standbytimer auf vorgewählte min setzen
  else
    sleepAtMillis = 0;                                                // Wenn Variable auf 0 ,Standbytimer deaktivieren
     
  if (mySettings.standbyTimer == 1)
    sleepAtMillis = millis() + (mySettings.standbyTimer * 1 * 1000);    // Wenn vom Schlummermodus auf 1 gesetzt, Standbytimer auf 1 sek setzen
   
  
  Serial.println(sleepAtMillis);
}

void disablestandbyTimer() {
  Serial.println(F("=== disablestandby()"));
  sleepAtMillis = 0;
}

void checkStandbyAtMillis() {
  if (sleepAtMillis != 0 && millis() > sleepAtMillis) {
    Serial.println(F("=== power off!"));
    // enter sleep state
    digitalWrite(UsbPowerPin, HIGH); // MosFet für USB-Port Aus
    delay(2000);
    digitalWrite(shutdownPin, LOW);  // Low Pegel zum Rücksetzen des Einschalt-Flip-Flop
    delay(500);

    // http://discourse.voss.earth/t/intenso-s10000-powerbank-automatische-abschaltung-software-only/805
    // powerdown to 27mA (powerbank switches off after 30-60s)
    mfrc522.PCD_AntennaOff();
    mfrc522.PCD_SoftPowerDown();
    //mp3.sleep();

    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    cli();  // Disable interrupts
    sleep_mode();
  }
}
//*********************************************************************************************

Habs getestet und läuft super. Jetzt bin ich zufrieden.
Hätts fast vergessen. Achtung wer die Änderungen übernehmen möchte, bitte beachten, dass ich die Pegel für die Ausschaltfunktion MOSFET/POLULO Invertiert habe, im Gegensatz zur Original DEV. Der Part UsbPowerPin ist zusätzlich , weil ich die +5V für den USB-Anschluss des USB Sticks über einen Mosfet schalte.

4 „Gefällt mir“

Hallo zusammen, ich habe auf Basis von Thomas Code anstelle eines linearen fadeouts in den letzten 20 Sekunden ein logarithmisches fade out über die letzten 5 Minuten erstellt.

class SleepTimer: public Modifier {
  private:
    unsigned long sleepAtMillis = 0;
    unsigned long timeuntilsleep = 0;
  public:
    void loop() {
      if (this->sleepAtMillis != 0 && millis() > this->sleepAtMillis) {
        Serial.println(F("=== SleepTimer::loop() -> SLEEP!"));
        mp3.pause();
        mySettings.standbyTimer = 1; // Setzt den Standbytimer auf 1 min.
        setstandbyTimer();
        activeModifier = NULL;
        delete this;
      } else {
        if (isPlaying() && this->sleepAtMillis > 0 && millis() > this->sleepAtMillis - timeuntilsleep) {
                if (volume > 0) {
                    volume--;
                }
                mp3.setVolume(volume);
                this->timeuntilsleep = this->timeuntilsleep * 3 / 4;
        }
      }
    }

    SleepTimer(uint8_t minutes) {
      Serial.println(F("=== SleepTimer()"));
      Serial.println(minutes);
      this->sleepAtMillis = millis() + minutes * 60000;
      this->timeuntilsleep = 5 * 60000; // 5 Minuten langes logarithmisches fade out
      //      if (isPlaying())
      //        mp3.playAdvertisement(302);
      //      delay(500);
    }
    uint8_t getActive() {
      Serial.println(F("== SleepTimer::getActive()"));
      return 1;
    }
};

Wie hört sich das akustisch an? Erst langsames ausfaden und dann zum Ende hin schnelleres ausfaden? Wie groß ist der Unterschied zum linearen Ausfaden der letzten 20 sek?

Ja genau, die Kurve sieht bei einem Schlummermodus von 15 Minuten und einer Ausgangslautstärke von 20 folgendermaßen aus:

Wie du siehst, spielt sich der größte Teil der Veränderung ebenfalls in der letzten halben Minute ab und somit ist natürllich der Unterschied zu deiner Lösung nicht eklatant. Ich empfinde es nur etwas harmonischer, wenn die Lautstärke vorher schon langsam abnimmt.

1 „Gefällt mir“

Auch nicht schlecht. Ich werde aber bei meiner Version bleiben, da ich wirklich um jedes Bit Programmspeicherplatz kämpfe. So groß ist ja der Unterschied nicht. Danke für die Auskunft.

Hi, ich hätte mal eine Frage / Anmerkung: Bei mir funktioniert Dein Code soweit gut, allerdings wird beim Auflegen der „Einschlafen in 5 Min“ Karte auch ein Titel weiter nach vorne gesprungen - woran kann das liegen? Ich habe den original Teil „class: SleepTimer:…“ gegen Deinen Part ersetzt.

Aus welchem Fork hast du das entnommen? In der Version Always Queue von GitHub funktioniert das bei mir einwandfrei. Den Link findest du unter FAQ Software.

1 „Gefällt mir“

Danke für die Info - nach dem ich nun die TonUINO-AlwaysQueue-AiO-and-Classic ausprobiert habe, funktioniert die Schlummer Funktion super! Vielen Dank! :grinning: