How to show/visualize daily amount of rain?

Hey everyone,

this is not a code related question (yet :smiley: ) but more a logical one.

I am building a weather station and have difficulties on some parameters.

Lets take the amount of rain.
This is a continous value that adds over time.

Normally I would display this in a superchart.
But this is an added value
 so it would rise endlessly.

So I have to combine it with time and give it a start and an end of the rain amount.
Lets say I set it to “amount of rain per 15min” and then I get a pretty good view of the rain over the day.

This would be great.

But further more, I would also like to get the total daily rain amount in sum.

Is there something I can calculate this based on the values stored at the blynk server from the “amount of rain per 15min” afterwards? Or do I have to count it on the Microcontroller and update it seperately to a new variable?

Its more like a question if I can somehow take the superchart values and calculate the area/integral over time.

Lastly:
Is it somehow possible to mark a part of the superchart to get the “integrated value” of it?
For example:
It rains 4 times a day, and I want to know only the amount of one time from start to finish on using my phone.
If it rained from 8:00 - 12:00 it would be great, if I can mark this time range with my fingers and I would get “250ml” or something like that.

Is this possible and if yes, how to do so?

I think, this is a pretty advanced questions and hope somehone can point me into the right driecton :slight_smile:

Thanks a lot!

Yes.

No, that’s not possible.

As far as rainfall is concerned, you need to decide what you want before you start coding.
Is it rainfall over the last rolling 24 hours, or rainfall since midnight?

I use a rolling 1 hour and 24 hour values for my weather station, as described here:

Pete.

Thanks a lot @PeteKnight for your answers!
They helped me a lot and thats why I am asking here before coding :slight_smile:

2 more questions:

  1. I will do the rolling rainfall as you did. Additionally I would like to see the overall rain amount per day.
    Is there something like a bar chart where I can set definite values for days?
    I know there is a superchart, but this a continous thing over time.
    I can also use a table like thing, but I really like the idea that the superchart stores all the values over the year for eg. my pool.
    That would allow me to see the rainfalls over the year, what I really would like.

  2. This question is related to the wind direction.
    How do I save/store the directions over time?
    It sometimes really windy here and it would be a great infromation to see what directions the wind had, as it was stormy. This can be “in theory” a superchart because it is a continous value and also linked to the wind speed, but I have no idea how I display wind directions in a time based chart (which is just 2 dimensional).

Sorry for those questions but the logic behind this really drives me crazy :smiley:

  1. If by “day” you mean midnight to midnight as opposed to a rolling 24 hour period, then you’d need to accumulate this figure and zero it at midnight.
    Just before you zero it then write the value to Superchart and choose the “connect missing data points option”. That should give you a daily total bar chart.

  2. I don’t try to do this but I guess that I’d record the wind direction in degrees (0-337.5 if you’re using 16 compass points).
    I think the problem would be that on a low wind day the wind direction may sit in the same place for hours, but that’s not representative of the actual wind.
    Maybe you do it another way and only record the direction when the speed above a certain value? I guess it depends on what info you really want and how much you want it :crazy_face:

What sort of measuring equipment are you using?
I’m using the “Maplin” stuff as shown here:

Pete.

1 Like

Thank you again @PeteKnight .

Your ideas are really helpful and I am starting to program it based on your ideas. Thank you!

For 1.
I will do both the rolling plus the accumulating - because I think its handy to have the best of both worlds.
Later on I can also export that “superchart bar graph” to an csv and do whatever I like for the whole year :smiley:

I am just a bit concerned about the reconnection of my router and some instabilities of the mobile (LTE) network of my garden, but this is a different story. So it might happen, that some days will get lost, but that is hopefully not too critical :wink:

For 2.
I also thought about that idea and as you dont have a better idea, I think it might be the best solution.
I saw something with chainging pictures as a compass and if there is a better way to show the wind direction please stop me :sweat_smile:

My idea about that is, that I will show a compass for the current wind direction and in addition I will put the direction over time to a graph/superchart that also includes the wind speed.
The wind direction will only have 8 or 16 rough values because I cant measure any more detailed anyways.
For me its just imprtant to know if the storms do only come from west or also from east or north

So I think that will be good enough.
Is it possible to name the y-axis values to N, NW, W
 instead of 0, 1, 2 
 ?

For your question regarding the equipement:
I am using a completely custom made station.
So its designed and constructed using CAD and realized using own build 3D printer (plus the electronics stuff to get the imporant data).

