weather station for mominlaw.... part1: the outdoor unit

General project help for Adafruit customers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
boelle
 
Posts: 58
Joined: Thu Sep 26, 2013 1:52 pm

weather station for mominlaw.... part1: the outdoor unit

Post by boelle »

So mominlaw got tired of the cheap stations that only last 6-12 months

She asked if i could make something stupid simple that would last.

No big requirement other than it can show temp and how many mm of rain during a month

the rain gauge box can almost house the electronics but i have not decided yet

What i would like for now is to have my code checked and if its sane and not bloated, i did hack together a few sketches mainly from adafruit but there might be code there that i no longer need


in big steps here is what i think my code does

counts number of tips that the rain gauge bucket makes
gets temp, humidity and pressure from sensor
get time and day of month from GPS (day of month is used as the date to reset rain data)
sends it all wireless via a NRF24L01 module

rain gauge is on an interrupt on the falling edge and a 15ms debounce, i will need to adjust this once i have the gauge and know how long it takes to tip over at the max flow it allows. pin number can change but i think pin 3 of a nano is ok

number of tips are set to 0 each time data is sent as all math etc is done indoors

Q on gps UTC offset... is the hour offset the same during both summer and winter time?

sketch attached as a .txt, rename it to .ino
transmitter.txt
rename to .ino
(6.38 KiB) Downloaded 102 times

boelle
 
Posts: 58
Joined: Thu Sep 26, 2013 1:52 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by boelle »

did i post the wrong place?

User avatar
kcl1s
 
Posts: 1512
Joined: Tue Aug 30, 2016 12:06 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by kcl1s »

Just a fellow hobbyist here. Critiquing code for a multi peripheral setup like you have is not easy, I have used most of the parts you are using in different projects and no errors pop out at a glance but I am sure you will find something when you put it together. Here are a couple of things I might do different but you may have good reasons for

You use all floats in your struct data. I try to use the smallest data type needed so I would use int's or byte's where I can. The beauty of structs is you can combine data types in them.

You clear the buckettips at the top of the loop. It looks like you could miss tip interrupts after you store it in the struct in the printValues function. I would clear it right after you store it.

Something that I was advised on when transmitting struct data is to use the same processor on both ends because a 32 bit processor may store the struct differently in memory than an 8 bit processor.

Good luck with the project

Keith

boelle
 
Posts: 58
Joined: Thu Sep 26, 2013 1:52 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by boelle »

you are correct on floats, i did not think of it as i just replicated the setup that was there allready. That will be changed at once

buckettips you are right again

thanks for the pointers

EDIT: new code attached

the whole idea i had by asking is to iron down the worst mistakes before i commit, and by worst i mean getting ideas that are near impossible for a dummie like me to executed.
Attachments
transmitter.txt
rename to .ino
(6.37 KiB) Downloaded 79 times

User avatar
kcl1s
 
Posts: 1512
Joined: Tue Aug 30, 2016 12:06 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by kcl1s »

It looks like you are storing the tips data in your function void printValues() with this statement data.tips = buckettips;. Your code returns from that function does the delayTime delay and the radio.write before you clear the buckettips variable. Any tip interrupt that occurs between storing and clearing (over 2 seconds) will be lost. I would put the clear right in the printValues() function right after you store the tip data so you don't miss any tips.

Code: Select all

    Serial.print("Bucket tipped ");
    Serial.print(buckettips);
    Serial.println(" times");
    data.tips = buckettips;
    buckettips = 0;
FYI- Putting code between the code tags using the blocks above the forum edit window makes it easier to get at.

Keith

boelle
 
Posts: 58
Joined: Thu Sep 26, 2013 1:52 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by boelle »

doh, i start to feel stupid

but at least it looks like i got something i can start with and i have made a shopping list for monday

Code: Select all

