My first weather station

i showed this picture because i think the situation is similar. i think the wire is floating in the air therefore, pick up faulty signals.

Nice job @Bill_Donnelly!!
Have you tried looking outside to make sure that it isn’t actually raining? :rofl:

I assume that you have an interrupt with some debounce code attached to your rain gauge pin, and that the pin is defined with INPUT_PULLUP?
I found that when the rain gauge bucket does tip then it needs a lot more debouncing than the wind gauge, but that’s obviously not what’s causing your issue here.

Are these false positives occurring when it’s windy? Your pole seems very long (as the actress said to the bishop :grinning: ) and I wonder if the reed switch is being vibrated open an closed, or if the switch and the magnet are right at the limit of their range.
This would only be an issue if the magnet was meant to keep the switch in its default state and moving it out of range causes an interrupt event. I’m not sure if this is the case, and I don’t have a rain gauge to hand. This website:
http://www.philpot.me/weatherinsider.html
has some photos of the inside of the gauge and it seems that the reed switch is on a circuit board which stands vertically at the side of the tipping bucket and the magnet is probably attached to the side of the bucket. Maybe padding-out the board so it sits closer to the bucket, and/or easing the reed switch away from the board slightly (without snapping the glass bead of course) would help?

Maybe a bit of food for thought?

Pete.

Thnx,

I have this on the interrupt pin . . .

pinMode(pin_rainGauge, INPUT_PULLUP);

It worked fine on the bench, just not on the 2m pole.

cul
billd

I didn’t say then. I assume that by unplugging the wind speed meter connector, the error is also eliminated.

Yes, both, I cut/paste your example code . . . which worked perfectly, thnx!!!

Wind was an issue with my prototype, I had a thin, aluminium tube (an old TV antenna) that swayed quite badly. This is a solid stainless steel pole, even when I try to move the pole (which takes some effort) it it doesn’t cause an issue.

I’m thinking I need to experiment with low/high vs high/low interrupt; and/or narrow the window when it detects the transition . . .in a previous life I had access to no end of test equipment, an decent CRO or Network Analyser would be very handy right now . . .

Oh well, trial and error troubleshooting it is.

cul
billd

1 Like

Hi Kastler, its the rain gauge, not the wind speed ;-)) and yeas the errors stop when disconnected.

I think its electrical noise on the 2m cable from the sensor to the interrupt pin.

cul
billd

Sorry. Try an external pull-up resistor.

i fixed some bugs i found …

1 Like
//Thanks to Khoih
#include <Time.h>
#ifndef ESP32
#error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting.
#endif

#define BLYNK_PRINT Serial

#define USE_BLYNK_WM          false
#define USE_SSL               false
#define USE_LOCAL_SERVER      false

#if USE_SSL
  #include <WiFiClientSecure.h>
#else
  #include <WiFiClient.h>
#endif
  
#if USE_BLYNK_WM

  // Not use #define USE_SPIFFS  => using EEPROM for configuration data in WiFiManager
  // #define USE_SPIFFS    false => using EEPROM for configuration data in WiFiManager
  // #define USE_SPIFFS    true  => using SPIFFS for configuration data in WiFiManager
  // Be sure to define USE_SPIFFS before #include <BlynkSimpleEsp8266_WM.h>
  
  //#define USE_SPIFFS                  true
  #define USE_SPIFFS                  false
  
  #if (!USE_SPIFFS)
    // EEPROM_SIZE must be <= 4096 and >= CONFIG_DATA_SIZE (currently 172 bytes)
    #define EEPROM_SIZE    (4 * 1024)
    // EEPROM_START + CONFIG_DATA_SIZE must be <= EEPROM_SIZE
    #define EEPROM_START   2048
  #endif
  
  // Force some params in Blynk, only valid for library version 1.0.1 and later
  #define TIMEOUT_RECONNECT_WIFI                    10000L
  #define RESET_IF_CONFIG_TIMEOUT                   true
  #define CONFIG_TIMEOUT_RETRYTIMES_BEFORE_RESET    5
  // Those above #define's must be placed before #include <BlynkSimpleEsp8266_WM.h>
   
  #if USE_SSL
    #include <BlynkSimpleEsp32_SSL_WM.h>          // https://github.com/khoih-prog/Blynk_WM
  #else
    #include <BlynkSimpleEsp32_WM.h>              // https://github.com/khoih-prog/Blynk_WM
  #endif
  
