/****************************** * * Fingers Rudercomputer 2021 * ******************************/ #include #include #include #include #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels // Tastenauswertung #define PINTASTE 7 #define NOKEY 10 #define SHORTKEY 20 #define LONGKEY 30 #define TASTENMAXDAUER 1000 #define PINHOLD 8 // Ablaufsteuerung #define ABBRUCH 10 #define ABLAUF 20 // Displaykram #define OLED_RESET -1 Adafruit_SSD1306 display (SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // Zeitsteuerung #define STARTZEIT 300 // 5 Minuten Ruderzeit #define ZEITSCHRITT 300 // 5 Minuten mehr #define MAXZEIT 5400 // Maximal 90 Minuten int Laufzeit = STARTZEIT; // Ablaufende Ruderzeit int EingestellteLaufzeit = STARTZEIT; // Eingestellte Ruderzeit // Lichrschranken und Wegmessung #define PINOPTO1 2 #define PINOPTO2 6 volatile long Pulszaehler = 0; // Gemessene Impulse vom Drehgeber long PulszaehlerAlt = 0; float Ruderstrecke = 0; // Daraus ermittelte Pulszaehler in Metern #define UMPULSEPROUMDREHUNG 52 #define UMDREHUNGENPROZUG 3.75 #define WEGFAKTOR ((float)UMDREHUNGENPROZUG * (float)UMPULSEPROUMDREHUNG) // Umrechnung Impulse -> Pulszaehler in Metern // Timeout zur Abschaltung #define RUDERTIMEOUT 15 // Sekunden bis Abschaltung bei Inaktivität unsigned int RuderTimeout = RUDERTIMEOUT; // Spannungsmessung float Spannung = 0; #define PINSPANNUG A0 #define SPANNUNGSFAKTOR (float)0.0156521739130435 /************************************** * * Zählt Impulse von der Lichtschranke * **************************************/ void ISROpto (void) { // if (digitalRead (PINOPTO2)) Pulszaehler++; Pulszaehler++; RuderTimeout = RUDERTIMEOUT; } /************************** * * Batteriespannung messen * **************************/ float GetSpannung (void) { char tmp [30]; sprintf (tmp, "Spannung A0=%d digits", analogRead (PINSPANNUG)); Serial.println (tmp); return ((float)(analogRead (PINSPANNUG)) * SPANNUNGSFAKTOR); } /********* * * Init * *********/ void setup () { // Gerät eingeschaltet halten pinMode (PINHOLD, OUTPUT); digitalWrite (PINHOLD, HIGH); // IOs klarmachen pinMode (PINTASTE, INPUT); digitalWrite (PINTASTE, HIGH); // Pullup aktivieren // Serielle anreisse.... Serial.begin (57600); Serial.println(F ("Start...")); // Display auftanken if (!display.begin (SSD1306_SWITCHCAPVCC, 0x3C)) Serial.println (F ("Das ging schief.....")); display.clearDisplay(); display.display(); Serial.println(F ("Startlogo")); display.display(); display.clearDisplay (); display.clearDisplay (); display.setTextSize (3); display.setCursor (0,0); display.setTextColor (SSD1306_WHITE); display.print ("Fingers"); display.setCursor (30,32); display.print ("Welt"); display.display(); delay (1000); display.clearDisplay (); display.setCursor (30,20); display.print ("2021"); display.display(); delay (1000); display.clearDisplay(); display.display(); // Batterie beurteilen display.setTextSize (2); display.setCursor (10,0); display.print ("Batterie"); display.setCursor (30,20); char tmp [10]; dtostrf(GetSpannung (),3,1,tmp); display.print (tmp); display.print ("V"); display.setCursor (10,40); if (GetSpannung () > 9) display.print ("Gut"); else if (GetSpannung () > 7) display.print ("Noch OK"); else display.print ("Schwach"); display.display(); delay (3000); display.setTextSize (3); display.clearDisplay(); display.display(); pinMode (PINOPTO1, INPUT); pinMode (PINOPTO2, INPUT); attachInterrupt (digitalPinToInterrupt(PINOPTO1), ISROpto, FALLING); } /***************************************** * * Taste abfragen, liefert Dauer zurück * *****************************************/ int GetTaste (void) { // Garnicht gedrückt? if (digitalRead (PINTASTE)) { // Serial.print ("Nix druck "); return (NOKEY); } // Prellen abwarten und Zeitmessung starten int Counter = 0; delay (2); char buf [10]; sprintf (buf, "C: %d ", Counter); Serial.print (buf); while (!digitalRead ( (PINTASTE)) && (Counter < TASTENMAXDAUER) ) { Counter++; delay (1); } if (Counter < TASTENMAXDAUER) { Serial.print (" S "); return (SHORTKEY); } Serial.print (" L "); sprintf (buf, "C: %d ", Counter); Serial.print (buf); return (LONGKEY); } /*************************** * * Schaltet den Computer aus * ***************************/ void Abschalten (void) { display.clearDisplay (); display.setTextSize (3); display.setCursor (30,20); display.print (F("Ende")); display.display (); delay (2000); display.clearDisplay (); display.display (); // Physikalisch abschalten digitalWrite (PINHOLD, LOW); Serial.println (F("System abgeschaltet")); while (1); Serial.print ("X"); } /********************** * * Ruderzeit auswählen * **********************/ void ZeitVorwahl (void) { Serial.println (F("Zeitvorwahl")); display.clearDisplay (); display.setCursor (30,20); display.setTextSize (3); char buf [15]; sprintf (buf, "%2d:%02d", EingestellteLaufzeit / 60, EingestellteLaufzeit % 60); display.drawLine(25, 50, 115, 50, SSD1306_WHITE); Serial.print ("Startzeit : "); Serial.println (buf); display.setTextColor (SSD1306_WHITE); display.print (buf); display.display (); // Menü darstellen byte Menue = 1; // Timeoutfunktionen #define VORWAHLTIMEOUT 30000 unsigned long VorWahlTimeout = millis (); while (Menue) { byte Taste = GetTaste (); //----------------------------------------- // Kurzer Tastendruck, Eins weiterschalten //----------------------------------------- if (Taste == SHORTKEY) { VorWahlTimeout = millis (); // Timeout neu setzen Serial.print ("Kurz "); EingestellteLaufzeit += ZEITSCHRITT; if (EingestellteLaufzeit > MAXZEIT) EingestellteLaufzeit = STARTZEIT; display.clearDisplay (); display.setCursor (30,20); char buf [15]; sprintf (buf, "%2d:%02d", EingestellteLaufzeit / 60, EingestellteLaufzeit % 60); display.print (buf); display.drawLine(25, 50, 115, 50, SSD1306_WHITE); display.display (); } // Von if (GetTaste == SHORTKEY) //-------------------------------------- // Langer Tastendruck -> Menü verlassen //-------------------------------------- if (Taste == LONGKEY) { Menue = 0; Serial.println (F("Raus hier")); Laufzeit = EingestellteLaufzeit; } //------------------- // Zu lange inaktiv? //------------------- if ((VorWahlTimeout + VORWAHLTIMEOUT) < millis ()) { Serial.println (F("Eingabe-Timeout!")); Abschalten (); } } // Von while (Menue) Serial.println (F("Zeitvorwahl Ende ")); display.clearDisplay (); display.display (); } /******************************************************************* * * Zeigt die restliche Laufzeit an bis abgelaufen oder abgebrochen * *******************************************************************/ int Zeitablauf (void) { char buf [15]; int Pause; display.clearDisplay (); display.setCursor (20,20); display.print ("Start"); display.display (); delay (2000); Pulszaehler = 0; while ((Laufzeit > 0) || (RuderTimeout > 0)) { #define SEKUNDE 129 Pause = SEKUNDE; #define FEINANPASSUNG 3 unsigned long SecCount = millis (); while ((SecCount+1000) > millis ()) // while (Pause > 0) { // delay (FEINANPASSUNG); if (GetTaste () == LONGKEY) { RuderTimeout = RUDERTIMEOUT; Serial.print (F("Tastenabbruch")); return (ABBRUCH); } //--------------------------- // Strecke und Zeit ausgeben // wenn noch Zeit dafür ist //--------------------------- if ((SecCount+950) > millis ()) { //------------------- // Strecke bestimmen //------------------- Ruderstrecke = (float)Pulszaehler / (float)WEGFAKTOR; display.clearDisplay (); // Zeit ausgeben display.setTextSize (3); display.setCursor (20,0); if ((Pause > (SEKUNDE / 2)) || (Laufzeit == 0)) sprintf (buf, "%2d:%02ds", Laufzeit / 60, Laufzeit % 60); else sprintf (buf, "%2d %02ds", Laufzeit / 60, Laufzeit % 60); display.print (buf); // Strecke ausgeben display.setTextSize (2); display.setCursor (10,32); char tmp [10]; dtostrf(Ruderstrecke,6,1,tmp); display.print (tmp); display.print ("m"); // Anzeigen display.display (); } // Von if ((SecCount+950) > millis ()) } // Timeouts bedienen if (Laufzeit > 0) Laufzeit--; if (RuderTimeout> 0) RuderTimeout--; if (RuderTimeout == 0) { Serial.println (F("Ruder-Timeout!")); Abschalten (); } } // Von while (Laufzeit > 0) display.setTextSize (3); return (ABLAUF); } /**************** * * Hauptprogramm * ****************/ void loop() { Serial.println ("Und wieder von vorne..."); ZeitVorwahl (); int Ergebnis = Zeitablauf (); }