/***************************************************************************
  This is a sketch for the BME280 humidity, temperature & pressure sensor
  and ultimate GPS breakout.

  It transmits data (temp., humidity, pressure, time and rainfall wirelss via a  
  NRF24L01 module
  
  ----> https://www.adafruit.com/products/2652  https://www.kiwi-electronics.nl/adafruit-bme280-i2c-spi-temperature-humidity-pressure-sensor
  ----> https://www.adafruit.com/product/746 https://www.kiwi-electronics.nl/Adafruit-Ultimate-GPS-Breakout-66-channel-10-Hz-updates-Version-3
  ----> https://www.adafruit.com/product/1066 https://www.kiwi-electronics.nl/componenten-onderdelen/power-converters/TSR-1-2433-3-3V-1A-switching-regulator
  ----> https://www.trab.dk/da/breakout/190-nrf24l01-antenne.html
  ----> https://www.frishop.dk/pi/Regnopsamler-med-5-m-ledning-til-Rosenborg-68250-og-68260_434118_21906.aspx

  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 <SoftwareSerial.h>
#include <Wire.h>
#include <Adafruit_GPS.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>

#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10 //->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Adafruit_BME280 bme(BME_CS); // hardware SPI

unsigned long delayTime;

//NRF24L01
const int pinCE = 9;
const int pinCSN = 10;   //->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
RF24 radio(pinCE, pinCSN);
byte addresses[][6] = {"0"};
// Single radio pipe address for the 2 nodes to communicate.
const uint64_t pipe = 0xE8E8F0F0E1LL;
struct package
{
  float temperature ;
  float pressure;
  float humidity ;
  int tips;
  int hours;
  int minutes;
  int seconds;
  int date;
};
typedef struct package Package;
Package data;

const byte interruptPin = 3;
int buckettips = 0;

long debouncing_time = 15; //Debouncing Time in Milliseconds
volatile unsigned long last_micros;

// Offset the hours from UTC (universal time) to your local time.
// This value, -7, will set the time to UTC-7 during
// daylight savings time.
#define HOUR_OFFSET       -7

// Create GPS objects.  These are global variables that
// can be accessed from both the setup and loop function below.

SoftwareSerial gpsSerial(8, 7);  // GPS breakout/shield will use a 
                                 // software serial connection with 
                                 // TX = pin 8 and RX = pin 7.
                                 //->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Adafruit_GPS gps(&gpsSerial);


void setup() {
    Serial.begin(9600);
    Serial.println(F("BME280 test"));

    bool status;
    
    // default settings
    // (you can also pass in a Wire library object like &Wire2)
    status = bme.begin();  
    if (!status) {
        Serial.println("Could not find a valid BME280 sensor, check wiring!");
        while (1);
    }
    
    Serial.println("-- Default Test --");

    radio.begin();
    radio.setChannel(115);
    radio.setPALevel(RF24_PA_MAX);
    radio.setDataRate( RF24_250KBPS ) ;
    radio.openWritingPipe( addresses[0]);
    
    delayTime = 2000;
    delay(1000);
    Serial.println();

    attachInterrupt(digitalPinToInterrupt(interruptPin), bucketTipped, FALLING);

    // Setup the GPS using a 9600 baud connection (the default for most
    // GPS modules).
    gps.begin(9600);

    // Configure GPS to onlu output minimum data (location, time, fix).
    gps.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);

    // Use a 1 hz, once a second, update rate.
    gps.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
  
    // Enable the interrupt to parse GPS data.
    enableGPSInterrupt();
    
}


void loop() { 
    printValues();
    delay(delayTime);
    radio.write(&data, sizeof(data));
    
      // Check if GPS has new data and parse it.
  if (gps.newNMEAreceived()) {
    gps.parse(gps.lastNMEA());
  }

}

SIGNAL(TIMER0_COMPA_vect) {
  // Use a timer interrupt once a millisecond to check for new GPS data.
  // This piggybacks on Arduino's internal clock timer for the millis()
  // function.
  gps.read();
}

void enableGPSInterrupt() {
  // Function to enable the timer interrupt that will parse GPS data.
  // 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);
}

void printValues() {
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature());
    Serial.println(" *C");
    data.temperature = bme.readTemperature();

    Serial.print("Pressure = ");

    Serial.print(bme.readPressure() / 100.0F);
    Serial.println(" hPa");
    data.pressure = (bme.readPressure() / 100.0F);

//    Serial.print("Approx. Altitude = ");
//    Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
//    Serial.println(" m");

    Serial.print("Humidity = ");
    Serial.print(bme.readHumidity());
    Serial.println(" %");
    data.humidity = bme.readHumidity();

    Serial.print("Bucket tipped ");
    Serial.print(buckettips);
    Serial.println(" times");
    data.tips = buckettips;
    buckettips = 0;
    Serial.print("Time is: ");

  // Grab the current hours, minutes, seconds from the GPS.
  // This will only be set once the GPS has a fix!  Make sure to add
  // a coin cell battery so the GPS will save the time between power-up/down.
  int hours = gps.hour + HOUR_OFFSET;  // Add hour offset to convert from UTC
                                       // to local time.
                                         
  // Handle when UTC + offset wraps around to a negative or > 23 value.
  if (hours < 0) {
    hours = 24+hours;
  }
  if (hours > 23) {
    hours = 24-hours;
  }
  Serial.print(hours);
  data.hours = hours;
  
  int minutes = gps.minute;

  Serial.print(":");
  Serial.print(minutes);
  data.minutes = minutes;
  
  int seconds = gps.seconds;

  Serial.print(":");
  Serial.print(seconds);
  data.seconds = seconds;

  int date = gps.day;

  Serial.print("Day of month: ");
  Serial.print(date);
  data.date = date;
    
    Serial.println();   
}

void bucketTipped() {
  if((long)(micros() - last_micros) >= debouncing_time * 1000) {
  buckettips++;
  last_micros = micros();
 }
}

EDIT: btw... the only reason i have the wait is to not transmit to often

boelle
 
Posts: 58
Joined: Thu Sep 26, 2013 1:52 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by boelle »

So i got most of the parts, radio modules will be here mid next week

i have tested the modules each on their own, gps can get the time thou it has a very hard time to get a fix, but i could not care less about that part, all i use it for is date and time

i have made up a sketch that should be able to deal with summer/winter time from the UTC time that the modules spits out, but for some strange reason nothing comes out on the serial and i simply cant figure why

Code: Select all

/***************************************************************************
  This is a sketch for the BME280 humidity, temperature & pressure sensor
  and ultimate GPS breakout.

  It transmits data (temp., humidity, pressure, time and rainfall wirelss via a  
  NRF24L01 module
  
  ----> https://www.adafruit.com/products/2652  https://www.kiwi-electronics.nl/adafruit-bme280-i2c-spi-temperature-humidity-pressure-sensor
  ----> https://www.adafruit.com/product/746 https://www.kiwi-electronics.nl/Adafruit-Ultimate-GPS-Breakout-66-channel-10-Hz-updates-Version-3
  ----> https://www.adafruit.com/product/1066 https://www.kiwi-electronics.nl/componenten-onderdelen/power-converters/TSR-1-2433-3-3V-1A-switching-regulator
  ----> https://www.trab.dk/da/breakout/190-nrf24l01-antenne.html
  ----> https://www.frishop.dk/pi/Regnopsamler-med-5-m-ledning-til-Rosenborg-68250-og-68260_434118_21906.aspx

  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
 ***************************************************************************/