#else
  #if USE_SSL
    #include <BlynkSimpleEsp32_SSL.h>
    #define BLYNK_SERVER_HARDWARE_PORT    9443    // blynk server SSL port
  #else
    #include <BlynkSimpleEsp32.h>
    #define BLYNK_SERVER_HARDWARE_PORT    8080    // blynk server port
  #endif

  char ssid[]   = ""; // wifi SSID
  char pass[]   = ""; // wifi password

  #if USE_LOCAL_SERVER
    char auth[]   = "";                     // Local Blynk server token
    char server[] = "accout.duckdns.org";   // blynk server
  #else
    char auth[]   = "";                     //Cloud Blynk server token
    char server[] = "blynk-cloud.com";      // Cloud Blynk server
  #endif

#endif
#define DEBUG_ON
#include <SPI.h>
#include <NTPClient.h>
#include <WidgetRTC.h>
#include <TimeLib.h>
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
WiFiUDP udp;
#include <ArduinoOTA.h>
#include <BME280I2C.h>                //https://github.com/finitespace/BME280/tree/master/src
#include <Wire.h>
#include <NTPtimeESP.h>
BME280I2C bme;

#define uS_TO_S_FACTOR      1000000
#define TIME_TO_SLEEP       600                       //set deep sleep time (in seconds)

#define COUNT_PERIOD        60000                      // measure interval (ms)
#define DEBOUNCE_TIME       90

#define RADIUS            (0.09f)           // in meter
#define DIAMETER          (2 * RADIUS)
#define RAIN_AMOUNT       (0.438f)          // Precipitation

#define VOLT_DETECTION_PIN    34  // voltage detection pin number
#define RAIN_GAUGE_PIN        14  // Rain pin number
#define WIND_SPEED_PIN        35  // wind speed pin number
#define UV_INDEX_PIN          36  // UV Index detection pin number
#define WIND_DIRECTION_PIN    39  // Wind direction pin number

#define BLYNK_VPIN_WIND_DIRECTION       V1
#define BLYNK_VPIN_TEMP                 V2
#define BLYNK_VPIN_WIND_SPEED           V3
#define BLYNK_VPIN_HUMID                V4
#define BLYNK_VPIN_RAIN_AMOUNT          V5
#define BLYNK_VPIN_PRESSURE             V6
#define BLYNK_VPIN_HALL_SENSOR          V7
#define BLYNK_VPIN_WIND_SPEED_MAX       V8
#define BLYNK_VPIN_NTP_TIME             V9
#define BLYNK_VPIN_CPU_TEMP2            V10
#define BLYNK_VPIN_BATT_VOLT            V11
#define BLYNK_VPIN_UV_INDEX             V12
#define BLYNK_VPIN_NTP_DATE             V13
#define BLYNK_VPIN_DEW_POINT2           V14
#define BLYNK_VPIN_RSSI1                V15
#define BLYNK_VPIN_NTPLED               V16
#define BLYNK_VPIN_LAST_DAY_RAIN        V17
#define BLYNK_VPIN_UV_MAX               V18

int Wdir              = 0;
int measurement       = 0;
unsigned int RPM      = 0; // Revolutions per minute
float windSpeedMetrePerSec    = 0; // Wind speed (m/s)
float windSpeedKmPerHr        = 0; // Wind speed (km/h)

float voltage                 = (((float)analogRead(VOLT_DETECTION_PIN) * (3.3 / 4095)) * 2) + 0.24; // battery voltage
float UVIndex                 = ((((float)analogRead(UV_INDEX_PIN) * (3.3 / 4095)) - 0.99)*8.333); // UV Index ML8511
float windDirection           = ((float)analogRead(WIND_DIRECTION_PIN)); // Wind direction

