Durchflusssensor auswerten

Hallo Zusammen,

ich bin dabei einen Durchflusssensor der Firma Biotech mit dem Arduino
Mega auszulesen.
Es handelt es sich um das gute Stück:
Hier

Datenblatt:
Hier

Angeschlossen wie folgt:
+Ub an 5V von Arduino
GND an GND des Arduino
S an Pin 2 des Arduino

Im Datenblatt steht: 435 Imp./L. Also im Programmcode mittels Interrupt
die Impulse gezählt und ab bestimmter Messzeit das ganze ausgerechnet.
Soweit klappt das alles auch und ich bekomme wohl realistische Werte von
bis zu 16,5 l/min.
Allerdings stimmt mein Wert nicht mehr wenn der Arduino im Loop mit
beispielsweise einer For Schleife für eine gewisse längere Zeit
beschäftigt ist. Je länger ein Delay in dem Loop desto mehr sinkt der
Wert. Das ganze verwundert mich weil ich für die Berechnung die
tatsächliche Zeit (differenceMillis) seit der letzten Rechnung bis zur
aktuellen Rechnung als Referenz nehme.

Hab ich ein Denkfehler?

Code:

double sensorCount, periode = 5000; //5 sec Imp. zählen
float durchfluss;
unsigned long startMillis;
unsigned long currentMillis;
unsigned long differenceMillis;

void setup() {
Serial1.begin(9600);
attachInterrupt(digitalPinToInterrupt(2), isr_durchfluss, CHANGE); //Datenkabel an Pin 2
startMillis = millis(); 
}

void loop() {

currentMillis = millis();
differenceMillis = currentMillis - startMillis; 
if (currentMillis - startMillis >= periode)
  {
  durchfluss = (sensorCount/435)*(60000/differenceMillis); //435 Imp./L, 1 min = 60 000 ms
  startMillis = millis();
  sensorCount =0;
  }
//Hier Bspw.:
//delay(6000); //je höher desto mehr sinkt der Durchfluss
}

void isr_durchfluss()
{
sensorCount++;
}

Hi,

den Fehler hast Du schon erkannt! Delay macht nichts anderes als die Ausführung Deines Codes anzuhalten, und er sieht nicht, wann Deine Badewanne überläuft! Ohne Delay programmieren ...

Gruß André

Warum nimmst Du float? unsigned long sollte doch reichen, ausserdem volatile und Interruptbehandlung richtig machen.
z.B. (ungetestet)

unsigned int  periode = 5000; //5 sec Imp. zählen
volatile unsigned long sensorCount;

float durchfluss;
unsigned long startMillis;
unsigned long currentMillis;
unsigned long differenceMillis;

void setup() {
Serial1.begin(9600);
attachInterrupt(digitalPinToInterrupt(2), isr_durchfluss, CHANGE); //Datenkabel an Pin 2
startMillis = millis();
}

void loop() {
unsigned long cnt;  // Hilfsvariable

currentMillis = millis();
differenceMillis = currentMillis - startMillis;
if (currentMillis - startMillis >= periode)
  {
     cli(); // Interrupt aus
     cnt = sensorCount; // Wert kopieren
     sensorCount = 0;
     sei(); // Interrupt erlauben
     durchfluss = (cnt/435)*(60000/differenceMillis); //435 Imp./L, 1 min = 60 000 ms
     startMillis = millis();
  }
//Hier Bspw.:
//delay(6000); //je höher desto mehr sinkt der Durchfluss
}

void isr_durchfluss()
{
sensorCount++;
}

Gruß Tommy

SpaghettiCode:
Hi,

den Fehler hast Du schon erkannt! Delay macht nichts anderes als die Ausführung Deines Codes anzuhalten, und er sieht nicht, wann Deine Badewanne überläuft! Ohne Delay programmieren ...

Gruß André

Ach mit Delay wird auch kein Interrupt mehr abgefragt?

Tommy56:
Warum nimmst Du float? unsigned long sollte doch reichen, ausserdem volatile und Interruptbehandlung richtig machen.
z.B. (ungetestet)

unsigned int  periode = 5000; //5 sec Imp. zählen

volatile unsigned long sensorCount;

float durchfluss;
unsigned long startMillis;
unsigned long currentMillis;
unsigned long differenceMillis;

void setup() {
Serial1.begin(9600);
attachInterrupt(digitalPinToInterrupt(2), isr_durchfluss, CHANGE); //Datenkabel an Pin 2
startMillis = millis();
}

void loop() {
unsigned long cnt;  // Hilfsvariable

currentMillis = millis();
differenceMillis = currentMillis - startMillis;
if (currentMillis - startMillis >= periode)
 {
    cli(); // Interrupt aus
    cnt = sensorCount; // Wert kopieren
    sensorCount = 0;
    sei(); // Interrupt erlauben
    durchfluss = (cnt/435)*(60000/differenceMillis); //435 Imp./L, 1 min = 60 000 ms
    startMillis = millis();
 }
//Hier Bspw.:
//delay(6000); //je höher desto mehr sinkt der Durchfluss
}

void isr_durchfluss()
{
sensorCount++;
}




Gruß Tommy

Float hab ich genommen weil ich den Wert anschließend per Serial1.print an ein Nextion Display sende, wo der Wert in einem Textfeld angezeigt wird.

Werde ich mal testen, danke dir Tommy!

Du kannst auch unsigned long per SerialX.print ausgeben.
Nur bei uint64_t wird es eng, da musst Du selbst bauen.

Gruß Tommy

attachInterrupt(digitalPinToInterrupt(2), isr_durchfluss, CHANGE);
Mißt beide Flanken und somit die doppelte Impulszahl.

Periode sollte auch ein unsigned long sein.

durchfluss = (sensorCount/435)*(60000/differenceMillis);

Hier werden die einzelnen Rechnungsschritte mit INT Variablen durchgeführt und deswegen ereignen sich sicher Überläufe.
Du mußt den Variablentyp definieren.

zB
durchfluss = (sensorCount/435,0)*(60000,0/differenceMillis);
(Hoffe habe das richtig geschrieben)

Grüße Uwe