//=========================================================================\\
// GPS Module                                                              \\
//=========================================================================\\
#include <SoftwareSerial.h>
#include <Adafruit_GPS.h>
SoftwareSerial gpsSerial(5, 4);  
Adafruit_GPS GPS(&gpsSerial);
boolean usingInterrupt = true;

//=========================================================================\\
// BME20                                                                   \\
//=========================================================================\\
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define BME_CS 9
Adafruit_BME280 bme(BME_CS);

//=========================================================================\\
// Radio Module                                                            \\
//=========================================================================\\
//#include <nRF24L01.h>
//#include <RF24.h>
//#include <RF24_config.h>
//const int pinCE = 8;
//const int pinCSN = 10;
//RF24 radio(pinCE, pinCSN);
//byte addresses[][6] = {"0"};
//// Single radio pipe address for the 2 nodes to communicate.
//const uint64_t pipe = 0xE8E8F0F0E1LL;
//struct package
//{
//  float temperature ;
//  float pressure;
//  float humidity ;
//  int tips;
//  int hh;
//  int mm;
//  int ss;
//  int dd;
//};
//typedef struct package Package;
//Package data;

//=========================================================================\\
// Time Zone Lib's                                                         \\
//=========================================================================\\
#include <Time.h>                  
#include <Timezone.h>              
TimeChangeRule aDST = { "ADT", Last, Sun, Mar, 2, -120 };  // UTC + 2 hrs.
TimeChangeRule aSTD = { "AST", Last, Sun, Oct, 2, -60 };   // UTC + 1 hr.
TimeChangeRule myDST = aDST;
TimeChangeRule mySTD = aSTD;
Timezone myTZ(myDST, mySTD);
TimeChangeRule *tcr;
time_t utc, local;
char sbuffer[64] = "";

