Reading a tipping bucket rain gauge

Because you will read the state of the button too fast. It will get executed thousands of times per second. This will most likely hang up your hardware.

Even a basic board like an UNO will be able to digitalRead() in the loop without hanging.

In my garden system, I have a similar reed sensor on my wind meter and that is spinnin at 300rpm! And my ESP has no problem reading it via my method above and doesn’t cause flood errors due to the prevButtonState flag.

I would still take a different approach, but then again, I al ready had some really frustrating moments because of buffer overflows, server floods and what not.

Besides all that, it’s good to take a look at what you are doing and find an optimal situation for the project you are doing. Pushing the hardware to it’s limit for a simple reading is, in my book, not a very good idea and when you expand the project you may get (like me) frustrating and weird results, not working stuff and general annoyance :slight_smile:

Fair enough. :slight_smile:

I’ll post up my garden system once its done. Currently has no problems reading wind, water flow and 3x moisture sensors via this in-the-loop method on an ESP-Dev board.
Maybe you will see signs of future issues that I dont :smiley:

Always good to share stuff and have someone else take a look at it. It usually leads to refreshing new insights :smiley:

Thanks everyone for your input, I now have my program reading the pulses from the rain gauge and updating in Blynk app reliably. It seems that using an interrupt is the way to go and a separate function to send the totals to Blynk. Thanks @Pavel for that idea and thanks to everyone that contributed in this thread.
Below is my code in its entirety, its a bit rough but I post it here for anyone that may like to have a play and improve on it.
Regards

/**************************************************************
 * Blynk is a platform with iOS and Android apps to control
 * Arduino, Raspberry Pi and the likes over the Internet.
 * You can easily build graphic interfaces for all your
 * projects by simply dragging and dropping widgets.
 *
 *   Downloads, docs, tutorials: http://www.blynk.cc
 *   Blynk community:            http://community.blynk.cc
 *   Social networks:            http://www.fb.com/blynkapp
 *                               http://twitter.com/blynk_app
 *
 * Blynk library is licensed under MIT license
 * This example code is in public domain.
 *
 **************************************************************
 * This example runs directly on ESP8266 chip.
 *
 * You need to install this for ESP8266 development:
 *   https://github.com/esp8266/Arduino
 *
 * Please be sure to select the right ESP8266 module
 * in the Tools -> Board menu!
 *
 * Change WiFi ssid, pass, and Blynk auth token to run :)
 *
 **************************************************************/

#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <Wire.h>
#include <BaroSensor.h>
#include "DHT.h"
#include <RCSwitch.h>
#define DHTPIN 10
#define DHTTYPE DHT22

DHT dht(DHTPIN,DHTTYPE,11);
RCSwitch mySwitch = RCSwitch();
WidgetLCD lcd(V11);
const int rainGauge = 12;   //Pin for rain gauge which has a resolution of .15mm
const int ledPin = 4;
float rainAmount = .3;     //variable to hold .3mm when bucket tips
float totalAmount;          //variable to hold total amount of rain that has fallen
long rssi;  //radio signal strength indicator
String mymin = " minutes";

char auth[] = "XXXXXXXXXXXXX";
char ssid[] = "NotTelling";  // Your WiFi credentials.
char pass[] = "NorHere";     // Set password to "" for open networks.

SimpleTimer timer;


void setup()
{
  attachInterrupt(rainGauge, rain, RISING); //interrupt to catch pulses sent from rain gauge
  Serial.begin(9600); 
  Wire.begin(2,14);  //I2C pins for barometer
  BaroSensor.begin();
  dht.begin();
  mySwitch.enableTransmit(0); // Transmitter is connected to ESP8266 Pin #0
  Blynk.begin(auth, ssid, pass);
  while (Blynk.connect() == false) { 
  // Wait until connected
  }
    pinMode(ledPin, OUTPUT);
    pinMode(rainGauge, INPUT_PULLUP);
    timer.setInterval(10000L, sendAllData); // set interval and function to call
    timer.setInterval(1000L, sendUptime);   // set interval and function to call
    timer.setInterval(1000L,rainupDate);    // set interval (1sec) to read rain gauge totals and send to Blynk app
}

void rainupDate(){
  Blynk.virtualWrite(V13,totalAmount); // send rain amount to Blynk app
}

