Go Down

Topic: Regenwippe soll interrupts zählen (Read 744 times) previous topic - next topic

freddy64

Oct 08, 2019, 08:07 pm Last Edit: Oct 08, 2019, 08:08 pm by freddy64
Hallo zusammen,
jetzt habe ich endlich Zeit, mich mit der Regenmengenmessung zu beschäftigen.
Als Sensor habe ich dieses Teil.
Der ist an 2 Pins am Arduino angeschlossen. D2 und D3.
D3 setze ich im Sketch auf HIGH und D2 geht über einen 10K Widerstand gegen GND.
Jetzt soll der Arduino die Interrupts zähen, also wie oft die Wippe kippt.
Dazu dieser Sketch:
Code: [Select]

const uint8_t gaugePin = 2;     // the number of the gauge pin
const uint8_t pwrPin = 3;        // the number of the power pin
const uint8_t ledPin =  13;      // the number of the LED pin

byte pinState = LOW;
volatile unsigned long IRQcount = 0;

void setup() {
  Serial.begin(9600);
  pinMode(pwrPin, OUTPUT);                       // set the Pwr Pin as output.
  digitalWrite(pwrPin, HIGH);
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the gauge pin as an input:
  pinMode(gaugePin, INPUT);
 
  // Attach an interrupt to the ISR vector
  attachInterrupt(0, pin_ISR, HIGH);
}

void loop() {
  cli(); //disable interrupts
  int result = IRQcount;
  sei(); //enable interrupts

  Serial.print(F("Counted: "));
  Serial.println(result);
 
  delay(10000);
}

void pin_ISR() {
  IRQcount++;
  pinState = digitalRead(gaugePin);
  digitalWrite(ledPin, pinState);
}

Ausgabe sofort nach Programmstart:
Counted: 1
Wenn sich die Wippe ein mal bewegt hat:
Counted: 7
Wenn sich die Wippe zwei mal bewegt hat:
Counted: 13

Prellt dieser Reed-Kontakt so?

Wie bekomme ich es in den Griff, dass wirklich nur die "Kipper" gezählt werden?

Gruß
Fred

HotSystems

#1
Oct 08, 2019, 08:21 pm Last Edit: Oct 08, 2019, 08:31 pm by HotSystems
Warum machst du das mit Interrupts ?
Das geht doch so langsam, dass du das Zählen problemlos in der Loop machen kannst.
Und ja, ich würde den Pin entprellen.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Tommy56

Der Reedkontakt prellt. Dadurch gibt es mehrere Impulse pro Ereignis.

Das geht auch mit Interrupts (Starkregen soll zunehmen ;) ):

Code: [Select]

const byte regenPin = 2; // anpassen
const uint16_t PRELL_ZEIT = 5; // in ms
volatile uint16_t regenCounter = 0;
volatile uint32_t lastRegenMillis = 0;

void regenISR() {
  if (millis() - lastRegenMillis >= PRELL_ZEIT) {
    regenCounter++;
    lastRegenMillis = millis();
  } 
}

void setup() {
  Serial.begin(115200);
  Serial.println("Start");
  pinMode(regenPin,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(regenPin),regenISR,FALLING);

}

void getRegenCount() {
static uint16_t regenCounterOld = 0;
uint16_t regenCounterLocal;
uint32_t lastRegenMillisLocal;

  cli();
  regenCounterLocal = regenCounter;
  lastRegenMillisLocal = lastRegenMillis;
  sei();
  if (regenCounterLocal != regenCounterOld) {
    regenCounterOld = regenCounterLocal;
    Serial.print("Counter: ");Serial.print(regenCounterLocal);
    Serial.print(" Millis: ");Serial.println(lastRegenMillisLocal);
  }
}

void loop() {
  getRegenCount();

}


Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

HotSystems

Der Reedkontakt prellt. Dadurch gibt es mehrere Impulse pro Ereignis.

Das geht auch mit Interrupts (Starkregen soll zunehmen ;) ):
Klar geht das, aber ist nicht nötig.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

freddy64

THX tommy,
hab auch eine Lösung gefunden:
Code: [Select]

#define RAIN_FACTOR 0.2794

const uint8_t gaugePin = 2;     // the number of the gauge pin
const uint8_t pwrPin = 3;
const uint8_t ledPin =  13;      // the number of the LED pin

