My first weather station

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

1 Like

1 Like

Greetings Blynk specialists, tell me how to install beautiful widgets like in your weather station project ??
Приветствую специалистов Blynk , подскажите как установить красивые виджеты как в вашем проекте метеостанции??