Hello!
I am using the program below to monitor a gascounter (MilliGascounter; http://www.milligascounter.de/).
Basically, the the program counts signals from the gasmeter and does some arithmetics with it. After a certain time (standard is 4h) the results are sent to a PC.
There, a very useful program called "CooltTerm" receives the data and saves it into a *.txt-file to process it in Excel later.
Everything was working just fine, until I recently did some changes. Now CoolTerm works as expected for a day or sometimes even a week (the experiments take quite a lot of time...), then suddenly CoolTerm doesn't receive any more data. However, the board seems to continue working, as the counter is still going up (when I restart, the saved value is higher than the last one documented. Also the results fit the expectations, so I don't think, they are just randomly created or anything).
Sadly I can't say what exactly caused the problems. I mainly changed the time recording from simple hours based on the millis()-funktion to an actual time using the time-library. Also the possibility to change the interval-length and to print manually are new.
I really hope, you can help me...
Thank you in advance.
PS: All the comments are in German, as it is my mother language. If you need any explanations, feel free to ask.
#include <Time.h>
#include <EEPROM.h>
const int gaszaehlerIn = 2; // digitalPin des Gaszählers
const float volume = 3.57; // Volumen pro Ausschlag; empirisch ermittelt
float interval = 240; // Intervalllänge (in min)
float flowRate = 0;
int currentState = 0; // aktueller Status des Reed-Schalters (offen / geschlossen)
int lastState = 0; // vorheriger Status
long signalCounter = 0; // Anzahl an Ausschlägen
long lastSignalCounter = 0; // Ausschläge bis zur jeweils letzten seriellen Ausgabe der Daten
unsigned long startTime = 0; // Startzeit des Loops; ermöglicht die Regelung seiner Dauer
unsigned long printDif = 0; // Zeit zwischen der letzten und aktuellen Ergebniszeile; zur korrekten Bestimmung des Volumenstroms
int Tag = 0;
int Monat = 0;
int Jahr = 0;
int Stunde = 0;
int Minute = 0;
const int Sekunde = 0;
String command = "";
void setup() {
pinMode(gaszaehlerIn, INPUT_PULLUP); // eingehende Signale werden registriert
Serial.begin(9600); // Baud für Verbindung wird festgelegt
while (!Serial) { // Board wartet auf eine serielle Verbindung
;
}
printDif = now();
Serial.println("Aktuelle Zeit einstellen [Tag,Monat,Jahr,Stunden,Minuten]");
while (!Serial.available());
getTime();
setTime(Stunde, Minute, Sekunde, Tag, Monat, Jahr);
Serial.println("Zeit eingestellt");
Serial.println("");
printHeader();
signalCounter = EEPROMReadlong(0); // signalCounter vom letzten Mal wird geladen
lastSignalCounter = signalCounter;
delay(1000); // muss mindestens eine Sekunde sein, da für den Volumenstrom sonst durch 0 geteilt wird
printResults();
}
void loop() {
startTime = now(); // now() gibt die Zahl an Sekunden, die seit 1970 verstrichen sind
do {
currentState = digitalRead(gaszaehlerIn);
if (currentState != lastState) { // eine Änderung des Signals vom Gaszähler initiiert den nächsten Schritt
if (currentState == LOW) { // ist das Signal LOW? (=liegt eine Spannung an?)
signalCounter++; // ist dem so, wird der Counter um 1 erhöht
delay (250); // 250ms Wartezeit, damit ein Signal nicht als mehrere gezählt wird
}
else { // für den Fall, dass das Signal LOW ist:
;
}
}
lastState = currentState; // lastState und currentState werden wieder gleich gesetzt
while (Serial.available()) {
command = Serial.readString();
if (command == "clear") { // Vorgehen, falls "clear" gesendet wurde
Serial.println("");
for (int i = 0; i <= 3; i++) { //
EEPROM.write(i, 0); // signalCounter wird wieder auf 0 gesetzt
Serial.print(".");
delay(250);
}
Serial.println("");
Serial.println("Variablen zurueckgesetzt, Programm gestoppt.");
while (1) {}
}
if (command == "interval") { // Vorgehen, falls "Intervall" gesendet wurde
Serial.println("");
Serial.println("Bitte Intervalldauer in Minuten eingeben");
while(!Serial.available());
interval = Serial.parseFloat();
Serial.println("Intervalldauer angepasst");
Serial.println("");
}
if (command == "print") {
printResults();
lastSignalCounter = signalCounter;
long address = 0;
EEPROMWritelong(address, signalCounter);
address += 4;
}
if (command == "help") {
Serial.println("");
Serial.println("- 'interval' ermoeglicht ein manuelles Festlegen des Abstands zwischen zwei Ergebniszeilen.");
Serial.println("- 'print' gibt eine neue Ergebniszeile aus, waehrend die Intervalldauer unveraendert bleibt.");
Serial.println("- 'clear' loescht den gespeicherten Stand des Gaszaehlers und stoppt das Programm.");
Serial.println("");
}
}
} while (((now() - startTime)) < (interval * 60)); // Dauer des Loops
printResults();
long address = 0;
EEPROMWritelong(address, signalCounter);
address += 4;
lastSignalCounter = signalCounter;
}
void EEPROMWritelong(int address, long value) // die Funktion EEPROMWritelong() wird etabliert
{ //
byte four = (value & 0xFF); //dabei wird eine 4 Byte große long-Variable
byte three = ((value >> 8) & 0xFF); //in ihre einzelnen Bytes zerlegt (one ... four),
byte two = ((value >> 16) & 0xFF); //die dann auf separate Speicherplätze gelegt
byte one = ((value >> 24) & 0xFF); //werden.
//
EEPROM.write(address, four); //
EEPROM.write(address + 1, three); //
EEPROM.write(address + 2, two); //
EEPROM.write(address + 3, one); //
}
long EEPROMReadlong(long address) // Funktion EEPROMReadlong wird etabliert
{ //
long four = EEPROM.read(address); // zunächst werden die vier Bytes ausgelesen
long three = EEPROM.read(address + 1); //
long two = EEPROM.read(address + 2); //
long one = EEPROM.read(address + 3); //
// die Funktion gibt die wieder zusammengesetzte Variable aus:
return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}
void printHeader() {
Serial.print("Zeit"); //
Serial.print(";"); //
Serial.print("Volumen gesamt [ml]"); //
Serial.print(";"); //
Serial.print("aktueller Volumenstrom [ml/min]"); //
Serial.print(";"); //
Serial.println("Ausschlaege"); // Benennung der Tabellenspalten
}
void printResults() {
flowRate = ((signalCounter - lastSignalCounter) * volume) / (now() - printDif) * 60;
Serial.print(day());
Serial.print(".");
Serial.print(month());
Serial.print(".");
Serial.print(year());
Serial.print(" ");
Serial.print(hour());
Serial.print(":");
Serial.print(minute());
Serial.print(":");
Serial.print(second());
Serial.print(";");
Serial.print(signalCounter * volume); // Berechnung des Gesamtvolumens
Serial.print(";");
Serial.print(flowRate); // Berechnung des aktuellen Volumenstroms
Serial.print(";");
Serial.println(signalCounter); // Menge der Ausschläge wird eingetragen
printDif = now(); // Zur Bestimmung des zeitlichen Abstands zwischen zwei Messungen
}
void getTime() {
String timeSet = "";
String arg = "";
int beginIdx = 0;
int idx = 0;
while (Serial.available()) {
timeSet = Serial.readString();
}
idx = timeSet.indexOf(',');
arg = timeSet.substring(beginIdx, idx);
Tag = arg.toInt();
beginIdx = idx + 1;
idx = timeSet.indexOf(",", beginIdx);
arg = timeSet.substring(beginIdx, idx);
Monat = arg.toInt();
beginIdx = idx + 1;
idx = timeSet.indexOf(",", beginIdx);
arg = timeSet.substring(beginIdx, idx);
Jahr = arg.toInt();
beginIdx = idx + 1;
idx = timeSet.indexOf(",", beginIdx);
arg = timeSet.substring(beginIdx, idx);
Stunde = arg.toInt();
beginIdx = idx + 1;
idx = timeSet.indexOf(",", beginIdx);
arg = timeSet.substring(beginIdx, idx);
Minute = arg.toInt();
beginIdx = idx + 1;
idx = timeSet.indexOf(",", beginIdx);
}