It looks pretty similar to your station.
Wind speed is also done via an anemometer that has 3 arms etc

Tricky was the water amount measuring
 I came up with the idea of a funnel plus a seesaw
 and realized after completion that this concept is already the standard and widely used :crazy_face:

The only “experimental” thing is my rain sensor. It just tells me if its currently raining or not.
Its based on copper pieces that are laminated in thin plasics to form a capacitor.
As I am using an ESP32, I am using the “touch” function to get the capacitance.
A bit filtering etc. made this really stable and reliable on detecting when its raining or when the surface is just wet - at lest tested with a sprayer in my kitchen :smiley:
Most interessting will be how long this last in the weather and if UV etc. will destroy the plastic cover of this sensor.
This way I might be able to also show the rain amount based on each rainfall.
There is a good chance that the data I am collecting is all too much, but I can drop then later on more easily then adding them :smiley:

TLDR;
I made my own weather station, because I dont want to spend so much money and prefer my own solution :slight_smile:

If you’re using the Blynk cloud server then you are limited to being able to export the last 10 days worth of data, so you’d need to do this on a weekly basis if you want to keep a long-term record.
If you’re using a local server then you have more choices, especially if you enable Raw data storage.

You should however think about the changes that are happening at the moment with the launch of Blynk.360, as this puts some doubt on the long term future of the current version of Blynk.

I found these two websites very helpful when it came to undemanding how the hardware I was using works:
http://www.philpot.me/weatherinsider.html

I assume that you’ve gone for the reed switch voltage divider approach described in the first link as the basis for your wind direction sensor?

I don’t think so. Probably better to use degrees rather than compass points.

Interesting. I have plans to add a “raindrop sensor” using something like this:


as a way of detecting if it’s currently raining (to keep Mrs K happy when she has washing outside and wants to know when spots of rain start to fall).

Pete.

I am using an own blynk server, but I have not seen how to “enable Raw data storage”.
Also a search could not help me to get more information for that.
Do you have a link maybe or can expand on this a little?

Actually I was not so smart :smiley:
I am just using 8 reed switches and use them directly to my inputs with the internal pullups.
I will think about this because it has the advantage of only 2 wires instead of 9 - but gives the disadvantage of less certain readings.
I really like this approach and will at least test it with the different voltage levels.

I hope that you will be more lucky then me.
These sensors have exposed conductors which will destroy themselves by galavanic reactions.
I used a capacitve one in the past, which was additionally protected by covering with epoxy glue.

It lasted 2 years and now I am trying a different approach.
If you find a good solution which is also not too expensive, let me know :slight_smile:

Thanks for you help Pete!
I am currently programming and testing everything :slight_smile:

My last information was, that the “old” blynk will still be availible but no or only small features will be added in the future.
Is the blynk that we know going to die?
Your message concern me a little, because I am using blynk to control my garden irrigation system.

The blynk.360 is really great I and hope that it will be widely used by the industry and business customers. But the pricing is just too much for a student that wants to control an irrigation system and to get data from a weather station :frowning:

https://github.com/blynkkk/blynk-server#enabling-raw-data-storage

As you’re running your own local server, it helps a bit, but I think eventually the apps will stop working on the latest versions of Android/iOS, so it has a limited life - but we don’t know how long because this depends on what Google and Apple do with their operating systems.

Pete.

1 Like

Thank you a lot Pete!

You are amazing :+1:

1 Like

So I am almost done with programming but there appeared some logic questions because my solution is “not perfect” :smiley:

Question #1:
I am doing the rolling 1h and rolling 24h rain amount like this:

double rainAmountCurrentMinute = 0;
double rainAmountLastHour = 0;
byte rainAmountLastHourRollingIndex = 0;
double rainAmountLastHourRolling [60];

double rainAmountLast24Hours = 0;
byte rainAmountLast24HoursRollingIndex = 0;
double rainAmountLast24HoursRolling [24];
byte rainAmountLast24HoursRollingCounter = 0;

