/* // ******************************************************************** // ********** GPS-SD.ino ********************************************** // ******************************************************************** // letzte Programm-Version mit Beep, Einschaltverzoegerung, Sensorik,** // Helligkeitsregelung und SD-Karten-Speicherung *** // Thermo/Hygro = DHT22 an Pin 10 (DHTPIN) *** // Beep = Piezo-Piepser an Pin 8 (TickPin) *** // Barometer = BMP085, oder BMP180 an PinSDA & SCL (i2C) *** // Einschaltverzoegerung als externe Transistorschaltung an Pin 9 *** // Helligkeitsregelung der Anzeige = Pin A0 (SensorPin) *** // Zeitzone = UTC & MEZ/MESZ *** // ******************************************************************** // Individualisiert und ausgebaut: B.Schnare, 19.06.bis 01.02.2016 *** // GPS-SD_Ampel.ino 13.02.2016 'Ampel'-Kontrollfeld, oben rechts *** // GPS-433.ino 02.08.2016 433 MHz Aussensensor-Empfang *** // GPS-433_20160082323.08.2016 Korrekturwerte Sensorik. Layout-Aend*** // * */ /* ******************************************************************** Hierbei handelt es sich um einen ARDUINO-Sketch, der mittels eines GPS-Empfaengers die Uhrzeit und das Datum synchronisieren und als UTC und Lokalzeit anzeigen soll. Es ist angelehnt an einen Beitrag in der 'MAKE 02/2015', als auch im Wesentlichen an die Entwicklungs- arbeiten von H.-J. Berndt --> www.hjberndt.de/soft/ardgpstime.html, sowie letztlich an Beispielen aus den Bibliotheken Time.h, Timezone.h, DHT, Adafruit_Bmp085 Als Anzeige wird ein Grafik-Display mit 4.3" verwendet. Und es ist ein Zeitzeichen eingebaut (beep). Benoetigt wird neben einem ARDUINO MEGA2560, der Empfaenger CRIUS NEO-6, ein 4.3"-TFT-Display, ein Temp./Humity-Sensoren, ein TFT-Shield, ein Luftdrucksensor (11.Nov.2015), sowie eine Transistorschaltung zur Einschaltverzoegerung (10.Nov.2015). Die Sensorik ist optional und muß nicht angeschlossen werden; ebenso wie ein Piezo-Piepser. Zuletzt ist noch ein Helligkeitsregler hinzugekommen (13.Nov.2015). Sowie die SD-Karten-Speicherung der Sensordaten im 10-Minuten-Interval (01.02.2016). . . Die UTC mit Namen wird neben der Lokalzeit angezeigt wird. Sommer- und Winterzeit werden automatisch ermittelt. Es werden die Geo-Daten eingeblendet, sowie die Sensor-Daten, sofern angeschlossen. Die verzoegerte Zuschaltung des GPS-Signals erfolgt hier mittels einer Transistor-Schaltung an Pin9. Nicht benötigte Bereiche muessen nicht auskommentiert werden. ..................................................................................... Das ist die vorläufig abschließende Version GPS-SD.ino offene Punkte : DHT22 anschliessen und testen --> OK Barometer einbinden --> 11.11.2015 Transistor-Einschaltverzoegerung --> 10.11.2015 Helligkeitsregler programmieren --> 13.11.2015 Keine Platzhalter, oder Texte wenn kein BMP085 angeschlossen --> 11.11.2015 Uhr soll auch laufen wenn BMP085 nicht angeschlossen ist Status-Hilfs-Script auf seriellem Monitor Sensordaten auf SD-Karte speichern --> 30.01.2016 drittes Speicher-Kriterium entwickeln --> 01.02.2016 433 MHz Aussensensor-Empfang --> 02.08.2016 Korrekturwerte für Sensorik, sowie Layout/Farb-Aenderungen --> 23.08.2016 ***************************************************************************************************** */ #include // #include // von der ARDUINO.cc-Seite #include // von der ARDUINO.cc-Seite UTFT LCD(ITDB43, 38, 39, 40, 41); // Pinbelegung auf MEGA 256 extern uint8_t SmallFont[]; // Auswahl der gewuenschten Schriftgroessen extern uint8_t BigFont[]; extern uint8_t SevenSegNumFont[]; const int C_PLUS_PORT = 9; // Einbinden der Verzoegerungsschaltung von V.v.d.Voort #define TICKPIN 8 // Ausgang fuer das Zeitzeichen int SensorPin = 1; // Pin fuer die Vergleichsmessung zur Auswahl der Farben int Value = 0; // Variable zur Aufnahme des Sensor-Wertes // *** fuer 433 MHz ******************************************************* #include // 433MHz-Empfaenger RCSwitch mySwitch = RCSwitch(); long wartezeit = 65000; // Vorgabe: aktuell 65 Sekunden long lastMillis = 0; // Variable für den letzten verfuegbaren Millis-Wert long zeitspanne = 0; // Variable fuer die Differenz von Millis zu lastMillis struct ts_ausgabe { int ident; float wert; int nachkomma; }; float ta; float ha; // *** fuer Sensorik ******************************************************* #include "DHT.h" #define DHTPIN 10 // Temperatur-Sensor #define DHTTYPE DHT22 // DHT11, DHT21, DHT22 DHT dht(DHTPIN, DHTTYPE); #include // BMP085-Bibliothek #include // I2C-Bibliothek einbinden Adafruit_BMP085 bmp; // Luftdruck-Sensor // *** fuer SD-Karte ******************************************************* #include // ein Synchronisations-Tool für ein –, oder mehrere Peripherie-Geräte  im IDE-Standard #include // fuer die SD-Karte  im IDE-Standard #define SD_CS 53 File logDat; // diese Variable 'logDat' im Format 'File' nimmt spaeter den Dateinamen und die Befehle auf String dataString = ""; // fuer die Aufnahme sämtlicher Sensor-Daten int go = 0; // SD-Schreib-Freigabe // *** fuer die Zeiten ***** int s10 = 0, s01 = 0; int m10 = 0, m01 = 0; int h10 = 2, h01 = 3; // *** Zeitzonen-Regeln, Wochentag ***************************************************** TimeChangeRule CEST = {"MESZ", Last, Sun, Mar, 2, 120}; // Beginn der Sommerzeit UTC +2Std. CentralEuropeanSommerTime TimeChangeRule CET = {"MEZ", Last, Sun, Oct, 3, 60}; // Beginn der Winterzeit UTC +1Std. CentralEuropeanTime // TimeChangeRule CEST = {"AEST", First, Sun, Mar, 2, 600}; // Beginn der Sommerzeit UTC +10 Std. AustralinDaylightTime // TimeChangeRule CET = {"AEDT", First, Sun, Oct, 3, 660}; // Beginn der Winterzeit UTC +11 Std. AustralianEasternStandardTime Timezone CE(CEST, CET); // Die Variable 'CE' beinhaltet die Info, in welcher Zeitzone wir uns aktuell befinden TimeChangeRule *tcr; time_t utc, local; // zusaetzlich // *** Wochentag erzeugen ************************************************************* char *Tag[7] = {"SONNTAG ", "MONTAG ", "DIENSTAG ", "MITTWOCH ", "DONNERSTAG", "FREITAG ", "SAMSTAG " }; String Line = ""; // Eine String-Variable fuer die Aufnahme der Eingangsdaten unsigned long nogps = 1000; // *** Vorbereitung auf den verzoegerten Start der seriellen Kommunikation ************ long count_millis = 0; boolean flag = 0; // ************************************************************************************ // *************** S E T U P ********************************************************* // ************************************************************************************ void setup() // *** SETUP fuer das TFT-Display *** // ********************************** { randomSeed(analogRead(0)); LCD.InitLCD(LANDSCAPE); // weisse Schrift auf schwarzem Grund - oder default-Wert > LCD.InitLCD(); < LCD.setFont(BigFont); // Schrifttyp LCD.clrScr(); // Loesche den Display-Inhalt byte br = 2; LCD.setBrightness(br); Line.reserve(100); Serial.begin(9600); Serial.println("Start "); // für event. Kontroll-Ausgabe auf dem Serial-Monitor // *** einstellbarer Farb-Wert *** // **** regelbares Poti ***** /* int Value = (analogRead(1) / 4); // Sensor-Wert durch 4, da Werte bis 1024 Serial.print("Helligkeitswert = "); Serial.println(Value); // Serial.print("Analog-Wert = "); Serial.println(analogRead(1)); LCD.fillScr(Value, Value, Value); // Bildschirmfarbe variabel */ // **** Wahlschalter **** der Fixwert fuer 'mein GRAU' liegt bei 86 *** // Serial.println(); // Serial.print("analogRead= "); Serial.println(analogRead(1)); if (analogRead(1) < 500) { int Value = 0; LCD.fillScr(Value, Value, Value); // schwarz, 0 } else if (analogRead(1) < 900) { int Value = 86; LCD.fillScr(Value, Value, Value); // grau, 86 } else if (analogRead(1) > 900) { int Value = 250; LCD.fillScr(Value, Value, Value); // weiss, 1016/250 // LCD.fillScr(255, 160, 0); // dunkel-Orange, 1016/250 } // Serial.print("Analog-Wert = "); Serial.println(analogRead(1)); // *** Fix-Werte ******* // LCD.fillScr(VGA_SILVER); // Bildschirmfarbe silbergrau // LCD.fillScr(VGA_OLIVE); // Bildschirmfarbe oliv // LCD.fillScr(244, 164, 96); // sandfarben // LCD.fillScr(255, 160, 0); // dunkel-Orange // *** SETUP fuer die Zeitverzöegerung *** // *************************************** pinMode(C_PLUS_PORT, OUTPUT); digitalWrite(C_PLUS_PORT, HIGH); // *** und fuer weiter Komponenten // ********************************** int h = 23; int m = 59; int s = 45; setTime(h, m, s, 0, 0, 0); // kurz vor 2K (2000) // **** Temp/Feuchte-Sensor starten ************* dht.begin(); // DHT-Sensorik // **** Empfaenger starten *********************** mySwitch.enableReceive(4); // interrupt 0=Pin2; 1=Pin3; 5=Pin18; 4=Pin19; 3=Pin20; 2=Pin21 // **** BMP085 starten ************************** Wire.begin(); // Initialisiere I2C (fuer BMP085) if (!bmp.begin()) { // ** Pruefen ob BMP085 laeuft *** Serial.println("Kein BMP085 gefunden ... I2C Adresse und Verkabelung pruefen !"); // Ausgabe nur auf dem seriellen Monitor while (1) {} } // **** GPS-Daten-Empfang pruefen *************** { while (Serial.available())Serial.read(); // Pruefen ob GPS-Daten vorhanden Serial.println("GPS-Daten werden empfangen. "); } // *** erstelle Frames **************** // ************************************ // *** oberer Rand *************** LCD.setColor(64, 64, 64); // grau - oberer Rand LCD.fillRect(0, 0, 479, 15); // links, oben, rechts, unten = volle Breite mit 15 Zeilen LCD.setBackColor(64, 64, 64); // Hintergrundfarbe der Anzeigefelder LCD.setColor(VGA_BLACK); // Schriftfarbe LCD.print("GPS-433.ino", CENTER, 0); // Text,zentriert,Zeile 0 // *** unterer Rand ************** LCD.setColor(64, 64, 64); // grau - unterer Rand LCD.fillRect(0, 258, 479, 271); // links, ab Z.258, volle Breite, bis Z.271 LCD.setBackColor(64, 64, 64); // Hintergrundfarbe der Anzeigefelder LCD.setColor(VGA_BLACK); // Schriftfarbe LCD.print("- DL2EBZ - Aug. 2016", CENTER, 258); // Text,zentriert,Zeile 258 // *** mittlerer Trennstreifen **** LCD.setColor(0, 0, 0); // schwarz - Trennlinie LCD.fillRect(100, 92, 400, 94); // links, oben, rechts, unten = volle Breite mit 15 Zeilen // *** Trennstreifen und Ueberschrift für die Sensorik *** LCD.setColor(VGA_WHITE); // Schriftfarbe // LCD.setBackColor(86, 86, 86); // grau LCD.setBackColor(0,0,0); // schwarz LCD.setFont(SmallFont); LCD.print ("innen aussen", 336, 180); // "Text",Spalte,Zeile LCD.setColor(255, 255, 255); // weiss - Trennlinie LCD.fillRect(220, 195, 472, 196); // waagerecht * links, oben, rechts, unten = volle Breite mit 15 Zeilen LCD.fillRect(387, 181, 388, 236); // senkrecht * // *** SETUP fuer die SD-Karte ******** // ************************************ Serial.print("Initialisiere SD-Card... "); // Zugriffs-Versuch auf die SD-Karte pinMode (53, OUTPUT); // fuer MEGA2560 // pinMode (10, OUTPUT); // fuer UNO R3 if (!SD.begin(SD_CS)) // oder auch --> if (!SD.begin(4)) { Serial.println(" Fehler !"); return; } Serial.println(" OK!"); // *** Ampel *** Speicher-Freigabe *** LCD.setColor(180, 0, 0); // rot LCD.fillRect(400, 2, 410, 12); // links,oben,rechts,unten --> also hier: ein kleines Quadrat, oben rechts } // SETUP // *** SETUP fuer das Stundensignal *** // ************************************ void beep() // Piept DLF-Signallaenge { int m = minute(); int s = second(); #define PIPS (TICKPIN,1000,150) #define BEEP (TICKPIN,1000,850) #define TICK (TICKPIN,1000,1) boolean mpips = m == 29 || m == 59; boolean spips = s == 57 || s == 58 || s == 59 || s == 55 || s == 56; boolean sbeep = m == 0 && s == 0; boolean pips = mpips && spips; if (sbeep)tone BEEP; else if (pips)tone PIPS; else tone TICK; } // beep // ************************************************************************************ // *************** L O O P *********************************************************** // ************************************************************************************ void loop() { // *** hier kommt ein originaler GPS-Teil ***** static int os = -1, om = -1, oh = -1; if (!(os % 3))if (getline("$GPGGA"))GGA(); if (!(os % 4))if (getline("$GPRMC"))RMC(); SerialClear(); if (second() != os) // jede Sekunde { s01 = second() % 10; s10 = second() / 10; m01 = minute() % 10; m10 = minute() / 10; h01 = hour() % 10; h10 = hour() / 10; // beep(); if (om != minute()) // jede Minute { if (oh != hour()) // jede Stunde { oh = hour(); } //hour om = minute(); } //minute os = second(); } //second { int buf[478]; int x, x2; int y, y2; int r; // *** UHRZEIT *** // *************** int Value = (analogRead(1) / 4); // Sensor-Wert durch 4, da Werte bis 1024 LCD.setBackColor(Value, Value, Value); // variabler Wert // LCD.setBackColor(VGA_SILVER); // Hintergrundfarbe des großen Mittelfeldes LCD.setColor(VGA_NAVY); // Schriftfarbe char t[10]; char h[2]; char m[2]; char a[2]; LCD.setFont(SevenSegNumFont); sprintf(h, "%02d", hour()); // Stunde-local LCD.print(h, 135, 100); LCD.setFont(BigFont); LCD.print(":", 196, 120); // Doppelpunkt LCD.print(":", 196, 60); // Doppelpunkt UTC LCD.setFont(SevenSegNumFont); sprintf(m, "%02d", minute()); // Minute-local LCD.print(m, 210, 100); LCD.print(m, 210, 40); // Minute UTC LCD.setFont(BigFont); LCD.print(":", 271, 120); // Doppelpunkt LCD.print(":", 271, 60); // Doppelpunkt UTC LCD.setFont(SevenSegNumFont); sprintf(a, "%02d", second()); // Sekunde-local LCD.print(a, 290, 100); LCD.print(a, 290, 40); // Sekunde UTC LCD.setFont(BigFont); LCD.print(tcr -> abbrev, 35, 120); // Anzeige der lokalen Zeitzone // ** und nochmals fuer die berechnete UTC ***** // ********************************************* LCD.setFont(BigFont); LCD.print("U T C", 20, 60); // *** DATUM *** // ************* LCD.setFont(BigFont); char s[10]; sprintf(s, "%02d.%03s.%04d", day(), monthShortStr(month()), year()); // Datum dd.mmm.yyyy LCD.print(s, 240, 160); // .. Spalte 240, Zeile 160 char u[10]; sprintf(u, "%02d.%02d.%02d", hour(), minute(), second()); // Uhrzeit dataString = (s); // Datum dataString += (";"); dataString += (u); // Uhrzeit dataString += (";"); } // Uhrzeit { // nur noch eine Kontrolle if (Serial.available()) Serial.write(Serial.read()); } // *** 433Mhz-Empfang ***** DL9VDV ************************* struct ts_ausgabe ls_ausgabe; if (mySwitch.available()) { ls_ausgabe = decode_433(mySwitch.getReceivedValue()); if (ls_ausgabe.ident > 0) { ausgabe(ls_ausgabe); ls_ausgabe.ident = 0; } mySwitch.resetAvailable(); } // *** TimeOut-Pruefung *** DL2EBZ *** zeitspanne = (millis() - lastMillis); if ((millis() - lastMillis) > wartezeit) { Serial.print ("Zeitspanne= "); Serial.print (zeitspanne); Serial.println(" Timeout-Zeit fuer den 433-MHz-Sender ist ueberschritten !!"); LCD.setColor(180, 0, 0); // rot, gruen, blau LCD.fillRect(395, 200, 455, 215); // links,oben,rechts,unten ... male den Bereich für die Feuchte rot aus LCD.fillRect(395, 220, 455, 235); // links,oben,rechts,unten ... male den Bereich für die Temp rot aus } else { // Serial.println(" Timeout-Zeit ist OK "); } // *** FLAG zum Schreiben setzen ****** // *** ... und in einem Zeit-Rhytmus von 10 Minuten --> wenn m=09 or m=19 or m=29 or ... and s=00 // *** ... Da jedoch eine Messmoeglichkeit nicht immer genau um xy:19:59 zur Verfuegung stehen wird (Programmdurchlauf), oder gerade dann // der Wert 'nan' ist, muß auch da zudem noch solange der Schreib-Kanal geöffnet bleiben, bis es zu einer Speicherung gekommen // ist - und dann 'weiter wie geplant' = xy:29:59 ! if ((minute() == 9 && second() == 59) || (minute() == 19 && second() == 59) || (minute() == 29 && second() == 59) || (minute() == 39 && second() == 59) || (minute() == 49 && second() == 59) || (minute() == 59 && second() == 59)) { go = 1; // ... DANN go=1 --- Variable zur Freigabe des SPEICHER-Vorgangs auf die SD-Karte. Funktion ist geprueft ! // *** Ampel *** LCD.setColor(0, 180, 0); // gruen LCD.fillRect(400, 2, 410, 12); // links,oben,rechts,unten --> also hier: ein kleines Quadrat, oben rechts } // if } // loop // *** FIX SAT und Ausgabe ******** G G A ********************************************* // *************************************************************************+ void GGA() // Anzeige von Anzahl Satelliten und Wochentag, sowie Sensorik (erfolgt erst nach Anschluß der TX/RX-Leitung und Empfang des Sat-Signals !) { LCD.setColor(VGA_BLUE); // Schriftfarbe LCD.setFont(BigFont); LCD.print(Tag[weekday() - 1], 70, 160); // Wochentag Sp70-Z160 // *** Im Folgenden werden Pruefdaten empfangen ************ LCD.setFont(SmallFont); LCD.print("EGNOS ", 70, 20); // EGNOS sendet 0=kein, 1=ohne, 2=OK LCD.print(getparam(6), 115, 20); LCD.print(getparam(7), 10, 20); // Anzahl Satelitten im Zugriff LCD.print("Sat", 40, 20); // *** Nun folgt die Ausgabe der Positionswerte *************************** LCD.setColor(VGA_WHITE); // Schriftfarbe LCD.print(getparam(2), 30, 200); // Position (N) LCD.print(getparam(3), 130, 200); // N LCD.print(getparam(4), 20, 220); // Position (E) LCD.print(getparam(5), 130, 220); // E // LCD.print(getparam(6), 20, 250); // FIX (Synchronisation) Zeichen = 2 LCD.print(getparam(9), 20, 240); // Hoehe (in meter) LCD.print(getparam(10), 75, 240); // M --> Meter // *** Wenn Zeitbasis synchronisiert - dann gruenes Feld als Bestaetigung *** LCD.setBackColor(0, 150, 0); // Hintergrundfarbe der Anzeigefelder LCD.setColor(0, 0, 0); // Schriftfarbe 'schwarz' LCD.print("s", 5, 0); // an sich sollte es heißen: if getparam(6) = 2 dann "sync" // *** Default-Werte für die Ampel-Darstellung *** // LCD.setColor(180, 0, 0); // LCD.fillRect(420, 2, 430, 12); // links,oben,rechts,unten --> also hier: ein kleines Quadrat, oben rechts // *** Sensorik --> Temperatur & Luftfeuchte **** // ***************** innen ********************** { float hygro = (dht.readHumidity() + 20); // Luftfeuchte auslesen, sowie mit einem Korrektur-Wert addieren float temp = (dht.readTemperature() -2); // Temperatur auslesen, sowie Korrektur // *** Luftdruck ******* float d = bmp.readPressure(); // Luftdruck float baro = (d + 1840) / 100; // Korrektur auf den hiesigen, aktuellen Wert Serial.println(); Serial.print("Luftdruck: "); Serial.println(baro); LCD.setFont(BigFont); // *** Farbauswahl **** int Value = (analogRead(1) / 4); // Sensor-Wert durch 4, da Werte bis 1024 LCD.setBackColor(Value, Value, Value); // variabler Wert // Serial.print("Hintergrundwert = "); Serial.println(Value); // LCD.setBackColor(VGA_SILVER); LCD.setColor(VGA_GREEN); // Schriftfarbe if (isnan(baro)) // Prüfen ob eine gueltige Zahl zurueckgegeben wird. Wenn NaN (not a number), dann ... { Serial.println(" Kein Luftdruck-Sensor verfuegbar !"); // Ausgabe nur auf dem seriellen Monitor // *** Ampel *** LCD.setColor(180, 0, 0); // rot LCD.fillRect(460, 2, 470, 12); // links,oben,rechts,unten --> also hier: ein kleines Quadrat, oben rechts } else { char ba[10]; dtostrf(baro, 2, 1, ba); LCD.setColor(VGA_GREEN); // Schriftfarbe LCD.print ("Baro :", 220, 240); // .., horizontal, vertikal LCD.print (ba, 318, 240); LCD.print ("hPa", 434, 240); // Serial.println(" Luftdruck-Sensor ist verfuegbar !"); // Ausgabe nur auf dem seriellen Monitor // *** Ampel *** LCD.setColor(0, 180, 0); // gruen LCD.fillRect(460, 2, 470, 12); // links,oben,rechts,unten --> also hier: ein kleines Quadrat, oben rechts } if (isnan(temp) || isnan(hygro)) // Prüfen ob eine gueltige Zahl zurückgegeben wird. Wenn ist NaN (not a number), dann ... { Serial.println(); // Serial.println("Kein Temp/Hygro-Sensor verfuegbar !"); // Ausgabe nur auf dem seriellen Monitor // *** Ampel *** LCD.setColor(180, 0, 0); // rot LCD.fillRect(440, 2, 450, 12); // links,oben,rechts,unten --> also hier: ein kleines Quadrat, oben rechts } else { char l1[10]; char l2[10]; // sprintf(l,"%f", hygro); dtostrf(hygro, 2, 1, l1); // Alternativ-Befehl, da Programmfehler bei Umwandlung von float, oder double Variablen zu String **** Float-Variable,2 Vorkommastellen, 2 Nachkommastellen, String-Variable dtostrf(ha, 2, 1, l2); LCD.print ("Hygro:", 220, 200); LCD.print (l1, 318, 200); LCD.print (l2, 395, 200); LCD.print ("%", 463, 200); Serial.print("Hygro,innen: "); Serial.println(l1); Serial.print("Hygro, aussen: "); Serial.println(l2); // LCD.print ("Hygro:", 235, 200); // LCD.print (l1, 365, 200); // LCD.print ("%", 435, 200); char b1[10]; // Alternativ-Befehl, da Programmfehler bei Umwandlung von float, oder double Variablen zu String **** Float-Variable,2 Vorkommastellen, 2 Nachkommastellen, String-Variable char b2[10]; dtostrf(temp, 2, 1, b1); dtostrf(ta, 2, 1, b2); LCD.print ("Temp :", 220, 220); LCD.print (b1, 318, 220); LCD.print (b2, 395, 220); LCD.print ("C", 463, 220); Serial.print("Temp, innen: "); Serial.println(b1); Serial.print("Temp, aussen: "); Serial.println(b2); // LCD.print ("Temp :", 235, 220); // LCD.print (b1, 365, 220); // LCD.print ("C", 435, 220); // Serial.println("Temp/Hygro-Sensor ist verfuegbar !"); // Ausgabe nur auf dem seriellen Monitor // *** Ampel *** LCD.setColor(0, 180, 0); // gruen LCD.fillRect(440, 2, 450, 12); // links,oben,rechts,unten --> also hier: ein kleines Quadrat, oben rechts } // *** Erstellen eines Datensatzes **** dataString += (temp); dataString += ";"; dataString += (ta); dataString += ";"; // dataString += " C;"; dataString += (hygro); dataString += ";"; dataString += (ha); dataString += ";"; // dataString += " %;"; dataString += (baro); dataString += ";"; // dataString += " hPa;"; dataString += (Tag[weekday() - 1]); dataString += ";"; dataString += (getparam(2)); // Koordinaten dataString += ";"; dataString += (getparam(3)); // Koordinaten dataString += ";"; dataString += (getparam(4)); // Koordinaten dataString += ";"; dataString += (getparam(5)); // Koordinaten dataString += ";"; // *** Speichern der Sensor-Daten ***** // ************************************ // *** hier werden die Kriterien ueberprueft, welche erfuellt sein muessen, um einen Schreib-Vorgang zu starten **** if (year() < 2016) { // *** 2. ... und wenn eine korrekt GPS-Zeit vorhanden ist Serial.println(); Serial.println(" Kein GPS-Signal "); // .. nichts machen // *** Default-Werte für die Ampel-Darstellung *** LCD.setColor(180, 0, 0); // rot LCD.fillRect(420, 2, 430, 12); // links,oben,rechts,unten --> also hier: ein kleines Quadrat, oben rechts } else { // ... ansonsten weitermachen Serial.print(" GPS-Signal vorhanden. year= "); Serial.println(year()); LCD.setColor(0, 180, 0); // Feldfarbe: grün LCD.fillRect(420, 2, 430, 12); // links,oben,rechts,unten --> also hier: ein kleines Quadrat, oben rechts if (isnan(temp) || isnan(hygro)) // *** 3. ... und keine Sensor-Werte fehlen --> wenn (hygro) oder (temp) = 'NAN' { Serial.println(" Keine Sensordaten "); // ... nichts machen } else { Serial.println(" Sensordaten komplett "); // ... ansonsten weitermachen if ( go < 1) { // *** 1. grundsaetzliche Speicherfreigabe gemaess Intervall-Vorgabe Serial.print(" Keine Freigabe ! go= "); Serial.println(go); // ... nichts machen } else { Serial.print("XY:"); Serial.print(minute()); Serial.print(":"); Serial.print(second()); Serial.print(" go= "); Serial.print(go); Serial.print(" year= "); Serial.print(year()); Serial.println(" Sensordaten verfuegbar "); logDat = SD.open("LogFile.txt", FILE_WRITE); // Oeffenen der Datei 'LogFile.txt' zum nachfolgenden SCHREIBEN Serial.println("LogFile.txt zum Schreiben oeffnen."); if (logDat) { logDat.println(dataString); // Beschreiben der soeben erstellten Datei logDat.close(); // Datei nach dem Schreiben wieder schliessen go = 0; // Intervall-Freigabe zuruecksetzen Serial.print("Speicherung erfolgt. "); Serial.print("Die Variable go wird zurueckgesetzt auf den Wert: "); Serial.println(go); // *** Ampel *** LCD.setColor(180, 0, 0); // rot LCD.fillRect(400, 2, 410, 12); // links,oben,rechts,unten --> also hier: ein kleines Quadrat, oben rechts } else { Serial.println("Fehler beim Oeffnen der Datei LogFile.txt !"); // Hinweis fuer den Fall, dass sich die Datei nicht mehr oeffnen laesst } // Ende Schreibfehler } // Ende GPS-Signal ? } // Ende else isnan } // Ende Speicher-Intervall } // Ende Sensorik }// Ende GPGGA void RMC() // *** TIME DATE ********************* RMC **************************** // ******************************************************************************* { setTime(getparam(1).substring(0, 0 + 2).toInt(), // Stunde getparam(1).substring(2, 2 + 2).toInt(), // Minute getparam(1).substring(4, 4 + 2).toInt(), // Sekunde getparam(9).substring(0, 0 + 2).toInt(), // Tag getparam(9).substring(2, 2 + 2).toInt(), // Monat getparam(9).substring(4, 4 + 2).toInt()); // Jahr time_t utc = (now()); // Mit der Variablen 'utc' habe ich hier die Basis-Zeit. Dieser Wert muss aber noch umgerechnet werden ! time_t cet = CE.toLocal(now(), &tcr); // Aufbereitung der UTC-Zeit nach der TimeZone-Regel setTime(cet); // Hier wird nun die GPS-Zeit im vorgegebenen Format in die interne Zeitbasis uebernommen // Serial.println("GPS-Zeit auf ARDUINO uebernommen"); // ** UTC-Syntetic-Zeit *** zu MEZ/MESZ *** int Value = (analogRead(1) / 4); // Sensor-Wert durch 4, da Werte bis 1024 LCD.setBackColor(Value, Value, Value); // variabler Wert // LCD.setBackColor(VGA_SILVER); // Hintergrundfarbe der Anzeigefelder LCD.setColor(VGA_NAVY); // Schriftfarbe LCD.setFont(SevenSegNumFont); // Schrift-Fonts // *** UTC ausgehend von der Lokalzeit und der Zeitdifferenz ermitteln int diff = (cet - utc) / 3600; // Zeitunterschied in Stunden ==>>> nur bei Sat-Empfang moeglich int ho; if ((hour() - diff) < 0) { ho = (hour() - diff) + 24; // WENN Lokalzeit - Zeitunterschied =< 00:00, dann 24 hinzurechnen } else { (ho = hour() - diff); // SONST Lokalzeit - Zeitunterschied } char c[2]; sprintf(c, "%02d", ho); // Ausgabe der errechneten UTC-Stunde LCD.print(c, 135 , 40); // *** namentliche Ausgabe der Zeitzone erstellen *** LCD.setFont(SmallFont); // Schrift-Fonts LCD.setBackColor(0, 0, 150); // Hintergrundfarbe der Anzeigefelder LCD.setColor(0, 0, 0); // Schriftfarbe 'schwarz' LCD.print(tcr -> abbrev, 25, 0); // Ausgabe der aktuellen Zeitzone } // GPRMC void SerialClear() //-------------- GPS-ROUTINEN ------------------------------------------------------------- // *** Hier werden nun im Folgenden die eingehenden GPS-Daten verarbeitet ***************** //----------------------------------------------------------------------------------------- { while (Serial.available())Serial.read(); // Wenn GPS-Daten vorhanden, dann weiter // Serial.println("Es werden GPS-Daten empfangen. "); } boolean getline(char *phrase) //HARD POLLING { char s[100]; byte b, n; unsigned long t = millis(); for (int i = 0; i < sizeof(s); i++)s[i] = 0; Line = ""; do { b = Serial.read(); if (millis() > (t + 100))return false; } while (b != '$'); s[0] = b; n = Serial.readBytesUntil('\n', &s[1], 90); s[n] = 0; if (strstr(s, phrase) == s) { for (int i = 0; i < n; i++)Line += s[i]; return true; } return false; } #define hex(i) ((i<=9) ? ('0'+i): ('A'- 10 + i)) boolean checksum() { byte b = 0; int e; e = Line.indexOf('*'); if (e > 10) { for (int i = 1; i < e; i++)b ^= Line[i]; if ((hex((b & 15)) == Line[e + 2]) && (hex(b / 16) == Line[e + 1]))return true; } return false; } String getparam(int ix) { int c, cc = 0; if (checksum()) { do { c = Line.indexOf(',', cc); if (c >= 0)cc = c + 1; else break; } while (--ix); return (Line.substring(c + 1, Line.indexOf(',', c + 1))); } return "xx"; //debug } // DL9VDV Beginn --- 433 MHz -------- void ausgabe( struct ts_ausgabe ls_ausgabe) { int lv_std, lv_min, lv_sek; long lv_wert; if (ls_ausgabe.ident == 10) // Luftfeuchte { // Serial.print("Aussen-Hygro: "); Serial.println(ls_ausgabe.wert, ls_ausgabe.nachkomma); ha = ((ls_ausgabe.wert) -7); // Sensorwert-Korrektur lastMillis = millis(); // aktualisieren des letzten erreichbaren Zeit-Wert (nur bei vorhandenem Empfang) } else if (ls_ausgabe.ident == 12) // Temperatur { // Serial.print("Aussen-Temp: "); Serial.println(ls_ausgabe.wert, ls_ausgabe.nachkomma); ta = ((ls_ausgabe.wert) -1); // Sensorwert-Korrektur lastMillis = millis(); // aktualisieren des letzten erreichbaren Zeit-Wert (nur bei vorhandenem Empfang) } // ***** weitere Sensoren anschliessbar *** /* else if (ls_ausgabe.ident == 14) { Serial.print("temp_bmp180: "); Serial.println(ls_ausgabe.wert, ls_ausgabe.nachkomma); lastMillis = millis(); // aktualisieren des letzten erreichbaren Zeit-Wert (nur bei vorhandenem Empfang) } else if (ls_ausgabe.ident == 16) { Serial.print("baro: "); Serial.println(ls_ausgabe.wert, ls_ausgabe.nachkomma); lastMillis = millis(); // aktualisieren des letzten erreichbaren Zeit-Wert (nur bei vorhandenem Empfang) } else if (ls_ausgabe.ident == 18) { lv_wert = ls_ausgabe.wert; lv_std = lv_wert / 10000; lv_min = (lv_wert - ((lv_wert / 10000) * 10000)) / 100; lv_sek = lv_wert - ((lv_wert / 100) * 100); Serial.print("zeit1: "); Serial.print(lv_std); Serial.print(":"); Serial.print(lv_min); Serial.print(":"); Serial.println(lv_sek); lastMillis = millis(); // aktualisieren des letzten erreichbaren Zeit-Wert (nur bei vorhandenem Empfang) } else if (ls_ausgabe.ident == 40) { Serial.print("Tests: "); Serial.println(ls_ausgabe.wert, ls_ausgabe.nachkomma); lastMillis = millis(); // aktualisieren des letzten erreichbaren Zeit-Wert (nur bei vorhandenem Empfang) } */ } // ausgabe // **** 433 MHz Empfang-Funktionen Beginn ***************************** /* vdv test 1234567890 mySwitch.send(4294967295, 32); Typ long max 10 Stellen 1-2: Code 10-40 in Zweierschritten - Identifikation des Wertes Zweierpaerchen: Code + 1 (ungerade) für negatives Vorzeichen 3: Anzahl der Nachkommastellen 4-9: Wert 6 Stellen 10: Pruefcode Module 9 Stellen 1-9 */ struct ts_ausgabe decode_433(unsigned long lv_input) { int lv_pruefcode; static unsigned long lv_last_command; int lv_ident; int lv_nachkomma; int lv_while; float lv_wert; struct ts_ausgabe ls_ausgabe; ls_ausgabe.ident = 0; if (lv_input < 1000000000 || lv_input > 4199999999) return ls_ausgabe; lv_pruefcode = lv_input - ((lv_input / 10) * 10); lv_input = lv_input / 10; if ((lv_input % 9) != lv_pruefcode) return ls_ausgabe; // Wiederholung ? #ifdef protokoll if (lv_input == lv_last_command) // Testausgabe { Serial.print("----- Wiederholung: "); Serial.println(lv_last_command); } #endif if (lv_input == lv_last_command) return ls_ausgabe; lv_last_command = lv_input; lv_ident = lv_input / 10000000; lv_input = lv_input - ((lv_input / 10000000) * 10000000); lv_nachkomma = lv_input / 1000000; lv_input = lv_input - ((lv_input / 1000000) * 1000000); lv_wert = lv_input; lv_while = lv_nachkomma; while (lv_while > 0) { lv_wert = lv_wert / 10.0; lv_while = lv_while - 1; } if (lv_ident % 2 != 0) { lv_wert = -lv_wert; lv_ident = lv_ident - 1; } if (lv_ident % 2 != 0) return ls_ausgabe; ls_ausgabe.ident = lv_ident; ls_ausgabe.wert = lv_wert; ls_ausgabe.nachkomma = lv_nachkomma; return ls_ausgabe; } // --- 433 MHz Empfang-Funktionen Ende ********************** // ***** ENDE des Script ****************************************************************