//=========================================================================\\
// Rain Gauge                                                              \\
//=========================================================================\\
const byte interruptPin = 3;
int buckettips = 0;
long debouncing_time = 15; //Debouncing Time in Milliseconds
volatile unsigned long last_micros;

//=========================================================================\\
// Standard Lib's                                                          \\
//=========================================================================\\
#include <Wire.h>
#include <SPI.h>

//=========================================================================\\
//=========================================================================\\

void setup() {

//=========================================================================\\
// Transmission  Speed USB                                                 \\
//=========================================================================\\
Serial.begin(115200);

//=========================================================================\\
// BME20                                                                   \\
//=========================================================================\\
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("-- BME280 Found --");
Serial.println();

//=========================================================================\\
// Radio Module                                                            \\
//=========================================================================\\
//radio.begin();
//radio.setChannel(115);
//radio.setPALevel(RF24_PA_MAX);
//radio.setDataRate( RF24_250KBPS ) ;
//radio.openWritingPipe( addresses[0]);

//=========================================================================\\
// Rain gauge                                                              \\
//=========================================================================\\
attachInterrupt(digitalPinToInterrupt(interruptPin), bucketTipped, FALLING);

//=========================================================================\\
// GPS Module                                                              \\
//=========================================================================\\
GPS.begin(9600);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
GPS.sendCommand(PGCMD_ANTENNA);
    
//=========================================================================\\
// Pause 1 sec                                                             \\
//=========================================================================\\
delay(1000);
gpsSerial.println(PMTK_Q_RELEASE);

}

uint32_t timer = millis();

//=========================================================================\\
//=========================================================================\\

void loop() { 
    uint8_t hh, mm, ss, dd, mo, yy;
    printValues();
    delay(2000);
//    radio.write(&data, sizeof(data));

  // 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 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
  }

 // if millis() timer wraps around, reset it
  if (timer > millis())
    timer = millis();

  // approximately every 10 ms, print out the current stats
  if ((uint32_t)millis() - timer >= 10) { 
    timer = millis(); // reset the timer
    

    
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.print(ss, DEC); Serial.print('.');
    Serial.println(GPS.milliseconds);
    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.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
    setTime(hh, mm, ss, dd, mo, yy);
    
  }
  utc = now();
  local = myTZ.toLocal(utc, &tcr);
  sprintf(sbuffer, "%02d:%02d:%02d ", hour(local), minute(local), second(local));
  Serial.print(sbuffer); 
  sprintf(sbuffer, "%s %02d %s %d %s\n", dayShortStr(weekday(local)), day(local), monthShortStr(month(local)), year(local), tcr -> abbrev);
  Serial.print(sbuffer);
}

void printValues() {
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature());
    Serial.println(" *C");
//    data.temperature = bme.readTemperature();

    Serial.print("Pressure = ");

    Serial.print(bme.readPressure() / 100.0F);
    Serial.println(" hPa");
//    data.pressure = (bme.readPressure() / 100.0F);

    Serial.print("Humidity = ");
    Serial.print(bme.readHumidity());
    Serial.println(" %");
//    data.humidity = bme.readHumidity();

    Serial.print("Bucket tipped ");
    Serial.print(buckettips);
    Serial.println(" times");
//    data.tips = buckettips;
    buckettips = 0;
}