//gets called every and once a minute
void everyMinute()
{
 //insert the new value to the rolling last hour array
    rainAmountLastHourRolling[rainAmountLastHourRollingIndex] = rainAmountCurrentMinute;
    //reset the rainAmountCurrentMinute
    rainAmountCurrentMinute = 0;

    //caculate the next rainAmountLastHourRollingIndex
    if (++rainAmountLastHourRollingIndex >= 60)
    {
      //reset the counter
      rainAmountLastHourRollingIndex = 0;
    }

    //reset the rain amount last hour variable
    rainAmountLastHour = 0;

    //calculate the current rolling last hour rain amount
    for (int i = 0; i < 60; i++)
    {
      //sum the rain amount
      rainAmountLastHour = rainAmountLastHour + rainAmountLastHourRolling[i];
    }


    //update the last hour rain amount to the last 24 hour rolling array
    rainAmountLast24HoursRolling[rainAmountLast24HoursRollingIndex] = rainAmountLastHour;

    //if 60min = 1 hour has passed
    if ( ++rainAmountLast24HoursRollingCounter >= 60)
    {
      //reset the counter
      rainAmountLast24HoursRollingCounter = 0;

      //caculate the next rainAmountLastHourRollingIndex
      if (++rainAmountLast24HoursRollingIndex >= 24)
      {
        rainAmountLast24HoursRollingIndex = 0;
      }

      //insert the new value to the rolling last hour array and override the oldest value by doing so
      rainAmountLast24HoursRolling[rainAmountLast24HoursRollingIndex] = rainAmountLastHour;
    }


    //reset the rain amount last 24 hour variable
    rainAmountLast24Hours = 0;

    //calculate the current rolling last 24 hour rain amount
    for (int i = 0; i < 24; i++)
    {
      //sum the rain amount
      rainAmountLast24Hours = rainAmountLast24Hours + rainAmountLast24HoursRolling[i];
    }
}

Probably the double array is a bit over kill for the rolling values but anyways

For the last 1h I store every minute the new value to the array and sum up the array elements to have the rain amount of the last 1h. Everything OK.

For the last 24 hours, the way I do it only stores the last 23 hours and constantly saves the rain amount of the current started hour.
So everytime 23 hours, I drop the oldest hour value und save the current hour rain constantly into the new value.
I have a few ideas how to give a more accurate rolling value, but this always includes to save the rain amount on a minute based array (a lot of storage will be used by that with 1440 doubles
 of maybe floats).
What do you think about that?

Question #2:
I am using a mobile wifi connection in my garden.
This is sometimes a little weak on stormy/bad weather and also reconnects once a day.
The reconnection takes sometimes a little while and the time is set by the provider.

So my devices are not 100% online all the time and the “offline time” is random.

At the end of each day, I send the rain amount of this day to the bar graph (superchart) for the daylie rain chart.

I do this also in the everyMinute() function by this:

//send all raingauge data at the last minute of the day
if (  (hour() == 23) && (minute() == 59) )
{
  //send the todays rain amount to visualize it on a bar chart
  sendTodaysRainAmountforBarChart();
}

If the device is offline in that periode, the data will be lost for that day, right?
I can store the values to “placeholder” variables fot that purpose, but I will not be able to save this value to the day before into the bar chart I’m afraid.
Do you have an idea for this?

Question #3:
I am also saving the values of the rain for todays, yesterday, 2days ago and 3days ago (calender days) into a “normal” blynk value (not a super chart).

It is a really rare case, but If I turn off the device or there happens power outage, is it possible to let the device request the time when the values have been saved to the server?

This way, it would be possible to sync the values at startup even if a (or more) day/s has passed.

Thanks again for your advices and help @PeteKnight