volatile unsigned int counter  = 0; // magnet counter for sensor
volatile unsigned int currentCount;
volatile float totalAmount     = 30;
volatile float lastRainAmount  = 0;
volatile int lastday;
volatile int startday = 0;
volatile float UVMax = 0;
volatile float windMax_kmh;
volatile int windDirAverage;
volatile float windDirCount;
volatile int windDirCalcNum;
volatile long startTime;
volatile long RainstartTime;
volatile bool windDataReady = false;
volatile int last_windspeed_interrupt = 0;
volatile int currMillis;
static long RainlastMillis = millis();
static long RaincurrMillis;
String currentTime;
String currentDate;
const String MyDayOfWeek[7] = {"Vasárnap", "Hétfő", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat"};
String printDigits(int digits)
  {
    String new_digits = ":";
    if (digits < 10) {
      new_digits += "0";
    }
  new_digits += String(digits);
  return new_digits;
  }

#ifdef __cplusplus
extern "C" {
#endif
uint8_t temprature_sens_read();
#ifdef __cplusplus
}
#endif

uint8_t temprature_sens_read();
BlynkTimer timer;
WidgetRTC  rtc;
WidgetLED ledntp(BLYNK_VPIN_NTPLED);
NTPClient timeClient(udp, "europe.pool.ntp.org", 3600, 60000);
NTPtime NTPch("ch.pool.ntp.org");   // Choose server pool as required
/*
 * The structure contains following fields:
 * struct strDateTime
{
  byte hour;
  byte minute;
  byte second;
  int year;
  byte month;
  byte day;
  byte dayofWeek;
  boolean valid;
};
 */
strDateTime dateTime;

BLYNK_CONNECTED()
{
  rtc.begin();
  Blynk.syncAll();
}

void IRAM_ATTR RainSensor();
void IRAM_ATTR WindSpeedSensor();


void setup()
{
  // Debug console
  pinMode(RAIN_GAUGE_PIN, INPUT);
  pinMode(WIND_SPEED_PIN, INPUT);
  pinMode(WIND_DIRECTION_PIN, INPUT);
  pinMode(UV_INDEX_PIN, INPUT);
  pinMode(VOLT_DETECTION_PIN, INPUT);

  float windDirection = ((float)analogRead(WIND_DIRECTION_PIN));

  Serial.begin(115200);
  
  #if USE_BLYNK_WM
    Blynk.begin("ESP32-Weather-Station");
  #else
    WiFi.mode(WIFI_STA);
    Blynk.connectWiFi(ssid, pass);
    Blynk.config(auth, server, BLYNK_SERVER_HARDWARE_PORT);
    Blynk.connect();
  #endif
  

  ArduinoOTA.setHostname("Weather-Station");
  ArduinoOTA.begin();
  
  Blynk.setProperty(BLYNK_VPIN_WIND_DIRECTION, "rotation", Wdir);

  Wire.begin();
  while (!bme.begin()) //start BME 280
  {
    Serial.println("Could not find BMP280 sensor!");
    delay(1000);
  }

  switch (bme.chipModel())
  {
    case BME280::ChipModel_BME280:
      Serial.println("Found BMP280 sensor! Success.");
      break;
    case BME280::ChipModel_BMP280:
      Serial.println("Found BMP280 sensor! No Humidity available.");
      break;
    default:
      Serial.println("Found UNKNOWN sensor! Error!");
  }
  timer.setInterval(500L, measureAll);
  timer.setInterval(50000L, CalibrateTimeWithNTP);
  timer.setInterval(300000L, sendSensor);

  attachInterrupt(digitalPinToInterrupt(WIND_SPEED_PIN), WindSpeedSensor, RISING);
  attachInterrupt(digitalPinToInterrupt(RAIN_GAUGE_PIN), RainSensor,  RISING);
  // start timing
  startTime = millis();
}

void loop()
{
  Blynk.run(); //start the Blynk sketch
  timer.run(); //start the timer
  ArduinoOTA.handle();
  
}

void measureAll()
{
  WindDir();
  if (millis() >= startTime + COUNT_PERIOD )
  {
    windDirCalcNum = 0;
    windDirCount  = 0;
    startTime     = millis();
    currentCount  = counter;
    counter       = 0;
    windDataReady = true;
  }
  WindVelocity();
}

void sendSensor()
{
  static float temp(NAN), hum(NAN), pres(NAN);
  static float voltage; // battery voltage
  static float UVIndex; // UV Index
  static float windDirection; // Szélirány
  static double gamma; // calculate dewpoint
  static double dp; // calculate dewpoint
  static long rssi; // read signal strength

  measurement = hallRead();
  
  BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);  // read BME 280
  BME280::PresUnit presUnit(BME280::PresUnit_hPa);      // read BME 280
  bme.read(pres, temp, hum, tempUnit, presUnit);        // read BME 280

  voltage       = (((float)analogRead(VOLT_DETECTION_PIN) * (3.3 / 4095)) * 2) + 0.24; // battery voltage
  UVIndex       = ((((float)analogRead(UV_INDEX_PIN) * (3.3 / 4095)) - 0.99)*8.333); // UV Index ML8511
  if (UVIndex < 0)
  {
    UVIndex = 0;
  }
  if (UVIndex > UVMax)
  {
    UVMax = UVIndex;
  }
  windDirection = ((float)analogRead(WIND_DIRECTION_PIN)); // Szélirány

  gamma         = log(hum / 100) + ((17.62 * temp) / (243.5 + temp));   // calculate dewpoint
  dp            = 243 * gamma / (17.62 - gamma);                        // calculate dewpoint

  rssi          = WiFi.RSSI();

  Blynk.setProperty(BLYNK_VPIN_WIND_DIRECTION, "rotation", windDirAverage);                   // image rotating to wind direction
  Blynk.virtualWrite(BLYNK_VPIN_WIND_DIRECTION, 1);
  Blynk.virtualWrite(BLYNK_VPIN_TEMP,               temp);                                    //temperature
  Blynk.virtualWrite(BLYNK_VPIN_WIND_SPEED,         windSpeedKmPerHr);                        //Wind speed
  Blynk.virtualWrite(BLYNK_VPIN_WIND_SPEED_MAX,     windMax_kmh);                             //Wind speed max
  Blynk.virtualWrite(BLYNK_VPIN_HUMID,              hum);                                     //humidity
  Blynk.virtualWrite(BLYNK_VPIN_LAST_DAY_RAIN,      lastRainAmount);                          // Yesterday's Rainfall
  Blynk.virtualWrite(BLYNK_VPIN_RAIN_AMOUNT,        totalAmount);                             // Today's Rainfall
  Blynk.virtualWrite(BLYNK_VPIN_PRESSURE,           pres);                                    //pressure
  Blynk.virtualWrite(BLYNK_VPIN_HALL_SENSOR,        measurement);                             //hallsensor
  Blynk.virtualWrite(BLYNK_VPIN_CPU_TEMP2,          (temprature_sens_read() - 32) / 1.8);     //CPU Temp
  Blynk.virtualWrite(BLYNK_VPIN_BATT_VOLT,          voltage);                                 //Battery Voltage
  Blynk.virtualWrite(BLYNK_VPIN_UV_INDEX,           UVIndex);                                 //UV index
  Blynk.virtualWrite(BLYNK_VPIN_DEW_POINT2,         dp);                                      //Dew point
  Blynk.virtualWrite(BLYNK_VPIN_RSSI1,              rssi);                                    //rssi
  Blynk.virtualWrite(BLYNK_VPIN_UV_MAX,             UVMax);                                   //UVMax today
  Blynk.virtualWrite(BLYNK_VPIN_NTP_TIME,           currentTime);                             //Time
  Blynk.virtualWrite(BLYNK_VPIN_NTP_DATE,           currentDate);                             //Date
}