void bucketTipped() {
  if((long)(micros() - last_micros) >= debouncing_time * 1000) {
  buckettips++;
  last_micros = micros();
 }
}

any pointers would be much appreciated :-D

boelle
 
Posts: 58
Joined: Thu Sep 26, 2013 1:52 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by boelle »

as an alternative i started to merge 2 of the test sketches that seperately work perfectly

Code: Select all

/***************************************************************************
  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>

#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 9

//#define SEALEVELPRESSURE_HPA (1013.25)

//Adafruit_BME280 bme; // I2C
Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI

unsigned long delayTime;

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

// If you're using a GPS module:
// Connect the GPS Power pin to 5V
// Connect the GPS Ground pin to ground
// If using software serial (sketch example default):
//   Connect the GPS TX (transmit) pin to Digital 3
//   Connect the GPS RX (receive) pin to Digital 2
// If using hardware serial (e.g. Arduino Mega):
//   Connect the GPS TX (transmit) pin to Arduino RX1, RX2 or RX3
//   Connect the GPS RX (receive) pin to matching TX1, TX2 or TX3

// If you're using the Adafruit GPS shield, change 
// SoftwareSerial mySerial(3, 2); -> SoftwareSerial mySerial(8, 7);
// and make sure the switch is set to SoftSerial

// If using software serial, keep this line enabled
// (you can change the pin numbers to match your wiring):
SoftwareSerial mySerial(5, 4);

// If using hardware serial (e.g. Arduino Mega), comment out the
// above SoftwareSerial line, and enable this line instead
// (you can change the Serial number to match your wiring):

//HardwareSerial mySerial = Serial1;


Adafruit_GPS GPS(&mySerial);


// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences. 
#define GPSECHO  true

// this keeps track of whether we're using the interrupt
// off by default!
boolean usingInterrupt = false;

void setup() {
    // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(115200);
    Serial.println(F("BME280 test"));

    bool status;
    
    // default settings
    // (you can also pass in a Wire library object like &Wire2)
    status = bme.begin();  
    if (!status) {
        Serial.println("Could not find a valid BME280 sensor, check wiring!");
        while (1);
    }
    
    Serial.println("-- Default Test --");
    delayTime = 1000;

    Serial.println();

  
  Serial.println("Adafruit GPS library basic test!");

  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.begin(9600);
  
  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
  // the parser doesn't care about other sentences at this time
  
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  // For the parsing code to work nicely and have time to sort thru the data, and
  // print it out we don't suggest using anything higher than 1 Hz

  // Request updates on antenna status, comment out to keep quiet
  GPS.sendCommand(PGCMD_ANTENNA);

  // the nice thing about this code is you can have a timer0 interrupt go off
  // every 1 millisecond, and read data from the GPS for you. that makes the
  // loop code a heck of a lot easier!
  useInterrupt(true);

  delay(1000);
  // Ask for firmware version
  mySerial.println(PMTK_Q_RELEASE);
}

// 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();
    delay(delayTime);
}


void printValues() {
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature());
    Serial.println(" *C");

    Serial.print("Pressure = ");

    Serial.print(bme.readPressure() / 100.0F);
    Serial.println(" hPa");

    //Serial.print("Approx. Altitude = ");
    //Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
    //Serial.println(" m");

    Serial.print("Humidity = ");
    Serial.print(bme.readHumidity());
    Serial.println(" %");

    Serial.println();

 // 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: ");
    Serial.print(GPS.hour, DEC); Serial.print(':');
    Serial.print(GPS.minute, DEC); Serial.print(':');
    Serial.print(GPS.seconds, DEC); Serial.print('.');
    Serial.println(GPS.milliseconds);
    Serial.print("Date: ");
    Serial.print(GPS.day, DEC); Serial.print('/');
    Serial.print(GPS.month, DEC); Serial.print("/20");
    Serial.println(GPS.year, DEC);
    Serial.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality); 
    
  }

    

output is:
Time: 10:54:27.304
Date: 11/7/2018
Fix: 0 quality: 0
$PGTOP,11,2*6E
$GPGGA,105428.305,,,,,0,00,,,M,,M,,*74
$GPRMC,105428.305,V,,,,,0.00,0.00,110718,,,N*4F
Temperature = 32.84 *C
Pressure = 1012.46 hPa
Humidity = 45.90 %
what i cant figure here is where the lines that start with $ comes from, since i only care about time i dont want to clutter my serial output with those lines

boelle
 
Posts: 58
Joined: Thu Sep 26, 2013 1:52 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by boelle »

of course... gpsecho was set to true


so i think i will continue with this sketch and get it to a working state and then ask for pointers on how to do cleanup etc

boelle
 
Posts: 58
Joined: Thu Sep 26, 2013 1:52 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by boelle »

Q about the BME280 module

is it possible to get the values as int and not float?

dont think mominlaw would care much about the extra digits :-D

and if the lib has a hidden setting i would rather change that than adding a convert step

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by adafruit_support_mike »

The output from the BME280 is pretty much fixed, but you can convert the floating-point values to integers in code without too much trouble:

Code: Select all

    float e = 2.71828;
    int e_int = e;

boelle
 
Posts: 58
Joined: Thu Sep 26, 2013 1:52 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by boelle »

that's easy :-D

because i from time to time have trouble with the full view i have to ask if it was just the 2 lines?
float e = 2.71828;
int e_int = e;

User avatar
kcl1s
 
Posts: 1512
Joined: Tue Aug 30, 2016 12:06 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by kcl1s »

Yes that is about it. Here is how it could look in your code with rounding.

Code: Select all

    Serial.print("Temperature = ");
    float temp = bme.readTemperature();
    temp = temp + 0.5;    //add 0.5 so value is rounded
    int temp_int = temp   //because this just truncates value
    Serial.print(temp_int);
    Serial.println(" *C");
Keith

boelle
 
Posts: 58
Joined: Thu Sep 26, 2013 1:52 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by boelle »

i took the plunge and now the complete code is:

Code: Select all

/***************************************************************************
  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

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;
int buckettips = 0;
long debouncing_time = 500; //Debouncing Time in Milliseconds
volatile unsigned long last_micros;



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_PULLUP);
  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);

  delay(1000);
  
  mySerial.println(PMTK_Q_RELEASE);

  delayTime = 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();
    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");
    Serial.print("Pressure = ");
    int pres_int = (bme.readPressure() / 100.0F);
    Serial.print(pres_int);
    Serial.println(" hPa");
    Serial.print("Humidity = ");
    int hum_int = bme.readHumidity();
    Serial.print(hum_int);
    Serial.println(" %");
    Serial.println();
    Serial.print("Bucket tipped ");
    Serial.print(buckettips);
    Serial.println(" times");

    

 // 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)
{
    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 %.2d %s %d",
        hour(t), minute(t), second(t), day(t), m, year(t));
    Serial.println(buf);
    Serial.print("---End---");
    //buckettips = 0;
    
}

void bucketTipped() {
  if((long)(micros() - last_micros) >= debouncing_time * 1000) {
  buckettips++;
  last_micros = micros();
 }
 }

if there is anything that could have been done better let me know :-D

ouput is currently like this from minicom on a pi, the good thing with GPS is that you dont have to wait for a fix to just get the time :
---Start---
Temperature = 30 *C
Pressure = 1010 hPa
Humidity = 42 %

Bucket tipped 0 times

Time: 13:24:5
Date: 12/7/2018

15:24:05 12 Jul 2018
---End---
its onlt the last date format the will be transmitted since that gets zero padded autoamtic and adjusted for time zone and summer/winter

boelle
 
Posts: 58
Joined: Thu Sep 26, 2013 1:52 pm

Re: weather station for mominlaw.... part1: the outdoor unit

Post by boelle »

rounding, good idea

can that be done to floats also? if anything i would reduce the 2 decimals to 1

but not sure, mominlaw is an old lady and those have their ideas about things so it might not even matter to her, and then again it could be that she wants a single decimal

radio modules are here next week and then i will add the code to transmit the numbers and i have an uno that can be at the other end

its going to be really "fun" when i want to add the 3.2" TFT

Locked
Please be positive and constructive with your questions and comments.

Return to “General Project help”