Q1) I do this in a different way (this sends the data to Node-Red via MQTT, so imagine that the MQTT publish statements are similar to Blynk.virtualwrites


//=======================================================
// Calculate the rainfall in the past minute and the rolling 60 minute total
// if 1 hour has elapsed then calculate the rolling 24 hour total as well
// 1 interrupt pulse = 0.2794 mm of rainfall
//=======================================================
void calcRainfall()
{
  // Calculate the rainfall in the last minute
  RainfallLastMinute_float=0.2794*numTipsOfRainGaugeInLastMinute;                                    // Convert tips in last minute to rainfall in mm in last minute
  Serial.print("Minute Pointer = ");
  Serial.println(RainfallMinutePointer);      
  Serial.print("Rainfall in last minute = ");
  Serial.print(RainfallLastMinute_float);
  Serial.println("mm");
  RainfallLastMinute_str = String(RainfallLastMinute_float,2);                                        // converting RainfallLastMinute_float to a string using 2 decimal places
  MQTTclient.publish((base_mqtt_topic + "/Rainfall_Last_Minute").c_str(),String(RainfallLastMinute_float,2).c_str(),true);   // Publish to MQTT
    
  // If we already have valid data for the past hour and/or 24 hours push it out again, so that the Blynk graphs ger updated every minute with the old data
  if (LastHourValidDataFlag==true)                                                                    // If we have some valid 6o minute rolling rainfall data then display and publish it...
  {
    MQTTclient.publish((base_mqtt_topic + "/Rainfall_Last_Hour").c_str(),String(RainfallLastHour_float,2).c_str(),true);   // Publish to MQTT
    MQTTclient.loop();
  }

  if (Last24HoursValidDataFlag==true)                                                                // If we have some valid 24 hour rolling rainfall data then display and publish it...
  {
    MQTTclient.publish((base_mqtt_topic + "/Rainfall_Last_24_Hours").c_str(),String(RainfallLast24Hours_float,2).c_str(),true);   // Publish to MQTT
    MQTTclient.loop();     
  }
     

  // Calculate the rolling 60 minute rainfall value - this is updated every minute...
  if (RainfallMinutePointer==59)                                                                      // If we have 60 (0 to 59) minutes of data then the 60 minute rolling total is valid
  {
    LastHourValidDataFlag=true;                                                                       // This is set to false at startup then never changes back to false after this point    
  }
  
  RainfallLastHour_float=RainfallLastHour_float-RainfallLastHourArray[RainfallMinutePointer];         // Subtract the rainfall for the 61st minute from the hourly total, as this is now old data
  if (RainfallLastHour_float<0)
  {
    RainfallLastHour_float=0;
  }
  RainfallLastHourArray[RainfallMinutePointer]=RainfallLastMinute_float;                              // Write the rainfall in the past minute into the appropriate slot in the 60 minute array 
  RainfallLastHour_float+=RainfallLastMinute_float;                                                   // Add the rainfall in the past minute to the hourly total
  if (LastHourValidDataFlag==true)                                                                    // If we have some valid 6o minute rolling rainfall data then display and publish it...
  {
    Serial.print("Hour Pointer = ");
    Serial.println(RainfallHourPointer);    
    Serial.print("Rainfall in last hour = ");
    Serial.print(RainfallLastHour_float);
    Serial.println("mm");
    MQTTclient.publish((base_mqtt_topic + "/Rainfall_Last_Hour").c_str(),String(RainfallLastHour_float,2).c_str(),true);   // Publish to MQTT
    MQTTclient.loop();
  }
   
  RainfallMinutePointer++;                                                                             // Increment the minute pointer   
   
  if (RainfallHourPointer==23)                                                      
  {  
    Last24HoursValidDataFlag=true;                                                                     // This is set to false at startup then never changes back to false after this point    
  }
   
  if (RainfallMinutePointer>59)                                                      
  {
    RainfallMinutePointer=0;                                                                           // Deal with rolling back to 0 after one complete 60 minute loop
    // Calculate the rolling 24 hour rainfall value - this is updated every hour...
    RainfallLast24Hours_float=RainfallLast24Hours_float-RainfallLast24HoursArray[RainfallHourPointer]; // Subtract the rainfall for the 25th hour from the 24 hourly total, as this is now old data      
    if (RainfallLast24Hours_float<0)
    {
       RainfallLast24Hours_float=0;
    }
    RainfallLast24HoursArray[RainfallHourPointer]=RainfallLastHour_float;                              // Write the rainfall in the past hour into the appropriate slot in the 24 hour array array 
    RainfallLast24Hours_float+=RainfallLastHour_float;                                                 // Add the rainfall in the past hour to the 24 hour total
     
     
    int hrPointer;
    for(hrPointer=0; hrPointer<24; hrPointer++)
    {
      Serial.println(RainfallLast24HoursArray[hrPointer]);
    }
       
       
          
     
    if (Last24HoursValidDataFlag==true)                                                                // If we have some valid 24 hour rolling rainfall data then display and publish it...
    {
      Serial.print("__________________________________Rainfall in last 24 hours = ");
      Serial.print(RainfallLast24Hours_float);
      Serial.println("mm");
      Serial.println();
      Serial.println();   
      MQTTclient.publish((base_mqtt_topic + "/Rainfall_Last_24_Hours").c_str(),String(RainfallLast24Hours_float,2).c_str(),true);   // Publish to MQTT

      MQTTclient.loop();     
    }
     
    RainfallHourPointer++;                                                                             // An hour has elapsed, so increment the hour pointer
    if (RainfallHourPointer>23)
    {
      RainfallHourPointer=0;                                                                           // Deal with rolling back to 0 after one complete 24 hour loop
    }     
  } 
  RainfallLastMinute_float=0;
  RainfallMinuteMillisCounter=millis();
  numTipsOfRainGaugeInLastMinute=0;
}

I don’t think that there’s any way around the two arrays, but I don’t have any issues on a Wemos D1 Mini / NodeMCU.

Q2) It’s a limitation of Blynk that you can’t post values into a different period for superchart. Maybe paying your ISP for a static IP address is the solution, as I guess that these daily reconnections are a result of them refreshing the IP address of their customers.

