/* Linear-Uhr mit 2 Skalen und Stepper-Motor by joergeli Linke Skala: Bereich von 0:00-12:00 Uhr Rechte Skala: Bereich von 12:00-0:00 (bzw. 24:00) Uhr Stepper-Motor dreht 8mm-Gewindestange (Steigung=1,25mm) Auf der Gewindestange befindet sich ein an einer M8-Mutter befestigter Schlitten, der durch die Drehung analog der Uhrzeit auf-, oder abwaerts bewegt wird. Zusaetzlich sind im Schlitten noch zwei "Zeiger"-LED's, die uhrzeitabhaengig links, oder rechts blinken. Die linke, oder rechte Skala wird ebenfalls zeitabhaengig via LED-Stripes hinterleuchtet. Die LED-Stripes, bzw. Skalenbeleuchtungen werden mit einem LDR 5-stufig gedimmt. */ #include // Wire-Library einbinden, zur Kommunikation via I2C-Bus #include "RTClib.h" // Echtzeituhr (RTC)-Library einbinden RTC_DS1307 RTC; #include // Stepper-Library einbinden int debug = 0 ; // Debuggen: 0 = keine serielle Ausgabe, 1 = serielle Ausgabe int zeitzone=1; // UTC=0 MEZ=1 (fuer Sommerzeitroutine) int jahr, monat, tag, stunde, minut, sekunde, wochentag, summertime; int akt_minute = 0; int last_minute = 0; int akt_sekunde = 0; int last_sekunde = 0; int richtung = 1; int downbutton = 2; // Down-Taster an Pin 2 int upbutton = 3; // Up-Taster an Pin 3 int fastdownbutton = 4; // Fast-Down-Taster an Pin 4 int fastupbutton = 7; // Fast-Up-Taster an Pin 7 int gobutton = 8; // Start-Taster an Pin 8 int skalenled_links = 5; // LED-Pin fuer linke Skalenbeleuchtung int skalenled_rechts = 6; // LED-Pin fuer rechte Skalenbeleuchtung int zeigerled_links = 14; // = A0 LED-Pin fuer linke Zeigerbeleuchtung int zeigerled_rechts = 15; // = A1 LED-Pin fuer rechte Zeigerbeleuchtung int ldr_pin = 16; // = A2 LDR-Pin fuer Helligkeitssteuerung const int laenge = 5; // 5 einzelne LDR-Werte fuer Mittelwertbildung int ldr_wert[laenge]; // Ringspeicher fuer LDR-Werte int zeiger = 0; // LDR Array-Zeiger long mittelwert = 0; // LDR-Mittelwert = 0 int bereich; // Variable zum Mappen der LDR-Werte // verwendeter Stepper-Motor hat 1,8 Grad pro Schritt -> insgesamt 200 Schritte pro Umdrehung (360 Grad). const int schritte_pro_umdrehung = 200; // Initialisieren der Stepper-Library AH_28BYJ48 stepper(schritte_pro_umdrehung , 9,10,11,12); // pin1 blue // pin2 pink // pin3 yellow // pin4 orange int anfangsflag = 1; // Anfangssequenz-Flag setzen, zum Stellen der Uhr int go_status = 0; // Go-Taster = offen int up_status = 0; // Up-Taster = offen int down_status = 0; // Down-Taster = offen int fast_down_status = 0; // Fast-Down-Taster = offen int fast_up_status = 0; // Fast-Up-Taster = offen void setup() { Wire.begin(); RTC.begin(); // Folgende Zeile setzt die RTC-Uhr auf Datum und Zeit, wann dieser Sketch kompiliert wurde. // Dazu muss die PC-Zeit ohne! Sommerzeitberuecksichtgung eingestellt werden. //_____________________________________________________________________________________ // RTC.adjust(DateTime(__DATE__, __TIME__)); //Auskommentierung entfernen, wenn Zeit gesetzt werden soll //_____________________________________________________________________________________ pinMode(zeigerled_links, OUTPUT); // LED-Pin linker Zeiger = Ausgang pinMode(zeigerled_rechts, OUTPUT); // LED-Pin rechter Zeiger = Ausgang digitalWrite(zeigerled_links, LOW); // LED-Zeiger links = aus digitalWrite(zeigerled_rechts, LOW); // LED-Zeiger rechts = aus pinMode(ldr_pin, INPUT); // LDR-Pin = Eingang pinMode(skalenled_links, OUTPUT); // LED-Pin linke Skala = Ausgang pinMode(skalenled_rechts, OUTPUT); // LED-Pin rechte Skala = Ausgang analogWrite(skalenled_links, 0); // Skala links = aus analogWrite(skalenled_rechts, 0); // Skala rechts = aus pinMode(gobutton, INPUT); pinMode(downbutton, INPUT); pinMode(upbutton, INPUT); pinMode(fastdownbutton, INPUT); pinMode(fastupbutton, INPUT); if (debug != 0 ){ Serial.begin(9600); } //Initialisieren LDR-Array fuer Mittelwertbildung for (int i=0; i von vorne anfangen if (zeiger>=laenge){ zeiger = 0; } //Addiere einzelne LDR-Werte for (int i=0; i von vorne anfangen if (zeiger>=laenge){ zeiger = 0; } //Addiere einzelne LDR-Werte for (int i=0; i= 0 && mittelwert < 200) bereich = 0; else if (mittelwert >= 200 && mittelwert < 450) bereich = 1; else if (mittelwert >= 450 && mittelwert < 600) bereich = 2; else if (mittelwert >= 600 && mittelwert < 880) bereich = 3; else if (mittelwert >= 880) bereich = 4; // Serielle Ausgabe von LDR- und Bereichs-Wert if (debug != 0 ){ Serial.print("LDR-Wert: "); Serial.print(analogRead(ldr_pin)); Serial.print(" LDR-Mittelwert: "); Serial.print(mittelwert); Serial.print(" = "); Serial.print(bereich); Serial.print(" "); } mittelwert = 0; /////////////////// Ende LDR fuer Helligkeits-Steuerung uhrzeit(); // Uhrzeit von RTC lesen led_zeiger(); // Subroutine fuer Umschaltung/Helligkeit von LED-Zeiger und Skalenbeleuchtung if (debug != 0 ){ uhrzeit_ausgabe(); } // serielle Ausgabe von Datum und Uhrzeit, nur zum Debuggen akt_minute = minut; if (akt_minute != last_minute ){ if (stunde >=0 && stunde <= 12){richtung=-1;} // Motor-Drehrichtung abwaerts if (stunde >=12 && stunde <= 23){richtung=1;} // Motor-Drehrichtung aufwaerts if(stunde==0 && minut==0) // Einmaliger Zeiger-Vorschub auf 00:00 { richtung=1; schrittmotor(); if (debug != 0 ){ Serial.print("Aktuell: "); Serial.print(stunde); Serial.print(":"); Serial.print(minut); Serial.println(" Einmaliger Vorschub aufwaerts um 00:00 und Skalenumschaltung"); } } else if(stunde==12 && minut==0) // Einmaliger Zeiger-Vorschub auf 12:00. { richtung=-1; schrittmotor(); if (debug != 0 ){ Serial.print("Aktuell: "); Serial.print(stunde); Serial.print(":"); Serial.print(minut); Serial.println(" Einmaliger Vorschub abwaerts um 12:00 und Skalenumschaltung"); } } else{ schrittmotor(); } last_minute = akt_minute; } // Ende if akt_minute != last_minute } //Ende loop // Schrittmotor-Routine void schrittmotor(){ // Stepper dreht alle 60 Sek insgesamt 288 Schritte //stepper.step(4320); // nur zum Testen: alle 60 Sek -> 4320 Schritte = 15 Min (fuer Skalentest) stepper.setSpeedHz(250); // sanfter Stepper-Anlauf mit speed = 250, dann stepper.step(richtung * 18); // 18 Schritte drehen, stepper.setSpeedHz(300); // dann mit speed = 300 stepper.step(richtung * 50); // 50 Schritte drehen, stepper.setSpeedHz(400); // dann mit speed = 400 stepper.step(richtung * 70); // 70 Schritte drehen, stepper.setSpeedHz(500); // dann mit speed = 500 stepper.step(richtung * 150); // 150 Schritte auf insgesamt 288 Schritte drehen , d.h. alle 60 Sek insgesamt 288 Schritte = 1 Min Wellen-Vorschub digitalWrite(9, LOW); // Motorspule stromlos - zur Stromersparnis digitalWrite(10, LOW); // Motorspule stromlos - zur Stromersparnis digitalWrite(11, LOW); // Motorspule stromlos - zur Stromersparnis digitalWrite(12, LOW); // Motorspule stromlos - zur Stromersparnis } // Ende schrittmotor // Zeit und Datum von RTC holen void uhrzeit(){ DateTime now = RTC.now(); wochentag = (now.dayOfWeek()); // Sonntag=0, Montag=1, Dienstag=2, Mittwoch=3, Donnerstag=4, Freitag=5, Samstag=6 jahr = (now.year()); monat = (now.month()); tag = (now.day()); stunde = (now.hour()); if (debug != 0 ){ Serial.print("RTC-Stunde: "); // reale Stunde in RTC Serial.print(stunde); Serial.print(" SomZeit: "); Serial.print(summertime); Serial.print(" "); } minut = (now.minute()); sekunde = (now.second()); sommerzeit(); // auf Sommerzeit pruefen } // Ende uhrzeit // pruefen, ob innerhalb von Sommerzeit void sommerzeit() { // keine Sommerzeit in Jan, Feb, Nov, Dez if (monat<3 || monat>10){summertime = 0;} // Sommerzeit in Apr, Mai, Jun, Jul, Aug, Sep else if (monat>3 && monat<10){summertime = 1;} // Sommerzeitanfang/-ende zum Ende Maerz, bzw. Ende Oktober else if (monat==3 && (stunde + 24 * tag)>=(1 + zeitzone + 24*(31 - (5 * jahr /4 + 4) % 7)) || monat==10 && (stunde + 24 * tag)<(1 + zeitzone + 24*(31 - (5 * jahr /4 + 1) % 7))) {summertime = 1;} else {summertime = 0;} stunde = stunde + summertime; if(stunde==24) { stunde=0; } } // Ende sommerzeit void led_zeiger(){ // links if (stunde >=0 && stunde <= 11){ analogWrite(skalenled_rechts, 0); // rechte Skalenbeleuchtung ausschalten skala_links(); // linke Skala via gemappten LDR dimmen zeiger_links(); // linker LED-Zeiger in Betrieb delay(2800); zeiger_aus(); delay(500); } // Ende links // rechts else if (stunde >=12 && stunde <= 23){ analogWrite(skalenled_links, 0); // linke Skalenbeleuchtung ausschalten skala_rechts(); // rechte Skala via gemappten LDR dimmen zeiger_rechts(); // rechter LED-Zeiger in Betrieb delay(2800); zeiger_aus(); delay(500); } // Ende rechts } // Ende led_zeiger void zeiger_links(){ digitalWrite(zeigerled_links, HIGH); digitalWrite(zeigerled_rechts, LOW); } void zeiger_rechts(){ digitalWrite(zeigerled_links, LOW); digitalWrite(zeigerled_rechts, HIGH); } void zeiger_aus(){ digitalWrite(zeigerled_links, LOW); digitalWrite(zeigerled_rechts, LOW); } void skalen_an(){ analogWrite(skalenled_links, 15); analogWrite(skalenled_rechts, 15); } void skalen_aus(){ analogWrite(skalenled_links, 0); analogWrite(skalenled_rechts, 0); } // Linke Skalenbeleuchtung via LDR 5-stufig dimmen void skala_links(){ switch (bereich) { case 0: // fast aus analogWrite(skalenled_links, 1); break; case 1: // sehr schwach analogWrite(skalenled_links, 8); break; case 2: // schwach analogWrite(skalenled_links, 25); break; case 3: // heller analogWrite(skalenled_links, 70); break; case 4: // am hellsten analogWrite(skalenled_links, 160); break; } // Ende switch } // Ende skala_links // Rechte Skalenbeleuchtung via LDR 5-stufig dimmen void skala_rechts(){ switch (bereich) { case 0: // fast aus analogWrite(skalenled_rechts, 1); break; case 1: // sehr schwach analogWrite(skalenled_rechts, 8); break; case 2: // schwach analogWrite(skalenled_rechts, 25); break; case 3: // heller analogWrite(skalenled_rechts, 70); break; case 4: // am hellsten analogWrite(skalenled_rechts, 160); break; } // Ende switch } // Ende skala_rechts void down (){ stepper.setSpeedHz(450); // Stepper-Speed aendern stepper.step(-4); } void fast_down(){ stepper.setSpeedHz(500); // Stepper-Speed aendern stepper.step(-200); } void up(){ stepper.setSpeedHz(450); // Stepper-Speed aendern stepper.step(4); } void fast_up(){ stepper.setSpeedHz(500); // Stepper-Speed aendern stepper.step(200); } // Serielle Ausgabe - nur zum Debuggen void uhrzeit_ausgabe(){ if (stunde < 10){ Serial.print("0"); } Serial.print(stunde); Serial.print(":"); if (minut < 10){ Serial.print("0"); } Serial.print(minut); Serial.print(":"); if (sekunde < 10){ Serial.print("0"); } Serial.print(sekunde); Serial.print(" "); Serial.print(wochentag); switch (wochentag) { case 0: Serial.print("=Son"); break; case 1: Serial.print("=Mon"); break; case 2: Serial.print("=Die"); break; case 3: Serial.print("=Mit"); break; case 4: Serial.print("=Don"); break; case 5: Serial.print("=Fre"); break; case 6: Serial.print("=Sam"); break; } // Ende switch Serial.print(", "); if (tag < 10){ Serial.print("0"); } Serial.print(tag); Serial.print("."); if (monat < 10){ Serial.print("0"); } Serial.print(monat); Serial.print("."); Serial.println(jahr); } // Ende Uhrzeit-Ausgabe