byte pinState = LOW;
volatile unsigned long IRQcount = 0;

double getRain(unsigned long readings) {
  return (double)readings * RAIN_FACTOR;
}

void setup() {
  Serial.begin(9600);
  pinMode(pwrPin, OUTPUT);                       // set the Pwr Pin as output.
  digitalWrite(pwrPin, LOW);
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the gauge pin as an input:
  //pinMode(gaugePin, INPUT);
  pinMode(gaugePin, INPUT_PULLUP);
  
  // Attach an interrupt to the ISR vector
  attachInterrupt(0, pin_ISR, FALLING);
}

void loop() {
  cli(); //disable interrupts
  double result = getRain(IRQcount);
  sei(); //enable interrupts

  Serial.print(F("Counted: "));
  Serial.println(result);
  
  delay(10000);
}

void pin_ISR() {
  static unsigned long last_interrupt_time = 0;
  unsigned long debounce_time = millis();
  // If interrupts come faster than 100ms, assume it's a bounce and ignore
  if (debounce_time - last_interrupt_time > 100) {
    IRQcount++;
    pinState = digitalRead(gaugePin);
    digitalWrite(ledPin, pinState);
  }
  last_interrupt_time = millis();
}

Jetzt wird die Wippe richtig gezählt. Ein klock = IRQcount +1.
Egal ob ich mit einer Spritze nur 10ml reinkippe oder mit einem Wasserglas Starkregen simuliere.
Jetzt muss ich noch die klocks im mm/m² umrechnen. ;-((

@HotSystems
Quote
Warum machst du das mit Interrupts ?
Der Arduino soll später in den DeepSleep, wenn es nicht regnet und durch einen Interrupt "geweckt" werden

@Tommy
Deinen Code probiere ich trotzdem auch noch aus.

agmue

D3 setze ich im Sketch auf HIGH und D2 geht über einen 10K Widerstand gegen GND.
@HotSystemsDer Arduino soll später in den DeepSleep, wenn es nicht regnet und durch einen Interrupt "geweckt" werden
Ist das nicht ein Widerspruch?
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

HotSystems

Naja zum Wecken kann ich es verstehen, aber zum Zählen.

Ok.....ist dein Projekt.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

freddy64

@agmue
Den Widerstand habe ich rausgeschmissen.

freddy64

Und jetzt kommt der Dreisatz:
Die Wippe kippt genau bei 1 ml.
Die Oberfläche des Sensors, in die die Messmenge einläuft beträgt 49x109 mm -> macht 0,005341m².
Wie viel Regen ist das in Liter/m² ?
Also rechne man: 0,001 Liter / 0,005341 m²
Ergibt: 0,18723085564501029769706047556637 l/m² bei einem Umkippen der Wippe.

Liege ich da richtig?

ABI ist schon 37 Jahre her.

Tommy56

Du kannst doch die Fläche vom Senor ausmessen. Die grundeten Ecken rausrechnen und dann kennst Du die Fläche.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

freddy64

Die Fläche habe ich doch (49x109mm).
Die Radien an den Ecken vernachlässige ich jetzt mal.

Es regnet sicherlich in dieser Woche noch viel. Dann stelle ich das Teil mal raus und daneben so einen analogen Regenmesser (Plastikbecher mit Skala).

Danach vergleichen. Auf 0.001 Liter genau geht es dabei nicht. Aber ich bin ein Krümelkacker und würde mich gern so genau wie möglich der Realität annähern.

An den Arduino kommt dann noch eine Funke und schon habe ich die Daten in der Pimatic.

Macht es eigentlich Sinn, so ein Teil im Winter zu heizen? Es gibt im INET solche Lösungen.

uwefed

Verstehe nicht wieso Du 2 Pins für einen Kontakt brauchst.

Die Fläche des Regensensors ist 0,049m * 0,109m = 0,005341m^2 Ich nehme mal an daß wegen der  abgerundeten Ecken die Fläche genau 0,005m^2 ist.
Wenn jetzt 1mL auf eine Fläche von 1/200 m^2 fällt dann fallen auf 1 m^2 200mal soviel also 0,2L
Also liegst Du da richtig und einer meiner ehemaliger Lehrer hätte Dir eine fette negative Note gegeben. Dies weil Du eine Genauigkeit mit Deinen 32 Kommastellen konstruierst, die Du gar nicht in den Vorgabe der Abmessungen des Sensors hast.

Du hast in der Angabe der Größen eine Genauigkeit von ca 1% in der Länge (109mm) und 2% in der Breite (49mm) und 10% in dem Volumen der Wippe (1mL) und willst auf eine Genauigkeit von über 1 ppb kommen.

Grüße Uwe

combie

#12
Oct 09, 2019, 06:19 am Last Edit: Oct 09, 2019, 08:19 am by combie
Quote
Regenwippe soll interrupts zählen
Aus meiner Sicht steckt in der Frage ein Fehler!
Ein Fehler in der Sichtweise auf das Problem.


Denn:
  • Eine Regenwippe kann keine Interrupts zählen.
  • Der Interrupt soll den µC wecken.
  • Die Wippvorgänge sollen gezählt werden.


Hört sich vielleicht arg pingelig an, aber,  wie soll denn die Lösung optimal werden, wenn schon die Sichtweise auf das Problem verworren ist.

--

Schön, dass es jetzt funktioniert.

--

Quote
Macht es eigentlich Sinn, so ein Teil im Winter zu heizen? Es gibt im INET solche Lösungen.
Nöö, mich stört das nicht, ich kann ja ein paar Wochen falsche Daten deiner Wippe tolerieren, bis der Schnee und das Eis von selber schmilzt
Alle sagen: Das geht nicht!
Einer wusste das nicht und probierte es aus.
Und: Es ging nicht.

agmue

Aus meiner Sicht steckt in der Frage ein Fehler!
Eine Fehler in der Sichtweise auf das Problem.
Jetzt ist mir bewußt geworden, was mich die ganze Zeit unterschwellig gestört hat :)

Warum machst du das mit Interrupts ?
Das ergibt sich aus der Produktbeschreibung:

"The sensor is a self-emptying tipping bucket collector. This means that for each 0.011" (0.2794mm) of rain that falls in the sensor, the bucket will tilt, dumping the water out and closing a momentary contact. The rain gauge is a self-emptying tipping bucket type. Each 0.011" (0.2794 mm) of rain causes one momentary contact closure that can be recorded with a digital counter or microcontroller interrupt input. The gauge's switch is connected to the two center conductors of the attached RJ11-terminated cable."

Den Widerstand habe ich rausgeschmissen.
Meine Frage hatte ich anders gemeint. Nach meinem Verständnis enthält der Regensensor einen Taster, der beim Umkippen betätigt wird. Dazu benötigst Du genau einen Eingang, nicht zwei. Im Schlaf kannst Du D3 auch nicht umschalten.

Also D2 mit INPUT_PULLUP (ca. 50 kOhm) auf HIGH ziehen und den einen Kontakt des Regensensortasters an D2 (bis hierhin hast Du das schon gemacht), den anderen an GND. So schließt man ganz normal einen Taster an und ich sehe keinen Grund, dies hier anders zu machen.

Ich würde übrigens auch einen Interrupt verwenden, kostet ja nicht extra :D
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

postmaster-ino

Hi

Ich würde den Interrupt aber nur zum Wecken benutzen.
Wenn ich schon wach bin - also der Taster prellt - zähle ich nicht weiter.

Regen ...
Wippe füllt sich ...
Wippe kippt ... Taster wird betätigt
Interrupt löst aus, Arduino wird wach, ist die letzte Auslösung >20ms her -> +1
Arduino schüttelt Sein Kopfkissen auf und haut Sich wieder auf's Ohr.

Den Interrupt brauchst Du, damit der Arduino wach wird - dabei ist's egal, Welcher ausgelöst hat - man müsste also auch noch prüfen, ob die Wippe (wohl PC-INT) und eben der Pin der Wippe - oder zumindest das Port) den Tiefschlaf unterbrochen hat - kann ja auch ein Timer sein oder was man sonst so an ISRs verbauen kann.
Wenn's nicht die Wippe war, legen wir den Arduino halt ohne was gearbeitet zu haben wieder hin.

MfG
anscheinend ist Es nicht erwünscht, einen Foren-internen Link als 'Homepage' einzubinden, damit JEDER nur einen Klick von combie's Liste zum Thema State-Maschine entfernt ist.
... dann eben nicht ...

Go Up