Hey guys! Thanks so very much for all the great comments. I haven't replied in a few days as I wanted to go back to the drawing board..... I didn't like that sketch, the sleep functions, etc etc.... It didn't also make sense clearly based on everyone's feedback ( Sorry I am just getting started with IDE... ) So, based on that, I've come up with the following, and if you could comment, modify where I messed up, it would be greatly appreciated. This sketch seems to work, and keep state on power LOSS. There's a relay for the garage door ( trigger, PIN 4 ), a reed switch to detect if the door is open or closed ( PIN 2 ), a DHT for Temp / Humidity ( PIN 7 ), and a PIR ( PIN 3 ) for motion activated events. Below is the sketch, and would really appreciate any great feedback.
Thanks again!
#define MY_DEBUG
#define MY_RADIO_NRF24
#define MY_REPEATER_FEATURE
#define MY_NODE_ID 50
#include <SPI.h>
#include <MySensors.h>
#include <Bounce2.h>
#include <DHT.h>
#define RELAY_1 4 // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
#define NUMBER_OF_RELAYS 1 // Total number of attached relays
#define RELAY_ON 1 // GPIO value to write to turn on attached relay
#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
#define TOGGLE_INTERVAL 350
#define CHILD_ID_SW 2
#define BUTTON_PIN 2 // Arduino Digital I/O pin for button/reed switch
// Sleep time between sensor updates (in milliseconds)
// Must be >1000ms for DHT22 and >2000ms for DHT11
static const uint64_t UPDATE_INTERVAL = 60000;
// Force sending an update of the temperature after n sensor reads, so a controller showing the
// timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
// the value didn't change since;
// i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
static const uint8_t FORCE_UPDATE_N_READS = 10;
float lastTemp;
float lastHum;
uint8_t nNoUpdatesTemp;
uint8_t nNoUpdatesHum;
bool metric = true;
#define CHILD_ID_HUM 10
#define CHILD_ID_TEMP 11
#define HUMIDITY_SENSOR_DIGITAL_PIN 7
// Set this offset if the sensor has a permanent small offset to the real temperatures
#define SENSOR_TEMP_OFFSET -1
#define CHILD_ID_PIR 3
#define PIR_PIN 3
byte StatePIR=0;
byte oldStatePIR=0;
Bounce debouncer = Bounce();
int oldValue=-1;
MyMessage msgSw(CHILD_ID_SW,V_TRIPPED);
MyMessage msgHum(CHILD_ID_HUM, V_HUM); // 1
MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); // 0
MyMessage msgPir(CHILD_ID_PIR, V_TRIPPED);
DHT dht;
void before()
{
for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
// Then set relay pins in output mode
pinMode(pin, OUTPUT);
// Set relay to last known state (using eeprom storage)
digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF);
}
}
void setup()
{
dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); // set data pin of DHT sensor
if (UPDATE_INTERVAL <= dht.getMinimumSamplingPeriod()) {
Serial.println("Warning: UPDATE_INTERVAL is smaller than supported by the sensor!");
}
// Sleep for the time of the minimum sampling period to give the sensor time to power up
// (otherwise, timeout errors might occure for the first reading)
sleep(dht.getMinimumSamplingPeriod());
pinMode(PIR_PIN, INPUT_PULLUP);
// Setup the button
pinMode(BUTTON_PIN,INPUT);
// Activate internal pull-up
digitalWrite(BUTTON_PIN,HIGH);
// After setting up the button, setup debouncer
debouncer.attach(BUTTON_PIN);
debouncer.interval(5);
}
void presentation()
{
// Send the sketch version information to the gateway and Controller
sendSketchInfo("Garage Multi Sensor", "1.0");
for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
// Register all sensors to gw (they will be created as child devices)
present(sensor, S_BINARY);
present(CHILD_ID_SW, S_DOOR);
present(CHILD_ID_HUM, S_HUM);
present(CHILD_ID_TEMP, S_TEMP);
present(CHILD_ID_PIR, S_MOTION);
metric = getConfig().isMetric;
}
}
void loop()
{
StatePIR=digitalRead(PIR_PIN);
if (StatePIR != oldStatePIR) {
oldStatePIR=StatePIR;
send(msgPir.set(StatePIR ? "ON" : "OFF"));
// Force reading sensor, so it works also after sleep()
dht.readSensor(true);
// Get temperature from DHT library
float temperature = dht.getTemperature();
if (isnan(temperature)) {
Serial.println("Failed reading temperature from DHT!");
} else if (temperature != lastTemp || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
// Only send temperature if it changed since the last measurement or if we didn't send an update for n times
lastTemp = temperature;
if (!metric) {
temperature = dht.toFahrenheit(temperature);
}
// Reset no updates counter
nNoUpdatesTemp = 0;
temperature += SENSOR_TEMP_OFFSET;
send(msgTemp.set(temperature, 1));
#ifdef MY_DEBUG
Serial.print("T: ");
Serial.println(temperature);
#endif
} else {
// Increase no update counter if the temperature stayed the same
nNoUpdatesTemp++;
}
// Get humidity from DHT library
float humidity = dht.getHumidity();
if (isnan(humidity)) {
Serial.println("Failed reading humidity from DHT");
} else if (humidity != lastHum || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
// Only send humidity if it changed since the last measurement or if we didn't send an update for n times
lastHum = humidity;
// Reset no updates counter
nNoUpdatesHum = 0;
send(msgHum.set(humidity, 1));
#ifdef MY_DEBUG
Serial.print("H: ");
Serial.println(humidity);
#endif
} else {
// Increase no update counter if the humidity stayed the same
nNoUpdatesHum++;
}
}
debouncer.update();
// Get the update value
int value = debouncer.read();
if (value != oldValue) {
// Send in the new value
send(msgSw.set(value==HIGH ? 1 : 0));
oldValue = value;
}
}
void receive(const MyMessage &message)
{
// We only expect one type of message from controller. But we better check anyway.
if (message.type==V_STATUS) {
// Change relay state
digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
//Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
delay( TOGGLE_INTERVAL );
digitalWrite( RELAY_1, RELAY_OFF );
// Store state in eeprom
saveState(message.sensor, message.getBool());
// Write some debug info
Serial.print("Incoming change for sensor:");
Serial.print(message.sensor);
Serial.print(", New status: ");
Serial.println(message.getBool());
}
}