code from link, and autoformatted
***************************************************************************
This is a library for the BME280 humidity, temperature & pressure sensor
Designed specifically to work with the Adafruit BME280 Breakout
---- > http : //www.adafruit.com/products/2650
These sensors use I2C or SPI to communicate, 2 or 4 pins are required
to interface. The device's I2C address is either 0x76 or 0x77.
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Limor Fried & Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Time.h>Â Â Â Â Â Â Â Â Â
#include <Timezone.h>
#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 9
Adafruit_BME280 bme(BME_CS); // hardware SPI
#include <RF24.h>
#define CE_PINÂ 8
#define CSN_PIN 10
const byte slaveAddress[5] = {'R','x','A','A','A'};
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
struct package
{
int temperature ;
int pressure;
int humidity ;
float rain;
int rf_hh;
int rf_mm;
int rf_dd;
int rf_mo;
int rf_yy;
};
typedef struct package Package;
Package data;
unsigned long delayTime;
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(5, 4);
Adafruit_GPS GPS(&mySerial);
#define GPSECHOÂ false
boolean usingInterrupt = false;
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120};Â Â // Central European Summer Time
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};Â Â Â // Central European Standard Time
Timezone CE(CEST, CET);
const byte interruptPin = 3;
volatile byte buckettips = 0;
long debouncing_time = 500; //Debouncing Time in Milliseconds
volatile unsigned long last_micros;
int Res = 0;
void setup() {
Serial.begin(115200);
Serial.println(F("BME280 test"));
bool status;
status = bme.begin();
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
Serial.println();
pinMode(3, INPUT);
attachInterrupt(digitalPinToInterrupt(interruptPin), bucketTipped, FALLING);
GPS.begin(9600);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);Â // 1 Hz update rate
GPS.sendCommand(PGCMD_ANTENNA);
useInterrupt(true);
mySerial.println(PMTK_Q_RELEASE);
radio.begin();
radio.setDataRate( RF24_250KBPS );
radio.openWritingPipe(slaveAddress);
delayTime = 1000;
delay(1000);
}
// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
char c = GPS.read();
// if you want to debug, this is a good time to do it!
#ifdef UDR0
if (GPSECHO)
if (c) UDR0 = c;
// writing direct to UDR0 is much much faster than Serial.print
// but only one character can be written at a time.
#endif
}
void useInterrupt(boolean v) {
if (v) {
// Timer0 is already used for millis() - we'll just interrupt somewhere
// in the middle and call the "Compare A" function above
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
usingInterrupt = true;
} else {
 // do not call the interrupt function COMPA anymore
 TIMSK0 &= ~_BV(OCIE0A);
 usingInterrupt = false;
}
}
uint32_t timer = millis();
void loop() {
 printValues();
 radio.write(&data, sizeof(data));
 // Always use sizeof() as it gives the size as the number of bytes.
 // For example if dataToSend was an int sizeof() would correctly return 2
 resetrain();
 delay(delayTime);
 Serial.write(27);   // ESC command
 Serial.print("[2J");  // clear screen command
 Serial.write(27);
 Serial.print("[H");  // cursor to home command
}
void printValues() {
 uint8_t hh, mm, ss, dd, mo, yy;
 Serial.println("---Start---");
 Serial.print("Temperature = ");
 int temp_int = bme.readTemperature();
 Serial.print(temp_int);
 Serial.println(" *C");
 data.temperature = temp_int;
 Serial.print("Pressure = ");
 int pres_int = (bme.readPressure() / 100.0F);
 Serial.print(pres_int);
 Serial.println(" hPa");
 data.pressure = pres_int;
 Serial.print("Humidity = ");
 int hum_int = bme.readHumidity();
 Serial.print(hum_int);
 Serial.println(" %");
 Serial.println();
 data.humidity = hum_int;
 Serial.print("Bucket tipped ");
 Serial.print(buckettips);
 Serial.println(" times");
 data.rain = buckettips * 0.33;
 Serial.print(data.rain);
 Serial.println(" mm of rain");
 // in case you are not using the interrupt above, you'll
 // need to 'hand query' the GPS, not suggested :(
 if (! usingInterrupt) {
  // read data from the GPS in the 'main loop'
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
  if (GPSECHO)
   if (c) Serial.print(c);
 }
 // if a sentence is received, we can check the checksum, parse it...
 if (GPS.newNMEAreceived()) {
  // a tricky thing here is if we print the NMEA sentence, or data
  // we end up not listening and catching other sentences!
  // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
  //Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
  if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
   return; // we can fail to parse a sentence in which case we should just wait for another
 }
 Serial.print("\nTime: ");
 hh = GPS.hour;
 Serial.print(hh, DEC); Serial.print(':');
 mm = GPS.minute;
 Serial.print(mm, DEC); Serial.print(':');
 ss = GPS.seconds;
 Serial.println(ss, DEC);
 Serial.print("Date: ");
 dd = GPS.day;
 Serial.print(dd, DEC); Serial.print('/');
 mo = GPS.month;
 Serial.print(mo, DEC); Serial.print("-20");
 yy = GPS.year;
 Serial.println(yy, DEC);
 Serial.println();
 setTime(hh, mm, ss, dd, mo, yy);
 time_t utc = now();
 //  local = myTZ.toLocal(utc, &tcr);
 printDateTime(CE, utc);
}
// given a Timezone object, UTC and a string description, convert and print local time with time zone
void printDateTime(Timezone tz, time_t utc)
{
 uint8_t rf_hh, rf_mm, rf_dd, rf_mo, rf_yy;
 char buf[40];
 char m[4];  // temporary storage for month string (DateStrings.cpp uses shared buffer)
 TimeChangeRule *tcr;    // pointer to the time change rule, use to get the TZ abbrev
 time_t t = tz.toLocal(utc, &tcr);
 strcpy(m, monthShortStr(month(t)));
 sprintf(buf, "%.2d:%.2d:%.2d %d/%d-%d",
     hour(t), minute(t), second(t), day(t), month(t), year(t));
 Serial.println(buf);
 data.rf_hh = hour(t);
 data.rf_mm = minute(t);
 data.rf_dd = day(t);
 data.rf_mo = month(t);
 data.rf_yy = year(t);
 Serial.print("---End---");
}
void resetrain() {
 if (data.rf_dd == 1)
 {
  if (data.rf_hh == 0)
  {
   if (data.rf_mm == 0)
   {
    if (Res == 0)
    {
     buckettips = 0;
     Res = 1;
    }
   }
  }
 }
 if (data.rf_dd == 1)
 {
  if (data.rf_hh == 0)
  {
   if (data.rf_mm == 1)
   {
    Res = 0;
   }
  }
 }
}
void bucketTipped() {
 if ((long)(micros() - last_micros) >= debouncing_time * 1000) {
  buckettips++;
  last_micros = micros();
 }
}