Lichtwecker n+1, Arduino
Moderatoren: Heaterman, Finger, Sven, TDI, Marsupilami72, duese
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Lichtwecker n+1, Arduino
N'abend allerseits,
ich frickel grade an nem Lichtwecker und wollte euch am bisherigen Fortschritt teilhaben lassen, das Thema geistert hier ja auch immer mal wieder rum.
Hardwareseitig habe ich im Einsatz:
Arduino Nano v3(Klon)
DS3231
4Stelliges 7-Segment Display (weiß) an TM1637
DFplayer mini
20x4 LCD an I2C Expander (zu Diagnosezwecken, kommt wieder raus)
billiger Mosfet Treiberbaustein
2x 12v 10W Chinaled
Kühlkörper von Xana
12V 2,5A Steckernetzteil von Maxens
der Testaubau sieht so aus: Der DFPlayer hat ne eigene Stromversorgung und versteckt sich hinter ner Menge Kabel
hier ist ne Skizze, wie das mal in etwa aussehen soll:
Der Druckknopf an der Front kommt noch nach rechts zum Encoder, ist besser weil man sonst bei der Bedienung die Hände wechseln muss oder mit der Hand übers Display fassen muss. Am Gehäuse hab ich auch schon gewerkelt, ist aber noch nicht fertig.
Todo: Frontplatte, Ausfräsung für Plexiglasabdeckung, Holzplatte für den Reflektor einsetzen, schwarztransparent beizen, denke noch über Schellack nach, wahrscheinlich wirds aber klarlackiert. Das sieht auf dem Bild so aus, als wäre die vordere Kante senkrecht, sie ist aber etwa 30° nach hinten geneigt. Der code ist Gegenstand aktueller Tests und müsste für Weckbetrieb angepasst werden, das fadet grad sehr schnell, ist aber zum Testen natürlich besser so. Hab versucht nen logarithmischen Fade hinzubekommen, ich bin auch der Meinung, das kommt so hin, nur ist am unteren Bereich des Fades der Unterschied so groß, dass man auch Wertsprünge von -+1 deutlich sieht.(dazu unten mehr)
Der Audioplayer startet im Moment direkt mit dem Fade, das werde ich noch anpassen, oder ich mach einfach 10 Minuten Stille an den Anfang der Sounds. Den Soundtrack hab ich von Freesounds.org. Geiler Scheiß, kann ich nur empfehlen sich das mal anzuhören, was es da so gibt. Grad jetzt, wo man nicht so viel rauskommt, mal angenehm, Natur hören zu können.
Was ich auch noch nicht programmiert habe ist, dass Sonnenaufgang 30Minuten vor der eingestellten Zeit beginnt.Kommt noch:
->umbenennen in *.ino
Dinge die noch nicht bei 100% sind:
4x7-Segment@TM1637 Sieht wirklich schön aus und ist sehr gut lesbar, aber ich habe noch keine Bib gefunden, die a) Meine Bedürfnisse erfüllt und b) tatsächlich das macht, was sie vorgibt. In Betrieb habe ich TM1637Display.h von hier. Ein Punkt der mich sehr geärgert hat, ist dass es so verkauft wird, als ob sowohl Dezimalpunkte, als auch der Doppelpunkt einzeln angesprochen werden können. Leider ist es so, dass nur entweder der Doppelpunkt, oder Die Dezimalpunkte funktionieren. Bei mir isses der Doppelpunkt. Das LED-Modul hat garnicht genügend Pins, damit man _alles_ ansprechen könnte, es sieht nur so aus als gäbe es Dezimalpunkte, wie doof ist denn das? Es gibt auf Ebay Displays mit nem anderen Controller, bei denen alles da ist, aber da steht nicht dran, welche Farbe die haben.
Ich wollte die Dezimalpunkte eigentlich zur Anzeige verschiedener Zustände nutzen, jetzt muss ich mir was andres überlegen. ich hätte die Front halt gerne so clean wies geht, extra LEDs verbauen ist doof. Fürs erste verwende ich den Doppelpunkt für Wecker an/aus, aber ich hätte den gerne dauerhaft an, sieht einfach besser aus bei ner Uhr.
Der andere Haken ist, dass ich es nicht schaffe, bestimmte Dinge anzuzeigen. Das Display soll zum Beispiel, wenn Button2 gehalten wird, die aktuelle Weckzeit anzeigen, und dabei entweder Minuten oder Stunden blinken lassen. (je nachdem, worauf der Encoder gerade eingestellt ist) Beim Blinken soll dann also gewechselt werden zwischen "12:34" und "12:_ _" Es gibt in der Library Beispiele, in denen das funktionieren sollte, aber die zeigen bei mir nicht das an, was sie sollen. Das zeigt dann "_ _:12" an, oder "_1:2_", oder "12:00".
Werd wohl nochmal ne andre Bibliothek ausprobieren müssen. Wahrscheinlich liegts auch eh nicht an der Bibliothek, sondern an meinem Display.
Zu dem stufigen Fade:
Mein Plan ist diesen kleinen Mister hier: umzufrickeln, sodass die 2 Mosfetse nicht mehr parallel, sondern einzeln schaltbar sind. Dann kann ich über unterschiedliche Vorwiderstände die doppelte Auflösung rausholen und das sollte dann ja wohl reichen. Ich brauche ja nur im unteren Bereich mehr, ab spätestens 35 von 255 merkt man nix mehr. Ich könnte auch zwei von den Kraftzwergen nehmen, aber der eine langweilt sich ja jetzt schon bei den lumpigen 600 bzw 1200mA, die die LEDs bekommen.
Sollte ja gehen, oder hab ich da nen Denkfehler?
Das wars soweit von mir, wünsche noch einen schönen Sonntag Abend
Moritz
ich frickel grade an nem Lichtwecker und wollte euch am bisherigen Fortschritt teilhaben lassen, das Thema geistert hier ja auch immer mal wieder rum.
Hardwareseitig habe ich im Einsatz:
Arduino Nano v3(Klon)
DS3231
4Stelliges 7-Segment Display (weiß) an TM1637
DFplayer mini
20x4 LCD an I2C Expander (zu Diagnosezwecken, kommt wieder raus)
billiger Mosfet Treiberbaustein
2x 12v 10W Chinaled
Kühlkörper von Xana
12V 2,5A Steckernetzteil von Maxens
der Testaubau sieht so aus: Der DFPlayer hat ne eigene Stromversorgung und versteckt sich hinter ner Menge Kabel
hier ist ne Skizze, wie das mal in etwa aussehen soll:
Der Druckknopf an der Front kommt noch nach rechts zum Encoder, ist besser weil man sonst bei der Bedienung die Hände wechseln muss oder mit der Hand übers Display fassen muss. Am Gehäuse hab ich auch schon gewerkelt, ist aber noch nicht fertig.
Todo: Frontplatte, Ausfräsung für Plexiglasabdeckung, Holzplatte für den Reflektor einsetzen, schwarztransparent beizen, denke noch über Schellack nach, wahrscheinlich wirds aber klarlackiert. Das sieht auf dem Bild so aus, als wäre die vordere Kante senkrecht, sie ist aber etwa 30° nach hinten geneigt. Der code ist Gegenstand aktueller Tests und müsste für Weckbetrieb angepasst werden, das fadet grad sehr schnell, ist aber zum Testen natürlich besser so. Hab versucht nen logarithmischen Fade hinzubekommen, ich bin auch der Meinung, das kommt so hin, nur ist am unteren Bereich des Fades der Unterschied so groß, dass man auch Wertsprünge von -+1 deutlich sieht.(dazu unten mehr)
Der Audioplayer startet im Moment direkt mit dem Fade, das werde ich noch anpassen, oder ich mach einfach 10 Minuten Stille an den Anfang der Sounds. Den Soundtrack hab ich von Freesounds.org. Geiler Scheiß, kann ich nur empfehlen sich das mal anzuhören, was es da so gibt. Grad jetzt, wo man nicht so viel rauskommt, mal angenehm, Natur hören zu können.
Was ich auch noch nicht programmiert habe ist, dass Sonnenaufgang 30Minuten vor der eingestellten Zeit beginnt.Kommt noch:
->umbenennen in *.ino
Dinge die noch nicht bei 100% sind:
4x7-Segment@TM1637 Sieht wirklich schön aus und ist sehr gut lesbar, aber ich habe noch keine Bib gefunden, die a) Meine Bedürfnisse erfüllt und b) tatsächlich das macht, was sie vorgibt. In Betrieb habe ich TM1637Display.h von hier. Ein Punkt der mich sehr geärgert hat, ist dass es so verkauft wird, als ob sowohl Dezimalpunkte, als auch der Doppelpunkt einzeln angesprochen werden können. Leider ist es so, dass nur entweder der Doppelpunkt, oder Die Dezimalpunkte funktionieren. Bei mir isses der Doppelpunkt. Das LED-Modul hat garnicht genügend Pins, damit man _alles_ ansprechen könnte, es sieht nur so aus als gäbe es Dezimalpunkte, wie doof ist denn das? Es gibt auf Ebay Displays mit nem anderen Controller, bei denen alles da ist, aber da steht nicht dran, welche Farbe die haben.
Ich wollte die Dezimalpunkte eigentlich zur Anzeige verschiedener Zustände nutzen, jetzt muss ich mir was andres überlegen. ich hätte die Front halt gerne so clean wies geht, extra LEDs verbauen ist doof. Fürs erste verwende ich den Doppelpunkt für Wecker an/aus, aber ich hätte den gerne dauerhaft an, sieht einfach besser aus bei ner Uhr.
Der andere Haken ist, dass ich es nicht schaffe, bestimmte Dinge anzuzeigen. Das Display soll zum Beispiel, wenn Button2 gehalten wird, die aktuelle Weckzeit anzeigen, und dabei entweder Minuten oder Stunden blinken lassen. (je nachdem, worauf der Encoder gerade eingestellt ist) Beim Blinken soll dann also gewechselt werden zwischen "12:34" und "12:_ _" Es gibt in der Library Beispiele, in denen das funktionieren sollte, aber die zeigen bei mir nicht das an, was sie sollen. Das zeigt dann "_ _:12" an, oder "_1:2_", oder "12:00".
Werd wohl nochmal ne andre Bibliothek ausprobieren müssen. Wahrscheinlich liegts auch eh nicht an der Bibliothek, sondern an meinem Display.
Zu dem stufigen Fade:
Mein Plan ist diesen kleinen Mister hier: umzufrickeln, sodass die 2 Mosfetse nicht mehr parallel, sondern einzeln schaltbar sind. Dann kann ich über unterschiedliche Vorwiderstände die doppelte Auflösung rausholen und das sollte dann ja wohl reichen. Ich brauche ja nur im unteren Bereich mehr, ab spätestens 35 von 255 merkt man nix mehr. Ich könnte auch zwei von den Kraftzwergen nehmen, aber der eine langweilt sich ja jetzt schon bei den lumpigen 600 bzw 1200mA, die die LEDs bekommen.
Sollte ja gehen, oder hab ich da nen Denkfehler?
Das wars soweit von mir, wünsche noch einen schönen Sonntag Abend
Moritz
Re: Lichtwecker n+1, Arduino
Wenn ich eins gelernt habe mit PWM und Licht, dann ist es eins: wenn möglich 16 Bit PWM verwenden. Dann kannst Du dir den doppel MOSFET sparen, weil Du dann 65536 Stufen statt 256 hast. So hab ich es bei meinem gemacht. Funktioniert super.Später Gast hat geschrieben: ↑Mo 23. Mär 2020, 00:04 umzufrickeln, sodass die 2 Mosfetse nicht mehr parallel, sondern einzeln schaltbar sind. Dann kann ich über unterschiedliche Vorwiderstände die doppelte Auflösung rausholen und das sollte dann ja wohl reichen. Ich brauche ja nur im unteren Bereich mehr, ab spätestens 35 von 255 merkt man nix mehr. Ich könnte auch zwei von den Kraftzwergen nehmen, aber der eine langweilt sich ja jetzt schon bei den lumpigen 600 bzw 1200mA, die die LEDs bekommen.
Sollte ja gehen, oder hab ich da nen Denkfehler?
Ich halte 7-Segement Displays für einen Wecker für eher ungeeignet, da die Dimmung nur schwer möglich ist. Ich hab ein LCD mit integriertem Controller verwendet. Dann benötigt man nur noch einen PWM für die Hintergrundbeleuchtung. Beim Energieverbrauch sind LCDs auch deutlich besser. Zu dem gibt es welche, bei denen man eigene Zeichen kreieren kann.
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Stimmt, guter Einwand, würde ich sehr gerne machen, ist aber deutlich außerhalb meiner Programmierkentnisse. Ich lese OCR0 und OCRA, verstehe nur Bahnhof und hab Angst um mein heißgeliebtes millis().
Hast du da nen Link wo ich das verstehe, oder womöglich was fertiges, was mir nicht den ganzen Sketch auf den Kopf stellt?
Der Punkt Dimming ist nicht ganz von der Hand zu weisen, Stufe 1 von 7 ist im Dunkeln schon etwas zu hell, alles andere ist dann nur noch mehr zu heller. Ich schreib das auf die Liste für wenn das Problem aktueller wird.Ich halte 7-Segement Displays für einen Wecker für eher ungeeignet, da die Dimmung nur schwer möglich ist. Ich hab ein LCD mit integriertem Controller verwendet. Dann benötigt man nur noch einen PWM für die Hintergrundbeleuchtung. Beim Energieverbrauch sind LCDs auch deutlich besser. Zu dem gibt es welche, bei denen man eigene Zeichen kreieren kann.
Stromverbrauch macht mir im Moment keine Sorgen, der ist auch mit dem 7Segment LED im Rahmen, außerdem werde ich den nicht aus dem Akku betreiben.
Nachdem Du jetzt den Punkt Dimming angesprochen hast, denke ich wieder über ne getönte Plexiglasscheibe vor dem Display nach. Da wollte ich mir was besorgen, um die bei Tageslicht leicht gelblich erscheinenden Segmente zu verstecken. Dann hab ich aber keine lokale Quelle gefunden und das wieder verworfen. Vielleicht einfach Tönungsfolie. irgendwas Dunkles halt. Das Ding stumpf mit 3,3V versorgen hilft schonmal ein bisschen. Senkt auch den Stromverbrauch.
Die Lesbarkeit und der Kontrast ist bei 7 Segment mMn höher, es ist für mich aber auch ne ästhetische Frage, ich möchte gerne große, leuchtende Lettern mit hohem Kontrast haben. Ich möchte nur Zahlen darstellen. Wenn ich nicht dieses 7Segment Display nehme, dann nehme ich ein größeres für noch bessere Lesbarkeit bei nächtlich verklebten Schmieraugen. K.I.S.S.
Der soll nur 2 Sachen können, aber die dafür gut.
Re: Lichtwecker n+1, Arduino
vielleicht mach ich sowas auch mal.
dann macht ich für die uhrzeit ein schiebepoti dran.
wenns genau sein muss bzw. zur kontrolle, serielle Konsole über handy.
dann macht ich für die uhrzeit ein schiebepoti dran.
wenns genau sein muss bzw. zur kontrolle, serielle Konsole über handy.
- Fritzler
- Beiträge: 12603
- Registriert: So 11. Aug 2013, 19:42
- Wohnort: D:/Berlin/Adlershof/Technologiepark
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Re: Lichtwecker n+1, Arduino
Fritzler, wenn du das Latch und den BCD Decoder durch HC595 ersetzt, kannst du mit nur 4 Pins die Segmente beglücken. Musst aber dann die Daten etwas anders aufbereiten und als 16Bit Wort über SPI prügeln.
- Fritzler
- Beiträge: 12603
- Registriert: So 11. Aug 2013, 19:42
- Wohnort: D:/Berlin/Adlershof/Technologiepark
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Ja, aber son uralt AVR hat meist nur 1 SPI und den muss man damit jetzt nicht vollballern.
Mehrere SW Teile auf 1 SPI loslassen geht zwar, aber dann kannste dir schön Semaphoren bauen und der Multiplexer muss immer vorrang haben.
Seidenn es ist die einzige SPI Ausgabe und das Sreg ist sehr groß
http://fritzler-avr.de/HP/ledscreen.php
Mehrere SW Teile auf 1 SPI loslassen geht zwar, aber dann kannste dir schön Semaphoren bauen und der Multiplexer muss immer vorrang haben.
Seidenn es ist die einzige SPI Ausgabe und das Sreg ist sehr groß
http://fritzler-avr.de/HP/ledscreen.php
Re: Lichtwecker n+1, Arduino
Achtung, graue Theorie: PWM wird über Timer gemacht. Davon hat der Atmega328, welcher auf dem Bord sitzt, drei Stück. Allerdings kann das Ausgangssignal nur an jeweils zwei festen Pins ausgegeben werden. In Deinem Fall D9 oder D10 (OC1A und OC1B).Später Gast hat geschrieben: ↑Mo 23. Mär 2020, 01:29 Stimmt, guter Einwand, würde ich sehr gerne machen, ist aber deutlich außerhalb meiner Programmierkentnisse. Ich lese OCR0 und OCRA, verstehe nur Bahnhof und hab Angst um mein heißgeliebtes millis().
Hast du da nen Link wo ich das verstehe, oder womöglich was fertiges, was mir nicht den ganzen Sketch auf den Kopf stellt?
Die Konfiguration des Timers ist relativ einfach:
Code: Alles auswählen
DDRB|=(1<<1);//Direction von D9 auf Output
TCCR1A=(1<<COM1A1)|(1<<WGM10)|(1<<WGM11);//Fast PWM
TCCR1B=(1<<WGM12)|(1<<WGM13)|(1<<CS12); //3900Hz (16e6/2^16/256)
OCR1A=3000;//Der aktuelle PWM Wert (0-65535)
Das feine daran neben der deutlich besseren Auflösung ist, dass die PWM Erzeugung vollständig im Hintergrund geschieht und keinerlei CPU Takte klaut. Lediglich der Wert von OCR1A muss geändert werden, um die Pulsweite zu verändern.
Achtung, noch was: Das Arduino Framework nutzt wohl eine Timer als Systemzeitreferenz. Es kann sein, das Funktionen, welche drauf angewiesen sind jetzt nicht mehr funktionieren.
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Danke! Das mit dem keine CPU-Takte klauen ist auch gut, man sieht die Stufen nämlich auch deswegen gut, weil jedes Neusetzen der PWM-Frequenz n Fitzel Zeit braucht und man die Aussetzer bei wenig Licht sehen kann.Anse hat geschrieben: ↑Mo 23. Mär 2020, 23:12Der Code muss irgend wo ins Setup. Hoffe mal, im Arduino Header sind die Register definiert. Wenn ich jetzt nichts gravierendes übersehen habe, sollte an D9 ein PWM Signal erscheinen.Code: Alles auswählen
DDRB|=(1<<1);//Direction von D9 auf Output TCCR1A=(1<<COM1A1)|(1<<WGM10)|(1<<WGM11);//Fast PWM TCCR1B=(1<<WGM12)|(1<<WGM13)|(1<<CS12); //3900Hz (16e6/2^16/256) OCR1A=3000;//Der aktuelle PWM Wert (0-65535)
Das feine daran neben der deutlich besseren Auflösung ist, dass die PWM Erzeugung vollständig im Hintergrund geschieht und keinerlei CPU Takte klaut. Lediglich der Wert von OCR1A muss geändert werden, um die Pulsweite zu verändern.
Achtung, noch was: Das Arduino Framework nutzt wohl eine Timer als Systemzeitreferenz. Es kann sein, das Funktionen, welche drauf angewiesen sind jetzt nicht mehr funktionieren.
Wenn ich das richtig gegoogelt hab, benutzt das Timer1, der ist für PWM und tone() zuständig, letzteres benutz ich nicht und PWM will ich ja ersetzen. Probleme gäbe es, wenn ich Timer0 verändern würde, der macht millis() und delay() und insbesondere millis() würde mir große Probleme bereiten. Ich probier das mal aus und berichte!
Re: Lichtwecker n+1, Arduino
Bitte, bin mal gespannt, ob es so klappt.
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Okay, ich habs jetzt mit diesem Code hier ans Leufen gebracht:
Den hab ich von hier. Das Problem war erst, dass irgendwas mit Pin9 veranstaltet. In deinem Code war ich mir nicht sicher, wie man den Pin ändert. (Womöglich mit "DDRB|=(1<<2);"?) Auf Pin 10 läufts. Jetzt muss ich nurnoch den Code für die neuen Zahlen fit machen.
Code: Alles auswählen
void setup() {
Serial.begin(9600);
setupPWM16();
}
uint16_t icr = 0xffff;
void loop() {
Serial.println("*");
for (uint16_t i = 0; i < 2000; i++)
{
analogWrite16(9, i);
delay(2);
}
}
void setupPWM16() {
DDRB |= _BV(PB1) | _BV(PB2); /* set pins as outputs */
TCCR1A = _BV(COM1A1) | _BV(COM1B1) /* non-inverting PWM */
| _BV(WGM11); /* mode 14: fast PWM, TOP=ICR1 */
TCCR1B = _BV(WGM13) | _BV(WGM12)
| _BV(CS10); /* prescaler 1 */
ICR1 = 65535; /* TOP counter value (freeing OCR1A*/
}
/* 16-bit version of analogWrite(). Works only on pins 9 and 10. */
void analogWrite16(uint8_t pin, uint16_t val)
{
switch (pin) {
case 9: OCR1A = val; break;
case 10: OCR1B = val; break;
}
}
Code: Alles auswählen
#include <SoftwareSerial.h>
#include <DFPlayerMini_Fast.h>
SoftwareSerial mySerial(7, 8); // RX, TX
DFPlayerMini_Fast myMP3;
Re: Lichtwecker n+1, Arduino
So müsste es für Pin 10 aussehen. Allerdings, wenn Du eine funktionierende Lösung hast ist das noch besser
Code: Alles auswählen
DDRB|=(1<<2);//Direction von D10 auf Output
TCCR1A=(1<<COM1B1)|(1<<WGM10)|(1<<WGM11);//Fast PWM
TCCR1B=(1<<WGM12)|(1<<WGM13)|(1<<CS12); //3900Hz (16e6/2^16/256)
OCR1B=3000;//Der aktuelle PWM Wert (0-65535)
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
So, bin hier mittlerweile so einiges weitergekommen.
-Auch mit 16Bit PWM kann ich beim Dimming am Anfang noch sehr gut Stufen erkennen. Stört mich aber nicht. Ich habe außerdem das Gefühl, dass das Setzen der PWM Zeit benötigt und in dieser Zeit ist der Ausgang 0. Ich meine jedenfalls kleine Wackler zwischen den Steps zu sehen.
-Dass die serielle Kommunikation mit dem dfPlayer Probleme an Pin 9 verursacht hat, lag natürlich an einem Lötfehler.
Hab von PullDown auf die interne PullUp Funktion umgestellt. Im Moment sind noch keine Serienwiderstände an den Schaltern, das hab ich aber vor. Wie sollte ich die bemessen?
-Das Display lässt sich sehr gut an 3,3V betreiben, die sind aber immernoch zu hell. 2,8 wären bei dunkler Raumumgebung optimal. Beim Experimentieren mit einer Diode in Serie hab ich rausgefunden, dass die 3,3V vom Nanoklon in wirklichkeit 3,8 sind. Ein anderer Nano den ich hier rumliegen hab macht 3,7V, hätte also nichts verbessert. mit 2 Dioden war die Spannung zu klein, mit einer zu groß. Nach etwas fruchtlosem rumhirnen und Käseschaltungen mit Dioden und Widerständen hatte ich die glorreiche Idee, die 16Bit PWM vom zweiten Pin zu nehmen, gleichzufiltern und als Versorgung zu verwenden. Der Nano kann pro Pin maximal 40mA, hab dann für das RC-Glied 100 Ohm genommen, dann fließen maximal 25mA, 1000µF als C und zack feddich ist die Dimmfunktion. Das kann jetzt wirklich große Helligkeitsunterschiede abdecken. Die Interne Dimmingfunktion verwende ich aber weiter, weil das Display bei knapper Spannungsversorgung sonst zu Flimmern beginnt. Das Display ist übrigens überhaupt kein Stromfresser. Auf volle Lotte nimmt sich das ~17mA, aber bei normalen Leuchtstärken reichen 3-10.
Damit ich von der Dimmfunktion auch was hab, hab ich nen Fotowiderstand mit nem 5k Widerling zu nem Spannungsteiler verheiratet und kann jetzt die Helligkeit der Umgebung automatisch anpassen.
Am Gehäuse bin ich auch soweit fertig. Leider bin ich im Planen nicht so strukturiert, und habe vorher nicht überlegt, wie ich die Lautsprecher im Gehäuse festschrauben will, wenn das Gehäuse mal zusammengebaut ist. Aber wer kennt nicht die alte Bastlerweisheit, "wer es nicht im Kopf hat, nimmt Heißkleber" Passiert sowas eigentlich nur mir? Geht ganzschön eng zu dadrinnen. Ich verschätz mich immer beim Platzbedarf der Elektronik. Hier ist es nochmal gutgegangen. Ohne Heißkleb wär ich aufgeschmissen. Die LED sind mit Endsieg befestigt. Hatte davor den Plan, das zu schrauben, aber der ist am nicht vorhandenen m2 Gewindeschneider gescheitert. Für Federklemmen ist da kein Platz.
Außerdem zu sehen der Fotoresistor. Hatte keine Lust, ein extra Loch in die Front zu bohren. Mach ich die Lichtmessung während des Weckvorgangs halt aus. Der Mosfet und die Vorwiderstände sowie eine 2A Sicherung sind unterm Reflektor. Da geh ich nochmal ran, wollte noch ne kleine Patine für die Widerlinge spendieren (ist noch Freiluftverdrahtung) und die Werte etwas nach oben anpassen. die haben jetzt 0,9 Ohm, da fließt bei 12,2V Versorgung, die aus dem Netzteil kommen 600mA und die steigen bei längerer Vollast nochmal deutlich an. Bei 40°C am Aluträger warens schon 2x700mA und hier wirds gut warm im Sommer, da können das sicher auch mal 60°C werden. Können sollten sie 1A pro Stück, da käme dann die Sicherung, aber da muss ichs ja nicht drauf ankommen lassen und das macht WIRKLICH gut Hell. *blinzel* Ich kann also etwas Reserve verschmerzen. Hirnlose Käseschaltung. Da hab ich das Gehäuse zum ersten Mal fertig aufgebaut, es fehlt aber noch die Mattierungsfolie für die Plexiglasscheibe. Mehr gibts später, hier gibts jetzt Futter.
-Auch mit 16Bit PWM kann ich beim Dimming am Anfang noch sehr gut Stufen erkennen. Stört mich aber nicht. Ich habe außerdem das Gefühl, dass das Setzen der PWM Zeit benötigt und in dieser Zeit ist der Ausgang 0. Ich meine jedenfalls kleine Wackler zwischen den Steps zu sehen.
-Dass die serielle Kommunikation mit dem dfPlayer Probleme an Pin 9 verursacht hat, lag natürlich an einem Lötfehler.
Hab von PullDown auf die interne PullUp Funktion umgestellt. Im Moment sind noch keine Serienwiderstände an den Schaltern, das hab ich aber vor. Wie sollte ich die bemessen?
-Das Display lässt sich sehr gut an 3,3V betreiben, die sind aber immernoch zu hell. 2,8 wären bei dunkler Raumumgebung optimal. Beim Experimentieren mit einer Diode in Serie hab ich rausgefunden, dass die 3,3V vom Nanoklon in wirklichkeit 3,8 sind. Ein anderer Nano den ich hier rumliegen hab macht 3,7V, hätte also nichts verbessert. mit 2 Dioden war die Spannung zu klein, mit einer zu groß. Nach etwas fruchtlosem rumhirnen und Käseschaltungen mit Dioden und Widerständen hatte ich die glorreiche Idee, die 16Bit PWM vom zweiten Pin zu nehmen, gleichzufiltern und als Versorgung zu verwenden. Der Nano kann pro Pin maximal 40mA, hab dann für das RC-Glied 100 Ohm genommen, dann fließen maximal 25mA, 1000µF als C und zack feddich ist die Dimmfunktion. Das kann jetzt wirklich große Helligkeitsunterschiede abdecken. Die Interne Dimmingfunktion verwende ich aber weiter, weil das Display bei knapper Spannungsversorgung sonst zu Flimmern beginnt. Das Display ist übrigens überhaupt kein Stromfresser. Auf volle Lotte nimmt sich das ~17mA, aber bei normalen Leuchtstärken reichen 3-10.
Damit ich von der Dimmfunktion auch was hab, hab ich nen Fotowiderstand mit nem 5k Widerling zu nem Spannungsteiler verheiratet und kann jetzt die Helligkeit der Umgebung automatisch anpassen.
Am Gehäuse bin ich auch soweit fertig. Leider bin ich im Planen nicht so strukturiert, und habe vorher nicht überlegt, wie ich die Lautsprecher im Gehäuse festschrauben will, wenn das Gehäuse mal zusammengebaut ist. Aber wer kennt nicht die alte Bastlerweisheit, "wer es nicht im Kopf hat, nimmt Heißkleber" Passiert sowas eigentlich nur mir? Geht ganzschön eng zu dadrinnen. Ich verschätz mich immer beim Platzbedarf der Elektronik. Hier ist es nochmal gutgegangen. Ohne Heißkleb wär ich aufgeschmissen. Die LED sind mit Endsieg befestigt. Hatte davor den Plan, das zu schrauben, aber der ist am nicht vorhandenen m2 Gewindeschneider gescheitert. Für Federklemmen ist da kein Platz.
Außerdem zu sehen der Fotoresistor. Hatte keine Lust, ein extra Loch in die Front zu bohren. Mach ich die Lichtmessung während des Weckvorgangs halt aus. Der Mosfet und die Vorwiderstände sowie eine 2A Sicherung sind unterm Reflektor. Da geh ich nochmal ran, wollte noch ne kleine Patine für die Widerlinge spendieren (ist noch Freiluftverdrahtung) und die Werte etwas nach oben anpassen. die haben jetzt 0,9 Ohm, da fließt bei 12,2V Versorgung, die aus dem Netzteil kommen 600mA und die steigen bei längerer Vollast nochmal deutlich an. Bei 40°C am Aluträger warens schon 2x700mA und hier wirds gut warm im Sommer, da können das sicher auch mal 60°C werden. Können sollten sie 1A pro Stück, da käme dann die Sicherung, aber da muss ichs ja nicht drauf ankommen lassen und das macht WIRKLICH gut Hell. *blinzel* Ich kann also etwas Reserve verschmerzen. Hirnlose Käseschaltung. Da hab ich das Gehäuse zum ersten Mal fertig aufgebaut, es fehlt aber noch die Mattierungsfolie für die Plexiglasscheibe. Mehr gibts später, hier gibts jetzt Futter.
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Okay, ich hab etwas mit dem armeleuteDAC rumgespielt und finds echt super. Das macht jetzt das Display so dunkel, dass es im gedimmten Zustand bei heller Umgebung aussieht, als sei es aus. Das lässt sich merkwürdiger Weise nicht wirklich fotografieren, das sieht immer heller aus, als es ist. Jedenfalls ist der Dimmbereich jetzt groß genug und fein aufgelöst, sodass es bei Nacht nicht unangenehm blendet. Die ungünstige Sensorposition merkt man schon etwas, aber dafür hab ich eine Kompensationsvariable eingebaut, mit der man es auf den Standort anpassen kann. So'n Lichtwecker wird ja nicht die ganze Zeit rumgetragen.
Der dfPlayer rauscht etwas, obwohl er eigentlich im Sleepmodus sein müsste, das sah mir schon beim Stromverbrauch merkwürdig aus. das muss ich mir nochmal genauer anschauen. Klanglich ist das aber echt in Ordnung. wer mit mono auskommt ist damit echt gut bedient.Ich hab 2 3W Speaker in Reihe dran und bei basslastiger Musik kriegen die hörbar zuviel auf Vol=30. Den Fade-in vom Sound mach ich in der MP3, da hab ich mehr Kontrolle und bessere Möglichkeiten. Geplant sind noch mehr Auswahl an verschiedene Aufwachgeräuschen wie anderes Vogelgezwitscher, oder Meeresrauschen, aber wirklich spannend fänd ich randomisiert mal mit Gewitter geweckt zu werden, oder mit nem Aufwachenden Festival. HEEELGA!
Noch besser wenn er sich online das Wetter holt und den passenden Sound abspielt. Aber da bräuchts dann wohl nodeMCU, soweit bin ich noch nicht.
Bin grad noch an den Zeitlichen Abläufen verhakt, ich hab wegen meiner Matheminderbemittelung ;-P den Logarithmus etwas blöd implementiert und kann daher nicht ausrechnen, wie oft die Routine aufgerufen werden muss, bis sie bei #Endwert ankommt. Hab das daher experimentell ermittelt und dann passend hinmultipliziert. Ich steig grade selber nicht mehr durch. das könnte man bestimmt eleganter lösen und ich werd das auch nochmal durchbürsten, aber fürs erste tuts.
So ganz knickfrei kommt mir das trotzdem nicht vor. Das ist auch garnicht so leicht zu 'sehen' son Helligkeitsverlauf mit so großen Intensitätsunterschieden.
und im loop steht noch
Ich mach morgen wenn die Sonne wieder da ist nochmal Fotos, versprochen
Der dfPlayer rauscht etwas, obwohl er eigentlich im Sleepmodus sein müsste, das sah mir schon beim Stromverbrauch merkwürdig aus. das muss ich mir nochmal genauer anschauen. Klanglich ist das aber echt in Ordnung. wer mit mono auskommt ist damit echt gut bedient.Ich hab 2 3W Speaker in Reihe dran und bei basslastiger Musik kriegen die hörbar zuviel auf Vol=30. Den Fade-in vom Sound mach ich in der MP3, da hab ich mehr Kontrolle und bessere Möglichkeiten. Geplant sind noch mehr Auswahl an verschiedene Aufwachgeräuschen wie anderes Vogelgezwitscher, oder Meeresrauschen, aber wirklich spannend fänd ich randomisiert mal mit Gewitter geweckt zu werden, oder mit nem Aufwachenden Festival. HEEELGA!
Noch besser wenn er sich online das Wetter holt und den passenden Sound abspielt. Aber da bräuchts dann wohl nodeMCU, soweit bin ich noch nicht.
Bin grad noch an den Zeitlichen Abläufen verhakt, ich hab wegen meiner Matheminderbemittelung ;-P den Logarithmus etwas blöd implementiert und kann daher nicht ausrechnen, wie oft die Routine aufgerufen werden muss, bis sie bei #Endwert ankommt. Hab das daher experimentell ermittelt und dann passend hinmultipliziert. Ich steig grade selber nicht mehr durch. das könnte man bestimmt eleganter lösen und ich werd das auch nochmal durchbürsten, aber fürs erste tuts.
So ganz knickfrei kommt mir das trotzdem nicht vor. Das ist auch garnicht so leicht zu 'sehen' son Helligkeitsverlauf mit so großen Intensitätsunterschieden.
Code: Alles auswählen
void alarm(){
//Sonnenaufgang: (neuer Fade:) nach #Zeitintervall wird der bisherige Helligkeitswert mit 1,01 multipliziert.
//20Minuten Fade
//MP3Start nach 10Minuten
//Anpassung auf 16Bit PWM
const int upSpeed=944; //(944neu=>20 Minuten, 100=>127sek.) sets Interval for multiplication of fadeVal(fade in)
//kleinere Werte=schnellerer Fade
const int dnSpeed=6; //(6) sets Interval for division of fadeVal (fade out)
const byte lowMinim=15; // Offset für Einstellung der niedrigsten Helligkeitsstufe, damit der langsame Teil des Fades auch im nützlichen Helligkeitsbereich ist
unsigned long fadeTime=(millis()-fadePointer);
// nicht mehr benötigt: fadeTime=constrain(fadeTime, 0, 1800000);
//Alarm Stufe 1: Sonnenaufgang, Gezwitscher
if (AlarmState==1 && fadeTime < 1200000){
//Start Audio
if(fadeTime>600000 && playing==0){ //10min nach Beginn(900K Millisekunden)
myMP3.wakeUp(); //soll nur einmal ausgeführt werden
delay(10);
myMP3.play(1); //spielt Vogelgezwitscher,
playing=1; //
}
if ((fadeZaehl+upSpeed)<fadeTime && fadeULong<4901480){ //Funktion wird ausgeführt, solange keine 5M erreicht werden können
fadeZaehl=fadeTime;
fadeULong=(fadeULong*1.01); //
fadeVal=fadeULong/76.3+lowMinim; //5000000/76,3= 65535, der 100%wert für PWM, map() macht mist
fadeVal=constrain(fadeVal, 0, 65535);
}
analogWrite16(ledPin, fadeVal);
}
//Immernoch Stufe 1 aber Vollgas Licht jetzt, Exit to 2
if (AlarmState==1 && fadeTime > 1199999){
if (fadeTime > 1199999){ //wenn nah genug an 5M, weiter bei AlarmState2, =5M
fadeULong=5000000; //maximum Warp
fadeVal=65535;
}
// Maximum, ist erreicht(1800000ms/30 Minuten preset)
if (fadeTime>1799999){
AlarmState=2;
}
analogWrite16(ledPin, fadeVal);
}
//Alarm Stufe 2: Vollgas Licht, laute Weck-Musik
if(AlarmState==2){ //schläft noch&& bisherige Maßnahmen zeigten keine Wirkung
fadeULong=5000000; //maximum Warp
fadeVal=65535;
if(playing!=2){
myMP3.play(2); //spielt laute Weckroutine
playing=2;
}
if (fadeTime>2400000){
myMP3.play(2); //<-Track erstellen und reinkopieren, nummer hierhin //35minuten Neuer, aggressiver Wecktrack, volle Lautstärkespielt laute Weckroutine
playing=2;
}
if (fadeTime>2100000){ //40 Minuten. genug geweckt, ist keiner Da-> ausschalten!
fadeULong=100;
fadeVal=0;
analogWrite16(ledPin, 0);
fadeZaehl=0;
AlarmState=0;
playing=0;
myMP3.sleep();
AlarmV=false;
}
analogWrite16(ledPin, fadeVal);
}
//Alarm Stufe3: ist wach, braucht aber noch Licht, Fadeval bleibt auf bisherigem Wert (||fester, angenehmer Wert?)
if(AlarmState==3){
if(playing!=3||playing==1){
myMP3.play(3); //angenehme leise Musik
playing=3;
}
analogWrite16(ledPin, fadeVal);
}
//Alarm Stufe 4: Es wird aufgestanden, Licht kann ausfaden, kleiner Soundschnipsel als Bestätigung
if(AlarmState==4&&fadeULong>100){ //steht jetzt auf Licht soll ausfaden
if(playing!=4){
myMP3.play(4); //sound +1Up Mario
playing=4;
}
if ((fadeZaehl+dnSpeed)<fadeTime){
fadeZaehl=fadeTime;
fadeULong=(fadeULong/1.01);
fadeVal=(fadeULong/76.3);
fadeVal=constrain(fadeVal, 0, 65535);
analogWrite16(ledPin, fadeVal);
}
}
if(AlarmState==4&&fadeULong<101){ //Fade ist durch, alles zurück auf Ausgangswerte/abschalten
fadeULong=100;
fadeVal=1;
analogWrite16(ledPin, 0);
fadeZaehl=0;
AlarmState=0;
playing=0;
myMP3.sleep();
AlarmV=false;
}
}
Code: Alles auswählen
if(AlarmV==true &&AlarmState==0 && hours==rAhours && mins==rAmins){ //30min früher als Amins/Ahours wg Dauer d Sonnenaufgang
fadePointer=millis();
und
if(AlarmState>0){
alarm();
}
Re: Lichtwecker n+1, Arduino
Sieht gut aus
Noch ein Wort zum Code. Hab nur schnell drüber geschaut. Wieso das PWM so spring kann ich Dir nicht genau sagen. Kann auch an der menschlichen Wahrnehmung liegen. Bei geringeren Helligkeit werden auch kleine Änderungen stark wahrgenommen.
Die Berechnung der Werte zur Laufzeit ist eigentlich unüblich. Hier ist es aber wahrscheinlich egal, da der µC sich eh langweilt und eigentlich schon den nächsten Schritt vorbereiten könnte, während er wartet.
Ich hab das damals mit einer Look Up Table gelöst. So konnte ich jeden beliebigen Helligkeitsverlauf einstellen. Man könnte sogar den örtlichen Sonnenaufgang mit loggen und verwenden
Nächster Schritt, Schlafphasen Wecker, oder?
Noch ein Wort zum Code. Hab nur schnell drüber geschaut. Wieso das PWM so spring kann ich Dir nicht genau sagen. Kann auch an der menschlichen Wahrnehmung liegen. Bei geringeren Helligkeit werden auch kleine Änderungen stark wahrgenommen.
Die Berechnung der Werte zur Laufzeit ist eigentlich unüblich. Hier ist es aber wahrscheinlich egal, da der µC sich eh langweilt und eigentlich schon den nächsten Schritt vorbereiten könnte, während er wartet.
Ich hab das damals mit einer Look Up Table gelöst. So konnte ich jeden beliebigen Helligkeitsverlauf einstellen. Man könnte sogar den örtlichen Sonnenaufgang mit loggen und verwenden
Nächster Schritt, Schlafphasen Wecker, oder?
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Ah stimmt, ein Array zu nehmen hatte ich zu Beginn überlegt, aber dann bin ich in Calc daran gescheitert, mir den Verlauf logarithmisch zu erechnen. Von Hand war mir natürlich zu blöd das auszurechnen, außerdem war das doof mit nur 255 Werten. große Sprünge am Ende einer grob aufgelösten Skala.
Ich dachte dann auch, ich müsste ja eigentlich nur die Funktion umkehren, also wieviel y für x, damit ich wenigstens immer nur Sprünge von +-1 hätte, aber in unterschiedlich viel Zeit und das war dann völlig außerhalb meiner Fähigkeiten.
Also hab ich angefangen runzusuchen und bin auf diese Idee gestoßen.¯\_(ツ)_/¯
Ich dachte dann auch, ich müsste ja eigentlich nur die Funktion umkehren, also wieviel y für x, damit ich wenigstens immer nur Sprünge von +-1 hätte, aber in unterschiedlich viel Zeit und das war dann völlig außerhalb meiner Fähigkeiten.
Also hab ich angefangen runzusuchen und bin auf diese Idee gestoßen.¯\_(ツ)_/¯
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Okay, mir ist was eingefallen, wie ich mir den Array erstelle, ich lass mir das über die serielle Schnittstelle ausgeben. Da kann ich dann auch gleich die passende Formatierung mit ausgeben lassen.
Das Gewackle bei den Stufen ist wahrscheinlich wirklich ein Wahrnehmungsproblem. So wie Nachbilder, wenn man zu lange in was Helles blickt.
hmm. Geraffel kommt mir beim Schlafen keins an den Körper und Sensorik am Bett ist mir glaub etwas zu umständlich. Der Lichtwecker macht ja im Grunde das gleiche. Es wird eine unterschwellige Störung erzeugt, die bei geringerer Schlaftiefe/Wachphase bemerkt wird. Der schlafphasen Wecker machts andersrum. Wachphase detektieren und dann gezielt stören. Ich glaube ich mag den Lichtwecker lieber, weil er eben unterschwellig arbeitet und nicht hart eingreift. Man hat die Wahl sich nochmal umzudrehen, ohne sich in die Snooze-Hölle zu begeben.Nächster Schritt, Schlafphasen Wecker, oder?
Außerdem hab ich da noch genug dran zu optimieren. Der dfPlayer schläft nicht und das Display macht auch nicht was es soll. (blinkende Digits, Dezimalpunkte) Ich hab eh den Plan, nen anderen DCDC Wandler einzusetzen, allerdings ziept der Player ein bißchen beim Powerup, sprich einfach nur den Wandler per Enable zu schalten ist blöd, weil das Lärm macht.
Die Reallife-Tests bisher standen unter keinem guten Stern. Ein mal dem Wecken unfassbar schlecht geschlafen und als er dann klingelte erstmal ausgeschaltet und 1,5h weitergepennt. Heute dann 3 Stunden vor dem Wecker wachgewesen. So wird das nix.
Bin auch noch nicht zum Bildermachen gekommen
-
- Beiträge: 259
- Registriert: So 28. Aug 2016, 20:31
- Wohnort: Südliches Niedersachsen
Re: Lichtwecker n+1, Arduino
Schlafphasen nachrüsten ist kein großer Aufwand, da reichen zwei Dehnungsmessstreifen aus einer Personenwaage unter den Füßen vom Bett. Das habe ich vor ein paar Jahren mal gemacht. Die Software überwacht die Schwankungen der Gewichtsverteilung und weckt ab einem bestimmten Grenzwert. Ich kann wenn gewünscht die Tage mal die Software dazu suchen.
- Bastelbruder
- Beiträge: 11559
- Registriert: Mi 14. Aug 2013, 18:28
Re: Lichtwecker n+1, Arduino
Zwei Dehnungsmeßstreifen, was für ein Aufwand!
Da war mal eine Geschichte mit Milchschüssel und Kochlöffel an den Matratzenfedern.
Ein Pendel mit einem kleinen Magnet, und drunter liegt eine Spule. Damit hab ich vor gut 35 Jahren eine Autoalarmanlage mit Funkalarmierung gebaut. Die Idee war aus Elektor.
Da war mal eine Geschichte mit Milchschüssel und Kochlöffel an den Matratzenfedern.
Ein Pendel mit einem kleinen Magnet, und drunter liegt eine Spule. Damit hab ich vor gut 35 Jahren eine Autoalarmanlage mit Funkalarmierung gebaut. Die Idee war aus Elektor.
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Naja, die Sensorik am Bett ist eine Sache, wobei mein Bett in KA keine Füße hat,(und keinen Bodenkontakt, an der Wand montiertes Hochbett) aber das ließe sich sicher am Lattenrost umgehen. Man muss die Sensoren aber auch irgendwie an den Wecker weiterleiten und ich möchte abgesehen vom Netzkabel da nichts reinführen, das hieße dann separate Stromversorgung und Funkmodule.
@Lüsterklemme: Danke für das Angebot, aber im Moment möchte ich das Dingens erstmal konsolidieren. Da ist wirklich noch genug dran, was noch nicht da ist, wo ich es haben will, und jetzt möchte ich erstmal rausfinden, wie ich das finde, vom Lichtwecker geweckt zu werden, und wie das für mich zu sein hat. Wenn das dann fertig ist, bleibt immernoch Platz für "feature creep".
Habe nur grade das "Problem" keinen Wecker zu brauchen, wenn die Sonne schon oben ist, merkt man von den 14W LED-Power gar nicht mal so viel. Die müssten dann schon direkt von oben kommen, die Jalousien lassen zu viel Sonnenlicht durch. Das langsam lauter werdende Gezwitscher ist aber wirklich nice, langsames Aufwachen ohne Weckschock.
@Lüsterklemme: Danke für das Angebot, aber im Moment möchte ich das Dingens erstmal konsolidieren. Da ist wirklich noch genug dran, was noch nicht da ist, wo ich es haben will, und jetzt möchte ich erstmal rausfinden, wie ich das finde, vom Lichtwecker geweckt zu werden, und wie das für mich zu sein hat. Wenn das dann fertig ist, bleibt immernoch Platz für "feature creep".
Habe nur grade das "Problem" keinen Wecker zu brauchen, wenn die Sonne schon oben ist, merkt man von den 14W LED-Power gar nicht mal so viel. Die müssten dann schon direkt von oben kommen, die Jalousien lassen zu viel Sonnenlicht durch. Das langsam lauter werdende Gezwitscher ist aber wirklich nice, langsames Aufwachen ohne Weckschock.
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Ich hab mal in meinem Kaninchenbau weitergebuddelt.
Ich habe jetzt endlich auch mal welche von den guten DCDC-Wandlern erhalten und eingebaut. ursprünglich war der Plan, dass der Arduino den Wandler bei Bedarf (Audio/Musik soll abgespielt werden -> dfPlayer braucht saft) über Enable anmacht. Dafür muss man dann aber auch am dfPlayer den Enable vom Verstärker betätigen, weil sonst bei jedem mal an/aus Gepupse aus den Lautsprechern kommt. Der dfPlayer macht mit dem Pin nichts (Der hängt dauerhaft mit 0 Ohm auf Masse=An), der 0Ohm Widerling muss also weg und da kommt dann der Enable Ausgang vom Arduino hin. Ist etwas hakelig, weil son SMD-Lötpäd nicht viel aushält und die Leitung ja irgendwie zum Arduino geführt werden muss. Ich hab das mit ner Zugentlastung aus Heißkleb gelöst. schöner wäre, einen der Pins vom dfPLayer umzuwidmen, da gibts ja genug, die hier nicht benutzt werden, war mir aber zu umständlich.
Da hab ich dann verschiedene Möglichkeiten durchprobiert, die Variante mit dem geringsten Stromverbrauch war, den Arduino am Wandler zu haben, der ist dann natürlich immer an, der dfPlayer wird über Diode +Elko versorgt (dfPlayer möchte am liebsten 4,2V und nicht 5), der Amp wird nur bei Bedarf aktiviert über den herausgeführten Enable.
Damit hab ich jetzt nur nen leisen Knackser, wenn Audioplayback aktiviert wird. Das passiert, wenn ich noch schlafe, stört also nicht. Langfristig kommt da noch ein Stereo-Amp dran, (PAM-irgendwas) dann werd ich hoffentlich auch den Knackser los.
Ich hab nochmal n anderes Display ausprobiert, mit ht16k33, wegen der indicator-Dots. Die Library von Adafruit ist riesig und umständlich, mit ner anderen gehts ganz gut, Aaaaber: Der gehackte Displayhelligkeits-DAC bringt da nichts, weil aus den Datenpins Strom in die Versorgung leakt und die damit immer bei 100% ist, selbst wenn aus dem PWM-Pin garnichts kommt. Widerstände in der Datenleitung sind entweder zu klein oder verhindern die Kommunikation. Das Display hat zwar 16 Helligkeitsstufen, aber die dunkelste ist wieder mal ziemlich hell, macht also keinen Spaß. Außerdem ist das Rot, das gefällt mir nicht. Muss wohl doch noch ne Led in die Front rein, am besten auch mit Dimming. -> toDo
Am Code hab ich auch nochmal einiges getan, kleine Bugs ausgemerzt und ne Lampenfunktion mittels Doppelklick implementiert. Die Helligkeit wird dann mit dem Encoder eingestellt, man kann ihn auch als Nachtlicht verwenden.
Das mit der Lookup table/Array hab ich gelassen, weil kein Platz!
Mein Sketch hat jetzt 93% ( Nano v3 mit ATmega168), Serielle Kommunikation zum PC musste ich schon rauskanten. Das Meiste werden wohl die Libs sein, aber ohne die bekomm ichs nicht hin.
Bei der aktuellen Auflösung (1/sekunde, 30minuten, 16Bit) bekomm ich das auf keinen Fall unter.
Ich hätte gerne dass der Encoder bei schnellem Drehen beschleunigt, dann müsste man nicht mehr zwischen Stunden und Minuten umschalten, da mach ich vllt noch was dran.
Es gibt es 4 Weckphasen,mit jeweils eigenen Soundtypen, aufgeteilt in eigene Verzeichnisse:
1. Ambient Sounds zum Aufwachen. Der Fade wird in die MP3Datei geschrieben, damit hab ich dann 16bit Auflösung ohne weitere Verrenkungen. Sounds haben 20 Minuten, der Fade geht über die komplette Länge. Der Alarm dauert 30 Minuten, nach 12 Minuten startet Audioplayback
2. aggressives Weckaudio immernoch zum Auffwachen, falls der Schläfer nach Ablauf von 1. noch hochohmig ist
3. angenehme Weckmusik. Ausgewählte Musik, die ich gerne zum Aufwachen hören möchte, Licht wird auf 30% gedimmt mit zwischenFade
4. kurzer Bestätigungssound, dass Alarm abgeschlossen ist (zb Super Mario +1Up), Licht->Fadeout
In jeden Ordner können max 255 Dateien rein, die werden dann zufällig ausgewählt, dann hat man nicht immer den gleichen Gockel der so nervig kräht, sondern etwas mehr Vielfalt. Die Anzahl der Dateien werden in Setup abgefragt, man kann also einfach beliebige Dateien dazupacken und sie werden automatisch berücksichtigt. Weil mir random() die Tracks immer in der gleichen Reihenfolge präsentiert hat, hab ich randomSeed im Setup, Quelle ist millis()+Usereingabe, nach Powerup zeigt das Display erstmal nur millis() an, bis man auf den großen Knopf drückt. Den muss man auch halten wenn man die Weckzeit einstellen will.
Während der Alarmphasen 1 und 3 wird abwechselnd verbliebene Weckzeit bis t=0 und aktuelle Uhrzeit angezeigt. Bei Phase 1 sind das 30 Minuten, bei Phase 3 ist der Proband schon wach und hat 10 Minuten zum Anziehen. Drückt er in dieser Zeit nicht auf den Arcade-Button, schaltet sich der Gerät von alleine ab.
Wenn man die normale Uhrzeit einstellen möchte, passiert das über die Weckzeit und einen langen(>5s Drücker auf den roten Knopf. Die Uhrzeit wird on release geschrieben, man kann also die aktuelle Uhrzeit+1 Minute einstellen und dann den Knopf solange gedrückt halten, bis eine genaue Uhr die nächste Minute anzeigt. Viele Arduino-Sketches zum Thema Uhr verwenden IDE um die Uhrzeit einzustellen, das finde ich ziemlich umständlich, ich will den Wecker ja nicht 2x im Jahr an den Rechner hängen müssen. Bis die EU mit der Zeitumstellung in die Pötte kommt, kann das sicher noch dauern.
Der Encoder ist zum Einstellen der Weckzeit wirklich toll, viel besser als diese "Knopf drücken und Halten-Lotterie". Musste wg eines Bugs die letzten Nächte die Weckzeit jedes Mal neu stellen und das geht selbst mit mächtig einen im T schnell und ohne den WAF zu beeinträchtigen. Der ist übrigens kristallgrün, sie meint, ich sollte in Serienfertigung gehen.
hier ist der aktuelle Code:
Ich habe jetzt endlich auch mal welche von den guten DCDC-Wandlern erhalten und eingebaut. ursprünglich war der Plan, dass der Arduino den Wandler bei Bedarf (Audio/Musik soll abgespielt werden -> dfPlayer braucht saft) über Enable anmacht. Dafür muss man dann aber auch am dfPlayer den Enable vom Verstärker betätigen, weil sonst bei jedem mal an/aus Gepupse aus den Lautsprechern kommt. Der dfPlayer macht mit dem Pin nichts (Der hängt dauerhaft mit 0 Ohm auf Masse=An), der 0Ohm Widerling muss also weg und da kommt dann der Enable Ausgang vom Arduino hin. Ist etwas hakelig, weil son SMD-Lötpäd nicht viel aushält und die Leitung ja irgendwie zum Arduino geführt werden muss. Ich hab das mit ner Zugentlastung aus Heißkleb gelöst. schöner wäre, einen der Pins vom dfPLayer umzuwidmen, da gibts ja genug, die hier nicht benutzt werden, war mir aber zu umständlich.
Da hab ich dann verschiedene Möglichkeiten durchprobiert, die Variante mit dem geringsten Stromverbrauch war, den Arduino am Wandler zu haben, der ist dann natürlich immer an, der dfPlayer wird über Diode +Elko versorgt (dfPlayer möchte am liebsten 4,2V und nicht 5), der Amp wird nur bei Bedarf aktiviert über den herausgeführten Enable.
Damit hab ich jetzt nur nen leisen Knackser, wenn Audioplayback aktiviert wird. Das passiert, wenn ich noch schlafe, stört also nicht. Langfristig kommt da noch ein Stereo-Amp dran, (PAM-irgendwas) dann werd ich hoffentlich auch den Knackser los.
Ich hab nochmal n anderes Display ausprobiert, mit ht16k33, wegen der indicator-Dots. Die Library von Adafruit ist riesig und umständlich, mit ner anderen gehts ganz gut, Aaaaber: Der gehackte Displayhelligkeits-DAC bringt da nichts, weil aus den Datenpins Strom in die Versorgung leakt und die damit immer bei 100% ist, selbst wenn aus dem PWM-Pin garnichts kommt. Widerstände in der Datenleitung sind entweder zu klein oder verhindern die Kommunikation. Das Display hat zwar 16 Helligkeitsstufen, aber die dunkelste ist wieder mal ziemlich hell, macht also keinen Spaß. Außerdem ist das Rot, das gefällt mir nicht. Muss wohl doch noch ne Led in die Front rein, am besten auch mit Dimming. -> toDo
Am Code hab ich auch nochmal einiges getan, kleine Bugs ausgemerzt und ne Lampenfunktion mittels Doppelklick implementiert. Die Helligkeit wird dann mit dem Encoder eingestellt, man kann ihn auch als Nachtlicht verwenden.
Das mit der Lookup table/Array hab ich gelassen, weil kein Platz!
Mein Sketch hat jetzt 93% ( Nano v3 mit ATmega168), Serielle Kommunikation zum PC musste ich schon rauskanten. Das Meiste werden wohl die Libs sein, aber ohne die bekomm ichs nicht hin.
Bei der aktuellen Auflösung (1/sekunde, 30minuten, 16Bit) bekomm ich das auf keinen Fall unter.
Ich hätte gerne dass der Encoder bei schnellem Drehen beschleunigt, dann müsste man nicht mehr zwischen Stunden und Minuten umschalten, da mach ich vllt noch was dran.
Es gibt es 4 Weckphasen,mit jeweils eigenen Soundtypen, aufgeteilt in eigene Verzeichnisse:
1. Ambient Sounds zum Aufwachen. Der Fade wird in die MP3Datei geschrieben, damit hab ich dann 16bit Auflösung ohne weitere Verrenkungen. Sounds haben 20 Minuten, der Fade geht über die komplette Länge. Der Alarm dauert 30 Minuten, nach 12 Minuten startet Audioplayback
2. aggressives Weckaudio immernoch zum Auffwachen, falls der Schläfer nach Ablauf von 1. noch hochohmig ist
3. angenehme Weckmusik. Ausgewählte Musik, die ich gerne zum Aufwachen hören möchte, Licht wird auf 30% gedimmt mit zwischenFade
4. kurzer Bestätigungssound, dass Alarm abgeschlossen ist (zb Super Mario +1Up), Licht->Fadeout
In jeden Ordner können max 255 Dateien rein, die werden dann zufällig ausgewählt, dann hat man nicht immer den gleichen Gockel der so nervig kräht, sondern etwas mehr Vielfalt. Die Anzahl der Dateien werden in Setup abgefragt, man kann also einfach beliebige Dateien dazupacken und sie werden automatisch berücksichtigt. Weil mir random() die Tracks immer in der gleichen Reihenfolge präsentiert hat, hab ich randomSeed im Setup, Quelle ist millis()+Usereingabe, nach Powerup zeigt das Display erstmal nur millis() an, bis man auf den großen Knopf drückt. Den muss man auch halten wenn man die Weckzeit einstellen will.
Während der Alarmphasen 1 und 3 wird abwechselnd verbliebene Weckzeit bis t=0 und aktuelle Uhrzeit angezeigt. Bei Phase 1 sind das 30 Minuten, bei Phase 3 ist der Proband schon wach und hat 10 Minuten zum Anziehen. Drückt er in dieser Zeit nicht auf den Arcade-Button, schaltet sich der Gerät von alleine ab.
Wenn man die normale Uhrzeit einstellen möchte, passiert das über die Weckzeit und einen langen(>5s Drücker auf den roten Knopf. Die Uhrzeit wird on release geschrieben, man kann also die aktuelle Uhrzeit+1 Minute einstellen und dann den Knopf solange gedrückt halten, bis eine genaue Uhr die nächste Minute anzeigt. Viele Arduino-Sketches zum Thema Uhr verwenden IDE um die Uhrzeit einzustellen, das finde ich ziemlich umständlich, ich will den Wecker ja nicht 2x im Jahr an den Rechner hängen müssen. Bis die EU mit der Zeitumstellung in die Pötte kommt, kann das sicher noch dauern.
Der Encoder ist zum Einstellen der Weckzeit wirklich toll, viel besser als diese "Knopf drücken und Halten-Lotterie". Musste wg eines Bugs die letzten Nächte die Weckzeit jedes Mal neu stellen und das geht selbst mit mächtig einen im T schnell und ohne den WAF zu beeinträchtigen. Der ist übrigens kristallgrün, sie meint, ich sollte in Serienfertigung gehen.
hier ist der aktuelle Code:
Code: Alles auswählen
//Lichtwecker v0.9
//todo:
//-> tm1637 bleibt. Separate Led für Alarmanzeige, wenn Zeit über. Soll auch gedimmt werden! (kompliziert?)
//
/*
*
Kann: Wecken mit 16bit Sonnenaufgang, dazu MP3 Abspielen. Es gibt 4 Weckzustande:
1. Sonnenaufgang, random MP3 aus Ordner1 wird abgespielt. dauert 30 Minuten
2. nach Ablauf von 1. ohne Interaktion kommt MP3 aus Ordner2 (lauteres, invasiveres Audio),
weiterhin volle Helligkeit
3. Wenn während 1. oder 2. der Ausknopf (Arcade/Button2) gedrückt wird, wird ein angenehmer H-Wert gesetzt und angenehme leise Musik(Ordner3) gespielt.
4. Wenn der Ausknopf erneut gedrückt wird, wird das Licht ausgefadet und abgeschaltet.
MP3 aus Ordner4 wird abgespielt (soll nur n kurzer Sound sein, unter 10s. Zu lang wird abgeschnitten wg ende des Fadeouts)
Weckzeit wird angezeigt bei gedrücktem Ausknopf(Button2) Eingestellt mittels Encoder,
Druck auf Encoder Pushbutton (Button0) wechselt Stunden/Minuten. Was gerade eingestellt wird,
kann im Moment noch nicht angezeigt werden.(todo, benötigt andere library)
Neue Uhrzeit wird eingestellt indem man die Uhrzeit als Weckzeit einstellt und dann den Alarm an/aus
Button (Button1) 5Sekunden oder länger hält. die Zeit wird on Button release geschrieben, man kann
also die nächste Minute einstellen, den Knopf gedrückt halten und im richtigen Moment loslassen und
hat eine sehr genau eingestellte Zeit.
Mit Doppelklick auf den Arcade Button (Button2) kann man die LED zu Beleuchtungszwecken verwenden, Über die Einstellung der Weckstunden
kann man die Intensität einstellen. Stufe 0 ist besonders Dunkel, zur Verwendendung als Nachtlicht.
Die Helligkeit des Displays wird automatisch der Umgebungshelligkeit angepasst. Zum Einlesen wird ein
Spannungsteiler zwischen 5v-Fotoresistor-5K_Ohm-GND Auf A7 eingelesen und nach Beschränkung auf
setBrightness gemappt.
*/
//DFPlayer mini
#include <SoftwareSerial.h>
#include <DFPlayerMini_Fast.h>
SoftwareSerial mySerial(A2, A1); // RX, TX
DFPlayerMini_Fast myMP3;
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68 //DS3231 Zeitgeber
//Tm1637
//#include <Arduino.h>
#include <TM1637Display.h>
// Module connection pins (Digital Pins)
#define CLK 5
#define DIO 4
TM1637Display display(CLK, DIO);
//Encoder
#include <Encoder.h>
Encoder myEnc(2, 3);
//Variablen
unsigned long schedulT = 0; //Aufrufe der Uhrzeit /DS3231 begrenzen auf 1x pro Sekunde
unsigned long fadePointer = 0; //wird bei Alarmauslösung gesetzt und dient zur Berechnung der Helligkeit während Alarmablaufs
unsigned long fadeZaehl=0; //siehe fadePointer
unsigned long LpTimer = 0; //erkennung von langen und kurzen Drückern auf button1 und button2. Kollision seeehr unwahrscheinlich
byte mins=0; // Uhrzeit Minuten
byte hours=0; // Uhrzeit Stunden
byte Amins=0; // Weckzeit Minuten
byte Ahours=0; // Weckzeit Stunden
byte rAmins=0; // Alarmbeginnzeit Minuten = 30 Minuten vor Weckzeit (r für real)
byte rAhours=0; // Alarmbeginnzeit Stunden
byte BrighVal=1; //Hwert Spwm
byte folder01 = 1; //wieviele Tracks in folder#?
byte folder02 = 1;
byte folder03 = 1;
byte folder04 = 1;
byte playing = 0; //(welches Verzeichnis)wird gerade abgespielt? 0=stop
byte AlarmState=0; //Wird gerade geweckt? Wo sind wir in der Weckfunktion?
bool AlarmV=false; //Weckfunktion an oder aus?
bool ZeigeAl=false; //Weckzeit anzeigen wenn true
//unsigned long fadeVal=1; //Helligkeitswert für analogWrite
unsigned long fadeULong=100; //Var für die Logarithmische Berechnung des Helligkeitswertes
// (war mal int, jetzt mehr Auflösung)
byte RestSchlaf=0; //Restschlafanzeige während Alarm
bool zeigeRS=false;
//bool lichtAn=false; //Var ist obsolet separate Leuchtfunktion an?
bool button2Pressed=false; //für lange und kurze drücker brauchts ne extra Var
bool button1Pressed=false; //für lange und kurze drücker brauchts ne extra Var
bool button0State = false;
bool button1State = false;
bool button2State = false;
byte encTarget=1; //encoder target wechselbar für Stunden/Minuten/Leuchtstärke
unsigned long debTimer=0; //Button debounce
int encVal = 0;
int realBrigh=1; //Durchschnittsbildung Helligkeitsmessung für Displayhelligkeit
//Eingänge
const byte button0Pin = 6; // the number of the Encoder pushbutton pin
const byte button1Pin = 7; // the number of other inputbuttons
const byte button2Pin = 13; // s.o.
const byte HellPin = A7; //Einlesen der aktuellen Helligkeit im Raum
//Ausgänge
const byte ledPin = 10; //(10)LED Treiber angeschlossen an Pin9 oder 10 (16Bit PWM)
const byte disPin = 9; //(9)Display Stromversorgung an armeleute DAC
//const byte DcdcEnPin = A3; //Obsolet: DCDC Enable, HIGH=An
const byte AmpEnPin = 8; //Amp Enable, High = Ausgeschaltet!
//------- nötig Zum Auslesen/schreiben von DS3231------------------------------------
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}
//--------------------------------------------------------------
//---------------------------------------------------------------
void setup(){
//Serial.begin(9600);
//I2C für DS3231
Wire.begin();
//Eingänge
pinMode (button0Pin, INPUT_PULLUP);
pinMode (button1Pin, INPUT_PULLUP);
pinMode (button2Pin, INPUT_PULLUP);
pinMode (2, INPUT_PULLUP); //encoder
pinMode (3, INPUT_PULLUP);
//Ausgänge
pinMode (AmpEnPin, OUTPUT);
//pinMode (DcdcEnPin, OUTPUT);
digitalWrite(AmpEnPin,HIGH); //Amp Aus
delay(10);
//digitalWrite(DcdcEnPin,HIGH); //DCDC an, DFPlayer an
//delay(600);
//serielle Verbindung zum DFplayer aufbauen
mySerial.begin(9600);
myMP3.begin(mySerial);
delay(400);
myMP3.volume(17); //Lautstärke
delay(10);
myMP3.EQSelect(3);
delay(10);
//byte volume = myMP3.currentVolume();
folder01 = myMP3.numTracksInFolder(01);
delay(10);
folder02 = myMP3.numTracksInFolder(02);
delay(10);
folder03 = myMP3.numTracksInFolder(03);
delay(10);
folder04 = myMP3.numTracksInFolder(04);
delay(10);
/*Serial.print("folder01 count");
Serial.println(folder01);
Serial.print("folder02 count");
Serial.println(folder02);
Serial.print("folder03 count");
Serial.println(folder03);
Serial.print("folder04 count");
Serial.println(folder04);
Serial.println("starting...");
delay(10); //Erkennung der Ordner, Anzahl Dateien */
//myMP3.sleep(); //Audio aus @Startup
//digitalWrite(DcdcEnPin, LOW); //Stromsparen
//TM1637
display.setBrightness(2);
//16bit PWM
setupPWM16(); //init
analogWrite16(ledPin, 0); //PWM an LED=0
analogWrite16(disPin, 55534); //PWM_DAC an Display=50000
while(digitalRead(button2Pin)==HIGH){
display.showNumberDec(millis(), true);
}
if (digitalRead(button2Pin)==LOW){
randomSeed(millis());
}
}
//---------------------------------------------
void setupPWM16() {
DDRB |= _BV(PB1) | _BV(PB2); /* set pins as outputs */
TCCR1A = _BV(COM1A1) | _BV(COM1B1) /* non-inverting PWM */
| _BV(WGM11); /* mode 14: fast PWM, TOP=ICR1 */
TCCR1B = _BV(WGM13) | _BV(WGM12)
| _BV(CS10); /* prescaler 1 */
ICR1 = 65535; /* TOP counter value (freeing OCR1A*/
}
//---------------------------------------------
//------------------------------
void analogWrite16(uint8_t pin, uint16_t val)
{
switch (pin) {
case 9: OCR1A = val; break;
case 10: OCR1B = val; break;
}
}
//-Helligkeitsanpassung Display-----------------------------------
void setBrigh(){
//wenn kein Alarm, Helligkeit anpassen
const int heller=1200; //Offset für Korrektur der Helligkeit, falls Anzeige zu dunkel.
int readBrigh = analogRead(HellPin); //Mittelwertbildung für Sprungfreiheit, wichtig wen Licht an ist (PWM-> springende Werte an/aus)
readBrigh=constrain(readBrigh, 0, 600);
realBrigh=(80*realBrigh+readBrigh)/81;
byte writeBrigh = map(realBrigh, 0, 600, 1,4); //Dimminfunktion _im_ Display, ist nötig, da sonst der Strom bei wenig licht zu groß ist und Display flimmert.
unsigned int disDAC= map(readBrigh, 0, 600, 34000, 62535); //Wenn unterer Wert zu niedrig geht nix oder flimmerts, bei Vollgas ist die Stromaufnahme zu hoch für den PWM-Pin(?)
/*
Serial.print("Einlesewert: ");
Serial.println(readBrigh);
Serial.print("Wert Display: ");
Serial.println(writeBrigh);
Serial.print("Wert PWM: ");
Serial.println(disDAC);*/
display.setBrightness(writeBrigh); //1-4
if(readBrigh>80){ //unterhalb 80 ist das Licht aus-> dunkles Display
analogWrite16(disPin, constrain((disDAC+heller), 34000, 62535)); //65535 PWM_DAC an Display
}
if(readBrigh<81){
analogWrite16(disPin, disDAC); //65535 PWM_DAC an Display
}
}
//---^setbrigh^----
//---dispTm1637 Anzeigefunktion----------------
void dispTm1637(byte Verbleib){
// Create time format to display:
int displaytime = 0;
if (Verbleib<1){
if(ZeigeAl==false && RestSchlaf<1){
displaytime=(hours * 100) + mins; //aktuelle Uhrzeit anzeigen
}
if(ZeigeAl==true ){
displaytime=(Ahours * 100) + Amins; // Alarmzeit anzeigen/einstellen
}
}
if (RestSchlaf>0){ //verbleibende Zeit im Sonnenaufgang
displaytime=Verbleib;
}
//Alarm An/Aus wird über den Doppelpunkt angezeigt
if (AlarmV){
display.showNumberDecEx(displaytime, 0b11100000, !Verbleib); //Wenn Alarm an, Doppelpunkt an. (...~decEx) die Lib nervt hart, das Display nervt, der Chip auch D:
} //shownumberDecEx(AnzuzeigendeZahl, DoppelpunktAn, padding/w Zeroes)
//zero-Padding soll während Anzeige von Restschlaf aus sein wg Verwechslungsgefahr mit aktueller Uhrzeit
if (!AlarmV){ //deswegen !Verbleib
display.showNumberDec(displaytime, !Verbleib); //wenn Alarm aus, Doppelpunkt aus.
}
}
//------------- /tm1637--------------------------
//-----audioPlbk()-------------
void audioPlbk(byte what){
//wenn gespielt wird, ales an ist und jetzt ausgeschaltet werden soll
if (playing && !what){
//myMP3.volume(0); //PopKlickVerhinderungsversuch
//delay(10);
//Serial.println("Amp ausschalten");
digitalWrite(AmpEnPin, HIGH); //AMP ausschalten(HIGH=aus!)
//delay(20);
//Serial.println("DCDC ausschalten");
//digitalWrite(DcdcEnPin, LOW); //DCDC aus
delay(10);
//digitalWrite(DcdcEnPin, LOW);
}
//Wenn nicht gespielt wird und daher alles aus ist, anschalten
if(!playing && what){
//Serial.println("DCDC Anschalten");
//digitalWrite(DcdcEnPin, HIGH); //DCDC an
//delay(1000);
//Serial.println("Volume 0");
myMP3.volume(0);
delay(20);
//Serial.println("Amp Anschalten");
digitalWrite(AmpEnPin, LOW); //AMP anschalten(HIGH=aus!)
//Serial.println("Volume 17");
myMP3.volume(17); //Lautstärke einstellen wg powercycle
}
//Was soll gespielt werden?
if (playing!=what){
if (what==1){
myMP3.playFolder(what, random(1,folder01));
}
if (what==2){
myMP3.playFolder(what, random(1,folder02));
}
if (what==3){
myMP3.volume(14); //etwas leiser als Alarm, ist Musik und daher höherer RMS als Ambient.
delay(10);
myMP3.playFolder(what, random(1,folder03));
}
if (what==4){
myMP3.playFolder(what, random(1,folder04));
}
//Serial.print("Spiele folder ");
//Serial.println(what);
playing=what;
}
}
//-----^audioPlbk()^-------------
void encoder() {
int newPosition = (myEnc.read())/4 ; //Liest pro Rastung 4 neue Werte ein, daher /4
if (newPosition != encVal) {
encVal = newPosition;
}
}
//----^encoder^--------------------------------------
//---Knöpfe einlesen-----------------------------------------
void buttonLogic(){
button0State = digitalRead(button0Pin);
button1State = digitalRead(button1Pin);
button2State = digitalRead(button2Pin);
if(AlarmState==false&&(button2State==LOW||encTarget==2)){
encoder();
}
//Zeiteinstellung. Wenn encTarget=2 ist Licht an, dann wird über Encoder die Helligkeit eingegeben
if(debTimer < millis() && button0State==LOW && encTarget!=2){ //Button0 selects encoder Target to adjust minutes and hours
if (encTarget==0 && debTimer<millis()){
debTimer=(millis()+300);
encTarget=!encTarget;
encVal=Amins;
myEnc.write(Amins*4);
}
if (encTarget==1&& debTimer<millis()){
debTimer=(millis()+300);
encTarget=!encTarget;
encVal=Ahours;
myEnc.write(Ahours*4);
}
}
if (encTarget==0 && AlarmV==false && ZeigeAl){ //Stunden für Alarm setzen, Überlauf bei 23 Stunden bzw 59 Minuten
if (encVal>23){ //wenn Alarm=aktiv ist verstellen unmöglich
encVal=0; //Bug: Encoder wird weiter eingelesen, bei der
myEnc.write(encVal*4); //nächsten Anzeige von Weckzeit wird der neue
} //Encoderwert geschrieben, kann zu wertesprüngen führen. >LowPrio
if (encVal<0){
encVal=23;
myEnc.write(encVal*4);
}
Ahours=encVal;
}
if (encTarget==1&& AlarmV==false && ZeigeAl){ //Minuten, Überlauf
if (encVal>59){
Ahours=Ahours+1;
encVal=0;
myEnc.write(encVal*4);
}
if (encVal<0){
Ahours=Ahours-1;
encVal=59;
myEnc.write(encVal*4);
}
Amins=encVal;
}
//Variablenabgleich nach möglicher Veränderung von encVal, Amins/AHours sollen gleich bleiben und nicht springen
if(encTarget==1 && Amins!=encVal && !ZeigeAl){ //encTarget zeigt auf Minuten, soll also diesen Wert haben
encVal=Amins;
myEnc.write(encVal*4);
}
if(encTarget==0 && Ahours!=encVal && !ZeigeAl){ //encTarget zeigt auf Stunden, soll also diesen Wert haben
encVal=Ahours;
myEnc.write(encVal*4);
}
//bei Licht an, gehen die Werte bis 48, kein Überlauf zu 0/48 wg Blendwirkung von 0->48, dunkel nach hell, stattdessen Wert halten
if (encTarget==2){
if (encVal>48){
encVal=48;
myEnc.write(encVal*4);
}
if (encVal<0){
encVal=0;
myEnc.write(encVal*4);
}
Leucht(encVal);
}
//--Erkennung von kurzen/langen Drückern auf button1--
if(button1State==LOW && button1Pressed==false ){ //press-Event
LpTimer=millis();
button1Pressed=true;
}
if(button1State==HIGH && button1Pressed==true){ //release-Event
//kurzer Knopfdruck = umschalten Alarm an/aus
if(millis()-LpTimer>10 && millis()-LpTimer<5000){
AlarmV=!AlarmV; //Wenn Alarm an, Alarm= aus
if(AlarmV){ //Wenn Alarm an, rAmins&rAhours schreiben für früheren Sonnenaufgangsbeginn
if (Amins>29){
rAmins = Amins-30; //Umrechnung der 30 Minuten Vorlauf auf Stunden
rAhours = Ahours;
}
if (Amins<29 &&Ahours>0){
rAmins = Amins+30;
rAhours = Ahours-1;
}
if (Amins>29 && Ahours==0){
rAmins = Amins+30;
rAhours = 23;
}
}
button1Pressed=false;
}
//langer Knopfdruck = Uhrzeit setzen
if(millis()-LpTimer>4999&&AlarmV==false){
setDS3231time(); // schreibt aktuelle Amins&AHours in DS3231
button1Pressed=false;
}
}
//Button2 (Arcade) Einfach- und Doppelklick
if(button2State==LOW && button2Pressed==false&&LpTimer<millis()&&debTimer<millis()){ //press-Event
button2Pressed=true;
debTimer=millis()+30;
}
if(button2State==HIGH && button2Pressed==true&&LpTimer<millis()&&debTimer<millis() ){ //release-Event
button2Pressed=false;
LpTimer=millis()+250;
debTimer=millis()+30;
}
if(button2State==LOW && button2Pressed==false&&LpTimer>millis()&&debTimer<millis()){ //doubleklick-Event
button2Pressed=false;
if(encTarget!=2){ //Licht wird angeschatet, Startwert Licht ist 24 von 48 Stufen
encTarget=2;
encVal=24;
myEnc.write(encVal*4);
//fadePointer=millis(); //für automatisches Licht-Abschalten
goto skip1;
}
if(encTarget==2){ //Licht wird ausgeschaltet, Encoder braucht die Werte aus Zeiteinstellung (es wird zu den Minuten gesprungen)
encVal=Amins;
myEnc.write(encVal*4);
encTarget=1;
analogWrite16(ledPin, 0); //Leucht() kann nur licht anschalten, aber nicht aus, deswegen hier
}
skip1:
debTimer=millis()+600;
}
//Alarmzeit soll angezeigt werden
if(button2State==LOW && AlarmState == 0){
ZeigeAl=true; //notwendig auch zum Einstellen des Alarms u. der Zeit
}
if (button2State==HIGH){
ZeigeAl=false;
}
//Alarmlogik Button 2 (Arcade Button)
if(button2State == LOW &&AlarmState == 1 && debTimer < millis()){ //Weckphase 1 läuft, Schläfer ist wach-> Sprung zu 3
debTimer=(millis()+900);
fadePointer=millis(); //Zähler reset für einfacheres Debugging
fadeZaehl=0;
AlarmState=3;
}
if(button2State == LOW && AlarmState == 2 && debTimer < millis()){ //WeckPhase 2(lauter als1) läuft, Schläfer ist wach-> Sprung zu 3
debTimer = (millis()+900);
fadePointer = millis(); //Zähler reset für einfacheres Debugging
fadeZaehl = 0;
AlarmState = 3;
}
if(button2State == LOW && AlarmState == 3 && debTimer < millis()){ //Schläfer steht auf und verlässt das Bett
debTimer = (millis()+900);
fadePointer = millis();
fadeZaehl = 0;
AlarmState = 4;
}
if(button2State == LOW && AlarmState == 4 && debTimer < millis()){ //Schläfer will das Licht schnell aus haben
debTimer = (millis()+900);
fadeULong = 100; //Alarm() A-state=4 macht den Rest
}
}//close ButtonLogic
//-----------------------------------------------------------------
void setDS3231time()
{
// sets time and date data to DS3231
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set next input to start at the seconds register
Wire.write(decToBcd(00)); // set seconds
Wire.write(decToBcd(Amins)); // set minutes
Wire.write(decToBcd(Ahours)); // set hours
//Wire.write(decToBcd(1)); // set day of week (1=Sunday, 7=Saturday)
//Wire.write(decToBcd(1)); // set date (1 to 31)
//Wire.write(decToBcd(1)); // set month
//Wire.write(decToBcd(0)); // set year (0 to 99)
Wire.endTransmission();
}
//----------------------------------------------------------------------
void readDS3231time()
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set DS3231 register pointer to 00h
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
// request seven bytes of data from DS3231 starting from register 00h
byte second = bcdToDec(Wire.read() & 0x7f); //wird gelesen, aber nicht gebraucht.
mins = bcdToDec(Wire.read());
hours = bcdToDec(Wire.read() & 0x3f);
//*dayOfWeek = bcdToDec(Wire.read());
//*dayOfMonth = bcdToDec(Wire.read());
//*month = bcdToDec(Wire.read());
//*year = bcdToDec(Wire.read());
}
//--------------------------------------------------
void alarm(){
//Sonnenaufgang: nach #Zeitintervall wird der bisherige Helligkeitswert mit 1,01 multipliziert.
//~22Minuten Fade
//MP3Start nach 12Minuten, random Track in Folder 01, Soundscapes sind mit Fade-In überlagert, Lautstärkekontrolle am dfPlayer Mini hat nur 30 Stufen (reicht nicht)
const int upSpeed=1000; //(1000neu=>20+x(?) Minuten, 100=>127sek.) sets Interval for multiplication of fadeULong(fade in)
//kleinere Werte=schnellerer Fade
const int dnSpeed=6; //(6) sets Interval for division of fadeULong (fade out)
const int lowMinim=100; // Offset für Einstellung der niedrigsten Helligkeitsstufe, damit der langsame Teil des Fades auch im nützlichen Helligkeitsbereich ist
//sollte nicht über 800 sein, sonst wird die auskommentierte constrain funktion in Sonnenaufgang notwendig
unsigned long fadeTime=(millis()-fadePointer); //wie lange läuft der Alarm schon? FadePointer bekommt von Buttonlogic() Reset bei Sprüngen in A-states 3+4
unsigned int fadeVal=1; //local Var für Ausgabe an 16Bit PWM
//Alarm Stufe 1: Sonnenaufgang, Gezwitscher
if (AlarmState==1 && fadeTime < 1200000){
//Start Audio wenn FadeTime>x
if(fadeTime>900000 && playing==0){ //15min nach Beginn(900K Millisekunden)
audioPlbk(1); //spielt Ordner 1 (Vogelgezwitscher, Ambient Sounds)
}
//pre-sunrise linearer fade-in für niedrige Helligkeit
if(fadeTime<100){ //nur 1x am Anfang ausführen
for (int i = 0; i <= lowMinim; i++) {
analogWrite16(ledPin, i);
//Serial.print("1schnell= ");
//Serial.println(i);
delay(30);
}
}
//Sonnenaufgang Berechnung
if ((fadeZaehl+upSpeed)<fadeTime &&fadeULong<4901480){ //Fade-Funktion wird ausgeführt, solange keine 5M erreicht werden können
fadeZaehl=fadeTime;
fadeULong=(fadeULong*1.01); //
fadeVal=fadeULong/76.3+lowMinim; //5000000/76,3= 65535, der 100%wert für PWM16, map() macht mist bei Werten größer als int
//fadeVal=constrain(fadeVal,1,65535);
analogWrite16(ledPin, fadeVal);
//Serial.print("1langsam= ");
//Serial.println(fadeVal);
}
}
// Maximum, ist erreicht(1800000ms/30 Minuten preset) //Nach T>30 Minuten weiter bei AlarmState2,
if(AlarmState==1 &&fadeTime>1800000){
AlarmState=2;
}
//Alarm Stufe 2: Vollgas Licht, laute Weck-Musik
if(AlarmState==2){ //schläft noch&& bisherige Maßnahmen zeigten keine Wirkung
fadeULong=5000000; //maximum Warp
fadeVal=65535;
analogWrite16(ledPin, fadeVal);
if(playing!=2){
audioPlbk(2); //spielt Ordner 2 (laute Weckroutine)
}
//renitenter Schläfer braucht nach 35Min noch härtere Gangart
if (fadeTime>2100000){
playing=1; //sonst nimmt audioPlbk() keine Befehle an
audioPlbk(2); //<-Track erstellen und neues Verzeichnis reinkopieren, nummer hierhin //35minuten Neuer, aggressiver Wecktrack, volle Lautstärkespielt laute Weckroutine
}
if (fadeTime>2400000){ //40 Minuten. genug geweckt, ist keiner Da-> ausschalten!
AlarmState=4; //AlarmState=4 macht das Licht aus
AlarmV=false;
}
}//close AState2
//Alarm Stufe3: ist wach, braucht aber noch Licht, Fadeval auf angenehmen Wert
if(AlarmState==3){
if(playing!=3||playing==1){
audioPlbk(3); //Spielt Ordner 3 (angenehme leise Musik)
}
if(fadeULong>2000000){ //angenehm hell, mit zwischenFadeout
for (unsigned long i = fadeULong; i >= 2000000; i=i*0.99) { //Zwischenfade
fadeVal=(i/76.3);
analogWrite16(ledPin, fadeVal);
//Serial.print("3zwischenF= ");
//Serial.println(i);
delay(10);
}
fadeULong=2000000;
}
if(fadeULong<2000000){ //angenehm hell, mit zwischenFadein
for (unsigned long i = fadeULong; i <= 2000000; i=i*1.01) { //Zwischenfade
fadeVal=(i/76.3)+lowMinim;
analogWrite16(ledPin, fadeVal);
//Serial.print("3zwischenF= ");
//Serial.println(i);
delay(10);
}
fadeULong=2000000;
}
fadeVal=(fadeULong/76.3); //Wert wird gehalten
analogWrite16(ledPin, fadeVal);
//Serial.print("3hold= ");
//Serial.println(fadeVal);
if (fadeTime>600000){ //ist Wach, hat Lichtausmachen vergessen(10 Minuten nach ButtonPress)
AlarmState=4;
}
}//close Astate3
//Alarm Stufe 4: Es wird aufgestanden, Licht kann ausfaden, kleiner Soundschnipsel als Bestätigung
if(AlarmState==4&&fadeULong>100){ //steht jetzt auf Licht soll ausfaden
if(playing!=4){
audioPlbk(4); //Spielt Ordner 4 (kurzer Bestätigungssound, +1Up Mario)
}
if ((fadeZaehl+dnSpeed)<fadeTime){
fadeZaehl=fadeTime;
fadeULong=(fadeULong/1.01);
fadeVal=(fadeULong/76.3);
analogWrite16(ledPin, fadeVal);
//Serial.print("4 out= ");
//Serial.println(fadeVal);
}
}
if(AlarmState==4&&fadeULong<101){ //Fade ist durch, alles zurück auf Ausgangswerte/abschalten
fadeULong=100;
fadeZaehl=0;
AlarmState=0;
audioPlbk(0);
AlarmV=false;
analogWrite16(ledPin, 0);
}
}
//----------^void alarm()^-------------------------------
//Lichtfunktion, bekommt Werte von Buttonlogic()/encoder und macht daraus Helligkeit
void Leucht(byte intens){
unsigned int leuchtVal= 10;
for (byte i = 0; i <=intens; i++) { //logarithmische Berechnung der Helligkeit
leuchtVal=leuchtVal*1.2;
}
if(leuchtVal<13){ //minimal-Licht zur Verwendung als Nachtlicht
leuchtVal=8;
}
analogWrite16(ledPin, leuchtVal);
//Serial.print("leuchtVal: " );
//Serial.println(leuchtVal);
//automatische Lichtabschaltung nach 2 Stunden, nur aktiv bei intens>0, 0=Schlaflicht
/* if(intens && (fadePointer-millis())>7200000){
encTarget=1;
encVal=Amins;
myEnc.write(encVal*4);
analogWrite16(ledPin, 0);
}*/
}
//-------^void Leucht()^----------------------------------------------------------------------------------------
void loop(){
if (schedulT<millis()){ //Aufrufe begrenzen
readDS3231time(); //Zeit einlesen
setBrigh(); //Helligkeit im Display an Umgebung anpassen, bei AlarmState>0 max Brightness
//Restschlafanzeige
if (AlarmState){
zeigeRS=!zeigeRS; // Abwechselnd Uhrzeit + Restschlaf anzeigen
if (zeigeRS&&AlarmState==1){
RestSchlaf=(1800000-(millis()-fadePointer))/60000; //Weckroutine dauert 30 Minuten
}
if (zeigeRS&&AlarmState==2){ //A-State=2 Heißt Zeit ist abgelaufen
RestSchlaf=0;
}
if (zeigeRS&&AlarmState==3){
RestSchlaf=(600000-(millis()-fadePointer))/60000; //hat 10 Minuten Zeit zum Anziehen
}
if (!zeigeRS){
RestSchlaf=0;
}
}
if (!AlarmState && encTarget!=2){ //Nur Uhrzeit wenn nicht benötigt
zeigeRS=false;
RestSchlaf=0;
}
//Zeit für Alarm?
if(AlarmV==true &&AlarmState==0 && hours==rAhours && mins==rAmins){ //Bedingung für Alarmauslösung
fadePointer=millis(); //Pointer setzen für Zeitablauf
//lichtAn=false;
encTarget=1; //Licht ausschalten, falls an
AlarmState=1;
}
/*Beleuchtung
if(lichtAn){
Leucht(Ahours);
}*/
/*Serial.print("AlarmState: " );
Serial.println(AlarmState);
Serial.print("fadeULong= ");
Serial.println(fadeULong); */
// 1x pro Sekunde
schedulT= millis()+1000;
}//scheduler zumachen
//Solange der Alarm läuft, wird die zugehörige Funktion auch aufgerufen
if(AlarmState){
alarm();
}
//Knöpfe einlesen
buttonLogic();
// display auf dem tm1637
dispTm1637(RestSchlaf);
// display auf dem LCD
}
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Ich habe einiges weitergefrickelt hier. Für den zweiten Wecker, den ja meine Schwester bekommt hab ich mir Stereosound vorgenommen, der soll von einem PAM 8403 verstärkt werden.
Ich habe mich versucht im Aufbau schönerer Platinen. Dann kam heraus, dass der dfPlayer ne kleine Drecksau ist, und Entstörungsmaßnahmen braucht. Obligatorisch ist die spannungreduzierte Versorgung @4,2V und die serielle Verbindung mit 1k inline für RX UND TX. Im Netz findet man Anleitungen, dass nur in einem Pfad(vergessen welcher) der Widerstand nötig wäre, aber das führt zu deutlich hörbaren Einstreuungen. Dann sollte es ja eigentlich reichen, die DAC-Ausgänge des dfPlayers über nen Spannungsteiler am Verstärker anzuschließen, nur leider wird da das Vergnügen durch ein brummähnliches Geräusch gestört. Nach etwas googeln hab ich ein Datenblatt zum yx5200 genannten Chip gefunden, und siehe da, es gibt einen Pin, der für "decoupling" verwendet werden soll. Da hab ich mal nen Elko mit 100µF drangehängt und mit dem Kopfhörer als einzige am DAC angeschlossene Last gekuckt, wie sich das verhält. Wenn ich den Elko direkt an der Masse vom Kopfhörer kontaktiert hab, ging das Geräusch weg, bei anderen Massepunkten nicht. Gleiches Prinzip am PAM8403 probiert: funzt.
Durch Labornetzteil-Fehlbedienung hab ich ne µSD-Karte gehimmelt und war am grübeln, ob das an meiner Entkopplungslösung gelegen haben könnte, die Neue zeigt aber keinerlei Ausfallserscheinungen, hoffentlich bleibt das so.
Da ich den integrierten Amp nicht nutze, hab ich den direkt von der Platine runtergelötet und einen der dadurch freiwerdenden Pins für die Entkopplungsleitung zum Verstärker genutzt. Hier ist der aktuelle Schaltplan: Der Spannungsteiler am Helligkeitssensor verträgt auch mehr als 20k, der Sensor, den ich da jetzt habe kommt von Maxens und hat ne etwas andere Kennlinie als der im ersten Wecker. Den höheren Vorwiderstand für die LED hab ich durch leicht unterdimensionierte Zuleitung erreicht, die lässt sich auch leichter verlegen.
Der Spannungsteiler vor den Eingängen am Verstärker verträgt wahrscheinlich auch 8-10k statt der 4,7. Mir ist das laut genug und man bekommt ne bessere SNR-Ratio, weil man den DAC voll(er) aussteuert. Die Platine die ich hier hab führt den Enable-Pin nicht heraus und hat dafür 2x GND, das fand ich unnötig und hab einen der beiden GND-Pins umgewidmet. Leider macht Pam Knackser, wenn sie über enable an- und ausgeschaltet wird, da hatte ich mir besseres erhofft.
kleine Anprobe, wird mal wieder knapp. Der Entkopplungselko kommt beim nächsten Mal auf die Lochrasterplatine, die Heißkleber-Huckepack Lösung ist nicht so schön... So sieht das jetzt aus. Die Verdunklungsfolie auf dem Display verbessert die Lesbarkeit enorm, weil man die inaktiven Segmente quasi nicht mehr sieht. Vorher war da der LED-Phosphor zu sehen, der natürlich auch auf blaues Licht aus anderen Quellen anspricht. Bei Gehäuse n°2 hab ich es geschafft, nicht bis ganz hinten durchzufräsen, der KüKö hat dadurch bessere Konvektion. Beim Bauhaus hatten sie wg Corona nurnoch Reststücke an Plexiglas, das größte hatte 6mm, nehm ich halt das. Ist jetzt auch ne andere Mattierungsfolie ohne Streifen und mit recht grober Textur. Gefällt mir besser. Am Code gings auch weiter, ich hatte zwischenzeitlich mit ner race-condition eine Beschleunigungsfunktion für den Encoder zusammengepfuscht, die bei schnellem Drehen statt Minuten halbe Stunden addiert/subtrahiert hat. Das war dann aber doch etwas fummelig und wurde wieder auf die Umschaltlösung zurückgebaut. Hab mal Quellen angegeben und hier und da etwas aufgeräumt. Die v1.0 kommt nah, ich muss mich zusammenreißen nicht neue features zu proggen, während noch ungeliebter Kleinkruscht abgearbeitet werden will.
Außerdem hab ich noch ne kleine Bedienungsanleitung geschrieben. Beidseitig ausdrucken auf A4, in der Mitte falten, fertig.
Grüße
Mo
Ich habe mich versucht im Aufbau schönerer Platinen. Dann kam heraus, dass der dfPlayer ne kleine Drecksau ist, und Entstörungsmaßnahmen braucht. Obligatorisch ist die spannungreduzierte Versorgung @4,2V und die serielle Verbindung mit 1k inline für RX UND TX. Im Netz findet man Anleitungen, dass nur in einem Pfad(vergessen welcher) der Widerstand nötig wäre, aber das führt zu deutlich hörbaren Einstreuungen. Dann sollte es ja eigentlich reichen, die DAC-Ausgänge des dfPlayers über nen Spannungsteiler am Verstärker anzuschließen, nur leider wird da das Vergnügen durch ein brummähnliches Geräusch gestört. Nach etwas googeln hab ich ein Datenblatt zum yx5200 genannten Chip gefunden, und siehe da, es gibt einen Pin, der für "decoupling" verwendet werden soll. Da hab ich mal nen Elko mit 100µF drangehängt und mit dem Kopfhörer als einzige am DAC angeschlossene Last gekuckt, wie sich das verhält. Wenn ich den Elko direkt an der Masse vom Kopfhörer kontaktiert hab, ging das Geräusch weg, bei anderen Massepunkten nicht. Gleiches Prinzip am PAM8403 probiert: funzt.
Durch Labornetzteil-Fehlbedienung hab ich ne µSD-Karte gehimmelt und war am grübeln, ob das an meiner Entkopplungslösung gelegen haben könnte, die Neue zeigt aber keinerlei Ausfallserscheinungen, hoffentlich bleibt das so.
Da ich den integrierten Amp nicht nutze, hab ich den direkt von der Platine runtergelötet und einen der dadurch freiwerdenden Pins für die Entkopplungsleitung zum Verstärker genutzt. Hier ist der aktuelle Schaltplan: Der Spannungsteiler am Helligkeitssensor verträgt auch mehr als 20k, der Sensor, den ich da jetzt habe kommt von Maxens und hat ne etwas andere Kennlinie als der im ersten Wecker. Den höheren Vorwiderstand für die LED hab ich durch leicht unterdimensionierte Zuleitung erreicht, die lässt sich auch leichter verlegen.
Der Spannungsteiler vor den Eingängen am Verstärker verträgt wahrscheinlich auch 8-10k statt der 4,7. Mir ist das laut genug und man bekommt ne bessere SNR-Ratio, weil man den DAC voll(er) aussteuert. Die Platine die ich hier hab führt den Enable-Pin nicht heraus und hat dafür 2x GND, das fand ich unnötig und hab einen der beiden GND-Pins umgewidmet. Leider macht Pam Knackser, wenn sie über enable an- und ausgeschaltet wird, da hatte ich mir besseres erhofft.
kleine Anprobe, wird mal wieder knapp. Der Entkopplungselko kommt beim nächsten Mal auf die Lochrasterplatine, die Heißkleber-Huckepack Lösung ist nicht so schön... So sieht das jetzt aus. Die Verdunklungsfolie auf dem Display verbessert die Lesbarkeit enorm, weil man die inaktiven Segmente quasi nicht mehr sieht. Vorher war da der LED-Phosphor zu sehen, der natürlich auch auf blaues Licht aus anderen Quellen anspricht. Bei Gehäuse n°2 hab ich es geschafft, nicht bis ganz hinten durchzufräsen, der KüKö hat dadurch bessere Konvektion. Beim Bauhaus hatten sie wg Corona nurnoch Reststücke an Plexiglas, das größte hatte 6mm, nehm ich halt das. Ist jetzt auch ne andere Mattierungsfolie ohne Streifen und mit recht grober Textur. Gefällt mir besser. Am Code gings auch weiter, ich hatte zwischenzeitlich mit ner race-condition eine Beschleunigungsfunktion für den Encoder zusammengepfuscht, die bei schnellem Drehen statt Minuten halbe Stunden addiert/subtrahiert hat. Das war dann aber doch etwas fummelig und wurde wieder auf die Umschaltlösung zurückgebaut. Hab mal Quellen angegeben und hier und da etwas aufgeräumt. Die v1.0 kommt nah, ich muss mich zusammenreißen nicht neue features zu proggen, während noch ungeliebter Kleinkruscht abgearbeitet werden will.
Code: Alles auswählen
Edit: Aktualisierter Code vom Post drunter
//Lichtwecker v1.0
//Dieser Sketch ist getestet auf Nano V3 (ATmega 168:Button2Pin@#13, nur <80 Plätze für shuffle wg wenig Speicherplatz; Bedarf wahrscheinlich weiterer Optimierungen
// AtMega 328T, Button2Pin@#12, Kann 255 Plätze für shuffle, Displayhelligkeit anderer Sensor und Spannungsteiler)
//done: Encoderbeschleunigung wieder rauswerfen, ist doof wg Undosierbarkeit.
//Done! beleuchteter Taster für Anzeige Alarm Scharfgestellt, LED soll auch gedimmt werden. Ungenutzten tm1637 Pin rausführen?
//done: Shuffle anstelle von Random für Songs abspielen. (Speicherbedarf! Ò_ó)
//done: neue Funktion für Fading: averaging vor Ausgabe an PWM, ersetzt jetzt nicht mehr notwendige for-loops.
//done: einstellbarer Sleep-Timer für Leselicht, nach x Minuten schaltet die Lampe von alleine ab.
//todo:
//
//neues Feature: Sleep Timer bekommt nach Wahl einen langsamen "Sonnenuntergang in den letzten x Minuten.
// ^Mangel an Bedienelementen?^
//
/* Beschreibung:
*
Kann: Wecken mit 16bit Sonnenaufgang, dazu MP3 Abspielen(no1). Es gibt 4 Weckzustande:
1. Sonnenaufgang, MP3 aus Ordner1 wird abgespielt. dauert 30 Minuten
2. nach Ablauf von 1. ohne Interaktion kommt MP3 aus Ordner2 (lauteres, invasiveres Audio),
weiterhin volle Helligkeit
3. Wenn während 1. oder 2. der Ausknopf (Button2) gedrückt wird, wird ein angenehmer H-Wert gesetzt und angenehme leise Musik(Ordner3) gespielt.
4. Wenn der Ausknopf erneut gedrückt wird, wird das Licht ausgefadet und abgeschaltet.
MP3 aus Ordner4 wird abgespielt (soll nur n kurzer Sound sein, unter 10s. Zu lang wird abgeschnitten wg ende des Fadeouts)
Weckzeit wird angezeigt bei gedrücktem Ausknopf(Button2) Eingestellt mittels Encoder,
Druck auf Encoder Pushbutton (Button0) wechselt Stunden/Minuten. Was gerade eingestellt wird,
kann im Moment noch nicht angezeigt werden.(todo, benötigt andere library)
Neue Uhrzeit wird eingestellt indem man die Uhrzeit als Weckzeit einstellt und dann den Alarm an/aus
Button (Button1) 5Sekunden oder länger hält. die Zeit wird on Button release geschrieben, man kann
also die nächste Minute einstellen, den Knopf gedrückt halten und im richtigen Moment loslassen und
hat eine sehr genau eingestellte Zeit.
Mit Doppelklick auf den Arcade Button (Button2) kann man die LED zu Beleuchtungszwecken verwenden, Über die Einstellung der Weckstunden
kann man die Intensität einstellen. Stufe 0 ist besonders Dunkel, zur Verwendendung als Nachtlicht.
Die Helligkeit des Displays wird automatisch der Umgebungshelligkeit angepasst. Zum Einlesen wird ein
Spannungsteiler zwischen 5v-Fotoresistor-20K_Ohm-GND Auf A7 eingelesen und nach Beschränkung auf
setBrightness gemappt.
Folgende Bibliotheken werden benötigt:
bereits in Arduino IDE integriert:
-wire.h
-SoftwareSerial.h
Separat zu installieren:
-DFPlayerMini_Fast by PowerBroker2
-TM1637 by Avishay Orpaz
-encoder.h by Paul Stoffregen
Die Codeschnipsel um den ds3231 einzulesen stammen von:
https://tronixstuff.com/2014/12/01/tutorial-using-ds1307-and-ds3231-real-time-clock-modules-with-arduino/
Die 16Bit-PWM Codeschnipsel stammen von:
https://github.com/RoboUlbricht/arduinoslovakia/blob/master/timer/timer1_pwm_16bit/timer1_pwm_16bit.ino
getestet auf: Arduino Nano v3 (AtMega168, AtMega328P) (bei 168 ist der Speicherplatz ist knapp, serial-> PC könnte Probleme verursachen, wenn es aktiviert wird)
*/
//DFPlayer mini
#include <SoftwareSerial.h>
#include <DFPlayerMini_Fast.h>
SoftwareSerial mySerial(A2, A1); // RX, TX
DFPlayerMini_Fast myMP3;
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68 //DS3231 Zeitgeber
//Tm1637
//#include <Arduino.h>
#include <TM1637Display.h>
// Module connection pins (Digital Pins)
#define CLK 5
#define DIO 4
TM1637Display display(CLK, DIO);
//Encoder
#include <Encoder.h>
Encoder myEnc(2, 3);
//Eingänge
#define button0Pin 6 // Encoder pushbutton pin
#define button1Pin 7 // Alarm an/aus & Zeit setzen Knopf
byte button2Pin = 12; // Arcade Button auf der Oberseite - Neue Rev:D12 alte Revision: Pin D13
const byte HellPin = A7; //Einlesen der aktuellen Helligkeit im Raum über Fotowiderstand*Spannungsteiler
//Ausgänge
const byte ledPin = 10; //(10)LED/Mosfet - Treiber angeschlossen an Pin9 oder 10 (16Bit PWM)
const byte disPin = 9; //(9)Display Stromversorgung an armeleute DAC//Spannung soll auch für Tasterbeleuchtung in V2 herhalten!
const byte AmpEnPin = 8; //Amp Enable, brauchts nicht mehr
const byte PampEnPin = A3; //ist A3, verschoben wg debug dfPlayer
//Variablen
unsigned long schedulT = 0; //Aufrufe der Uhrzeit /DS3231 begrenzen auf 1x pro Sekunde
unsigned long fadePointer = 0; //wird bei Alarmauslösung gesetzt und dient zur Berechnung der Helligkeit während Alarmablaufs
unsigned long fadeZaehl=0; //siehe fadePointer
unsigned long LpTimer = 0; //Erkennung von langen und kurzen Drückern auf button1.
unsigned long DCTimer = 0; //Erkennung von Doppelklick auf Button2.
unsigned long LedPWMVal =0; //Smoothing und Ausgabe Der LEd-PWM
unsigned int leuchtVal1= 0; //für Übertragung des PWM-Werts zwischen Berechnung und Smoothing/Ausgabe
int smooBrigh=400; //Helligkeitssensor braucht smoothing, da die PWM der LED (wenn an) stark
//unterschiedliche Helligkeiten erzeugt. (besser wäre kleiner Elko)
byte mins=0; // Uhrzeit Minuten
byte hours=0; // Uhrzeit Stunden
byte Amins=0; // Anzeige-Weckzeit Minuten
byte Ahours=0; // Anzeige-Weckzeit Stunden
byte rAmins=0; // Alarmbeginnzeit Minuten = 30 Minuten vor Weckzeit (r für real)
byte rAhours=0; // Alarmbeginnzeit Stunden
byte folder01 = 1; //wieviele Tracks in folder#?
byte folder02 = 1;
byte folder03 = 1;
byte folder04 = 1;
byte playing = 0; //(welches Verzeichnis)wird gerade abgespielt? 0=stop
byte AlarmState=0; //Wird gerade geweckt? Wo sind wir in der Weckfunktion? (0-4)
bool AlarmV=false; //Weckfunktion an oder aus?
bool ZeigeAl=false; //Weckzeit anzeigen wenn true
bool lichtAn=false; //Variable für Lichtfunktion
unsigned long fadeULong=100; //Var für die Logarithmische Berechnung des Helligkeitswertes
byte RestSchlaf=0; //Restschlafanzeige während Alarm
bool zeigeRS=false;
bool button2Pressed=false; //für lange und kurze drücker brauchts ne extra Var
bool button1Pressed=false; //für lange und kurze drücker brauchts ne extra Var
bool button0State = false;
bool button1State = false;
bool button2State = false;
byte buttonCount = 0; //Wie weit ist der Doppelklick schon fortgeschritten?
bool encTarget=0; //encoder target wechselbar für Stunden/Minuten/Leuchtstärke(Nachtlicht)
unsigned long debTimer=0; //Button debounce
byte encVal = 0;
byte SleepTime=0; //Wie lang soll die Lampe Leuchten bei Aktivierung des Sleeptimers?
bool sleepStell=false; //wird gerade der Sleeptimer eingestellt?
int oldPosition=0;
int realBrigh=1; //Durchschnittsbildung Helligkeitsmessung für Displayhelligkeit
// Array geht von 1-255 Wird nach jedem Durchlauf mit neuen Zufallszahlen beschrieben und braucht Platz
// zum Abspeichern der schon gespielten Tracks
byte questionNumberArray[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,
226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
247, 248, 249, 250, 251, 252, 253, 254, 255};
/* restliche Zahlen aus Array werden akut nicht benötigt da unter 100 Songs, Speicherplatz sparen@ atmega168.
Zahlen hierhin verschieben:
---
---
-----*/
//---ende Array
byte shufflePos = 0; //wieviele Tracks wurden schon gespielt?
//------- nötig Zum Auslesen/schreiben von DS3231------------------------------------
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val){
return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val){
return( (val/16*10) + (val%16) );
}
//--------------------------------------------------------------
//---------------------------------------------------------------
void setup(){
//Serial.begin(9600); //Debugging, if needed only.
//I2C für DS3231
Wire.begin();
//Eingänge
pinMode (button0Pin, INPUT_PULLUP);
pinMode (button1Pin, INPUT_PULLUP);
pinMode (button2Pin, INPUT_PULLUP);
pinMode (2, INPUT_PULLUP); //encoder
pinMode (3, INPUT_PULLUP);
//Ausgänge
pinMode (AmpEnPin, OUTPUT);
pinMode (PampEnPin, OUTPUT);
//pinMode (DcdcEnPin, OUTPUT);
digitalWrite(AmpEnPin,HIGH); //Amp(dfPlayer) Aus, Logik invertiert
digitalWrite(PampEnPin,LOW); //Amp(Pam8403) Aus
delay(10);
//serielle Verbindung zum DFplayer aufbauen
mySerial.begin(9600);
myMP3.begin(mySerial);
delay(400);
myMP3.volume(18); //Lautstärke (soll 18) Wird außerdem in void audioPlbk() gesetzt für Geräusche vs Musik
delay(10);
myMP3.EQSelect(3); //ohne Pam8403 -> EQ=3 ist cool, mit Pam EQ=aus, sonst Clipping im DAC!
delay(10);
//byte volume = myMP3.currentVolume();
folder01 = myMP3.numTracksInFolder(01); //Einlesen von Anzahl Dateien in #folder
delay(10);
folder02 = myMP3.numTracksInFolder(02);
delay(10);
folder03 = myMP3.numTracksInFolder(03);
delay(10);
folder04 = myMP3.numTracksInFolder(04);
delay(10);
/*
//Erkennung der Ordner, Anzahl Dateien
Serial.print("folder01 count"); //Kontrolle ob Kommunikation mit dfPlayer klappt, wenn nicht gibt er 255 für alle Verzeichnisinhalte aus
Serial.println(folder01); //häufiger Fehler: 12v Powersupply fehlt u. Arduino hängt nur am USB
Serial.print("folder02 count");
Serial.println(folder02);
Serial.print("folder03 count");
Serial.println(folder03);
Serial.print("folder04 count");
Serial.println(folder04);
Serial.println("starting...");
delay(10); */
//7myMP3.sleep(); //Audio aus @Startup
//TM1637
display.setBrightness(2);
//16bit PWM
setupPWM16(); //init
analogWrite16(ledPin, 0); //PWM an LED=0
analogWrite16(disPin, 55534); //PWM_DAC an Display=50000
while(digitalRead(button2Pin)==HIGH){ //@Startup wird randomSeed() verwendet, um den Zufall zu verbessern.
display.showNumberDec(millis(), true);
}
if (digitalRead(button2Pin)==LOW){ //Quelle für randomSeed() ist Button2Pin / User Eingabe
randomSeed(millis());
shuffle(); //gut mischeln
shuffle();
shuffle();
shuffle();
shuffle();
}
}//^setup^-------------------------------------
//---------------------------------------------
void setupPWM16() {
DDRB |= _BV(PB1) | _BV(PB2); /* set pins as outputs */
TCCR1A = _BV(COM1A1) | _BV(COM1B1) /* non-inverting PWM */
| _BV(WGM11); /* mode 14: fast PWM, TOP=ICR1 */
TCCR1B = _BV(WGM13) | _BV(WGM12)
| _BV(CS10); /* prescaler 1 */
ICR1 = 65535; /* TOP counter value (freeing OCR1A*/
}
//---------------------------------------------
void analogWrite16(uint8_t pin, uint16_t val){
switch (pin) {
case 9: OCR1A = val; break;
case 10: OCR1B = val; break;
}
}
//---------------------------------------------
void shuffle(){
byte n = folder03+1;
for (byte i = 0; i < n - 1; i++){
byte j = random(0, n - i);
int t = questionNumberArray[i];
questionNumberArray[i] = questionNumberArray[j];
questionNumberArray[j] = t;
}
for (byte i = 0; i < n - 1; i++){
Serial.print(questionNumberArray[i]);
Serial.print(", ");
}
Serial.println(" "); //*/
}
//-----audioPlbk()---------- Funktion zur Audiowiedergabe
void audioPlbk(byte what){
//wenn gerade gespielt wird, deswegen alles an ist und jetzt ausgeschaltet werden soll
//enthält Code zur Diagnose des dfPlayers. Popclick et Al.
//Wenn gespielt wird und ausgeschaltet werden soll
if (playing && !what){
//myMP3.volume(0); //PopKlickVerhinderungsversuch
//delay(10);
//Serial.println("Amp ausschalten");
digitalWrite(AmpEnPin, HIGH); //AMP ausschalten(HIGH=aus!)
digitalWrite(PampEnPin,LOW); //Pam8403 ausschalten
delay(10);
}
//Wenn nicht gespielt wird und daher alles aus ist, anschalten
if(!playing && what){
myMP3.volume(0); //Popklickverhinderungsversuch
delay(20);
digitalWrite(AmpEnPin, LOW); //AMP anschalten(HIGH=aus!)
digitalWrite(PampEnPin,HIGH); //Pam8403 anschalten, High =an
myMP3.volume(20); //Lautstärke (war=18) einstellen wg powercycle
}
//Was soll gespielt werden?
if (playing!=what){ //immer nur ein Mal das Kommando senden
playing=what;
if (what==1){
myMP3.playFolder(what, random(1,folder01));
}
if (what==2){
myMP3.playFolder(what, random(1,folder02));
}
if (what==3){
myMP3.volume(16); //(war=12)etwas leiser als Alarm, ist Musik und daher höherer RMS als Ambient. Außerdem Chill mal ;)
delay(10);
myMP3.playFolder(what, questionNumberArray[shufflePos]);
shufflePos++;
if(shufflePos>=folder03){ //Wenn alle Tracks gespielt wurden
shufflePos=0; //von vorne
shuffle(); //neu mischeln
}
}
if (what==4){
myMP3.playFolder(what, random(1,folder04));
}
//Serial.print("Spiele folder ");
//Serial.println(what);
}
}
//-----^audioPlbk()^-------------
//---dispTm1637 Anzeigefunktion-Led Display-----
/*-Variante ohne beleuchteten Button 1, Alarmstatus wird über Doppelpunkt angezeigt
*
//
//OLD -dispTm1637 Anzeigefunktion-Led Display----- OLD
void dispTm1637(byte Verbleib){
// erzeuge Zeitformat für die Anzeige:
int displaytime = 0;
if (Verbleib<1){
if(ZeigeAl==false && RestSchlaf<1){
displaytime=(hours * 100) + mins; //aktuelle Uhrzeit anzeigen
}
if(ZeigeAl==true ){
displaytime=(Ahours * 100) + Amins; // Alarmzeit anzeigen/einstellen
}
}
if (RestSchlaf>0){ //verbleibende Zeit im aktuellen Alarmzustand
displaytime=Verbleib;
}
//Alarm An/Aus wird über den Doppelpunkt angezeigt //besser über separate Led, -> toDo, Hardwareupgrade nötig
if (AlarmV){
display.showNumberDecEx(displaytime, 0b11100000, !Verbleib); //Wenn Alarm an, Doppelpunkt an. (...~decEx)
} //shownumberDecEx(AnzuzeigendeZahl, DoppelpunktAn, padding/w Zeroes)
//zero-Padding soll während Anzeige von Restschlaf aus sein wg Verwechslungsgefahr mit aktueller Uhrzeit
if (!AlarmV){ //deswegen !Verbleib
display.showNumberDec(displaytime, !Verbleib); //wenn Alarm aus, Doppelpunkt aus.
}
}
//OLD----------- /tm1637OLD--------------------------OLD
*
*/
void dispTm1637(byte Verbleib){
// erzeuge Zeitformat für die Anzeige:
int displaytime = 0;
if (Verbleib<1){
if(ZeigeAl==false && RestSchlaf<1){
displaytime=(hours * 100) + mins; //aktuelle Uhrzeit anzeigen
}
if(ZeigeAl==true ){
displaytime=(Ahours * 100) + Amins; // Alarmzeit anzeigen/einstellen
}
}
if (RestSchlaf){ //verbleibende Zeit im aktuellen Alarmzustand, Doppelpunkt aus
displaytime=Verbleib;
if (AlarmV){
display.showNumberDecEx(displaytime, 0b10100000, !Verbleib); //(alt:0b11100000) Wenn Alarm an, Tasterled. (...~decEx)
} //shownumberDecEx(AnzuzeigendeZahl, DoppelpunktAn, padding/w Zeroes)
//zero-Padding soll während Anzeige von Restschlaf aus sein wg Verwechslungsgefahr mit aktueller Uhrzeit
if (!AlarmV){ //deswegen !Verbleib
display.showNumberDecEx(displaytime, 0b00000000, !Verbleib); //(alt:0b01000000)wenn Alarm aus, Tasterled aus, Doppelpunkt an.
}
}
//Alarm An/Aus wird über den Doppelpunkt angezeigt //besser über separate Led, -> toDo, Hardwareupgrade nötig
if (!RestSchlaf){
if (AlarmV){
display.showNumberDecEx(displaytime, 0b11100000, !Verbleib); //Wenn Alarm an, Doppelpunkt an. (...~decEx)
} //shownumberDecEx(AnzuzeigendeZahl, DoppelpunktAn, padding/w Zeroes)
//zero-Padding soll während Anzeige von Restschlaf aus sein wg Verwechslungsgefahr mit aktueller Uhrzeit
if (!AlarmV){ //deswegen !Verbleib
display.showNumberDecEx(displaytime, 0b01000000, !Verbleib); //wenn Alarm aus, Tasterled aus, Doppelpunkt an.
}
}
}
//------------- /tm1637--------------------------
//-Helligkeitsanpassung Display-----------------
void setBrigh(){
//wenn kein Alarm, Helligkeit anpassen
const int heller=1200; //Offset für Korrektur der Helligkeit, falls Anzeige zu dunkel.
int readBrigh = analogRead(HellPin); //Mittelwertbildung für Sprungfreiheit, wichtig wen Licht an ist (PWM-> springende Werte an/aus)
readBrigh=constrain(readBrigh, 0, 900);
smooBrigh=(smooBrigh*5+readBrigh)/6;
int writeBrigh = map(smooBrigh, 0, 900, 1,4); //Dimminfunktion _im_ Display, ist nötig, da sonst der Strom bei wenig licht zu groß ist und Display flimmert.
unsigned int disDAC= map(smooBrigh, 0, 900, 34000, 61535); //Wenn unterer Wert zu niedrig geht nix oder flimmerts, bei Vollgas ist die Stromaufnahme zu hoch für den PWM-Pin(?)
//Displayhelligkeit über TM1637
display.setBrightness(writeBrigh); //, 1-4
//Displayhelligkeit über Versorgung
if(smooBrigh>8){ //unterhalb 7 ist das Licht aus-> dunkles Display, oberhalb Helligkeitsboost
analogWrite16(disPin, constrain((disDAC+heller),34000, 61535)); //65535 PWM_DAC an Display oberhalb 61535 ist der Stromverbrauch zu hoch für den Arduino Pin
}
if(smooBrigh<9){
analogWrite16(disPin, disDAC); // Boost ist ausgeschaltet, PWM_DAC an Display
}
/* Serielle Ausgabe für debugging des Helligkeitssensors
Serial.print("Einlesewert: "); //Kontrolle Displayfading
Serial.print(readBrigh);
Serial.print(" Wert Display: ");
Serial.print(writeBrigh);
Serial.print(" Wert PWM Ausgabe: ");
Serial.println(disDAC); // */
}
//---^setbrigh^---------------------------------
//Encoder mit ohne Beschleunigung (war race condition, wieder rausgeworfen)
void encoder() {
int newPosition = myEnc.read()/4 ; //Liest pro Rastung 4 neue Werte ein, daher /4
if (newPosition != oldPosition) {
int AccVal=(newPosition-oldPosition);
oldPosition=newPosition;
//Bei encTarget=1 werden Minuten bei 0 Stunden verstellt
if (ZeigeAl && !AlarmV && !sleepStell){ //bei aktiviertem Alarm und bei Sleeptimereinstellung soll nix verstellt werden
if (encTarget){
Amins = Amins+AccVal; //Bei enctarget werden Minuten verändert
}
if (!encTarget){
Ahours = Ahours+AccVal; //Bei !enctarget werden Stunden verändert
}
//Minuten, Überlauf
if (Amins>59&& Amins<201){ //Überläufe in Plus-Richtung, Amins ist byte(unsigned) und läuft nach unten zu 255 über
Amins=0;
Ahours++;
}
if (Amins>200){ //Überläufe in Minus-Richtung, Amins ist byte(unsigned) und läuft nach unten zu 255 über
Amins=59;
Ahours--;
}
//Stunden, Überlauf
if(Ahours>23 &&Ahours<201){ //Überläufe in Plus-Richtung, s.o.
Ahours=0;
}
if (Ahours>200){ //Überläufe in Minus-Richtung, s.o.
Ahours=23;
}
}
//Bei lichtAn=1 wird Helligkeit eingestellt
//bei Licht an, gehen die Werte bis 48, kein Überlauf zu 0/48 wg Blendwirkung von 0->48, dunkel nach hell, stattdessen Wert halten
if (lichtAn && !ZeigeAl && !sleepStell){
if(encVal>0 || encVal<48){
encVal = encVal+ AccVal; //keine Beschleunigung in der Beleuchtungsfunktion
if (encVal>100){ //Überlauf von byte 0 -> 255 abfangen. Möglich wg Beschleunigung
encVal=0;
}
if (encVal>48){ //hellste Stufe der Beleuchtung, bei constrain meckert der Compiler, warum auch immer(?)
encVal=48;
}
Leucht(encVal);
}
}
// Bei sleepStell=1 Wird SleepTimer eingestellt
if (sleepStell){
SleepTime = SleepTime + AccVal; // MaximalZeit ist 255Min wg Überlauf byte
RestSchlaf=SleepTime; // Ausgabe über Display via RestSchlaf
}
}
}
//----^encoder^--------------------------------------
//---Knöpfe einlesen, Dinge tun -----------------------------------------
void buttonLogic(){
button0State = digitalRead(button0Pin); //Encoder Pushbutton
button1State = digitalRead(button1Pin); //roter Knopf vorne
button2State = digitalRead(button2Pin); //schwarzer Knopf oben(arcade)
if(button2State==LOW || lichtAn){ //Encoder muss eingelesen werden
encoder();
}
//Umschaltung encTarget Minuten/Stunden
if(!button2State && !button0State && (millis()-debTimer)>300 ){ //nur ausführen, wenn Alarmzeit angezeigt wird, sonst kann der Sleeptimer nicht aktiviert werden (kollision mit debtimer)
encTarget=!encTarget;
debTimer=millis();
}
//--Erkennung von kurzen/langen Drückern auf button1-- Roter Knopf
if(button1State==LOW && button1Pressed==false ){ //press-Event
LpTimer=millis();
button1Pressed=true;
}
if(button1State==HIGH && button1Pressed==true){ //release-Event (2 Möglichkeiten)
//kurzer Knopfdruck = umschalten Alarm an/aus
if(millis()-LpTimer>20 && millis()-LpTimer<4000){
AlarmV=!AlarmV; //Wenn Alarm an, Alarm= aus
if(AlarmV){ //Wenn Alarm an, rAmins&rAhours schreiben für früheren Sonnenaufgangsbeginn
//Umrechnung der 30 Minuten Vorlauf auf Stunden
if (Amins>29 ){ //Minuten 30-59, Stunden 0-23
rAmins = Amins-30; //
rAhours = Ahours;
}
if (Amins<30 && Ahours>0){ //Minuten 0-29, Stunden 1-23
rAmins = Amins+30;
rAhours = Ahours-1;
}
if (Amins<30 && Ahours==0){ //Minuten 0-29, Stunde 0
rAmins = Amins+30;
rAhours = 23;
}
}
button1Pressed=false;
}
//langer Knopfdruck = Uhrzeit setzen
if(millis()-LpTimer>6000 &&AlarmV==false){
setDS3231time(); // schreibt aktuelle Amins&AHours in DS3231
button1Pressed=false;
}
}
//(neu) Button2 (Arcade) Einfach- und Doppelklick
//-press-Event ------
if(button2State==LOW && !buttonCount && millis()-debTimer > 600){
buttonCount=1;
debTimer=millis();
Serial.print("buttonCount");
Serial.println(buttonCount);
}
//release-Event
if(button2State&& buttonCount==1 &&millis()-debTimer>10){
buttonCount++;
Serial.print("buttonCount");
Serial.println(buttonCount);
}
//-Doubleclick -Event
if(buttonCount==2 &&!button2State && millis()-debTimer>10 &&millis()-debTimer<270){ //Test-Op:
lichtAn=!lichtAn;
if(lichtAn){ //Licht wird angeschaltet, Startwert Licht ist 24 von 48 Stufen
encVal=24;
Leucht(encVal); //muss hier einmal ausgeführt werden, weil encoder() nur bei veränderungen aufruft
}
if(!lichtAn){ //Licht wird ausgeschaltet, Encoder braucht die Werte aus Zeiteinstellung (es wird zu den Minuten gesprungen)
leuchtVal1=0; //Leucht() kann nur licht anschalten, aber nicht aus, deswegen hier
SleepTime=0; //Sleeptimer ausschalten
RestSchlaf=0; //zur Sicherheit mal auf 0 setzen (obsolet?)
}
buttonCount=0;
debTimer=millis();
Serial.print("buttonCount");
Serial.println(buttonCount);
//Serial.print("millis()");Serial.println(millis());
}
//-erase event -----
if(millis()-debTimer>270&&buttonCount){
buttonCount=0;
Serial.print("buttonCount");
Serial.println(buttonCount);
}
//Sleeptimer Einstellung aktivieren
if(lichtAn && !SleepTime && !sleepStell && !button0State && millis()-debTimer>400){
sleepStell=1; //Verstellung des Timers über Encoder wird aktiviert
SleepTime=10; //Default =10 Minuten
RestSchlaf=SleepTime; //Anzeige im Display über Variable RestSchlaf
debTimer=millis();
}
//Sleeptimer setzen und aktivieren, Einstellung abschalten
if(lichtAn && SleepTime && sleepStell && !button0State && millis()-debTimer>400){
sleepStell=0; //Einstellung fertig, deaktivieren
fadePointer=millis(); //fadePointer ist eine recycelte Variable, die auch in der Weckroutine verwendet wird. Dient hier für Zeitmessung seit sleeptimeraktivierung
debTimer=millis();
}
//Alarmzeit soll angezeigt werden
if(button2State==LOW && !AlarmState){
ZeigeAl=true; //notwendig auch zum Einstellen des Alarms u. der Zeit
}
if (button2State==HIGH){
ZeigeAl=false;
}
//Alarmlogik Button 2 (Arcade Button)
if(buttonCount==1 && AlarmState == 1 ){ //Weckphase 1 läuft, Schläfer ist wach-> Sprung zu 3, extra lange Debounce-Zeiten weil schläfriger User
fadePointer=millis(); //Zähler reset für einfacheres Debugging
fadeZaehl=0;
AlarmState=3;
}
if(buttonCount==1 && AlarmState == 2 ){ //WeckPhase 2(lauter als1) läuft, Schläfer ist wach-> Sprung zu 3
fadePointer = millis(); //Zähler reset für einfacheres Debugging
fadeZaehl = 0;
AlarmState = 3;
}
if(buttonCount==1 && AlarmState == 3 && millis()-fadePointer >900 ){ //Schläfer steht auf und verlässt das Bett
debTimer = millis();
fadePointer = millis();
fadeZaehl = 0;
AlarmState = 4;
}
if(buttonCount==1 && AlarmState == 4 && millis()-fadePointer >700){ //Schläfer will das Licht schnell aus haben
fadeULong = 100; //Alarm() A-state=4 macht den Rest
}
}//close ButtonLogic
//Lichtfunktion, bekommt bei lichtAn==1 Werte von encoder()und macht daraus logarithmische Helligkeitsstufen
void Leucht(byte intens){
unsigned int leuchtVal= 10;
for (byte i = 0; i <=intens; i++) { //logarithmische Berechnung der Helligkeit
leuchtVal=leuchtVal*1.2;
}
if(leuchtVal<13){ //minimal-Licht zur Verwendung als Nachtlicht
leuchtVal=9;
}
leuchtVal1= leuchtVal; //Ausgabe mit smoother(), der tut jetzt
//alt: analogWrite16(ledPin, leuchtVal);
//Sleeptimer: automatische Lichtabschaltung nach via Encoder und Buttonlogic eingestellte Minuten
if(!sleepStell && SleepTime && (millis()-fadePointer)>SleepTime*60000L){
encTarget=0;
leuchtVal1=0; //Ausgabe mit smoother()
SleepTime=0;
lichtAn=0;
}
}
//-------^void Leucht()^----------------------------------------------------------------------------------------
//---- smoothing für stufenlose Helligkeitseinstellung
void smoother(){
if(leuchtVal1 != LedPWMVal){
LedPWMVal=(20*LedPWMVal+leuchtVal1)/21;
if(LedPWMVal<leuchtVal1 && leuchtVal1-LedPWMVal<30){
LedPWMVal++; //Bei steigenden Werten wird sonst kein Endwert erreicht
}
/* if(LedPWMVal<5){ //not needed
LedPWMVal=0;*/
analogWrite16(ledPin, LedPWMVal);
/*
Serial.print("leuchtVal1= ");
Serial.print(leuchtVal1);
Serial.print("LedPWMVal= ");
Serial.println(LedPWMVal); // */
}
}//---Ende smoother
//-----------------------------------------------------------------
void setDS3231time(){
// sets time and date data to DS3231
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set next input to start at the seconds register
Wire.write(decToBcd(00)); // set seconds
Wire.write(decToBcd(Amins)); // set minutes
Wire.write(decToBcd(Ahours)); // set hours
//Wire.write(decToBcd(1)); // set day of week (1=Sunday, 7=Saturday)
//Wire.write(decToBcd(1)); // set date (1 to 31)
//Wire.write(decToBcd(1)); // set month
//Wire.write(decToBcd(0)); // set year (0 to 99)
Wire.endTransmission();
}
//----------------------------------------------------------------------
void readDS3231time(){
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0); // set DS3231 register pointer to 00h
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
// request seven bytes of data from DS3231 starting from register 00h
byte second = bcdToDec(Wire.read() & 0x7f); //wird gelesen, aber nicht gebraucht.
mins = bcdToDec(Wire.read());
hours = bcdToDec(Wire.read() & 0x3f);
//*dayOfWeek = bcdToDec(Wire.read());
//*dayOfMonth = bcdToDec(Wire.read());
//*month = bcdToDec(Wire.read());
//*year = bcdToDec(Wire.read());
}
//--------------------------------------------------
void alarm(){
//Sonnenaufgang: nach #Zeitintervall wird der bisherige Helligkeitswert mit 1,01 multipliziert.
//~22Minuten Fade
//MP3Start nach 12Minuten, random Track in Folder 01, Soundscapes sind mit Fade-In überlagert, Lautstärkekontrolle am dfPlayer Mini hat nur 30 Stufen (reicht nicht)
const int upSpeed=1000; //(1000neu=>20+x(?) Minuten, 100=>127sek.) sets Interval for multiplication of fadeULong(fade in)
//kleinere Werte=schnellerer Fade
const int dnSpeed=6; //(6) sets Interval for division of fadeULong (fade out)
const int lowMinim=20; // Offset für Einstellung der niedrigsten Helligkeitsstufe, damit der langsame Teil des Fades auch im nützlichen Helligkeitsbereich ist
//sollte nicht über 800 sein, sonst wird die auskommentierte constrain funktion in Sonnenaufgang notwendig
unsigned long fadeTime=(millis()-fadePointer); //wie lange läuft der Alarm schon? FadePointer bekommt von Buttonlogic() Reset bei Sprüngen in A-states 3+4
unsigned int fadeVal=1; //local Var für Ausgabe an 16Bit PWM
//Alarm Stufe 1: Sonnenaufgang, Gezwitscher
if (AlarmState==1 && fadeTime < 1200000){
//pre-sunrise linearer fade-in für niedrige Helligkeit
if(fadeTime<100){ //nur 1x am Anfang ausführen
leuchtVal1=lowMinim;
//Serial.print("1schnell= ");
//Serial.println(i);
}
//Start Audio wenn FadeTime>x
if(fadeTime>900000 && playing==0){ //12min nach Beginn(900K Millisekunden)
audioPlbk(1); //spielt Ordner 1 (Vogelgezwitscher, Ambient Sounds)
}
//Sonnenaufgang Berechnung der Helligkeitswerte abhänging von bereits abgelaufener Alarmzeit
if ((fadeZaehl+upSpeed)<fadeTime &&fadeULong<4901480){ //Fade-Funktion wird ausgeführt, solange keine 5M erreicht werden können
fadeZaehl=fadeTime;
fadeULong=(fadeULong*1.01); //
fadeVal=fadeULong/76.3+lowMinim; //5000000/76,3= 65535, der 100%wert für PWM16, map() macht mist bei Werten größer als int
leuchtVal1 = fadeVal;
//Serial.print("1langsam= ");
//Serial.println(fadeVal);
}
}
// Maximum, ist erreicht(1800000ms/30 Minuten preset) //Nach T>30 Minuten weiter bei AlarmState2,
if(AlarmState==1 &&fadeTime>1800000){
AlarmState=2;
}
//Alarm Stufe 2: Vollgas Licht, laute Weck-Musik
if(AlarmState==2){ //schläft noch&& bisherige Maßnahmen zeigten keine Wirkung
fadeULong=5000000; //maximum Warp
fadeVal=65535;
leuchtVal1 = fadeVal;
if(playing!=2){
audioPlbk(2); //spielt Ordner 2 (laute Weckroutine)
}
//renitenter Schläfer braucht nach 35Min noch härtere Gangart
if (fadeTime>2100000){
playing=1; //sonst nimmt audioPlbk() keine Befehle an
audioPlbk(2); //<-Track erstellen und neues Verzeichnis reinkopieren, nummer hierhin //35minuten Neuer, aggressiver Wecktrack, volle Lautstärkespielt laute Weckroutine
}
//40 Minuten vorbei. Genug geweckt, ist keiner Da-> ausschalten!
if (fadeTime>2400000){
AlarmState=4; //AlarmState=4 macht das Licht aus
AlarmV=false;
}
}//close AState2
//Alarm Stufe3: ist wach, braucht aber noch Licht, Fadeval auf angenehmen Wert
if(AlarmState==3){
if(playing!=3||playing==1){
audioPlbk(3); //Spielt Ordner 3 (angenehme leise Musik)
}
if(fadeULong>2000000){ //angenehm hell, mit zwischenFadeout
if ((fadeZaehl+dnSpeed)<fadeTime){
fadeZaehl=fadeTime;
fadeULong=(fadeULong/1.01);
}
if(fadeULong<2010000){
fadeULong=2000000;
}
}
if(fadeULong<2000000){ //angenehm hell, mit zwischenFadein
if ((fadeZaehl+dnSpeed)<fadeTime){
fadeZaehl=fadeTime;
fadeULong=(fadeULong*1.01);
}
if(fadeULong>1990000){
fadeULong=2000000;
}
}
fadeVal=(fadeULong/76.3)+lowMinim; //Ausgabe über Smoother
leuchtVal1 = fadeVal; //Wert wird gehalten */
/*umbauweg: fadeULong=2000000; //angenehm hell, mit zwischenFadeout
fadeVal=(fadeULong/76.3)+lowMinim;
leuchtVal1 = fadeVal; //Wert wird gehalten */
//Serial.print("3hold= ");
//Serial.println(fadeVal);
if (fadeTime>600000){ //ist Wach, hat Lichtausmachen vergessen(10 Minuten nach ButtonPress)
AlarmState=4;
}
}//close Astate3
//Alarm Stufe 4: Es wird aufgestanden, Licht kann ausfaden, kleiner Soundschnipsel als Bestätigung
if(AlarmState==4&&fadeULong>100){ //steht jetzt auf Licht soll ausfaden
if(playing!=4){ //Spielt Ordner 4 (kurzer Bestätigungssound, +1Up Mario)
audioPlbk(4);
}
if ((fadeZaehl+dnSpeed)<fadeTime){
fadeZaehl=fadeTime;
fadeULong=(fadeULong/1.01);
fadeVal=(fadeULong/76.3);
leuchtVal1 = fadeVal;
//Serial.print("4 out= ");
//Serial.println(fadeVal);
}
}
if(AlarmState==4&&fadeULong<101){ //Fade ist durch, alles zurück auf Ausgangswerte/abschalten
fadeULong=100;
fadeZaehl=0;
AlarmState=0;
audioPlbk(0);
AlarmV=false;
leuchtVal1 = 0;
}
}
//----------^void alarm()^-------------------------------
void loop(){
if (schedulT<millis()){ //Aufrufe begrenzen
readDS3231time(); //Zeit einlesen
setBrigh(); //Helligkeit im Display an Umgebung anpassen, bei AlarmState>0 max Brightness
//Restschlafanzeige und Sleeptimeranzeige
if (AlarmState || (SleepTime&&!sleepStell)){
zeigeRS=!zeigeRS; // Abwechselnd Uhrzeit + Restschlaf anzeigen
if (zeigeRS&&AlarmState==1){
RestSchlaf=((1800000-(millis()-fadePointer))/60000); //Weckroutine dauert 30 Minuten 1 800 000ms + 59000 für Trunkierung Ganzzahlarithmetik
}
if (zeigeRS&&AlarmState==2){ //A-State=2 Heißt Zeit ist abgelaufen
RestSchlaf=0;
}
if (zeigeRS&&AlarmState==3){
RestSchlaf=((659000-(millis()-fadePointer))/60000); //hat 10 Minuten Zeit zum Anziehen
}
//Sleeptimer anzeigen
if (zeigeRS && !AlarmState){
RestSchlaf= ((fadePointer + SleepTime*60000L)-millis()+59000)/60000 ; // Wie lange noch bis zur automatischen Lichtabschaltung?
Leucht(encVal); // Wird sonst nur bei Encodereingaben aufgerufen, dann bleibt das Licht an, auch wenn Zeit abgelaufen ist.
}
if (!zeigeRS){ // Bei Restschlaf= 0 wird nur die aktuelle Uhrzeit angezeigt
RestSchlaf=0;
}
}
if (!AlarmState && !encTarget &&!SleepTime){ //fängt Anzeige von Restschlaf ab, wenn nicht benötigt (obsolet?)
zeigeRS=false;
RestSchlaf=0;
}
//Zeit für Alarm?
if(AlarmV==true &&AlarmState==0 && hours==rAhours && mins==rAmins){ //Bedingung für Alarmauslösung
fadePointer=millis(); //Pointer setzen für Zeitablauf
//lichtAn=false;
lichtAn = 0; //Licht ausschalten, falls an
SleepTime=0; //Sleeptimer reset
AlarmState=1;
}
/*Serial.print("AlarmState: " );
Serial.println(AlarmState);
Serial.print("fadeULong= ");
Serial.println(fadeULong); */
// 1x pro Sekunde
schedulT= millis()+1000;
}//scheduler zumachen
//Solange der Alarm läuft, wird die zugehörige Funktion auch aufgerufen
if(AlarmState){
alarm();
}
//Knöpfe einlesen
buttonLogic();
// display auf dem tm1637
dispTm1637(RestSchlaf);
// smoother aufrufen
smoother();
}//loop
Außerdem hab ich noch ne kleine Bedienungsanleitung geschrieben. Beidseitig ausdrucken auf A4, in der Mitte falten, fertig.
Grüße
Mo
- Dateianhänge
-
- Lichtwecker Bda_09.pdf
- (196.18 KiB) 33-mal heruntergeladen
Zuletzt geändert von Später Gast am Do 4. Mär 2021, 19:25, insgesamt 1-mal geändert.
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
N'Abend zusammen,
es gibt noch Fortschritte hier:
Ich habe mittlerweile LED-beleuchtete Taster gefunden, bestellt und erhalten, die nicht kackhässlich sind und am Wecker verbaut werden dürfen: Ebay
Um den leuchten zu lassen hab ich beim Treiberchip vom LED-Display mal nach unbenutzten Ausgängen gesucht und bin fündig geworden, ich kann den jetzt über die Library ansteuern, als wäre er ein Dezimalpunkt. Einziges Problem war die Angleichung der Tasterled an die Displayhelligkeit, nur mit Vorwiderstand wars entweder bei hellem Display zu dunkel oder bei dunklem Display zu hell, aber ne Diode in Reihe hat geholfen, die Spannung so zu senken, dass das in etwa passt jetzt.
Hab mal versucht, das abzulichten, aber der wirkliche Helligkeitseindruck ist mit Fotos nicht darstellbar, zumindest nicht ohne größere Klimmzüge...
Bei Dunkelheit, an bei Helligkeit, an und bei Helligkeit, aus.
An der Software gings auch voran, eimal Bugfixes: Zb gab es n paar Timerabläufe, die nicht sauber mit millis()-timer>xy gelöst waren und bei meiner Schwester dann nach 50 Tagen Betrieb dazu geführt haben, dass plötzlich ein Taster nicht mehr ging.
Aber es gibt auch einige neue Features, die "nach dem Aufwachen-Musikberieselung" wird jetzt geshuffelt und nicht randomisiert. Der dafür notwendige Array verbraucht allerdings soviel Platz, dass der 168er Nano jetzt zu klein ist.
Weiters kann man die Beleuchtung jetzt von einem Sleep-Timer abschalten lassen.
Dann hab ich für die Helligkeitsverstellung noch ne Zwischenstufen-Berechnung gebastelt, so wirkt die Verstellung jetzt stufenlos, was sehr angenehm ist. Bei den ganz niedrigen Helligkeitsstufen sieht man die einzelnen PWM-Schritte noch, aber das lässt sich bei logarithmischer Abstufung wohl nicht vermeiden.
Ich überlege noch, für den Timer eine Sonnenuntergangs-Simulation einzubauen, dass man auch sagen kann ich les jetzt noch ne halbe Stunde und wenns zu dunkel zum Lesen ist, leg ich das Buch halt weg und mach die Äuglein zu.
Aktuellen Code mach ich gleich noch in den Post eins drüber rein, der is eh verbuggt, will ja keiner haben sowas.
Was die Benutzung/Funktion angeht bin ich sehr angetan, das ist wirklich eine sehr angenehme Art, das Problem aufstehen müssen, aber nicht wollen zu entschärfen. Selbst wenn ich viel zu spät ins Bett gegangen bin, macht mir das keine schlimme Bäh geh weg mit dem Gepiepse! - schlechte Laune mehr morgens. Meine Schweser ist auch nur begeistert und war erst ganz geknickt, dass ich das Gerät zum Kundendienst haben wollte, weil ich erst an ein abbes Kabel oder nen futschen Mosfet dachte, bis sie das Gerät zwischendurch mal vom Strom genommen hatte. Frontpanel abschrauben und gepatchte Firmware flashen kriegt sie hin, und bis es wieder eng wird hat sie noch 40 Tage Zeit...
Grüße
Moritz
es gibt noch Fortschritte hier:
Ich habe mittlerweile LED-beleuchtete Taster gefunden, bestellt und erhalten, die nicht kackhässlich sind und am Wecker verbaut werden dürfen: Ebay
Um den leuchten zu lassen hab ich beim Treiberchip vom LED-Display mal nach unbenutzten Ausgängen gesucht und bin fündig geworden, ich kann den jetzt über die Library ansteuern, als wäre er ein Dezimalpunkt. Einziges Problem war die Angleichung der Tasterled an die Displayhelligkeit, nur mit Vorwiderstand wars entweder bei hellem Display zu dunkel oder bei dunklem Display zu hell, aber ne Diode in Reihe hat geholfen, die Spannung so zu senken, dass das in etwa passt jetzt.
Hab mal versucht, das abzulichten, aber der wirkliche Helligkeitseindruck ist mit Fotos nicht darstellbar, zumindest nicht ohne größere Klimmzüge...
Bei Dunkelheit, an bei Helligkeit, an und bei Helligkeit, aus.
An der Software gings auch voran, eimal Bugfixes: Zb gab es n paar Timerabläufe, die nicht sauber mit millis()-timer>xy gelöst waren und bei meiner Schwester dann nach 50 Tagen Betrieb dazu geführt haben, dass plötzlich ein Taster nicht mehr ging.
Aber es gibt auch einige neue Features, die "nach dem Aufwachen-Musikberieselung" wird jetzt geshuffelt und nicht randomisiert. Der dafür notwendige Array verbraucht allerdings soviel Platz, dass der 168er Nano jetzt zu klein ist.
Weiters kann man die Beleuchtung jetzt von einem Sleep-Timer abschalten lassen.
Dann hab ich für die Helligkeitsverstellung noch ne Zwischenstufen-Berechnung gebastelt, so wirkt die Verstellung jetzt stufenlos, was sehr angenehm ist. Bei den ganz niedrigen Helligkeitsstufen sieht man die einzelnen PWM-Schritte noch, aber das lässt sich bei logarithmischer Abstufung wohl nicht vermeiden.
Ich überlege noch, für den Timer eine Sonnenuntergangs-Simulation einzubauen, dass man auch sagen kann ich les jetzt noch ne halbe Stunde und wenns zu dunkel zum Lesen ist, leg ich das Buch halt weg und mach die Äuglein zu.
Aktuellen Code mach ich gleich noch in den Post eins drüber rein, der is eh verbuggt, will ja keiner haben sowas.
Was die Benutzung/Funktion angeht bin ich sehr angetan, das ist wirklich eine sehr angenehme Art, das Problem aufstehen müssen, aber nicht wollen zu entschärfen. Selbst wenn ich viel zu spät ins Bett gegangen bin, macht mir das keine schlimme Bäh geh weg mit dem Gepiepse! - schlechte Laune mehr morgens. Meine Schweser ist auch nur begeistert und war erst ganz geknickt, dass ich das Gerät zum Kundendienst haben wollte, weil ich erst an ein abbes Kabel oder nen futschen Mosfet dachte, bis sie das Gerät zwischendurch mal vom Strom genommen hatte. Frontpanel abschrauben und gepatchte Firmware flashen kriegt sie hin, und bis es wieder eng wird hat sie noch 40 Tage Zeit...
Grüße
Moritz
- Fritzler
- Beiträge: 12603
- Registriert: So 11. Aug 2013, 19:42
- Wohnort: D:/Berlin/Adlershof/Technologiepark
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Also ich persönlich find ja die hier *rschgeil:
https://de.aliexpress.com/item/32899654 ... 458aJTw05j
Viel günstiger sind die auch noch
https://de.aliexpress.com/item/32899654 ... 458aJTw05j
Viel günstiger sind die auch noch
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
Stimmt, die sehen gut aus. Für den Wecker wären mir die aber ne Spur zu clean. Ich wollte auch, dass der Taster selbst ein Stückchen aus dem Gehäuse rausragt und nicht so ganz glatt anliegt. Sonst müsste ich auch den Encoderknopf nochmal ändern, das soll ja irgendwie zusammenpassen.
Das von mir verlinkte Angebot sind übrigens 9x2=18 Stück, das ist schon noch günstiger. Wie die auf die Idee mit dieser merkwürdigen Zählweise kommen ist mir aber ein Rätsel. Ist ja fast wie bei den Franzosen.
Das von mir verlinkte Angebot sind übrigens 9x2=18 Stück, das ist schon noch günstiger. Wie die auf die Idee mit dieser merkwürdigen Zählweise kommen ist mir aber ein Rätsel. Ist ja fast wie bei den Franzosen.
Re: Lichtwecker n+1, Arduino
Etwas OT, aber für das Protokoll:
Ich habe 4 Ziffern zu je 7 Segementen so angesteuert, dass immer nur eines der 28 Segmente leuchtet.
Die Stromaufnahme ist damit mehr oder weniger konstant und geht nicht über die Stromaufnahme einer LED hinaus.
Allerdings war das kein Arduino mit Bibliotheken, sondern C auf einem PIC.
Ändert jedoch nichts am Prinzip, falls das mal wer benötigt. So als Anregung.
Ich hatte diese Problemstellung auch, vor allem im Zusammenhang mit dem Kontrast und Akkubetrieb.
Ich habe 4 Ziffern zu je 7 Segementen so angesteuert, dass immer nur eines der 28 Segmente leuchtet.
Die Stromaufnahme ist damit mehr oder weniger konstant und geht nicht über die Stromaufnahme einer LED hinaus.
Allerdings war das kein Arduino mit Bibliotheken, sondern C auf einem PIC.
Ändert jedoch nichts am Prinzip, falls das mal wer benötigt. So als Anregung.
- Später Gast
- Beiträge: 1704
- Registriert: Di 5. Apr 2016, 22:03
- Wohnort: Karlsruhe
- Kontaktdaten:
Re: Lichtwecker n+1, Arduino
So OT ist das gar nicht. Die Library steuert nämlich nur 4 Dezimalen an, auch wenn der Chip 6 könnte. Vllt könnte sie das auch und ich war zu faul es rauszufinden.
Dadurch liegt der Dezimalpunkt/die Tasterled auf einer Ziffer, die in Benutzung ist, und für die Anzeige verbleibender Minuten des Sleep-Timers und des Sonnenaufgang- Alarmablaufs schalte ich die vorderen beiden Ziffern ab. Die Stromregelung des Treiberchips misst aber nur segmentweise, wenn der Rest von der Ziffer aus ist, leuchtet das verbliebene Segment also sichtbar heller. Die Folge ist, dass bei aktivierter Tasterled und Anzeige von Restminuten die Tasterled zwischen leuchtet und leuchtet heller "blinkt".
Wenn jetzt immer nur ein Segment gleichzeitig an wäre, träte das Problem nicht mehr auf. Ich fürchte nur, da reicht mein Perfektionismus grade nicht aus, das anzugehen. Klingt, als bräuchte man da recht genaues scheduling, man will ja auch nicht nur das Display beschicken, sondern auch n paar andere Sachen rechnen. Was ich mal probiert hab, ist das ganze Display über aus- und anschalten zu dimmen. Quasi soft-PWM. Furchtbar.
Dadurch liegt der Dezimalpunkt/die Tasterled auf einer Ziffer, die in Benutzung ist, und für die Anzeige verbleibender Minuten des Sleep-Timers und des Sonnenaufgang- Alarmablaufs schalte ich die vorderen beiden Ziffern ab. Die Stromregelung des Treiberchips misst aber nur segmentweise, wenn der Rest von der Ziffer aus ist, leuchtet das verbliebene Segment also sichtbar heller. Die Folge ist, dass bei aktivierter Tasterled und Anzeige von Restminuten die Tasterled zwischen leuchtet und leuchtet heller "blinkt".
Wenn jetzt immer nur ein Segment gleichzeitig an wäre, träte das Problem nicht mehr auf. Ich fürchte nur, da reicht mein Perfektionismus grade nicht aus, das anzugehen. Klingt, als bräuchte man da recht genaues scheduling, man will ja auch nicht nur das Display beschicken, sondern auch n paar andere Sachen rechnen. Was ich mal probiert hab, ist das ganze Display über aus- und anschalten zu dimmen. Quasi soft-PWM. Furchtbar.