Merge branch 'master' into development
Conflicts: libraries/MySensors/MyGateway.cpp libraries/MySensors/MyGateway.h libraries/MySensors/MyMessage.h libraries/MySensors/examples/LightLuxSensor/LightLuxSensor.ino
This commit is contained in:
@@ -41,12 +41,55 @@ typedef enum {
|
||||
C_STREAM = 4 // For Firmware and other larger chunks of data that need to be divided into pieces.
|
||||
} mysensor_command;
|
||||
|
||||
// Type of sensor (used when presenting sensors)
|
||||
typedef enum {
|
||||
S_DOOR, // Door sensor, V_TRIPPED, V_ARMED
|
||||
S_MOTION, // Motion sensor, V_TRIPPED, V_ARMED
|
||||
S_SMOKE, // Smoke sensor, V_TRIPPED, V_ARMED
|
||||
S_LIGHT, // Binary light or relay, V_STATUS (or V_LIGHT), V_WATT
|
||||
S_BINARY=3, // Binary light or relay, V_STATUS (or V_LIGHT), V_WATT (same as S_LIGHT)
|
||||
S_DIMMER, // Dimmable light or fan device, V_STATUS (on/off), V_DIMMER (dimmer level 0-100), V_WATT
|
||||
S_COVER, // Blinds or window cover, V_UP, V_DOWN, V_STOP, V_DIMMER (open/close to a percentage)
|
||||
S_TEMP, // Temperature sensor, V_TEMP
|
||||
S_HUM, // Humidity sensor, V_HUM
|
||||
S_BARO, // Barometer sensor, V_PRESSURE, V_FORECAST
|
||||
S_WIND, // Wind sensor, V_WIND, V_GUST
|
||||
S_RAIN, // Rain sensor, V_RAIN, V_RAINRATE
|
||||
S_UV, // Uv sensor, V_UV
|
||||
S_WEIGHT, // Personal scale sensor, V_WEIGHT, V_IMPEDANCE
|
||||
S_POWER, // Power meter, V_WATT, V_KWH
|
||||
S_HEATER, // Header device, V_HVAC_SETPOINT_HEAT, V_HVAC_FLOW_STATE
|
||||
S_DISTANCE, // Distance sensor, V_DISTANCE
|
||||
S_LIGHT_LEVEL, // Light level sensor, V_LIGHT_LEVEL (uncalibrated in percentage), V_LEVEL (light level in lux)
|
||||
S_ARDUINO_NODE, // Used (internally) for presenting a non-repeating Arduino node
|
||||
S_ARDUINO_REPEATER_NODE, // Used (internally) for presenting a repeating Arduino node
|
||||
S_LOCK, // Lock device, V_LOCK_STATUS
|
||||
S_IR, // Ir device, V_IR_SEND, V_IR_RECEIVE
|
||||
S_WATER, // Water meter, V_FLOW, V_VOLUME
|
||||
S_AIR_QUALITY, // Air quality sensor, V_LEVEL
|
||||
S_CUSTOM, // Custom sensor
|
||||
S_DUST, // Dust sensor, V_LEVEL
|
||||
S_SCENE_CONTROLLER, // Scene controller device, V_SCENE_ON, V_SCENE_OFF.
|
||||
S_RGB_LIGHT, // RGB light. Send color component data using V_RGB. Also supports V_WATT
|
||||
S_RGBW_LIGHT, // RGB light with an additional White component. Send data using V_RGBW. Also supports V_WATT
|
||||
S_COLOR_SENSOR, // Color sensor, send color information using V_RGB
|
||||
S_HVAC, // Thermostat/HVAC device. V_HVAC_SETPOINT_HEAT, V_HVAC_SETPOINT_COLD, V_HVAC_FLOW_STATE, V_HVAC_FLOW_MODE
|
||||
S_MULTIMETER, // Multimeter device, V_VOLTAGE, V_CURRENT, V_IMPEDANCE
|
||||
S_SPRINKLER, // Sprinkler, V_STATUS (turn on/off), V_TRIPPED (if fire detecting device)
|
||||
S_WATER_LEAK, // Water leak sensor, V_TRIPPED, V_ARMED
|
||||
S_SOUND, // Sound sensor, V_TRIPPED, V_ARMED, V_LEVEL (sound level in dB)
|
||||
S_VIBRATION, // Vibration sensor, V_TRIPPED, V_ARMED, V_LEVEL (vibration in Hz)
|
||||
S_MOISTURE, // Moisture sensor, V_TRIPPED, V_ARMED, V_LEVEL (water content or moisture in percentage?)
|
||||
} mysensor_sensor;
|
||||
|
||||
// Type of sensor data (for set/req/ack messages)
|
||||
typedef enum {
|
||||
V_TEMP, // S_TEMP
|
||||
V_HUM, // S_HUM
|
||||
V_LIGHT, // S_LIGHT, S_DIMMER
|
||||
V_DIMMER, // S_DIMMER
|
||||
V_STATUS, // S_LIGHT, S_DIMMER, S_SPRINKLER, Used for setting binary (on/off) status. 1=on, 0=off
|
||||
V_LIGHT=2, // S_LIGHT, S_DIMMER. Same as V_STATUS
|
||||
V_PERCENTAGE, // S_DIMMER. Used for sending a percentage value (0-100).
|
||||
V_DIMMER=3, // S_DIMMER. Same as V_PERCENTAGE.
|
||||
V_PRESSURE, // S_BARO
|
||||
V_FORECAST, // S_BARO
|
||||
V_RAIN, // S_RAIN
|
||||
@@ -59,14 +102,15 @@ typedef enum {
|
||||
V_DISTANCE, // S_DISTANCE
|
||||
V_IMPEDANCE, // S_MULTIMETER, S_WEIGHT
|
||||
V_ARMED, // S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER
|
||||
V_TRIPPED, // S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER
|
||||
V_TRIPPED, // S_DOOR, S_MOTION, S_SMOKE, S_SPRINKLER (for sprinklers with fire detection)
|
||||
V_WATT, // S_POWER, S_LIGHT, S_DIMMER
|
||||
V_KWH, // S_POWER
|
||||
V_SCENE_ON, // S_SCENE_CONTROLLER
|
||||
V_SCENE_OFF, // S_SCENE_CONTROLLER
|
||||
V_HEATER, // S_HEATER
|
||||
V_HEATER_SW, // S_HEATER
|
||||
V_LIGHT_LEVEL, // S_LIGHT_LEVEL (light level in uncalibrated percentage)
|
||||
V_HEATER, // Deprecated. Use V_HVAC_FLOW_STATE instead.
|
||||
V_HVAC_FLOW_STATE=21, // HVAC flow state ("Off", "HeatOn", "CoolOn", or "AutoChangeOver"). S_HEATER, S_HVAC
|
||||
V_HVAC_SPEED, // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto")
|
||||
V_LIGHT_LEVEL, // S_LIGHT_LEVEL (light level in uncalibrated percentage) or S_LEVEL (light level in lux)
|
||||
V_VAR1, V_VAR2, V_VAR3, V_VAR4, V_VAR5,
|
||||
V_UP, // S_COVER
|
||||
V_DOWN, // S_COVER
|
||||
@@ -76,27 +120,27 @@ typedef enum {
|
||||
V_FLOW, // S_WATER
|
||||
V_VOLUME, // S_WATER
|
||||
V_LOCK_STATUS, // S_LOCK
|
||||
V_DUST_LEVEL, // S_DUST
|
||||
V_LEVEL, // S_DUST, S_AIR_QUALITY, S_SOUND (dB), S_VIBRATION (hz), S_LIGHT_LEVEL (lux)
|
||||
V_VOLTAGE, // S_MULTIMETER
|
||||
V_CURRENT, // S_MULTIMETER
|
||||
V_RGB, // S_RGB_LIGHT, S_COLOR_SENSOR.
|
||||
// Used for sending color information for led lighting or color sensors.
|
||||
// Sent as ascii hex. RRGGBB (RR=red, GG=green, BB=blue component)
|
||||
V_RGBW, // S_RGB_LIGHT
|
||||
// Used for sending color information to led lighting.
|
||||
// Sent as ascii hex. RRGGBBWW (WW=while component)
|
||||
// Used for sending color information for multi color LED lighting or color sensors.
|
||||
// Sent as ASCII hex: RRGGBB (RR=red, GG=green, BB=blue component)
|
||||
V_RGBW, // S_RGBW_LIGHT
|
||||
// Used for sending color information to multi color LED lighting.
|
||||
// Sent as ASCII hex: RRGGBBWW (WW=while component)
|
||||
V_ID, // S_TEMP
|
||||
// Used for reporting the sensor internal ids (E.g. DS1820b).
|
||||
V_LIGHT_LEVEL_LUX, // S_LIGHT, Light level in lux
|
||||
// Used for sending in sensors hardware ids (i.e. OneWire DS1820b).
|
||||
V_UNIT_PREFIX, // Allows sensors to send in a string representing the
|
||||
// unit prefix to be displayed in GUI, not parsed! E.g. cm, m, km, inch.
|
||||
// Can be used for S_DISTANCE
|
||||
V_SOUND_DB, // S_SOUND sound level in db
|
||||
V_VIBRATION_HZ, // S_VIBRATION vibration i Hz
|
||||
V_ENCODER_VALUE, // S_ROTARY_ENCODER. Rotary encoder value.
|
||||
// unit prefix to be displayed in GUI, not parsed by controller! E.g. cm, m, km, inch.
|
||||
// Can be used for S_DISTANCE or gas concentration (S_DUST, S_AIR_QUALITY)
|
||||
V_HVAC_SETPOINT_COLD, // HVAC cold setpoint (Integer between 0-100). S_HVAC
|
||||
V_HVAC_SETPOINT_HEAT, // HVAC/Heater setpoint (Integer between 0-100). S_HEATER, S_HVAC
|
||||
V_HVAC_FLOW_MODE, // Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn"). S_HVAC
|
||||
|
||||
} mysensor_data;
|
||||
|
||||
|
||||
// Type of internal messages (for internal messages)
|
||||
typedef enum {
|
||||
I_BATTERY_LEVEL, I_TIME, I_VERSION, I_ID_REQUEST, I_ID_RESPONSE,
|
||||
@@ -105,43 +149,6 @@ typedef enum {
|
||||
I_REBOOT, I_GATEWAY_READY, I_REQUEST_SIGNING, I_GET_NONCE, I_GET_NONCE_RESPONSE
|
||||
} mysensor_internal;
|
||||
|
||||
// Type of sensor (for presentation message)
|
||||
typedef enum {
|
||||
S_DOOR, // V_TRIPPED, V_ARMED
|
||||
S_MOTION, // V_TRIPPED, V_ARMED
|
||||
S_SMOKE, // V_TRIPPED, V_ARMED
|
||||
S_LIGHT, // V_LIGHT, V_WATT
|
||||
S_DIMMER, // V_LIGHT, V_DIMMER, V_WATT
|
||||
S_COVER, // V_UP, V_DOWN, V_STOP
|
||||
S_TEMP, // V_TEMP
|
||||
S_HUM, // V_HUM
|
||||
S_BARO, // V_PRESSURE, V_FORECAST
|
||||
S_WIND, // V_WIND, V_GUST
|
||||
S_RAIN, // V_RAIN, V_RAINRATE
|
||||
S_UV, // V_UV
|
||||
S_WEIGHT, // V_WEIGHT, V_IMPEDANCE
|
||||
S_POWER, // V_WATT, V_KWH
|
||||
S_HEATER, // V_HEATER, V_HEATER_SW
|
||||
S_DISTANCE, // V_DISTANCE
|
||||
S_LIGHT_LEVEL, // V_LIGHT_LEVEL
|
||||
S_ARDUINO_NODE,
|
||||
S_ARDUINO_REPEATER_NODE,
|
||||
S_LOCK, // V_LOCK_STATUS
|
||||
S_IR, // V_IR_SEND, V_IR_RECEIVE
|
||||
S_WATER, // V_FLOW, V_VOLUME
|
||||
S_AIR_QUALITY, // V_VAR1
|
||||
S_CUSTOM,
|
||||
S_DUST, // V_DUST_LEVEL
|
||||
S_SCENE_CONTROLLER, // V_SCENE_ON, V_SCENE_OFF.
|
||||
S_RGB_LIGHT, // Send data using V_RGB or V_RGBW
|
||||
S_COLOR_SENSOR, // Send data using V_RGB
|
||||
S_MULTIMETER, // V_VOLTAGE, V_CURRENT, V_IMPEDANCE
|
||||
S_SPRINKLER, // V_TRIPPED, V_ARMED
|
||||
S_WATER_LEAK, // V_TRIPPED, V_ARMED
|
||||
S_SOUND, // V_TRIPPED, V_ARMED, V_SOUND_DB
|
||||
S_VIBRATION, // V_TRIPPED, V_ARMED, V_VIBRATION_HZ
|
||||
S_ROTARY_ENCODER, // V_ENCODER_VALUE
|
||||
} mysensor_sensor;
|
||||
|
||||
// Type of data stream (for streamed message)
|
||||
typedef enum {
|
||||
|
||||
@@ -77,7 +77,7 @@ float SmokeCurve[3] ={2.3,0.53,-0.44}; //two points are taken from
|
||||
|
||||
|
||||
MySensor gw;
|
||||
MyMessage msg(CHILD_ID_MQ, V_VAR1);
|
||||
MyMessage msg(CHILD_ID_MQ, V_LEVEL);
|
||||
|
||||
|
||||
void setup()
|
||||
|
||||
@@ -48,6 +48,8 @@ void setup()
|
||||
{
|
||||
// Startup up the OneWire library
|
||||
sensors.begin();
|
||||
// requestTemperatures() will not block current thread
|
||||
sensors.setWaitForConversion(false);
|
||||
|
||||
// Startup and initialize MySensors library. Set callback for incoming messages.
|
||||
gw.begin();
|
||||
@@ -71,7 +73,12 @@ void loop()
|
||||
gw.process();
|
||||
|
||||
// Fetch temperatures from Dallas sensors
|
||||
sensors.requestTemperatures();
|
||||
sensors.requestTemperatures();
|
||||
|
||||
// query conversion time and sleep until conversion completed
|
||||
int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
|
||||
// sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
|
||||
gw.sleep(conversionTime);
|
||||
|
||||
// Read temperatures and send them to controller
|
||||
for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
|
||||
@@ -94,6 +101,3 @@ void loop()
|
||||
}
|
||||
gw.sleep(SLEEP_TIME);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ float calcVoltage = 0;
|
||||
float dustDensity = 0;
|
||||
|
||||
MySensor gw;
|
||||
MyMessage dustMsg(CHILD_ID_DUST, V_DUST_LEVEL);
|
||||
MyMessage dustMsg(CHILD_ID_DUST, V_LEVEL);
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
@@ -43,12 +43,16 @@
|
||||
#include <Wire.h>
|
||||
|
||||
#define CHILD_ID_LIGHT 0
|
||||
#define LIGHT_SENSOR_ANALOG_PIN 0
|
||||
unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
|
||||
|
||||
BH1750 lightSensor;
|
||||
MySensor gw;
|
||||
MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL_LUX);
|
||||
|
||||
// V_LIGHT_LEVEL should only be used for uncalibrated light level 0-100%.
|
||||
// If your controller supports the new V_LEVEL variable, use this instead for
|
||||
// transmitting LUX light level.
|
||||
MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
|
||||
// MyMessage msg(CHILD_ID_LIGHT, V_LEVEL);
|
||||
uint16_t lastlux;
|
||||
|
||||
void setup()
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
// This sketch is to integrate the Playing With Fusion AXS3935 Lightning Sensor Breakout Board
|
||||
// with the MySensors environment and is based on a sketch provided by Playing With Fusion
|
||||
// http://playingwithfusion.com/productview.php?pdid=22&catid=1001
|
||||
//
|
||||
#include "MySensor.h"
|
||||
// the lightning sensor can communicate via SPI or I2C. This sketch uses the SPI interface
|
||||
#include "SPI.h"
|
||||
// include Playing With Fusion AXS3935 libraries
|
||||
#include "PWFusion_AS3935.h"
|
||||
|
||||
// setup CS pins used for the connection with the lightning sensor
|
||||
// other connections are controlled by the SPI library)
|
||||
int8_t CS_PIN = 8;
|
||||
int8_t SI_PIN = 7;
|
||||
int8_t IRQ_PIN = 3;
|
||||
volatile int8_t AS3935_ISR_Trig = 0;
|
||||
|
||||
// #defines
|
||||
#define AS3935_INDOORS 1
|
||||
#define AS3935_OUTDOORS 0
|
||||
#define AS3935_DIST_DIS 0
|
||||
#define AS3935_DIST_EN 1
|
||||
#define AS3935_CAPACITANCE 96 // <-- SET THIS VALUE TO THE NUMBER LISTED ON YOUR BOARD
|
||||
// prototypes
|
||||
void AS3935_ISR();
|
||||
|
||||
PWF_AS3935 lightning0(CS_PIN, IRQ_PIN, SI_PIN);
|
||||
|
||||
#define CHILD_ID_DISTANCE 1
|
||||
#define CHILD_ID_INTENSITY 2
|
||||
MySensor gw;
|
||||
MyMessage msgDist(CHILD_ID_DISTANCE, V_DISTANCE);
|
||||
MyMessage msgInt(CHILD_ID_INTENSITY, V_VAR1);
|
||||
|
||||
void setup()
|
||||
{
|
||||
gw.begin();
|
||||
|
||||
// Send the sketch version information to the gateway and Controller
|
||||
gw.sendSketchInfo("Lightning Sensor", "1.1");
|
||||
|
||||
// Register all sensors to gw (they will be created as child devices)
|
||||
gw.present(CHILD_ID_DISTANCE, S_DISTANCE);
|
||||
gw.present(CHILD_ID_INTENSITY, S_CUSTOM);
|
||||
boolean metric = gw.getConfig().isMetric;
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println("Playing With Fusion: AS3935 Lightning Sensor, SEN-39001");
|
||||
Serial.println("beginning boot procedure....");
|
||||
|
||||
// setup for the the SPI library:
|
||||
SPI.begin(); // begin SPI
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV4); // SPI speed to SPI_CLOCK_DIV16/1MHz (max 2MHz, NEVER 500kHz!)
|
||||
SPI.setDataMode(SPI_MODE1); // MAX31855 is a Mode 1 device
|
||||
// --> clock starts low, read on rising edge
|
||||
SPI.setBitOrder(MSBFIRST); // data sent to chip MSb first
|
||||
|
||||
lightning0.AS3935_DefInit(); // set registers to default
|
||||
// now update sensor cal for your application and power up chip
|
||||
lightning0.AS3935_ManualCal(AS3935_CAPACITANCE, AS3935_OUTDOORS, AS3935_DIST_EN);
|
||||
// AS3935_ManualCal Parameters:
|
||||
// --> capacitance, in pF (marked on package)
|
||||
// --> indoors/outdoors (AS3935_INDOORS:0 / AS3935_OUTDOORS:1)
|
||||
// --> disturbers (AS3935_DIST_EN:1 / AS3935_DIST_DIS:2)
|
||||
// function also powers up the chip
|
||||
|
||||
// enable interrupt (hook IRQ pin to Arduino Uno/Mega interrupt input: 1 -> pin 3 )
|
||||
attachInterrupt(1, AS3935_ISR, RISING);
|
||||
// dump the registry data to the serial port for troubleshooting purposes
|
||||
lightning0.AS3935_PrintAllRegs();
|
||||
|
||||
// delay execution to allow chip to stabilize.
|
||||
delay(1000);
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
// This program only handles an AS3935 lightning sensor. It does nothing until
|
||||
// an interrupt is detected on the IRQ pin.
|
||||
while(0 == AS3935_ISR_Trig){}
|
||||
|
||||
// reset interrupt flag
|
||||
AS3935_ISR_Trig = 0;
|
||||
|
||||
// now get interrupt source
|
||||
uint8_t int_src = lightning0.AS3935_GetInterruptSrc();
|
||||
if(0 == int_src)
|
||||
{
|
||||
Serial.println("Unknown interrupt source");
|
||||
}
|
||||
else if(1 == int_src)
|
||||
{
|
||||
uint8_t lightning_dist_km = lightning0.AS3935_GetLightningDistKm();
|
||||
uint32_t lightning_intensity = lightning0.AS3935_GetStrikeEnergyRaw();
|
||||
|
||||
Serial.print("Lightning detected! Distance to strike: ");
|
||||
Serial.print(lightning_dist_km);
|
||||
Serial.println(" kilometers");
|
||||
Serial.print("Lightning detected! Lightning Intensity: ");
|
||||
Serial.println(lightning_intensity);
|
||||
gw.send(msgDist.set(lightning_dist_km));
|
||||
gw.send(msgInt.set(lightning_intensity));
|
||||
}
|
||||
else if(2 == int_src)
|
||||
{
|
||||
Serial.println("Disturber detected");
|
||||
}
|
||||
else if(3 == int_src)
|
||||
{
|
||||
Serial.println("Noise level too high");
|
||||
}
|
||||
}
|
||||
|
||||
// this is irq handler for AS3935 interrupts, has to return void and take no arguments
|
||||
// always make code in interrupt handlers fast and short
|
||||
void AS3935_ISR()
|
||||
{
|
||||
AS3935_ISR_Trig = 1;
|
||||
}␍
|
||||
@@ -35,7 +35,21 @@
|
||||
#define BARO_CHILD 0
|
||||
#define TEMP_CHILD 1
|
||||
|
||||
unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in seconds)
|
||||
const float ALTITUDE = 688; // <-- adapt this value to your own location's altitude.
|
||||
|
||||
// Sleep time between reads (in seconds). Do not change this value as the forecast algorithm needs a sample every minute.
|
||||
const unsigned long SLEEP_TIME = 60000;
|
||||
|
||||
const char *weather[] = { "stable", "sunny", "cloudy", "unstable", "thunderstorm", "unknown" };
|
||||
enum FORECAST
|
||||
{
|
||||
STABLE = 0, // "Stable Weather Pattern"
|
||||
SUNNY = 1, // "Slowly rising Good Weather", "Clear/Sunny "
|
||||
CLOUDY = 2, // "Slowly falling L-Pressure ", "Cloudy/Rain "
|
||||
UNSTABLE = 3, // "Quickly rising H-Press", "Not Stable"
|
||||
THUNDERSTORM = 4, // "Quickly falling L-Press", "Thunderstorm"
|
||||
UNKNOWN = 5 // "Unknown (More Time needed)
|
||||
};
|
||||
|
||||
Adafruit_BMP085 bmp = Adafruit_BMP085(); // Digital Pressure Sensor
|
||||
MySensor gw;
|
||||
@@ -43,206 +57,243 @@ MySensor gw;
|
||||
float lastPressure = -1;
|
||||
float lastTemp = -1;
|
||||
int lastForecast = -1;
|
||||
const char *weather[] = {"stable","sunny","cloudy","unstable","thunderstorm","unknown"};
|
||||
int minutes;
|
||||
float pressureSamples[7][6];
|
||||
|
||||
const int LAST_SAMPLES_COUNT = 5;
|
||||
float lastPressureSamples[LAST_SAMPLES_COUNT];
|
||||
|
||||
// this CONVERSION_FACTOR is used to convert from Pa to kPa in forecast algorithm
|
||||
// get kPa/h be dividing hPa by 10
|
||||
#define CONVERSION_FACTOR (1.0/10.0)
|
||||
|
||||
int minuteCount = 0;
|
||||
bool firstRound = true;
|
||||
float pressureAvg[7];
|
||||
// average value is used in forecast algorithm.
|
||||
float pressureAvg;
|
||||
// average after 2 hours is used as reference value for the next iteration.
|
||||
float pressureAvg2;
|
||||
|
||||
float dP_dt;
|
||||
boolean metric;
|
||||
boolean metric;
|
||||
MyMessage tempMsg(TEMP_CHILD, V_TEMP);
|
||||
MyMessage pressureMsg(BARO_CHILD, V_PRESSURE);
|
||||
MyMessage forecastMsg(BARO_CHILD, V_FORECAST);
|
||||
|
||||
void setup() {
|
||||
gw.begin();
|
||||
|
||||
// Send the sketch version information to the gateway and Controller
|
||||
gw.sendSketchInfo("Pressure Sensor", "1.0");
|
||||
void setup()
|
||||
{
|
||||
gw.begin();
|
||||
|
||||
if (!bmp.begin()) {
|
||||
Serial.println("Could not find a valid BMP085 sensor, check wiring!");
|
||||
while (1) { }
|
||||
}
|
||||
// Send the sketch version information to the gateway and Controller
|
||||
gw.sendSketchInfo("Pressure Sensor", "1.1");
|
||||
|
||||
// Register sensors to gw (they will be created as child devices)
|
||||
gw.present(BARO_CHILD, S_BARO);
|
||||
gw.present(TEMP_CHILD, S_TEMP);
|
||||
metric = gw.getConfig().isMetric;
|
||||
if (!bmp.begin())
|
||||
{
|
||||
Serial.println("Could not find a valid BMP085 sensor, check wiring!");
|
||||
while (1) {}
|
||||
}
|
||||
|
||||
// Register sensors to gw (they will be created as child devices)
|
||||
gw.present(BARO_CHILD, S_BARO);
|
||||
gw.present(TEMP_CHILD, S_TEMP);
|
||||
metric = gw.getConfig().isMetric;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
float pressure = bmp.readSealevelPressure(205)/100.0; // 205 meters above sealevel
|
||||
float temperature = bmp.readTemperature();
|
||||
|
||||
if (!metric) {
|
||||
// Convert to fahrenheit
|
||||
temperature = temperature * 9.0 / 5.0 + 32.0;
|
||||
}
|
||||
|
||||
int forecast = sample(pressure);
|
||||
void loop()
|
||||
{
|
||||
float pressure = bmp.readSealevelPressure(ALTITUDE) / 100.0;
|
||||
float temperature = bmp.readTemperature();
|
||||
|
||||
Serial.print("Temperature = ");
|
||||
Serial.print(temperature);
|
||||
Serial.println(metric?" *C":" *F");
|
||||
Serial.print("Pressure = ");
|
||||
Serial.print(pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.println(weather[forecast]);
|
||||
if (!metric)
|
||||
{
|
||||
// Convert to fahrenheit
|
||||
temperature = temperature * 9.0 / 5.0 + 32.0;
|
||||
}
|
||||
|
||||
int forecast = sample(pressure);
|
||||
|
||||
Serial.print("Temperature = ");
|
||||
Serial.print(temperature);
|
||||
Serial.println(metric ? " *C" : " *F");
|
||||
Serial.print("Pressure = ");
|
||||
Serial.print(pressure);
|
||||
Serial.println(" hPa");
|
||||
Serial.print("Forecast = ");
|
||||
Serial.println(weather[forecast]);
|
||||
|
||||
|
||||
if (temperature != lastTemp) {
|
||||
gw.send(tempMsg.set(temperature,1));
|
||||
lastTemp = temperature;
|
||||
}
|
||||
if (temperature != lastTemp)
|
||||
{
|
||||
gw.send(tempMsg.set(temperature, 1));
|
||||
lastTemp = temperature;
|
||||
}
|
||||
|
||||
if (pressure != lastPressure) {
|
||||
gw.send(pressureMsg.set(pressure, 0));
|
||||
lastPressure = pressure;
|
||||
}
|
||||
if (pressure != lastPressure)
|
||||
{
|
||||
gw.send(pressureMsg.set(pressure, 0));
|
||||
lastPressure = pressure;
|
||||
}
|
||||
|
||||
if (forecast != lastForecast) {
|
||||
gw.send(forecastMsg.set(weather[forecast]));
|
||||
lastForecast = forecast;
|
||||
}
|
||||
|
||||
/*
|
||||
DP/Dt explanation
|
||||
if (forecast != lastForecast)
|
||||
{
|
||||
gw.send(forecastMsg.set(weather[forecast]));
|
||||
lastForecast = forecast;
|
||||
}
|
||||
|
||||
0 = "Stable Weather Pattern"
|
||||
1 = "Slowly rising Good Weather", "Clear/Sunny "
|
||||
2 = "Slowly falling L-Pressure ", "Cloudy/Rain "
|
||||
3 = "Quickly rising H-Press", "Not Stable"
|
||||
4 = "Quickly falling L-Press", "Thunderstorm"
|
||||
5 = "Unknown (More Time needed)
|
||||
*/
|
||||
|
||||
gw.sleep(SLEEP_TIME);
|
||||
gw.sleep(SLEEP_TIME);
|
||||
}
|
||||
|
||||
int sample(float pressure) {
|
||||
// Algorithm found here
|
||||
// http://www.freescale.com/files/sensors/doc/app_note/AN3914.pdf
|
||||
if (minuteCount == 180)
|
||||
minuteCount = 5;
|
||||
|
||||
//From 0 to 5 min.
|
||||
if (minuteCount <= 5){
|
||||
pressureSamples[0][minuteCount] = pressure;
|
||||
}
|
||||
//From 30 to 35 min.
|
||||
if ((minuteCount <= 30) && (minuteCount >= 35)){
|
||||
pressureSamples[1][minuteCount - 30] = pressure;
|
||||
}
|
||||
//From 55 to 60 min.
|
||||
if ((minuteCount <= 55) && (minuteCount >= 60)){
|
||||
pressureSamples[2][minuteCount - 55] = pressure;
|
||||
}
|
||||
//From 90 to 95 min.
|
||||
if ((minuteCount <= 90) && (minuteCount >= 95)){
|
||||
pressureSamples[3][minuteCount - 90] = pressure;
|
||||
}
|
||||
//From 115 to 119 min.
|
||||
if ((minuteCount <= 115) && (minuteCount >= 120)){
|
||||
pressureSamples[4][minuteCount - 115] = pressure;
|
||||
}
|
||||
//From 150 to 155 min.
|
||||
if ((minuteCount <= 150) && (minuteCount >= 155)){
|
||||
pressureSamples[5][minuteCount - 150] = pressure;
|
||||
}
|
||||
//From 175 to 180 min.
|
||||
if ((minuteCount <= 175) && (minuteCount >= 180)){
|
||||
pressureSamples[6][minuteCount - 175] = pressure;
|
||||
}
|
||||
|
||||
float getLastPressureSamplesAverage()
|
||||
{
|
||||
float lastPressureSamplesAverage = 0;
|
||||
for (int i = 0; i < LAST_SAMPLES_COUNT; i++)
|
||||
{
|
||||
lastPressureSamplesAverage += lastPressureSamples[i];
|
||||
}
|
||||
lastPressureSamplesAverage /= LAST_SAMPLES_COUNT;
|
||||
|
||||
return lastPressureSamplesAverage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Algorithm found here
|
||||
// http://www.freescale.com/files/sensors/doc/app_note/AN3914.pdf
|
||||
// Pressure in hPa --> forecast done by calculating kPa/h
|
||||
int sample(float pressure)
|
||||
{
|
||||
// Calculate the average of the last n minutes.
|
||||
int index = minuteCount % LAST_SAMPLES_COUNT;
|
||||
lastPressureSamples[index] = pressure;
|
||||
|
||||
minuteCount++;
|
||||
if (minuteCount > 185)
|
||||
{
|
||||
minuteCount = 6;
|
||||
}
|
||||
|
||||
if (minuteCount == 5) {
|
||||
// Avg pressure in first 5 min, value averaged from 0 to 5 min.
|
||||
pressureAvg[0] = ((pressureSamples[0][0] + pressureSamples[0][1]
|
||||
+ pressureSamples[0][2] + pressureSamples[0][3]
|
||||
+ pressureSamples[0][4] + pressureSamples[0][5]) / 6);
|
||||
} else if (minuteCount == 35) {
|
||||
// Avg pressure in 30 min, value averaged from 0 to 5 min.
|
||||
pressureAvg[1] = ((pressureSamples[1][0] + pressureSamples[1][1]
|
||||
+ pressureSamples[1][2] + pressureSamples[1][3]
|
||||
+ pressureSamples[1][4] + pressureSamples[1][5]) / 6);
|
||||
float change = (pressureAvg[1] - pressureAvg[0]);
|
||||
if (minuteCount == 5)
|
||||
{
|
||||
pressureAvg = getLastPressureSamplesAverage();
|
||||
}
|
||||
else if (minuteCount == 35)
|
||||
{
|
||||
float lastPressureAvg = getLastPressureSamplesAverage();
|
||||
float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
|
||||
if (firstRound) // first time initial 3 hour
|
||||
dP_dt = ((65.0 / 1023.0) * 2 * change); // note this is for t = 0.5hour
|
||||
{
|
||||
dP_dt = change * 2; // note this is for t = 0.5hour
|
||||
}
|
||||
else
|
||||
dP_dt = (((65.0 / 1023.0) * change) / 1.5); // divide by 1.5 as this is the difference in time from 0 value.
|
||||
} else if (minuteCount == 60) {
|
||||
// Avg pressure at end of the hour, value averaged from 0 to 5 min.
|
||||
pressureAvg[2] = ((pressureSamples[2][0] + pressureSamples[2][1]
|
||||
+ pressureSamples[2][2] + pressureSamples[2][3]
|
||||
+ pressureSamples[2][4] + pressureSamples[2][5]) / 6);
|
||||
float change = (pressureAvg[2] - pressureAvg[0]);
|
||||
{
|
||||
dP_dt = change / 1.5; // divide by 1.5 as this is the difference in time from 0 value.
|
||||
}
|
||||
}
|
||||
else if (minuteCount == 65)
|
||||
{
|
||||
float lastPressureAvg = getLastPressureSamplesAverage();
|
||||
float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
|
||||
if (firstRound) //first time initial 3 hour
|
||||
dP_dt = ((65.0 / 1023.0) * change); //note this is for t = 1 hour
|
||||
{
|
||||
dP_dt = change; //note this is for t = 1 hour
|
||||
}
|
||||
else
|
||||
dP_dt = (((65.0 / 1023.0) * change) / 2); //divide by 2 as this is the difference in time from 0 value
|
||||
} else if (minuteCount == 95) {
|
||||
// Avg pressure at end of the hour, value averaged from 0 to 5 min.
|
||||
pressureAvg[3] = ((pressureSamples[3][0] + pressureSamples[3][1]
|
||||
+ pressureSamples[3][2] + pressureSamples[3][3]
|
||||
+ pressureSamples[3][4] + pressureSamples[3][5]) / 6);
|
||||
float change = (pressureAvg[3] - pressureAvg[0]);
|
||||
{
|
||||
dP_dt = change / 2; //divide by 2 as this is the difference in time from 0 value
|
||||
}
|
||||
}
|
||||
else if (minuteCount == 95)
|
||||
{
|
||||
float lastPressureAvg = getLastPressureSamplesAverage();
|
||||
float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
|
||||
if (firstRound) // first time initial 3 hour
|
||||
dP_dt = (((65.0 / 1023.0) * change) / 1.5); // note this is for t = 1.5 hour
|
||||
{
|
||||
dP_dt = change / 1.5; // note this is for t = 1.5 hour
|
||||
}
|
||||
else
|
||||
dP_dt = (((65.0 / 1023.0) * change) / 2.5); // divide by 2.5 as this is the difference in time from 0 value
|
||||
} else if (minuteCount == 120) {
|
||||
// Avg pressure at end of the hour, value averaged from 0 to 5 min.
|
||||
pressureAvg[4] = ((pressureSamples[4][0] + pressureSamples[4][1]
|
||||
+ pressureSamples[4][2] + pressureSamples[4][3]
|
||||
+ pressureSamples[4][4] + pressureSamples[4][5]) / 6);
|
||||
float change = (pressureAvg[4] - pressureAvg[0]);
|
||||
{
|
||||
dP_dt = change / 2.5; // divide by 2.5 as this is the difference in time from 0 value
|
||||
}
|
||||
}
|
||||
else if (minuteCount == 125)
|
||||
{
|
||||
float lastPressureAvg = getLastPressureSamplesAverage();
|
||||
pressureAvg2 = lastPressureAvg; // store for later use.
|
||||
float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
|
||||
if (firstRound) // first time initial 3 hour
|
||||
dP_dt = (((65.0 / 1023.0) * change) / 2); // note this is for t = 2 hour
|
||||
{
|
||||
dP_dt = change / 2; // note this is for t = 2 hour
|
||||
}
|
||||
else
|
||||
dP_dt = (((65.0 / 1023.0) * change) / 3); // divide by 3 as this is the difference in time from 0 value
|
||||
} else if (minuteCount == 155) {
|
||||
// Avg pressure at end of the hour, value averaged from 0 to 5 min.
|
||||
pressureAvg[5] = ((pressureSamples[5][0] + pressureSamples[5][1]
|
||||
+ pressureSamples[5][2] + pressureSamples[5][3]
|
||||
+ pressureSamples[5][4] + pressureSamples[5][5]) / 6);
|
||||
float change = (pressureAvg[5] - pressureAvg[0]);
|
||||
{
|
||||
dP_dt = change / 3; // divide by 3 as this is the difference in time from 0 value
|
||||
}
|
||||
}
|
||||
else if (minuteCount == 155)
|
||||
{
|
||||
float lastPressureAvg = getLastPressureSamplesAverage();
|
||||
float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
|
||||
if (firstRound) // first time initial 3 hour
|
||||
dP_dt = (((65.0 / 1023.0) * change) / 2.5); // note this is for t = 2.5 hour
|
||||
{
|
||||
dP_dt = change / 2.5; // note this is for t = 2.5 hour
|
||||
}
|
||||
else
|
||||
dP_dt = (((65.0 / 1023.0) * change) / 3.5); // divide by 3.5 as this is the difference in time from 0 value
|
||||
} else if (minuteCount == 180) {
|
||||
// Avg pressure at end of the hour, value averaged from 0 to 5 min.
|
||||
pressureAvg[6] = ((pressureSamples[6][0] + pressureSamples[6][1]
|
||||
+ pressureSamples[6][2] + pressureSamples[6][3]
|
||||
+ pressureSamples[6][4] + pressureSamples[6][5]) / 6);
|
||||
float change = (pressureAvg[6] - pressureAvg[0]);
|
||||
{
|
||||
dP_dt = change / 3.5; // divide by 3.5 as this is the difference in time from 0 value
|
||||
}
|
||||
}
|
||||
else if (minuteCount == 185)
|
||||
{
|
||||
float lastPressureAvg = getLastPressureSamplesAverage();
|
||||
float change = (lastPressureAvg - pressureAvg) * CONVERSION_FACTOR;
|
||||
if (firstRound) // first time initial 3 hour
|
||||
dP_dt = (((65.0 / 1023.0) * change) / 3); // note this is for t = 3 hour
|
||||
{
|
||||
dP_dt = change / 3; // note this is for t = 3 hour
|
||||
}
|
||||
else
|
||||
dP_dt = (((65.0 / 1023.0) * change) / 4); // divide by 4 as this is the difference in time from 0 value
|
||||
pressureAvg[0] = pressureAvg[5]; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past.
|
||||
{
|
||||
dP_dt = change / 4; // divide by 4 as this is the difference in time from 0 value
|
||||
}
|
||||
pressureAvg = pressureAvg2; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past.
|
||||
firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop.
|
||||
}
|
||||
|
||||
int forecast = UNKNOWN;
|
||||
if (minuteCount < 35 && firstRound) //if time is less than 35 min on the first 3 hour interval.
|
||||
return 5; // Unknown, more time needed
|
||||
{
|
||||
forecast = UNKNOWN;
|
||||
}
|
||||
else if (dP_dt < (-0.25))
|
||||
return 4; // Quickly falling LP, Thunderstorm, not stable
|
||||
{
|
||||
forecast = THUNDERSTORM;
|
||||
}
|
||||
else if (dP_dt > 0.25)
|
||||
return 3; // Quickly rising HP, not stable weather
|
||||
{
|
||||
forecast = UNSTABLE;
|
||||
}
|
||||
else if ((dP_dt > (-0.25)) && (dP_dt < (-0.05)))
|
||||
return 2; // Slowly falling Low Pressure System, stable rainy weather
|
||||
{
|
||||
forecast = CLOUDY;
|
||||
}
|
||||
else if ((dP_dt > 0.05) && (dP_dt < 0.25))
|
||||
return 1; // Slowly rising HP stable good weather
|
||||
else if ((dP_dt > (-0.05)) && (dP_dt < 0.05))
|
||||
return 0; // Stable weather
|
||||
{
|
||||
forecast = SUNNY;
|
||||
}
|
||||
else if ((dP_dt >(-0.05)) && (dP_dt < 0.05))
|
||||
{
|
||||
forecast = STABLE;
|
||||
}
|
||||
else
|
||||
return 5; // Unknown
|
||||
{
|
||||
forecast = UNKNOWN;
|
||||
}
|
||||
|
||||
// uncomment when debugging
|
||||
//Serial.print(F("Forecast at minute "));
|
||||
//Serial.print(minuteCount);
|
||||
//Serial.print(F(" dP/dt = "));
|
||||
//Serial.print(dP_dt);
|
||||
//Serial.print(F("kPa/h --> "));
|
||||
//Serial.println(weather[forecast]);
|
||||
|
||||
return forecast;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,594 @@
|
||||
/*
|
||||
Arduino Tipping Bucket Rain Gauge
|
||||
|
||||
April 26, 2015
|
||||
|
||||
Version 1.4.1 alpha
|
||||
|
||||
Arduino Tipping Bucket Rain Gauge
|
||||
|
||||
Utilizing a tipping bucket sensor, your Vera home automation controller and the MySensors.org
|
||||
gateway you can measure and sense local rain. This sketch will create two devices on your
|
||||
Vera controller. One will display your total precipitation for the last 5 days. The other,
|
||||
a sensor that changes state if there is recent rain (up to last 120 hours) above a threshold.
|
||||
Both these settings are user definable.
|
||||
|
||||
There is a build overview video here: https://youtu.be/1eMfKQaLROo
|
||||
|
||||
This sketch features the following:
|
||||
|
||||
* Allows you to set the rain threshold in mm
|
||||
* Allows you to determine the tripped indicator window up to 120 hours.
|
||||
* Displays the last 5 days of rain in Variable1 through Variable5
|
||||
of the Rain Sensor device
|
||||
* Configuration changes to Sensor device updated every hour
|
||||
* Should run on any Arduino
|
||||
* Will retain Tripped/Not Tripped status and data in a power interruption, saving small amount
|
||||
of data to EEPROM (Circular Buffer to maximize life of EEPROM)
|
||||
* LED status indicator
|
||||
* Optional Temp/Humidity (DHT-22 or DHT-11) and Light LUX (BH1750) sensors. To use, uncomment
|
||||
#define DHT_ON and/or #define LUX_ON
|
||||
* Optionally send total accumulation of each day's rainfall or send only individual days rainfall totals.
|
||||
Comment out #define USE_DAILY to display individual daily rainfall.
|
||||
|
||||
by @BulldogLowell and @PeteWill for free public use
|
||||
|
||||
*/
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
#include <math.h>
|
||||
#include <Time.h>
|
||||
|
||||
#define NODE_ID 24 //or AUTO to let controller assign
|
||||
#define SKETCH_NAME "Rain Gauge"
|
||||
#define SKETCH_VERSION "1.4.1a"
|
||||
|
||||
#define DWELL_TIME 125 // this allows for radio to come back to power after a transmission, ideally 0
|
||||
|
||||
//#define DEBUG_ON // comment out this line to disable serial debug
|
||||
#define DHT_ON // uncomment out this line to enable DHT sensor
|
||||
#define LUX_ON // uncomment out this line to enable BH1750 sensor
|
||||
//#define USE_DAILY // displays each time segment as an accumulation of prior periods inclusive. Comment out to display individual daily rainfall totals in the variables sent to your controller.
|
||||
|
||||
#define CALIBRATE_FACTOR 60 // amount of rain per rain bucket tip e.g. 5 is .05mm
|
||||
#define DHT_LUX_DELAY 300000 //Delay in milliseconds that the DHT and LUX sensors will wait before sending data
|
||||
|
||||
#define CHILD_ID_RAIN_LOG 3 // Keeps track of accumulated rainfall
|
||||
#define CHILD_ID_TRIPPED_INDICATOR 4 // Indicates Tripped when rain detected
|
||||
#define EEPROM_BUFFER_LOCATION 0 // location of the EEPROM circular buffer
|
||||
#define E_BUFFER_LENGTH 240
|
||||
#define RAIN_BUCKET_SIZE 120
|
||||
|
||||
#ifdef DEBUG_ON
|
||||
#define DEBUG_PRINT(x) Serial.print(x)
|
||||
#define DEBUG_PRINTLN(x) Serial.println(x)
|
||||
#define SERIAL_START(x) Serial.begin(x)
|
||||
#else
|
||||
#define DEBUG_PRINT(x)
|
||||
#define DEBUG_PRINTLN(x)
|
||||
#define SERIAL_START(x)
|
||||
#endif
|
||||
//
|
||||
MySensor gw;
|
||||
//
|
||||
MyMessage msgRainRate(CHILD_ID_RAIN_LOG, V_RAINRATE);
|
||||
MyMessage msgRain(CHILD_ID_RAIN_LOG, V_RAIN);
|
||||
//
|
||||
MyMessage msgRainVAR1(CHILD_ID_RAIN_LOG, V_VAR1);
|
||||
MyMessage msgRainVAR2(CHILD_ID_RAIN_LOG, V_VAR2);
|
||||
MyMessage msgRainVAR3(CHILD_ID_RAIN_LOG, V_VAR3);
|
||||
MyMessage msgRainVAR4(CHILD_ID_RAIN_LOG, V_VAR4);
|
||||
MyMessage msgRainVAR5(CHILD_ID_RAIN_LOG, V_VAR5);
|
||||
//
|
||||
MyMessage msgTripped(CHILD_ID_TRIPPED_INDICATOR, V_TRIPPED);
|
||||
MyMessage msgTrippedVar1(CHILD_ID_TRIPPED_INDICATOR, V_VAR1);
|
||||
MyMessage msgTrippedVar2(CHILD_ID_TRIPPED_INDICATOR, V_VAR2);
|
||||
//
|
||||
#ifdef DHT_ON
|
||||
#include <DHT.h>
|
||||
#define CHILD_ID_HUM 0
|
||||
#define CHILD_ID_TEMP 1
|
||||
#define HUMIDITY_SENSOR_DIGITAL_PIN 8
|
||||
DHT dht;
|
||||
float lastTemp;
|
||||
float lastHum;
|
||||
boolean metric = true;
|
||||
MyMessage msgHum(CHILD_ID_HUM, V_HUM);
|
||||
MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
|
||||
#endif
|
||||
//
|
||||
#ifdef LUX_ON
|
||||
//BH1750 is connected to SCL (analog input A5) and SDA (analog input A4)
|
||||
#include <BH1750.h>
|
||||
#include <Wire.h>
|
||||
#define CHILD_ID_LIGHT 2
|
||||
BH1750 lightSensor;
|
||||
MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
|
||||
unsigned int lastlux;
|
||||
byte heartbeat = 10; //Used to send the light lux to gateway as soon as the device is restarted and after the DHT_LUX_DELAY has happened 10 times
|
||||
#endif
|
||||
unsigned long sensorPreviousMillis;
|
||||
int eepromIndex;
|
||||
int tipSensorPin = 3; // Pin the tipping bucket is connected to. Must be interrupt capable pin
|
||||
int ledPin = 5; // Pin the LED is connected to. PWM capable pin required
|
||||
unsigned long dataMillis;
|
||||
unsigned long serialInterval = 600000UL;
|
||||
const unsigned long oneHour = 3600000UL;
|
||||
unsigned long lastTipTime;
|
||||
unsigned long lastRainTime; //Used for rainRate calculation
|
||||
unsigned int rainBucket [RAIN_BUCKET_SIZE] ; /* 24 hours x 5 Days = 120 hours */
|
||||
unsigned int rainRate = 0;
|
||||
byte rainWindow = 72; //default rain window in hours. Will be overwritten with msgTrippedVar1.
|
||||
volatile int wasTippedBuffer = 0;
|
||||
int rainSensorThreshold = 50; //default rain sensor sensitivity in hundredths. Will be overwritten with msgTrippedVar2.
|
||||
byte state = 0;
|
||||
byte oldState = -1;
|
||||
int lastRainRate = 0;
|
||||
int lastMeasure = 0;
|
||||
boolean gotTime = false;
|
||||
byte lastHour;
|
||||
byte currentHour;
|
||||
//
|
||||
void setup()
|
||||
{
|
||||
SERIAL_START(115200);
|
||||
//
|
||||
// Set up the IO
|
||||
pinMode(tipSensorPin, INPUT_PULLUP);
|
||||
attachInterrupt (1, sensorTipped, FALLING); // depending on location of the hall effect sensor may need CHANGE
|
||||
pinMode(ledPin, OUTPUT);
|
||||
digitalWrite(ledPin, HIGH);
|
||||
//
|
||||
//Let's get the controller talking to the Arduino
|
||||
gw.begin(getVariables, NODE_ID);
|
||||
gw.sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
|
||||
gw.wait(DWELL_TIME);
|
||||
gw.present(CHILD_ID_RAIN_LOG, S_RAIN);
|
||||
gw.wait(DWELL_TIME);
|
||||
gw.present(CHILD_ID_TRIPPED_INDICATOR, S_MOTION);
|
||||
gw.wait(DWELL_TIME);
|
||||
DEBUG_PRINTLN(F("Sensor Presentation Complete"));
|
||||
//
|
||||
//Sync time with the server, this will be called hourly in order to keep time from creeping with the crystal
|
||||
//
|
||||
unsigned long functionTimeout = millis();
|
||||
while (timeStatus() == timeNotSet && millis() - functionTimeout < 30000UL)
|
||||
{
|
||||
gw.process();
|
||||
gw.requestTime(receiveTime);
|
||||
DEBUG_PRINTLN(F("Getting Time"));
|
||||
gw.wait(1000); // call once per second
|
||||
DEBUG_PRINTLN(F("."));
|
||||
}
|
||||
currentHour = hour();
|
||||
lastHour = hour();
|
||||
//
|
||||
//retrieve from EEPROM stored values on a power cycle.
|
||||
//
|
||||
boolean isDataOnEeprom = false;
|
||||
for (int i = 0; i < E_BUFFER_LENGTH; i++)
|
||||
{
|
||||
byte locator = gw.loadState(EEPROM_BUFFER_LOCATION + i);
|
||||
if (locator == 0xFE) // found the EEPROM circular buffer index
|
||||
{
|
||||
eepromIndex = EEPROM_BUFFER_LOCATION + i;
|
||||
DEBUG_PRINT(F("EEPROM Index "));
|
||||
DEBUG_PRINTLN(eepromIndex);
|
||||
//Now that we have the buffer index let's populate the rainBucket[] with data from eeprom
|
||||
loadRainArray(eepromIndex);
|
||||
isDataOnEeprom = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//
|
||||
if (!isDataOnEeprom) // Added for the first time it is run on a new Arduino
|
||||
{
|
||||
DEBUG_PRINTLN(F("I didn't find valid EEPROM Index, so I'm writing one to location 0"));
|
||||
eepromIndex = EEPROM_BUFFER_LOCATION;
|
||||
gw.saveState(eepromIndex, 0xFE);
|
||||
gw.saveState(eepromIndex + 1, 0xFE);
|
||||
//then I will clear out any bad data
|
||||
for (int i = 2; i <= E_BUFFER_LENGTH; i++)
|
||||
{
|
||||
gw.saveState(i, 0x00);
|
||||
}
|
||||
}
|
||||
dataMillis = millis();
|
||||
lastTipTime = millis() - oneHour; //why is this -oneHour?? Doesn't millis() start at 0 when first powered on?
|
||||
//
|
||||
gw.request(CHILD_ID_TRIPPED_INDICATOR, V_VAR1);
|
||||
gw.wait(DWELL_TIME);
|
||||
gw.request(CHILD_ID_TRIPPED_INDICATOR, V_VAR2);
|
||||
gw.wait(DWELL_TIME);
|
||||
//
|
||||
#ifdef DHT_ON
|
||||
dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN);
|
||||
// Register all sensors to gw (they will be created as child devices)
|
||||
gw.present(CHILD_ID_HUM, S_HUM);
|
||||
gw.wait(DWELL_TIME);
|
||||
gw.present(CHILD_ID_TEMP, S_TEMP);
|
||||
gw.wait(DWELL_TIME);
|
||||
metric = gw.getConfig().isMetric;
|
||||
gw.wait(DWELL_TIME);
|
||||
#endif
|
||||
//
|
||||
#ifdef LUX_ON
|
||||
gw.present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
|
||||
gw.wait(DWELL_TIME);
|
||||
lightSensor.begin();
|
||||
#endif
|
||||
//
|
||||
DEBUG_PRINTLN(F("Radio Setup Complete!"));
|
||||
transmitRainData();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
gw.process();
|
||||
if (state)
|
||||
{
|
||||
prettyFade(); // breathe if tripped
|
||||
}
|
||||
else
|
||||
{
|
||||
slowFlash(); // blink if not tripped
|
||||
}
|
||||
#ifdef DEBUG_ON // Serial Debug Block
|
||||
if ( (millis() - dataMillis) >= serialInterval)
|
||||
{
|
||||
for (int i = 24; i <= 120; i = i + 24)
|
||||
{
|
||||
updateSerialData(i);
|
||||
}
|
||||
dataMillis = millis();
|
||||
}
|
||||
#endif
|
||||
//
|
||||
// let's constantly check to see if the rain in the past rainWindow hours is greater than rainSensorThreshold
|
||||
//
|
||||
int measure = 0; // Check to see if we need to show sensor tripped in this block
|
||||
for (int i = 0; i < rainWindow; i++)
|
||||
{
|
||||
measure += rainBucket [i];
|
||||
if (measure != lastMeasure)
|
||||
{
|
||||
// DEBUG_PRINT(F("measure value (total rainBucket within rainWindow): "));
|
||||
// DEBUG_PRINTLN(measure);
|
||||
lastMeasure = measure;
|
||||
}
|
||||
}
|
||||
//
|
||||
state = (measure >= (rainSensorThreshold * 100));
|
||||
if (state != oldState)
|
||||
{
|
||||
gw.send(msgTripped.set(state));
|
||||
gw.wait(DWELL_TIME);
|
||||
DEBUG_PRINT(F("New Sensor State... Sensor: "));
|
||||
DEBUG_PRINTLN(state ? "Tripped" : "Not Tripped");
|
||||
oldState = state;
|
||||
}
|
||||
//
|
||||
unsigned long tipDelay = millis() - lastRainTime;
|
||||
if (wasTippedBuffer) // if was tipped, then update the 24hour total and transmit to Vera
|
||||
{
|
||||
DEBUG_PRINTLN(F("Sensor Tipped"));
|
||||
DEBUG_PRINT(F("rainBucket [0] value: "));
|
||||
DEBUG_PRINTLN(rainBucket [0]);
|
||||
gw.send(msgRain.set((float)rainTotal(currentHour) / 100, 1)); //Calculate the total rain for the day
|
||||
gw.wait(DWELL_TIME);
|
||||
wasTippedBuffer--;
|
||||
rainRate = ((oneHour) / tipDelay);
|
||||
if (rainRate != lastRainRate)
|
||||
{
|
||||
gw.send(msgRainRate.set(rainRate, 1));
|
||||
gw.wait(DWELL_TIME);
|
||||
DEBUG_PRINT(F("RainRate= "));
|
||||
DEBUG_PRINTLN(rainRate);
|
||||
lastRainRate = rainRate;
|
||||
}
|
||||
lastRainTime = lastTipTime;
|
||||
}
|
||||
//
|
||||
currentHour = hour();
|
||||
if (currentHour != lastHour)
|
||||
{
|
||||
DEBUG_PRINTLN(F("One hour elapsed."));
|
||||
gw.send(msgRain.set((float)rainTotal(currentHour) / 100, 1)); // send today's rainfall
|
||||
gw.wait(DWELL_TIME);
|
||||
gw.saveState(eepromIndex, highByte(rainBucket[0]));
|
||||
gw.saveState(eepromIndex + 1, lowByte(rainBucket[0]));
|
||||
DEBUG_PRINT(F("Saving rainBucket[0] to eeprom. rainBucket[0] = "));
|
||||
DEBUG_PRINTLN(rainBucket[0]);
|
||||
for (int i = RAIN_BUCKET_SIZE - 1; i >= 0; i--)//cascade an hour of values back into the array
|
||||
{
|
||||
rainBucket [i + 1] = rainBucket [i];
|
||||
}
|
||||
gw.request(CHILD_ID_TRIPPED_INDICATOR, V_VAR1);
|
||||
gw.wait(DWELL_TIME);
|
||||
gw.request(CHILD_ID_TRIPPED_INDICATOR, V_VAR2);
|
||||
gw.wait(DWELL_TIME);
|
||||
rainBucket[0] = 0;
|
||||
eepromIndex = eepromIndex + 2;
|
||||
if (eepromIndex > EEPROM_BUFFER_LOCATION + E_BUFFER_LENGTH)
|
||||
{
|
||||
eepromIndex = EEPROM_BUFFER_LOCATION;
|
||||
}
|
||||
DEBUG_PRINT(F("Writing to EEPROM. Index: "));
|
||||
DEBUG_PRINTLN(eepromIndex);
|
||||
gw.saveState(eepromIndex, 0xFE);
|
||||
gw.saveState(eepromIndex + 1, 0xFE);
|
||||
gw.requestTime(receiveTime); // sync the time every hour
|
||||
gw.wait(DWELL_TIME);
|
||||
transmitRainData();
|
||||
rainRate = 0;
|
||||
gw.send(msgRainRate.set(rainRate, 1));
|
||||
gw.wait(DWELL_TIME);
|
||||
DEBUG_PRINTLN(F("Sending rainRate is 0 to controller"));
|
||||
lastHour = currentHour;
|
||||
}
|
||||
if (millis() - sensorPreviousMillis > DHT_LUX_DELAY)
|
||||
{
|
||||
#ifdef DHT_ON //DHT Code
|
||||
doDHT();
|
||||
#endif
|
||||
#ifdef LUX_ON
|
||||
doLUX();
|
||||
#endif
|
||||
sensorPreviousMillis = millis();
|
||||
}
|
||||
}
|
||||
//
|
||||
#ifdef DHT_ON
|
||||
void doDHT(void)
|
||||
{
|
||||
float temperature = dht.getTemperature();
|
||||
if (isnan(temperature))
|
||||
{
|
||||
DEBUG_PRINTLN(F("Failed reading temperature from DHT"));
|
||||
} else if (temperature != lastTemp)
|
||||
{
|
||||
lastTemp = temperature;
|
||||
if (!metric)
|
||||
{
|
||||
temperature = dht.toFahrenheit(temperature);
|
||||
}
|
||||
gw.send(msgTemp.set(temperature, 1));
|
||||
gw.wait(DWELL_TIME);
|
||||
DEBUG_PRINT(F("Temperature is: "));
|
||||
DEBUG_PRINTLN(temperature);
|
||||
}
|
||||
float humidity = dht.getHumidity();;
|
||||
if (isnan(humidity))
|
||||
{
|
||||
DEBUG_PRINTLN(F("Failed reading humidity from DHT"));
|
||||
} else if (humidity != lastHum)
|
||||
{
|
||||
lastHum = humidity;
|
||||
gw.send(msgHum.set(humidity, 1));
|
||||
gw.wait(DWELL_TIME);
|
||||
DEBUG_PRINT(F("Humidity is: "));
|
||||
DEBUG_PRINTLN(humidity);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//
|
||||
#ifdef LUX_ON
|
||||
void doLUX(void)
|
||||
{
|
||||
unsigned int lux = lightSensor.readLightLevel();// Get Lux value
|
||||
DEBUG_PRINT(F("Current LUX Level: "));
|
||||
DEBUG_PRINTLN(lux);
|
||||
heartbeat++;
|
||||
if (lux != lastlux || heartbeat > 10)
|
||||
{
|
||||
gw.send(msg.set(lux));
|
||||
lastlux = lux;
|
||||
}
|
||||
if (heartbeat > 10)
|
||||
{
|
||||
heartbeat = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//
|
||||
void sensorTipped()
|
||||
{
|
||||
unsigned long thisTipTime = millis();
|
||||
if (thisTipTime - lastTipTime > 100UL)
|
||||
{
|
||||
rainBucket[0] += CALIBRATE_FACTOR; // adds CALIBRATE_FACTOR hundredths of unit each tip
|
||||
wasTippedBuffer++;
|
||||
}
|
||||
lastTipTime = thisTipTime;
|
||||
}
|
||||
//
|
||||
int rainTotal(int hours)
|
||||
{
|
||||
int total = 0;
|
||||
for ( int i = 0; i <= hours; i++)
|
||||
{
|
||||
total += rainBucket [i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
void updateSerialData(int x)
|
||||
{
|
||||
DEBUG_PRINT(F("Rain last "));
|
||||
DEBUG_PRINT(x);
|
||||
DEBUG_PRINTLN(F(" hours: "));
|
||||
float tipCount = 0;
|
||||
for (int i = 0; i < x; i++)
|
||||
{
|
||||
tipCount = tipCount + rainBucket [i];
|
||||
}
|
||||
tipCount = tipCount / 100;
|
||||
DEBUG_PRINTLN(tipCount);
|
||||
}
|
||||
|
||||
void loadRainArray(int value) // retrieve stored rain array from EEPROM on powerup
|
||||
{
|
||||
for (int i = 0; i < RAIN_BUCKET_SIZE; i++)
|
||||
{
|
||||
value = value - 2;
|
||||
if (value < EEPROM_BUFFER_LOCATION)
|
||||
{
|
||||
value = EEPROM_BUFFER_LOCATION + E_BUFFER_LENGTH;
|
||||
}
|
||||
DEBUG_PRINT(F("EEPROM location: "));
|
||||
DEBUG_PRINTLN(value);
|
||||
byte rainValueHigh = gw.loadState(value);
|
||||
byte rainValueLow = gw.loadState(value + 1);
|
||||
unsigned int rainValue = rainValueHigh << 8;
|
||||
rainValue |= rainValueLow;
|
||||
rainBucket[i + 1] = rainValue;
|
||||
//
|
||||
DEBUG_PRINT(F("rainBucket[ value: "));
|
||||
DEBUG_PRINT(i + 1);
|
||||
DEBUG_PRINT(F("] value: "));
|
||||
DEBUG_PRINTLN(rainBucket[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
void transmitRainData(void)
|
||||
{
|
||||
DEBUG_PRINT(F("In transmitRainData. currentHour = "));
|
||||
DEBUG_PRINTLN(currentHour);
|
||||
int rainUpdateTotal = 0;
|
||||
for (int i = currentHour; i >= 0; i--)
|
||||
{
|
||||
rainUpdateTotal += rainBucket[i];
|
||||
DEBUG_PRINT(F("Adding rainBucket["));
|
||||
DEBUG_PRINT(i);
|
||||
DEBUG_PRINTLN(F("] to rainUpdateTotal."));
|
||||
}
|
||||
DEBUG_PRINT(F("TX Day 1: rainUpdateTotal = "));
|
||||
DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
|
||||
gw.send(msgRainVAR1.set((float)rainUpdateTotal / 100.0, 1)); //Send current day rain totals (resets at midnight)
|
||||
gw.wait(DWELL_TIME);
|
||||
#ifdef USE_DAILY
|
||||
rainUpdateTotal = 0;
|
||||
#endif
|
||||
for (int i = currentHour + 24; i > currentHour; i--)
|
||||
{
|
||||
rainUpdateTotal += rainBucket[i];
|
||||
DEBUG_PRINT(F("Adding rainBucket["));
|
||||
DEBUG_PRINT(i);
|
||||
DEBUG_PRINTLN(F("] to rainUpdateTotal."));
|
||||
}
|
||||
DEBUG_PRINT(F("TX Day 2: rainUpdateTotal = "));
|
||||
DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
|
||||
gw.send(msgRainVAR2.set((float)rainUpdateTotal / 100.0, 1));
|
||||
gw.wait(DWELL_TIME);
|
||||
#ifdef USE_DAILY
|
||||
rainUpdateTotal = 0;
|
||||
#endif
|
||||
for (int i = currentHour + 48; i > currentHour + 24; i--)
|
||||
{
|
||||
rainUpdateTotal += rainBucket[i];
|
||||
DEBUG_PRINT(F("Adding rainBucket["));
|
||||
DEBUG_PRINT(i);
|
||||
DEBUG_PRINTLN(F("] to rainUpdateTotal."));
|
||||
}
|
||||
DEBUG_PRINT(F("TX Day 3: rainUpdateTotal = "));
|
||||
DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
|
||||
gw.send(msgRainVAR3.set((float)rainUpdateTotal / 100.0, 1));
|
||||
gw.wait(DWELL_TIME);
|
||||
#ifdef USE_DAILY
|
||||
rainUpdateTotal = 0;
|
||||
#endif
|
||||
for (int i = currentHour + 72; i > currentHour + 48; i--)
|
||||
{
|
||||
rainUpdateTotal += rainBucket[i];
|
||||
DEBUG_PRINT(F("Adding rainBucket["));
|
||||
DEBUG_PRINT(i);
|
||||
DEBUG_PRINTLN(F("] to rainUpdateTotal."));
|
||||
}
|
||||
DEBUG_PRINT(F("TX Day 4: rainUpdateTotal = "));
|
||||
DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
|
||||
gw.send(msgRainVAR4.set((float)rainUpdateTotal / 100.0, 1));
|
||||
gw.wait(DWELL_TIME);
|
||||
#ifdef USE_DAILY
|
||||
rainUpdateTotal = 0;
|
||||
#endif
|
||||
for (int i = currentHour + 96; i > currentHour + 72; i--)
|
||||
{
|
||||
rainUpdateTotal += rainBucket[i];
|
||||
DEBUG_PRINT(F("Adding rainBucket["));
|
||||
DEBUG_PRINT(i);
|
||||
DEBUG_PRINTLN(F("] to rainUpdateTotal."));
|
||||
}
|
||||
DEBUG_PRINT(F("TX Day 5: rainUpdateTotal = "));
|
||||
DEBUG_PRINTLN((float)rainUpdateTotal / 100.0);
|
||||
gw.send(msgRainVAR5.set((float)rainUpdateTotal / 100.0, 1));
|
||||
gw.wait(DWELL_TIME);
|
||||
}
|
||||
|
||||
void getVariables(const MyMessage &message)
|
||||
{
|
||||
if (message.sensor == CHILD_ID_RAIN_LOG)
|
||||
{
|
||||
// nothing to do here
|
||||
}
|
||||
else if (message.sensor == CHILD_ID_TRIPPED_INDICATOR)
|
||||
{
|
||||
if (message.type == V_VAR1)
|
||||
{
|
||||
rainWindow = atoi(message.data);
|
||||
if (rainWindow > 120)
|
||||
{
|
||||
rainWindow = 120;
|
||||
}
|
||||
else if (rainWindow < 1)
|
||||
{
|
||||
rainWindow = 1;
|
||||
}
|
||||
if (rainWindow != atoi(message.data)) // if I changed the value back inside the boundries, push that number back to Vera
|
||||
{
|
||||
gw.send(msgTrippedVar1.set(rainWindow));
|
||||
}
|
||||
}
|
||||
else if (message.type == V_VAR2)
|
||||
{
|
||||
rainSensorThreshold = atoi(message.data);
|
||||
if (rainSensorThreshold > 10000)
|
||||
{
|
||||
rainSensorThreshold = 10000;
|
||||
}
|
||||
else if (rainSensorThreshold < 1)
|
||||
{
|
||||
rainSensorThreshold = 1;
|
||||
}
|
||||
if (rainSensorThreshold != atoi(message.data)) // if I changed the value back inside the boundries, push that number back to Vera
|
||||
{
|
||||
gw.send(msgTrippedVar2.set(rainSensorThreshold));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void prettyFade(void)
|
||||
{
|
||||
float val = (exp(sin(millis() / 2000.0 * PI)) - 0.36787944) * 108.0;
|
||||
analogWrite(ledPin, val);
|
||||
}
|
||||
|
||||
void slowFlash(void)
|
||||
{
|
||||
static boolean ledState = true;
|
||||
static unsigned long pulseStart = millis();
|
||||
if (millis() - pulseStart < 100UL)
|
||||
{
|
||||
digitalWrite(ledPin, !ledState);
|
||||
pulseStart = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void receiveTime(unsigned long time)
|
||||
{
|
||||
DEBUG_PRINTLN(F("Time received..."));
|
||||
setTime(time);
|
||||
char theTime[6];
|
||||
sprintf(theTime, "%d:%2d", hour(), minute());
|
||||
DEBUG_PRINTLN(theTime);
|
||||
}
|
||||
@@ -40,6 +40,11 @@
|
||||
// When MEASURE_INTERVAL is 60000 and FORCE_TRANSMIT_INTERVAL is 30, we force a transmission every 30 minutes.
|
||||
// Between the forced transmissions a tranmission will only occur if the measured value differs from the previous measurement
|
||||
|
||||
// HUMI_TRANSMIT_THRESHOLD tells how much the humidity should have changed since last time it was transmitted. Likewise with
|
||||
// TEMP_TRANSMIT_THRESHOLD for temperature threshold.
|
||||
#define HUMI_TRANSMIT_THRESHOLD 0.5
|
||||
#define TEMP_TRANSMIT_THRESHOLD 0.5
|
||||
|
||||
// Pin definitions
|
||||
#define TEST_PIN A0
|
||||
#define LED_PIN A2
|
||||
@@ -73,7 +78,6 @@ int lastHumidity = -100;
|
||||
long lastBattery = -100;
|
||||
|
||||
RunningAverage raHum(AVERAGES);
|
||||
RunningAverage raTemp(AVERAGES);
|
||||
|
||||
/****************************************************
|
||||
*
|
||||
@@ -109,9 +113,10 @@ void setup() {
|
||||
gw.begin(NULL,AUTO,false);
|
||||
#endif
|
||||
|
||||
humiditySensor.begin();
|
||||
|
||||
digitalWrite(LED_PIN, LOW);
|
||||
|
||||
humiditySensor.begin();
|
||||
Serial.flush();
|
||||
Serial.println(F(" - Online!"));
|
||||
gw.sendSketchInfo("Sensebender Micro", RELEASE);
|
||||
@@ -123,10 +128,10 @@ void setup() {
|
||||
gw.present(BATT_SENSOR, S_POWER);
|
||||
#endif
|
||||
|
||||
|
||||
isMetric = gw.getConfig().isMetric;
|
||||
Serial.print(F("isMetric: ")); Serial.println(isMetric);
|
||||
raHum.clear();
|
||||
raTemp.clear();
|
||||
sendTempHumidityMeasurements(false);
|
||||
sendBattLevel(false);
|
||||
}
|
||||
@@ -179,21 +184,19 @@ void sendTempHumidityMeasurements(bool force)
|
||||
bool tx = force;
|
||||
|
||||
si7021_env data = humiditySensor.getHumidityAndTemperature();
|
||||
float oldAvgTemp = raTemp.getAverage();
|
||||
float oldAvgHum = raHum.getAverage();
|
||||
|
||||
raTemp.addValue(data.celsiusHundredths);
|
||||
raHum.addValue(data.humidityPercent);
|
||||
|
||||
float diffTemp = abs(lastTemperature - data.celsiusHundredths/100);
|
||||
float diffTemp = abs(lastTemperature - (isMetric ? data.celsiusHundredths : data.fahrenheitHundredths)/100);
|
||||
float diffHum = abs(oldAvgHum - raHum.getAverage());
|
||||
|
||||
Serial.print(F("TempDiff :"));Serial.println(diffTemp);
|
||||
Serial.print(F("HumDiff :"));Serial.println(diffHum);
|
||||
|
||||
if (isnan(diffTemp)) tx = true;
|
||||
if (diffTemp > 0.3) tx = true;
|
||||
if (diffHum >= 0.5) tx = true;
|
||||
if (isnan(diffHum)) tx = true;
|
||||
if (diffTemp > TEMP_TRANSMIT_THRESHOLD) tx = true;
|
||||
if (diffHum >= HUMI_TRANSMIT_THRESHOLD) tx = true;
|
||||
|
||||
if (tx) {
|
||||
measureCount = 0;
|
||||
|
||||
Reference in New Issue
Block a user