/* (C) 2019 R.Schick / Thorsten Gurzan - beelogger.de This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ // beelogger.de - Arduino Datenlogger für Imker // Erläuterungen dieses Programmcodes unter http://beelogger.de // Version 2020.04.13 // für Tobias Weiberle abgeänderter Sketch -- 24.04.21 // // SMS senden alle 2 Tage #include #include #include "Multi_SD_config.h" // Konfiguration und Kalibrierung eintragen #include "beelogger_config.h" //############### Konfig Start ################################### //---------------------------------------------------------------- #define ID_ID "xyID" // SystemID für den Datentransfer, // minimal zwei Zeichen; diese werden in PC-Dateiname übernommen //---------------------------------------------------------------- //---------------------------------------------------------------- // Konfiguration Datentransfer via Serial / FTDI / USB //---------------------------------------------------------------- #define Serial_DATA 0 // mit oder ohne USB-Datentransfer //---------------------------------------------------------------- //---------------------------------------------------------------- // Konfiguration Datentransfer via SoftwareSerial Bluetooth z.B. HC-05 Modul //---------------------------------------------------------------- #define Bluetooth 0 // mit oder ohne Bluetooth #define Blue_Baurate 38400 #define Blue_On A3 // PIN A3 Bluetooth An Erkennung (Schalter) //---------------------------------------------------------------- //############### Konfig Ende #################################### #include // Bluetooth Serial // RX/TX der seriellen Schnittstelle zum HC-05, autom. Konfiguration. #if defined(ARDUINO_AVR_NANO) // beelogger_Universal (NANO) #define Blue_TX 9 // PIN 8 Bluetooth #define Blue_RX 8 // PIN 9 Bluetooth #else // beelogger Solar (PRO MINI and other) #define Blue_TX 8 // PIN 8 Bluetooth #define Blue_RX 9 // PIN 9 Bluetooth #endif //---------------------------------------------------------------- //---------------------------------------------------------------- // Parameter SD-Kartenmodul //---------------------------------------------------------------- #include #include // Dateiname ablegen #define SD_CLK 13 // SD Card Clock #define SD_MISO 12 // SD Card MISO #define SD_MOSI 11 // SD Card MOSI #define SD_CS 10 // SD Card Chip Select #define SD_LED 7 // LED optional byte LED_ON = 0; // LED Nutzung an/aus char DatenString[96]; char File_Name[15] = "beelogger_Lukas_1.csv"; // Stringlänge beachten !!! //---------------------------------------------------------------- //---------------------------------------------------------------- // Variablen //---------------------------------------------------------------- const float No_Val = 99.9; // Vorbelegung, Wert nicht gemessen const float No_Value = -1.0; // Vorbelegung, Wert nicht gemessen // DHT1, DHT2, Si7021, SHT31a, SHT31b, BMEa, BMEb, DS18B20a,DS18B20b float SensorTemp[10] = {No_Val, No_Val, No_Val, No_Val, No_Val, No_Val, No_Val, No_Val, No_Val, No_Val}; // DHT1, DHT2, Si7021, SHT31a, SHT31b, BMEa, BMEb , leer , leer float SensorFeuchte[10] = {No_Value, No_Value, No_Value, No_Value, No_Value, No_Value, No_Value, No_Value, No_Value, No_Value}; // Kein_Sensor, Luftdruck, ZählerRegen, unbelegt float Aux[4] = {No_Value, No_Value, No_Value, No_Value}; float Licht = No_Value; float DS_Temp = No_Val; float Gewicht[4] = {No_Value, No_Value, No_Value, No_Value}; float LetztesGewicht[4] = {No_Value, No_Value, No_Value, No_Value}; float Batteriespannung = No_Value; float Solarspannung = No_Value; float Service = 0.0; DateTime aktuell; byte User_Action = 0; volatile bool ok_sleep = true; bool SMS_senden = 0; //---------------------------------------------------------------- //---------------------------------------------------------------- //---------------------------------------------------------------- void setup() { //---------------------------------------------------------------- // System on //---------------------------------------------------------------- digitalWrite(Power_Pin, HIGH); pinMode(Power_Pin, OUTPUT); delay(5); setup_hx711(); //---------------------------------------------------------------- //---------------------------------------------------------------- // Setup RTC //---------------------------------------------------------------- rtc.begin(); rtc.clearINTStatus(); delay(5); DateTime pc_tim = DateTime(__DATE__, __TIME__); long l_pczeit = pc_tim.get(); aktuell = rtc.now(); long l_zeit = aktuell.get(); if (l_pczeit > l_zeit) rtc.setDateTime(l_pczeit); // RS //---------------------------------------------------------------- int hnow = aktuell.hour(); int mnow = aktuell.minute(); uint32_t unix = aktuell.getEpoch(); if ( hnow = 21 && mnow >= 30 && mnow <= 39) { if ( ((unix /60 /60 /24) %2) == 1 ) // jeden zweiten Tag ausrechnen { SMS_senden = 1; } } //---------------------------------------------------------------- // Sleep Mode Interrupt //---------------------------------------------------------------- pinMode(DS3231_Interrupt_Pin, INPUT_PULLUP); delay(5); //---------------------------------------------------------------- //---------------------------------------------------------------- // Setup SD-Kartenmodul //---------------------------------------------------------------- digitalWrite(SD_LED, LOW); pinMode(SD_LED, OUTPUT); byte ee_val = EEPROM.read(0); // Dateiname in EE-Prom if ((ee_val >= '0') && (ee_val <= '9')) { // Pruefe erstes Zeichen EEPROM.get(0, File_Name); // Hole aktuellen Dateiname aus EE-Prom } //---------------------------------------------------------------- //---------------------------------------------------------------- // Setup Gewicht //---------------------------------------------------------------- Sensor_Gewicht(true); // Startwert Gewicht holen //---------------------------------------------------------------- // USB Serieller Datentransfer //---------------------------------------------------------------- Seriell_data(); // Datenabfrage via FTDI(USB) } //---------------------------------------------------------------- //################################################################## void loop() { if (User_Action == 1) { BlueTooth_data(); // Bluetooth(SoftSerial) User_Action = 0; } else { debugbegin(57600); debugprintln(ID_ID); debugflush(); Spannungen_messen(); if (Batteriespannung > VMinimum) { DS_Temp = No_Val; Sensor_DS18B20(); Sensor_DHT(); Sensor_Si7021(); Sensor_SHT31(); Sensor_BME280(); if (DS_Temp == No_Val) DS_Temp = rtc.getTemperature(); Sensor_Licht(); Sensor_Gewicht(false); for (int i = 0; i < Anzahl_Sensoren_Gewicht; i++) { if (DS_Temp != No_Val) { Gewicht[i] = Gewicht[i] - ((DS_Temp - Kalibriertemperatur[i]) * KorrekturwertGrammproGrad[i]); } } Daten_auf_SD_speichern(); Daten_per_SMS_senden(); } Alarm_konfigurieren(); debugflush(); debugend(); Serial_rxtx_off(); SleepNow(); } } //################################################################## //---------------------------------------------------------------- // Funktion SIM-Modul - Daten per SMS senden //---------------------------------------------------------------- void Daten_per_SMS_senden() { if (SMS_senden) { // SMS senden // SoftSerial kommuniation starten SoftwareSerial SIMSerial(9, 8); //SIM800L Tx & Rx is connected to Arduino #9 & #8 SIMSerial.begin(9600); //SIMSerial.println("AT"); //Once the handshake test is successful, it will back to OK SIMSerial.println("AT+CMGF=1"); // Text-Mode für SMS delay(500); SIMSerial.print("AT+CMGS="); // Telefonnummer übbertragen SIMSerial.println(telNummer); delay(500); SIMSerial.print(DatenString); delay(500); SIMSerial.write(26); // Von Datenblatt so verlangt delay(500); delay(5000); //Pause damit SMS raus kann bevor Arduino einschläft SMS_senden = 0; // wichtig sonst wird SMS immer wieder geschickt! } } //---------------------------------------------------------------- // Funktion SD-Kartenmodul - Daten auf SD speichern //---------------------------------------------------------------- void Daten_auf_SD_speichern() { SdFat SD; File dataFile; if (SD.begin(SD_CS, SPI_HALF_SPEED)) { DatenString_erstellen(); debugprint("to SD "); dataFile = SD.open(File_Name, FILE_WRITE); if (dataFile) { dataFile.println(DatenString); dataFile.close(); debugprint("written: "); debugprintln(DatenString); debugflush(); if (LED_ON == 1) { digitalWrite(SD_LED, HIGH); delay(150); digitalWrite(SD_LED, LOW); LED_ON = 0; } } } if (LED_ON == 1) { digitalWrite(SD_LED, HIGH); LowPower.powerStandby(SLEEP_2S, ADC_OFF, BOD_OFF); digitalWrite(SD_LED, LOW); } delay(100); SPI.end(); LED_ON = 0; } //---------------------------------------------------------------- //---------------------------------------------------------------- // Funktion Datenstring erstellen //---------------------------------------------------------------- void DatenString_erstellen() { int count = 0; aktuell = rtc.now(); count = sprintf(DatenString, "%d/", aktuell.year()); count += sprintf(DatenString + count, "%2.2d/", aktuell.month()); count += sprintf(DatenString + count, "%2.2d ", aktuell.date()); count += sprintf(DatenString + count, "%2.2d:", aktuell.hour()); count += sprintf(DatenString + count, "%2.2d:", aktuell.minute()); count += sprintf(DatenString + count, "%2.2d", aktuell.second()); if (Anzahl_Sensoren_Gewicht > 1) { count = Wert_hinzufuegen(count, DS_Temp, 1, No_Val); // Wägezellentemperatur } count = Wert_hinzufuegen(count, SensorTemp[Beute1], 1, No_Val); // Stocktemperatur 1 if (Anzahl_Sensoren_Gewicht > 1) { count = Wert_hinzufuegen(count, SensorTemp[Beute2], 1, No_Val); // Stocktemperatur 2 } if (Anzahl_Sensoren_Gewicht > 2) { count = Wert_hinzufuegen(count, SensorTemp[Beute3], 1, No_Val); // Stocktemperatur 3 } if (Anzahl_Sensoren_Gewicht > 3) { count = Wert_hinzufuegen(count, SensorTemp[Beute4], 1, No_Val); // Stocktemperatur 4 } float AussenTemp = SensorTemp[Aussenwerte]; if (AussenTemp == No_Val) AussenTemp = DS_Temp; // Temp aus RTC count = Wert_hinzufuegen(count, AussenTemp, 1, No_Val); // Außentemperatur count = Wert_hinzufuegen(count, SensorFeuchte[Beute1], 1, No_Value); // Stockluftfeuchte 1 if (Anzahl_Sensoren_Gewicht > 1) { count = Wert_hinzufuegen(count, SensorFeuchte[Beute2], 1, No_Value); // Stockluftfeuchte 2 } if (Anzahl_Sensoren_Gewicht > 2) { count = Wert_hinzufuegen(count, SensorFeuchte[Beute3], 1, No_Value); // Stockluftfeuchte 3 } if (Anzahl_Sensoren_Gewicht > 3) { count = Wert_hinzufuegen(count, SensorFeuchte[Beute4], 1, No_Value); // Stockluftfeuchte 4 } count = Wert_hinzufuegen(count, SensorFeuchte[Aussenwerte], 1, No_Value); // Außenluftfeuchte count = Wert_hinzufuegen(count, Licht, 1, No_Value); // Licht count = Wert_hinzufuegen(count, Gewicht[0], 2, No_Value); // Gewicht 1 if (Anzahl_Sensoren_Gewicht > 1) { count = Wert_hinzufuegen(count, Gewicht[1], 2, No_Value); // Gewicht 2 } if (Anzahl_Sensoren_Gewicht > 2) { count = Wert_hinzufuegen(count, Gewicht[2], 2, No_Value); // Gewicht 3 } if (Anzahl_Sensoren_Gewicht > 3) { count = Wert_hinzufuegen(count, Gewicht[3], 2, No_Value); // Gewicht 4 } count = Wert_hinzufuegen(count, Batteriespannung, 2, No_Value); // Akkuspannung count = Wert_hinzufuegen(count, Solarspannung, 2, No_Value); // Solarspannung count = Wert_hinzufuegen(count, Service, 2, No_Value); // Service count = Wert_hinzufuegen(count, Aux[1], 1, No_Value); // Aux 1 count = Wert_hinzufuegen(count, Aux[2], 2, No_Value); // Aux 2 count = Wert_hinzufuegen(count, Aux[3], 2, No_Value); // Aux 3 count = Wert_hinzufuegen(count, No_Value, 2, No_Value); // dummy count = Wert_hinzufuegen(count, No_Value, 2, No_Value); // dummy DatenString[count] = 0; } //---------------------------------------------------------------- //---------------------------------------------------------------- // Funktion Wert hinzufügen //---------------------------------------------------------------- int Wert_hinzufuegen(int count, float Wert, byte Nachkommastellen, float Fehler) { char Konvertierung[16]; int count_neu = count; if (Wert == Fehler) { count_neu += sprintf(DatenString + count, ",%s", ""); } else { dtostrf(Wert, 1, Nachkommastellen, Konvertierung); count_neu += sprintf(DatenString + count, ",%s", Konvertierung); } return count_neu; } //---------------------------------------------------------------- //---------------------------------------------------------------- // Funktion Spannungen messen //---------------------------------------------------------------- void Spannungen_messen() { Batteriespannung = Messe_Spannung(Batterie_messen); #if myDEBUG Serial.print(F(" Batterie [V]: ")); Serial.println(Batteriespannung); Serial.flush(); #endif if (Batteriespannung > VMinimum) { Solarspannung = Messe_Spannung(Solarzelle_messen); #if myDEBUG Serial.print(F(" Solarspannung [V]: ")); Serial.println(Solarspannung); Serial.flush(); #endif } } float Messe_Spannung (byte Pin) { int Messung_Spannung; float Spannung; Messung_Spannung = analogRead(Pin); Messung_Spannung = 0; for (byte j = 0 ; j < 16; j++) { Messung_Spannung += analogRead(Pin); } Messung_Spannung = Messung_Spannung >> 2; Spannung = (float)map(Messung_Spannung, 0, Kalib_Bitwert, 0, Kalib_Spannung) / 1000.0; return (Spannung); } //---------------------------------------------------------------- //---------------------------------------------------------------- // Funktion Alarm konfigurieren //---------------------------------------------------------------- void Alarm_konfigurieren() { int IntervallMinuten; long l_tm = aktuell.get(); int hnow = aktuell.hour(); if (Batteriespannung > VAlternativ) { IntervallMinuten = WeckIntervall_default; // Lora spezial Intervall konfig if (WeckIntervall_aktiv) { // Manuelle Intervalsteuerung aktiviert if ( (hnow >= WeckIntervall_Nacht_Anfang ) || (hnow < WeckIntervall_Nacht_Ende) ) { IntervallMinuten = WeckIntervall_Nacht; } else { IntervallMinuten = WeckIntervall_Tag; } if (WeckIntervall_Winter_aktiv == 1) { // Winterintervall aktiviert if ((aktuell.month() > WeckIntervall_Winter_Anfang) || (aktuell.month() < WeckIntervall_Winter_Ende)) { IntervallMinuten = WeckIntervall_Winter; } } } } else { IntervallMinuten = AlternativIntervallMinuten; } if (IntervallMinuten < 5) IntervallMinuten = 5; // minimal Intervall aktuell = l_tm + IntervallMinuten * 60; // xx Minuten später // rtc.enableInterrupts(aktuell.hour(), aktuell.minute(), 0); //interrupt at hour, minute, second l_tm = aktuell.minute() - aktuell.minute() % IntervallMinuten; // Auf Minuten runden rtc.enableInterrupts(aktuell.hour(), l_tm, 0); //interrupt at hour, minute, second debugprintF("Wakeup at: "); debugprint(aktuell.hour()); debugprint(":"); #if myDEBUG if (aktuell.minute() < 10) debugprint("0"); #endif debugprintln(aktuell.minute()); debugflush(); } //---------------------------------------------------------------- //---------------------------------------------------------------- // Funktion SleepNow //---------------------------------------------------------------- void SleepNow() { delay(5); hx711_SCK_Low(); // code order, important! digitalWrite(Power_Pin, LOW); delay(5); TWCR &= ~(bit(TWEN) | bit(TWIE) | bit(TWEA)); digitalWrite (A4, LOW); digitalWrite (A5, LOW); digitalWrite (SD_CS, LOW); digitalWrite (ONE_WIRE_BUS, LOW); digitalWrite (DHT_Sensor_Pin[0], LOW); digitalWrite (DHT_Sensor_Pin[1], LOW); pinMode (SD_MOSI, INPUT); attachInterrupt(0, WakeUp, LOW); delay(1); while (ok_sleep) { LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); delay(50); } pinMode (SD_MOSI, OUTPUT); hx711_SCK_High(); digitalWrite (DHT_Sensor_Pin[0], HIGH); digitalWrite (DHT_Sensor_Pin[1], HIGH); digitalWrite(Power_Pin, HIGH); delay (5); rtc.begin(); rtc.clearINTStatus(); // check for User Interrupt LowPower.powerStandby(SLEEP_500MS, ADC_OFF, BOD_OFF); #if Bluetooth // nur wenn konfiguriert if (digitalRead(DS3231_Interrupt_Pin) == 0) { LowPower.powerStandby(SLEEP_500MS, ADC_OFF, BOD_OFF); if (digitalRead(DS3231_Interrupt_Pin) == 0) { User_Action = 1; } } #else // while nicht bei INT mit Schalter, sonst while endlos while (digitalRead(DS3231_Interrupt_Pin) == false) {}; #endif delay(50); ok_sleep = true; } //---------------------------------------------------------------- //---------------------------------------------------------------- // Funktion WakeUp //---------------------------------------------------------------- void WakeUp() { ok_sleep = false; detachInterrupt(0); } //---------------------------------------------------------------- //---------------------------------------------------------------- // Funktion Seriell_data(); // Datenabfrage via FTDI(USB) //---------------------------------------------------------------- void Seriell_data() // Sende Daten an PC { #if Serial_DATA SdFat SD; File dataFile; long l_time; int i; unsigned int j; char c_data; // das öffnen des Comport am PC löst einen Reset des Arduino aus // das Zeichen vom PC startet die gewaehlte Aktion // = ? Daten holen // = # aktuelle Daten lesen // = Z setze Zeit // = * neuen Namen für Datendatei // Serial.begin(57600, SERIAL_8N1); // fuer Datenabfrage Serial starten delay(10); { //USB-Seriell Serial.println("*"); // Sende an PC fertig für Empfang for (i = 0; i < 30; i++) { // warte auf Kommando vom PC delay(100); // alle 100ms abfragen if (Serial.available() > 0) { // Daten ? char inChar = (char)Serial.read(); // get the new byte: if (inChar == '?') { // if the incoming character is a ? //while ((char)Serial.read() != -1 ) {}; // Input leer ? sprintf(DatenString, "%s", ID_ID); sprintf(DatenString + 2, "%s", File_Name); Serial.println(DatenString); // Waagekennung für PC Serial.flush(); if (SD.begin(SD_CS, SPI_HALF_SPEED)) { if ( dataFile = SD.open(File_Name, FILE_READ)) { j = 0; while (dataFile.available()) { // Zeichen für Zeichen c_data = dataFile.read(); if ((c_data == '\r') || (c_data == '\n')) { // Zeilenende DatenString[j - 1] = 0; Serial.println(DatenString); // mit NL Serial.flush(); delay(10); // damit seriell fertig wird j = 0; // buffer von vorne fuellen } else if (j < sizeof(DatenString)) { // grenze buffer DatenString[j] = c_data; j++; } } dataFile.close(); // close the file delay(5000); // force PC-Software timeout } // file open } // SD begin break; // end for } else if (inChar == 'Z') { //Setze Zeit in RTC j = 0; while ((c_data = Serial.read()) != -1 ) { // Input lesen DatenString[j] = c_data; j++; if (j > 16) break; } DatenString[j] = 0; l_time = atol(DatenString); l_time = l_time - 946684800; // EPOCH_TIME_OFF = Korrektur DS3231 rtc.setDateTime(l_time); aktuell = rtc.now(); // neue Zeit break; // end for } else if (inChar == '*') { // neuer Name fuer Datei auf SD sprintf(File_Name, "%d", aktuell.year()); // 20xy sprintf(File_Name + 4, "%2.2d", aktuell.month()); // Monat sprintf(File_Name + 6, "%2.2d", aktuell.date()); // Tag File_Name[8] = '.'; File_Name[9] = 'c'; File_Name[10] = 's'; File_Name[11] = 'v'; File_Name[12] = 0; EEPROM.put(0, File_Name); Serial.println(File_Name); // mit NL break; // end for } else if (inChar == '#') { // aktuelle Werte Spannungen_messen(); DS_Temp = No_Val; Sensor_DS18B20(); Sensor_DHT(); if ((DS_Temp == No_Val)) DS_Temp = rtc.getTemperature(); Sensor_Licht(); Sensor_Gewicht(true); DatenString_erstellen(); // CSV-Datenstring Serial.println(DatenString); // mit NL Serial.println(File_Name); Serial.println(ID_ID); break; // end for } } // serial available } // for i delay(50); // damit seriell fertig wird } // USB-Seriell #if not Debug Serial.end(); // Serial aus delay(50); digitalWrite(USB_RX, LOW); // Port aus pinMode(USB_TX, INPUT); digitalWrite(USB_TX, LOW); // Port aus #endif #endif } //---------------------------------------------------------------- //---------------------------------------------------------------- // Funktion BlueTooth_data(); // Bluetooth(SoftSerial) //---------------------------------------------------------------- void BlueTooth_data() { #if Bluetooth // nur wenn konfiguriert SdFat SD; File dataFile; unsigned int j; char c_data; // = ? Daten holen // = # aktuelle Daten lesen // = * neuer Dateiname // Bluetooth via HC-05 Modul // beelogger braucht Ein-Schalter für Modul und externen Reset-Taster // Das Signal "eingeschaltet" wird auf Pin Blue_on gelegt. // Mit manuellem Reset wird der SoftwareSerial gestartet und wartet auf Eingaben. // Beenden mit Aus-Schalten der Bluetoooth-Modul Versorgung. SoftwareSerial blueSerial(Blue_RX, Blue_TX); //RX,TX blueSerial.begin(Blue_Baurate); delay(200); #if Debug Serial.println("BT on"); #endif while (digitalRead(Blue_On)) { delay(100); // alle 100ms abfragen if (blueSerial.available() > 0) { // Daten ? char inChar = (char)blueSerial.read(); // get the new byte: #if Debug Serial.print("Ser-in: "); Serial.println(inChar); #endif while (blueSerial.read() != -1 ) {}; // Input leer ? if (inChar == '?') { // if the incoming character is a ? if (SD.begin(SD_CS, SPI_HALF_SPEED)) { #if Debug Serial.print("SD: "); #endif if ( dataFile = SD.open(File_Name, FILE_READ)) { #if Debug Serial.print(" open ! "); Serial.println(File_Name); #endif j = 0; while (dataFile.available()) { // Zeichen für Zeichen c_data = dataFile.read(); #if Debug Serial.print(c_data); delay(5); #endif if ((c_data == '\r') || (c_data == '\n')) { // Zeilenende DatenString[j] = c_data; DatenString[j + 1] = 0; blueSerial.print(DatenString); // mit NL delay(50); // damit seriell fertig wird j = 0; // buffer von vorne fuellen } else if (j < sizeof(DatenString)) { DatenString[j] = c_data; j++; } } dataFile.close(); // close the file }// file open } } else if (inChar == '*') { // neuer Name fuer Datei auf SD sprintf(File_Name, "%d", aktuell.year()); // 20xy sprintf(File_Name + 4, "%2.2d", aktuell.month()); // Monat sprintf(File_Name + 6, "%2.2d", aktuell.date()); // Tag File_Name[8] = '.'; File_Name[9] = 'c'; File_Name[10] = 's'; File_Name[11] = 'v'; File_Name[12] = 0; EEPROM.put(0, File_Name); Serial.println(File_Name); // mit NL break; // end for } else if (inChar == '#') { // # = aktuelle Werte blueSerial.println(File_Name); Spannungen_messen(); DS_Temp = No_Val; Sensor_DS18B20(); if ((DS_Temp == No_Val)) DS_Temp = rtc.getTemperature(); Sensor_Licht(); Sensor_Gewicht(true); DatenString_erstellen(); // CSV-Datenstring #if Debug Serial.println(DatenString); #endif blueSerial.println(DatenString); // mit NL delay(50); // damit seriell fertig wird } else { #if not Debug // break; // ungültiges Zeichen, Ende while #endif } } // serial available } // while blue on delay(50); blueSerial.end(); delay(10); digitalWrite (Blue_TX, LOW); // TX aus pinMode( Blue_TX, INPUT); digitalWrite (Blue_RX, LOW); #endif // Bluetooth } //----------------------------------------------------------------