void WindDir()
{
  float windDirection = ((float)analogRead(WIND_DIRECTION_PIN));
  
  if (windDirection < 190)
    Wdir = 270;       // W
  else if (windDirection < 420)
    Wdir = 315;       // NW
  else if (windDirection < 700)
    Wdir = 292.5;     // W-NW
  else if (windDirection < 900)
    Wdir = 0;         // N
  else if (windDirection < 1300)
    Wdir = 337.5;     // N-NW
  else if (windDirection < 1500)
    Wdir = 225;       // SW
  else if (windDirection < 1600)
    Wdir = 247.5;     // W-SW
  else if (windDirection < 2250)
    Wdir = 45;        // NE
  else if (windDirection < 2400)
    Wdir = 22.5;      // N-NE
  else if (windDirection < 2900)
    Wdir = 180;       // S
  else if (windDirection < 3100)
    Wdir = 202.5;     // S-SW
  else if (windDirection < 3400)
    Wdir = 135;       // SE
  else if (windDirection < 3600)
    Wdir = 157.5;     // S-SE
  else if (windDirection < 3840)
    Wdir = 90;        // E
  else if (windDirection < 3950)
    Wdir = 67, 5;     // E-NE
  else if (windDirection < 4095)
    Wdir = 112.5;     // E-SE
  else
    Wdir = 0;         // N

  windDirCalcNum++;
  windDirCount += Wdir;
  windDirAverage = windDirCount / windDirCalcNum;
  //Blynk.virtualWrite(V20,        windDirAverage);
}