void sendAllData(){  // this function sends all sensor data to Blynk app
    float temp = BaroSensor.getTemperature();
    int newtemp = ((temp + 0.05) * 10);
    temp = (newtemp / 10.0);   //returns temperature to 1 decimal place
    float pr = BaroSensor.getPressure();
    float p = pr + 50;        //adjust barometer value for height above sea level
    float h = dht.readHumidity();
    int lightReading = analogRead(A0);
    int light = map(lightReading,0,1023,0,100);   //Set the light reading to a pecentage of 100 with a 100% being full sun
    if (isnan(h)) 
      {
        Serial.println("Failed to read from DHT sensor!");
        return;
      }

    if(!BaroSensor.isOK()) 
      {
        Serial.print("Sensor not Found/OK. Error: "); 
        Serial.println(BaroSensor.getError());
        BaroSensor.begin(); // Try to reinitialise the sensor if we can
      }
  else 
  {
      Serial.print(" Pressure: ");
      Serial.print(p);
      Serial.print(" hPa\t");
      Serial.print("Temperature: ");
      Serial.print(temp);
      Serial.print("'C");
      Serial.print("\t");
      Serial.print("Humidity: ");
      Serial.print(h);
      Serial.print("%\t");
      Serial.print("Light ");
      Serial.println(light);
      
      Blynk.virtualWrite(V0,temp);
      Blynk.virtualWrite(V1,h);
      Blynk.virtualWrite(V2,p);
      Blynk.virtualWrite(V3,light);
  }
}

void sendUptime()
  {
    // This function sends Arduino up time every 1 second to Virtual Pin (V4)
    // In the app, Widget's reading frequency should be set to PUSH
    // You can send anything with any interval using this construction
    // Don't send more that 10 values per second
    Blynk.virtualWrite(V4, millis() / 1000);
    lcd.print(0,0,"Time connected");
    lcd.print(0,1, millis()/1000/60 + mymin);
  }

  void rain(){
      int buttonState = digitalRead(rainGauge);
      if(buttonState==0){  //it is raining
      digitalWrite (ledPin,HIGH);   //LED for visual feedback that pulses from rain gauge are being received
      totalAmount += rainAmount; //add up the total amount of rain that has fallen and put it in variable totalAmount
      Serial.print("this is the total rain that has fallen ");  //Print out to serial monitor
      Serial.print(totalAmount); 
      Serial.println(" mm");    
      digitalWrite(ledPin,LOW);
    }
  }

BLYNK_WRITE(V12){  // this function returnes WiFi signal strength
  rssi = WiFi.RSSI();
  int pinData = param.asInt(); 
  if(pinData==1)
  {
    lcd.clear();
    lcd.print(0 ,0,"Wifi Strength");   
    lcd.print(0 ,1,rssi);
  }
 }

 bool isFirstConnect = true; // Keep this flag not to re-sync on every reconnection

  // This function will run every time Blynk connection is established
  BLYNK_CONNECTED() 
  {
    if (isFirstConnect) 
    {
      // Request Blynk server to re-send latest values for all pins
//      Blynk.syncAll();
      // You can also update an individual Virtual pin like this:
      Blynk.syncVirtual(V0);
      Blynk.syncVirtual(V1);
      Blynk.syncVirtual(V2);
      Blynk.syncVirtual(V3);
      Blynk.syncVirtual(V4);
      Blynk.syncVirtual(V11);
      Blynk.syncVirtual(V13);
      isFirstConnect = false;
    }
  }
  

void loop()
{
  Blynk.run();
  timer.run();
}

/*Remote control of switches
-------------------------------------------------*/

  BLYNK_WRITE(V5){
    mySwitch.send(14331050,24); //turn on switch 3A
  }
  BLYNK_WRITE(V6){
    mySwitch.send(14331042,24); //turn off switch 3A
  }
  BLYNK_WRITE(V7){
    mySwitch.send(14331052,24); //turn on switch 2A
  }
  BLYNK_WRITE(V8){
    mySwitch.send(14331044,24); //turn off switch 2A
  }
  BLYNK_WRITE(V9){
    mySwitch.send(354206,24);  //turn on switch 1B
  }
  BLYNK_WRITE(V10){
    mySwitch.send(354198,24); //turn off switch 1B
  }
  

I could have put the Blynk.virtual Write from the rainUpdate function into the sendAllData function and then deleted rainUpdate and the corresponding timer. That would then mean one less timer and function for the program to worry about but I will leave that for another day.

2 Likes

thank you - I learned a bit from this thread :slight_smile:

EDIT New discussion about timers moved to: