Hey guys:
I’m hoping someone can help me, I have a sensor built with the following:
Arduino Uno
PIR - PIN 3
DHT - PIN 7
Relay - PIN 4
Reed switch - PIN 2
I wanted to share this with everyone, but also hoping someone can help perfect it…
It is connected to my push button garage door opener to send a momentary press to open / close the door
The Reed switch determines if the door is open or closed, and the PIR / DHT are really there just for fun ( Temp and motion triggers )
Basically It works great, and integrates very nicely into HA ( Thanks @martinhjelmare ) for this!
Where I am stuck, and have tried many things is keeping the arduino relay state after power outage, but cannot figure it out. I believe the sketch is ok, and is based off mysensors 2, but honestly looking for some feedback if possible, and help with keeping the relay state in memory I have tried adding:
// Set relay to last known state (using eeprom storage)
digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF);
But obviously am not doing it right…
Below is my sketch, and if anyone can please help / comment it would be greatly appreciated. I think many folks can benefit from this once completed
#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 CHILD_ID_TEMP 11
#define CHILD_ID_HUM 10
#define CHILD_ID_MOT 3 // Id of the sensor child
#define CHILD_ID_REL 1
#define RELAY_PIN 4
#define RELAY_ON 1
#define RELAY_OFF 0
#define TOGGLE_INTERVAL 350 //Tells how many milliseconds the relay will be held closed
#define CLOSED 0
#define OPEN 1
#define BUTTON_PIN_1 2
#define CHILD_ID_SW 2
#define HUMIDITY_SENSOR_DIGITAL_PIN 7
#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your motion sensor. (Only 2 and 3 generates interrupt!)
#define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
// Set this offset if the sensor has a permanent small offset to the real temperatures
#define SENSOR_TEMP_OFFSET 1
Bounce debouncer = Bounce();
int oldValue=-1;
bool state = false;
bool initialValueSent = false;
byte StatePIR=0;
byte oldStatePIR=0;
unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in milliseconds)
DHT dht;
float lastTemp;
float lastHum;
boolean metric = true;
bool StateREL=0, StateREL1=0;
MyMessage msgHum(CHILD_ID_HUM, V_HUM);
MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
MyMessage msgMot(CHILD_ID_MOT, V_TRIPPED);
MyMessage msg(CHILD_ID_REL, V_STATUS);
MyMessage msgSW(CHILD_ID_SW,V_TRIPPED);
void presentation()
{
// Send the Sketch Version Information to the Gateway
sendSketchInfo("Garage Multi Sensor", "1.0");
// Register all sensors to gw (they will be created as child devices)
delay(100);
present(CHILD_ID_TEMP, S_TEMP);
delay(100);
present(CHILD_ID_HUM, S_HUM);
delay(100);
present(CHILD_ID_MOT, S_MOTION);
delay(100);
present(CHILD_ID_REL, S_BINARY);
delay(100);
present(CHILD_ID_SW, S_DOOR);
metric = getConfig().isMetric;
}
void setup()
{
// Setup the button
pinMode(BUTTON_PIN_1,INPUT);
// Activate internal pull-up
digitalWrite(BUTTON_PIN_1,HIGH);
// After setting up the button, setup debouncer
debouncer.attach(BUTTON_PIN_1);
debouncer.interval(5);
// Make sure relays are off when starting up
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, StateREL1);
dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN);
if (SLEEP_TIME <= 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());
// metric = getConfig().isMetric;
pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input
}
void loop()
{
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;
}
StatePIR=digitalRead(DIGITAL_INPUT_SENSOR);
if (StatePIR != oldStatePIR) {
oldStatePIR=StatePIR;
send(msgMot.set(StatePIR ? 1 : 0));
}
if (!initialValueSent) {
Serial.println("Sending initial value");
send(msg.set(state?RELAY_ON:RELAY_OFF));
Serial.println("Requesting initial value from controller");
request(CHILD_ID_REL, V_STATUS);
wait(2000, C_SET, V_STATUS);
}
if (debouncer.update()) {
if (debouncer.read()==LOW) {
state = !state;
// Send new state and request ack back
send(msg.set(state?RELAY_ON:RELAY_OFF), true);
}
}
// Read digital motion value
boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
Serial.println(tripped);
send(msgMot.set(tripped?"1":"0")); // Send tripped value to gw
delay(dht.getMinimumSamplingPeriod());
// Fetch temperatures from DHT sensor
float temperature = dht.getTemperature();
if (isnan(temperature)) {
Serial.println("Failed reading temperature from DHT");
} else if (temperature != lastTemp) {
lastTemp = temperature;
if (!metric) {
temperature = dht.toFahrenheit(temperature);
}
temperature += SENSOR_TEMP_OFFSET;
send(msgTemp.set(temperature, 1));
#ifdef MY_DEBUG
Serial.print("T: ");
Serial.println(temperature);
#endif
}
// Fetch humidity from DHT sensor
float humidity = dht.getHumidity();
if (isnan(humidity)) {
Serial.println("Failed reading humidity from DHT");
} else if (humidity != lastHum) {
lastHum = humidity;
send(msgHum.set(humidity, 1));
#ifdef MY_DEBUG
Serial.print("H: ");
Serial.println(humidity);
#endif
}
sleep(INTERRUPT,CHANGE, SLEEP_TIME); //sleep a bit
}
void receive(const MyMessage &message) {
if (message.isAck()) {
Serial.println("This is an ack from gateway");
}
if (message.type == V_STATUS) {
if (!initialValueSent) {
Serial.println("Receiving initial value from controller");
initialValueSent = true;
}
// Change relay state
state = (bool)message.getInt();
digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
//Keep the relay on for the amount of time defined by TOGGLE_INTERVAL
delay( TOGGLE_INTERVAL );
digitalWrite( RELAY_PIN, RELAY_OFF );
// Store state in eeprom
saveState(message.sensor, message.getBool());
send(msg.set(state?RELAY_ON:RELAY_OFF));
}
}
Thanks Again!