Über den digitalen Ausgang kann man das nicht zählen. Der Gaszähler bleibt stehen wo er stehen bleibt. Manchmal eben auch da, wo er im Ripple vom LM939 (Komparator) liegt. Beibt er im Kippbereich stehen, wird auch ein delay nicht helfen, da der Zähler ja Stunden in dieser Stellung verbleiben kann. Und dann zählt er in jedem Schleifenumlauf einen Impuls weiter oder auch mal nicht.
Die einzige Möglichkeit das sauber zu zählen, bin hier langsam in der finalen Testphase, den Analogwert abzufragen. Da dieser aber genauso flackert muss man die Näherungsflanke sowie die Magnetverlassenflanke überwachen und dann auf der Verlassenflanke zählen, da der Zähler ja für Stunden auf dem Magnet stehen bleiben kann.
## Funktionsweise
| Zustand | Aktion |
|----|----|
| A0 < 490 | Magnet erkannt (fallende Flanke möglich) |
| A0 > 520 | Magnet weg (steigende Flanke → **Zählung!**) |
| 490–520 | keine Änderung, Rauschunterdrückung aktiv |
| Bei Start | aktueller Zustand (Magnet da oder nicht) wird erkannt | | | | |
Diese Werte habe ich bei einem Arduino Nano mit 5V Versorgung des KY024. Wenn man den mit 3,3V über den ESP8266 versorgt, dann sind die Werte kleiner, müssen angepasst ermittelt werden.
Das Programm für den Arduino Nano mit MiniDisplay sieht folgendermaßen aus:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define SENSOR_DO 2
#define SENSOR_AO A0
unsigned long impulseCount = 0;
float faktor = 0.1; // 1 Impuls = 0,1 m³
int analogValue = 0;
int minVal = 1023;
int maxVal = 0;
int d0State = 0;
// — Hysterese-Parameter —
const int BASELINE = 505; // typischer Mittelwert ohne Magnet
const int DELTA = 15; // Rauschbereich / Totzone
const int LOW_THRESHOLD = BASELINE - DELTA; // z. B. 490
const int HIGH_THRESHOLD = BASELINE + DELTA; // z. B. 520
bool magnetDetected = false; // Zustand: Magnet aktuell erkannt
bool lastMagnetDetected = false; // Zustand im letzten Durchlauf
#define GRAPH_WIDTH 128
#define GRAPH_HEIGHT 12
int graphData\[GRAPH_WIDTH\];
int graphIndex = 0;
void setup() {
pinMode(SENSOR_DO, INPUT);
pinMode(SENSOR_AO, INPUT);
Serial.begin(9600);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F(“Displayfehler!”));
for(;;);
}
impulseCount = 0;
// — Initialzustand erfassen —
int startValue = analogRead(SENSOR_AO);
if (startValue < LOW_THRESHOLD) {
magnetDetected = true;
} else {
magnetDetected = false;
}
lastMagnetDetected = magnetDetected;
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(“Gaszaehler Init…”);
display.display();
delay(1000);
}
void loop() {
analogValue = analogRead(SENSOR_AO);
d0State = digitalRead(SENSOR_DO);
// Min/Max verfolgen
if (analogValue < minVal) minVal = analogValue;
if (analogValue > maxVal) maxVal = analogValue;
// — Hysterese mit Rauschunterdrückung —
if (analogValue < LOW_THRESHOLD) {
magnetDetected = true;
}
else if (analogValue > HIGH_THRESHOLD) {
magnetDetected = false;
}
// Zwischenbereich: Zustand bleibt unverändert
// — Flankenerkennung —
if (lastMagnetDetected == false && magnetDetected == true) {
// Magnet kommt (fallende Flanke)
Serial.println(“FALLENDE Flanke erkannt”);
}
else if (lastMagnetDetected == true && magnetDetected == false) {
// Magnet verlässt Sensor (steigende Flanke)
impulseCount++;
Serial.print("Impuls erkannt! Gesamt: ");
Serial.println(impulseCount);
}
lastMagnetDetected = magnetDetected;
// Graph-Daten
graphData\[graphIndex\] = analogValue;
graphIndex = (graphIndex + 1) % GRAPH_WIDTH;
float volumen_m3 = impulseCount \* faktor;
// — Anzeige —
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.print(“Imp:”);
display.print(impulseCount);
display.print(" ");
display.print(volumen_m3, 1);
display.print(“m3”);
display.setCursor(0, 10);
display.print(“A0:”);
display.print(analogValue);
display.print(" Min:“);
display.print(minVal);
display.print(” Max:");
display.print(maxVal);
display.setCursor(0, 20);
display.print(“D0:”);
display.print(d0State == HIGH ? “HIGH” : “LOW “);
display.print(” M:”);
display.print(magnetDetected ? “Y” : “N”);
// Graph zeichnen
for (int x = 0; x < GRAPH_WIDTH; x++) {
int idx = (graphIndex + x) % GRAPH_WIDTH;
int y = map(graphData\[idx\], 0, 1023, SCREEN_HEIGHT - 1, SCREEN_HEIGHT - GRAPH_HEIGHT);
display.drawPixel(x, y, SSD1306_WHITE);
}
display.display();
delay(100);
}
---
\- - - Ende Arduino Code - - -
Für den ESP8266 ist es für die Testphase ist es hilfreich einen Webserver zu installlieren, und die Min und Maxwerte auf der Webseite auszugeben und dann die Triggerwerte entsprechend anzupassen.
by HarryP: Code-/Logzeilen formatiert (bitte immer in </> einbinden)
s.a.: (Neues Update & Features - Hier in der Community 🫶)