void IRAM_ATTR RainSensor() 
{
  RaincurrMillis = millis();
  
  if (millis() >= RainlastMillis + DEBOUNCE_TIME)
  {
    totalAmount += RAIN_AMOUNT;
    RainlastMillis  = millis();
  }
}

void WindVelocity() 
{
  if (windDataReady)
  {
    noInterrupts();
    windDataReady = false;
    RPM = (( currentCount * (60000 / COUNT_PERIOD ))/2);
    windSpeedMetrePerSec = (RPM * DIAMETER * PI) / 60;               
  
    windSpeedKmPerHr = windSpeedMetrePerSec * 3.6;                                              // Calculate wind speed on km/h
    if (windSpeedKmPerHr >= windMax_kmh)
    {
      windMax_kmh = windSpeedKmPerHr;
    }
    Blynk.setProperty(BLYNK_VPIN_WIND_DIRECTION, "rotation", windDirAverage);                   // image rotating to wind direction
    Blynk.virtualWrite(BLYNK_VPIN_WIND_DIRECTION, 1);                                           // image number
    Blynk.virtualWrite(BLYNK_VPIN_WIND_SPEED, windSpeedKmPerHr);                                // Wind speed sending
    Blynk.virtualWrite(BLYNK_VPIN_WIND_SPEED_MAX, windMax_kmh);                                 // Wind speed max
    Blynk.virtualWrite(BLYNK_VPIN_RAIN_AMOUNT,        totalAmount);                             // Today's Rainfall
    interrupts();
  }
}

void IRAM_ATTR WindSpeedSensor() 
{
  if ( micros() - last_windspeed_interrupt >= 250 )
  {
    counter++;
    last_windspeed_interrupt = micros();
  }
}

void CalibrateTimeWithNTP()
{
  // first parameter: Time zone in floating point (for India); second parameter: 1 for European summer time; 2 for US daylight saving time; 0 for no DST adjustment; (contributed by viewwer, not tested by me)
  dateTime = NTPch.getNTPtime(1.0, 1);

  // check dateTime.valid before using the returned time
  // Use "setSendInterval" or "setRecvTimeout" if required
  if(dateTime.valid){
    NTPch.printDateTime(dateTime);
    byte actualHour = dateTime.hour;
    byte actualMinute = dateTime.minute;
    byte actualsecond = dateTime.second;
    int actualyear = dateTime.year;
    byte actualMonth = dateTime.month;
    byte actualday = dateTime.day;
    byte actualdayofWeek = dateTime.dayofWeek;
    String currentTime = String(dateTime.hour) + printDigits(dateTime.minute);
    String currentDate = String(dateTime.year) + "." + dateTime.month + "." + dateTime.day + "  " + MyDayOfWeek[(dateTime.dayofWeek)-1];
    if ( lastday != dateTime.day )
    {
      startday = 1;
      lastday = dateTime.day;
    }
    if (startday == 1)
    {
      startday = 0;
      lastRainAmount = totalAmount;
      totalAmount   = 0;
      windMax_kmh = 0;
      UVMax = 0;
      ledntp.on();
    }else{
      ledntp.off();
    }
    Blynk.virtualWrite(BLYNK_VPIN_NTP_TIME,           currentTime);                                   //Time
    Blynk.virtualWrite(BLYNK_VPIN_NTP_DATE,           currentDate);                                   //Date
  }  
}
1 Like

Looks very interesting. I want to do something similar. Do you have manual or something?

The circuit diagram and the PCB plans (made in EAGLE) are unfortunately on my laptop that I can’t turn on. But the files needed to build after that are basically here in these topics.

1 Like

Hi,
Just a question: Why are you using a 100mH coil on the DC output?

100uH was designed for dc converter noise filtering, but not included in the final version.

1 Like


I inserted the image of such a tiny wifi camera into the blynk as a weather image. For the time being, only on a temporary basis.

UPDATE: Confirmed the noise on the cable . . . it runs very close to 240V light cable in my garage . . . triggered by PIR sensor . . . everytime the light switches on/off there is a random spike in rain value. I’ve tested this by adjusting the sensor time to a few seconds, then deliberating triggering it, this causes a corresponding increase in rainfall . . .

I’ve moved the sensor cables as far away from the power cable, it has helped but still getting RFI . . . I have ordered a shield for the cable . . . ZUJ . . .

cul
billd

2 Likes

1 Like