Q3) I think you’d need to write the time to the server as a field then retrieve that value, so you’d need to use the RTC widget to get the server time (if you aren’t already).

Pete.

Thanks Pete again.

Q1: Looks like my approach is then a good way.

Q2: Its really a mobile internet solution with LTE. Static IP is not possible.
Looks like I then have to deal with some lost values. Not a big deal, but if you smart guys had already a work around or a solution for that, it would have been good to implement it.

Q3: I am already using the RTC widget and sync the time on a 15min basis.
Your Idea is good.
I will use that approach in the future and send the time every 15min.
As this is a mobile internet solution, I also have to send as few data as possible :slight_smile:

And while I still have enough other things to test, I will note that idea on the list and implement it later :slight_smile:

Thanks for your ideas!

1 Like

Ok, here I have a weird problem which costed me 2 days to track


I am storing some value on the device that can be changed from the app.

These values should be read from the server, but the timing is strange.
Here is some example code:

double windspeedCorrectionFactor = 1.0;
BLYNK_CONNECTED() 
{
  //after connection is established, read all the the "BLYNK_WRITE" values from the server
  Blynk.syncAll();

  //debug
  Serial.println("Sending some data to the server: ");
  Serial.print("windspeedCorrectionFactor: ");
  Serial.println(windspeedCorrectionFactor);

  Blynk.virtualWrite(V14, windspeedCorrectionFactor);
}

//sync the windspeedCorrectionFactor (read it from server/app)
BLYNK_WRITE(V14)
{
  windspeedCorrectionFactor = param.asDouble(); //save value to variable

  //debug
  Serial.print("windspeedCorrectionFactor received from server: ");
  Serial.println(windspeedCorrectionFactor);
}

What I would expect as output would be:

windspeedCorrectionFactor received from server: VALUE_from_server
Sending some data to the server:
windspeedCorrectionFactor: VALUE_from_device

but instead I am getting:

Sending some data to the server:
windspeedCorrectionFactor: VALUE_from_device
windspeedCorrectionFactor received from server: VALUE_from_server

Why is the

Blynk.virtualWrite(V14, windspeedCorrectionFactor);

performed earlier than the

Blynk.syncAll();  

which should call the BLYNK_WRITE functions before?

I also tried a delay(1000); after the Blynk.syncAll(); but the Blynk.virtualWrite() is still performed earlier.

I know now, that I can use the explicit call of

Blynk.syncVirtual(V14);

to sync it.
But I would like to know why this happens to learn it and avoid this in the future :slight_smile:

First of all, I would only sync the virtual pins you need, rather than syncAll.

Secondly, I’ve ran into this problem before when using deep sleep and the only solution for me was to call my one-time functions from BLYNK_CONNECTED. When you aren’t using deep sleep then I guess setting a flag when receiving the correction factor, or testing that the correction factor isn’t what you set it to at start-up, is the best option.

Pete.

Thanks for your fast reply @PeteKnight :+1:

I am not using some fancy deep sleep functions etc.

I will do it already discovered and you suggested by using

Blynk.syncVirtual(VXXX);

But its really a mystery for me :smiley:

The Blynk.syncAll(); is handy for this, but I guess its always a thing between comfort and stability :smiley:

One thing completely independed:
The time input widget has a isStartSunrise() function which brought me to a question I could not find.
Is it possible to get the sunrise and sunset times from the server to the device?

I am currently calculate it myself but it might be interessing for lower powered ”C then the ESP32 to use it in the future.

Have a nice day Pete :slight_smile:

EDIT:

I found that even with multiple

Blynk.syncVirtual(VXXX);

before the

Blynk.virtualWrite(VXXX, Value);

it appears that sime sychronizations from server to device are beeing performed AFTER the virtual writes


So this is not really a workaround :frowning:
And ideas?

No, but it is in Blynk 2.0.
You’d need to use an API or library in Blynk 1.0 to get this.

I wasn’t suggesting it was, but syncAll is ugly!
The flag is the solution.

Pete.