House sensors by Markus Rohner 11.2015
Have the house observed and controlled by Arduino Nanos with ESP8266 as
WiFi shield and multiple sensors and relays (referenced as Sensor 1-11)
- Same program for all nodes and Master node
- Digital and Analog Pins are used the same way for all nodes
- Virtual Pins for Blynk are shared amongst all nodes and master through Bridge Widget
- In Vacation mode lights are switched on and off automatically
beeing derived from actual light levels and a random number of
minutes until lights are switched off again. - Arduino nodes and master must have loaded parameters into EEPROM such as
id, sensors and auth tokens. See separate program. - The IRREmote library to control TV etc. could not be implemented successfully
It seems to be incompatible with Blynk or just uses more memory to influence
connection with Blynk server. - A soft reset function was implemented if it all hangs.
- A small PCB board was developped for all nodes. (see separate File)
including a 3.3V Power supply for the ESP8266. - Notifies my iPhone when Alarm (Water, Fire, Door, CO2 and movements)
Arduino Pins:
D0: (RX) ESP8266 TX
D1: (TX) ESP8266 RX 3.3V!
D2: PIR (Sensor 1)
D3: IR transmitter (Sensor 11)
D4: Relays1 default LOW e.g. Coffee machine, TV (Sensor 9)
D5: SO High temp (Sensor 6)
D6: SCK High temp (Sensor 6)
D7: CS High temp (Sensor 6)
D8: Relays 2 / MOC3021 vacation lights default HIGH (Sensor 2)
D9: Vacation Pin (only used for master)
D10: Master Slide for reset
D11: Master Switch for reset
D12:
D13:Switch input i.e Garage door (Sensor 3)
A0: Light measurement (Sensor 8)
D15 (A1):
(D16) A2: floating when Lightsensor installed used for Random number generator
(D17) A3: Availability bin
D18 (A4): DHT11 (Sensor 4)
(D19) A5: Water/Rain measurement (Sensor 7)
A6: CO2 measurement MQ-7 (Sensor 5)
A7: Flame sensor (Sensor 10)
RST:To Reset button
GND:Ground
5V: Power supply 5V
Blynk shared virtual ports
V0:Temp Bedroom
V1-V8: LEDs Up
V9:LED Relays2 Office
V10:LED Relays Bed
V11-V18:Alarms
V19:LED Relays2 Living
V20:LED Relays2 Dining
V21:vacation LED
V22:Humidity Bedroom
V23:Garage door push button
V24:LED Relays2 Garage
V25:Thermo Heating
V26:Temp Living
V27:Humidity Living
V28:Temp Office
V29:Humidity Office
V30: Bridge to Base
V31: Up Base
//#define BLYNK_DEBUG
#include <SoftwareSerial.h>
SoftwareSerial MySerial(9,10); // RX, TX attached to a FDDI adapter
//#define BLYNK_PRINT MySerial
// Set ESP8266 Serial object
#include <ESP8266_HardSer.h>
#include <BlynkSimpleShieldEsp8266_HardSer.h>
#define EspSerial Serial
ESP8266 wifi(EspSerial);
WidgetBridge bridge1(V30);
WidgetLED led21(21);
#include <SimpleTimer.h>
#include "DHT.h"
#include <EEPROM.h>
#include "max6675.h"
//#include <IRremote.h>
//#include <IRremoteInt.h>
//#define SEND_SAMSUNG // TV
// System parameters
const byte max_nbr_sensors = 6; //max number of sensors attached per Arduino
const byte max_nbr_dif_sensors = 11; //max number of different sensors in the network
struct MyObject {
uint16_t this_node;
char room[9];
byte sensoren[max_nbr_sensors];
char auth[33];
char othauth [33];
};
MyObject configuration; //Variable to store custom object read from EEPROM.
const int PirPin = 2; // choose the input pin (for PIR sensor)
const int RelayPin1 = 4; //the "s" of relay module attach to
const int thermoDO = 5;
const int thermoCLK = 6;
const int thermoCS = 7;
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
const int RelayPin2 = 8; // the "s" of relay module attach to
const int VacationPin = 9;
const int DoorPin = 13;
const int LightSensor = A0;
#define DHTPIN 18 // what pin we're connected to
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
const int WaterSensor = A5;
const int Co2Sensor = A6; //analog Pin connected to "out" from sensor board
const int FlamePin = A7; // define the flame sensor interface
//IRsend irsend;
SimpleTimer timer;
int lighttimer = -1;
int checktimer;
long int didit = -72000000;
bool runn = 0;
bool alarm_movement = 0;
bool movement;
bool movement_did_it = 0;
bool alarm_door = 0;
bool door;
bool door_did_it = 0;
bool alarm_CO2 = 0;
bool CO2;
bool CO2_did_it = 0;
bool alarm_water = 0;
bool water;
bool water_did_it = 0;
bool alarm_flame = 0;
bool flame;
bool flame_did_it = 0;
int thermo = 0;
int vacation = 0;
int h = 0;
int t = 0;
int UP_LED = V1;
long int last_UP_change = millis();
int ALARM_LED = V11;
bool Alarm_last_reading = 0;
int Relay1_LED = V9;
int Relay2_LED = V9;
void setup_sensors (int node);
void switchofflight();
void checklight();
void checkvacation();
void sendData();
void is_it_vacation();
// setup reset
void(* resetFunc) (void) = 0;//declare reset function at address 0
void setup()
{
MySerial.begin(9600);
MySerial.println(F("setup start"));
EEPROM.get(0, configuration);
pinMode(VacationPin, OUTPUT); //initialize relay as an output
digitalWrite(VacationPin,LOW);
pinMode(DoorPin, INPUT);
pinMode(PirPin, INPUT); // declare PIR sensor as input
pinMode(RelayPin1, OUTPUT); //initialize relay as an output
digitalWrite(RelayPin1,LOW);
pinMode(RelayPin2, OUTPUT); //initialize relay as an output
digitalWrite(RelayPin2,HIGH);
pinMode (FlamePin, INPUT); // output interface defines the flame sensor
// Set ESP8266 baud rate
EspSerial.begin(115200);
delay(10);
Blynk.begin(configuration.auth, wifi, "wireless", "key");
MySerial.println(F("while loop starting"));
while (Blynk.connect() == false) { // Wait until connected
if ((millis() - last_UP_change) > 120000) {
MySerial.println(F("resetting"));
resetFunc();
}
}
if (configuration.this_node != 0) bridge1.setAuthToken(configuration.othauth);
vacation = led21.getValue();
MySerial.print(F("led21: "));
MySerial.println(vacation);
checkvacation ();
switch (configuration.this_node) {
case 0: //Master
UP_LED = V31;
if (vacation) digitalWrite(VacationPin,HIGH);
break;
case 1: //Office
UP_LED = V1;
ALARM_LED = V11;
setup_sensors(1);
break;
case 2: //Bed room
UP_LED = V2;
ALARM_LED = V12;
setup_sensors(2);
break;
case 3: //Living room
UP_LED = V3;
ALARM_LED = V13;
setup_sensors(3);
break;
case 4: //Dining room
UP_LED = V4;
ALARM_LED = V14;
setup_sensors(4);
break;
case 5: //Terasse
UP_LED = V5;
ALARM_LED = V15;
setup_sensors(5);
break;
case 6: //Heating
UP_LED = V6;
ALARM_LED = V16;
setup_sensors(6);
break;
case 7: //Garage
UP_LED = V7;
ALARM_LED = V17;
setup_sensors(7);
break;
case 8: //Laundry room
UP_LED = V8;
ALARM_LED = V18;
setup_sensors(8);
break;
}
Blynk.virtualWrite(UP_LED,0); // turn Up off
Blynk.virtualWrite(ALARM_LED,0); // turn Alarm off
timer.setInterval(2000L, sendData);
timer.setInterval(10000L, is_it_vacation);
}
void loop()
{
Blynk.run();
if ((millis() - last_UP_change) > 120000) {
resetFunc();
}
timer.run(); // Initiates SimpleTimer
}
void setup_sensors (int node) {
MySerial.println(F("Node: "));
MySerial.println(node);
MySerial.println(configuration.auth);
MySerial.println(F("Sensoren: "));
for(int i=0; i<max_nbr_sensors; i++){
MySerial.println(configuration.sensoren[i]);
switch (configuration.sensoren[i]) {
case 0: // no such sensor installed
break;
case 2: //
switch (node) {
case 1:
Relay2_LED = V9;
break;
case 2:
Relay2_LED = V10;
break;
case 3:
Relay2_LED = V19;
break;
case 4:
Relay2_LED = V20;
break;
}
case 4: // DHT11 temp and humidity sensor
dht.begin();
break;
case 8: // Photoresistor
checktimer = timer.setInterval(10000L, checklight);
break;
}
}
}
void sendData()
{
// Please don't send more that 10 values per second.
// Turn runn LED on/off
Blynk.virtualWrite(UP_LED,runn); // turn Up off
runn = !runn;
for(int i=0; i<max_nbr_sensors; i++){ // Read all sensors and take action
switch (configuration.sensoren[i]) {
case 0: // no such sensor installed
break;
case 1: // Pir movement sensor
movement = digitalRead(PirPin);
if (movement && !movement_did_it) {
alarm_movement = 1;
Blynk.notify("Movement in " + String(configuration.room));
movement_did_it = 1;
}
else if (!movement && !vacation) {
alarm_movement = 0;
movement_did_it = 0;
}
break;
case 2: // Light
Blynk.virtualWrite(Relay2_LED, digitalRead(RelayPin2));
break;
case 3: // Door closed switch and vacation switch on Base
door = digitalRead(DoorPin);
if (door && !door_did_it) {
alarm_door = 1;
Blynk.notify("Door open in " + String(configuration.room));
door_did_it = 1;
}
else if (!door && !vacation) {
alarm_door = 0;
door_did_it = 0;
}
break;
case 5: // CO2 sensor
CO2 = analogRead(Co2Sensor);
if (CO2 > 150 && !CO2_did_it) {// Value to be verified
alarm_CO2 = 1;
Blynk.notify("CO2 in " + String(configuration.room));
CO2_did_it = 1;
}
else if (!CO2 && !vacation) {
alarm_CO2 = 0;
CO2_did_it = 0;
}
break;
case 7: // Water or Rain sensor
water = analogRead(WaterSensor);
if (water > 150 && !water_did_it) {// this value to be tested
alarm_water = 1;
Blynk.notify("Water in " + String(configuration.room));
water_did_it = 1;
}
else if (!water && !vacation) {
alarm_water = 0;
water_did_it = 0;
}
break;
case 10: // Flame sensor
flame = analogRead(FlamePin);
if (flame > 150 && !flame_did_it) {// this value to be tested
alarm_flame = 1;
Blynk.notify("Fire in " + String(configuration.room));
flame_did_it = 1;
}
else if (!flame && !vacation) {
alarm_flame = 0;
flame_did_it = 0;
}
break;
}
if (!alarm_movement && !alarm_door && !alarm_CO2 && !alarm_water && !alarm_flame && Alarm_last_reading) {
Blynk.virtualWrite(ALARM_LED, 0);
Alarm_last_reading = 0;
}
else {
if (!Alarm_last_reading && (alarm_movement || alarm_door || alarm_CO2 || alarm_water || alarm_flame)) {
Blynk.virtualWrite(ALARM_LED, 1);
Alarm_last_reading = 1;
}
}
}
}
void is_it_vacation() {
int temp_vacation;
if (configuration.this_node == 0) {
temp_vacation = digitalRead(VacationPin);
}
else {
temp_vacation = led21.getValue();
}
if (vacation != temp_vacation) {
vacation = temp_vacation;
if (configuration.this_node == 0) {
Blynk.virtualWrite(V21, vacation);
}
checkvacation();
}
}
void checkvacation()
{
MySerial.println(F("check vacation"));
if(vacation && !timer.isEnabled(lighttimer)) {
digitalWrite(RelayPin2, LOW); //Switch off everything on that pin
}
if (vacation) digitalWrite(RelayPin1, LOW); //Switch off everything on that pin
else {
digitalWrite(RelayPin2, HIGH); //Switch on everything on that pin
}
MySerial.print(F("Vacation: "));
MySerial.println(vacation);
}
void checklight() {
if (vacation) {
int light = analogRead(LightSensor);
MySerial.print(F("Light: "));
MySerial.println(light);
if ((millis() - didit) > 72000000 && light > 700 && !timer.isEnabled(lighttimer)) { //after 20 hours
randomSeed(analogRead(A2)); // Zufallsgenerator initialisieren
digitalWrite(RelayPin2, HIGH); // turn the LED on (HIGH is the voltage level)
lighttimer = timer.setTimeout((random(120, 300) * 60000), switchofflight); // between 120 to 300 minutes
didit=millis();
}
}
}
void switchofflight() {
digitalWrite(RelayPin2, LOW);
timer.deleteTimer(lighttimer);
}
BLYNK_READ(V0) {
// Read temperature as Celsius
t = dht.readTemperature();
Blynk.virtualWrite(V26, t);
last_UP_change = millis();
}
BLYNK_READ(V22) {
h = dht.readHumidity();
Blynk.virtualWrite(V27, h);
}
BLYNK_READ(V23) {//Garage door open and close
}
BLYNK_READ(V25) {
thermo = thermocouple.readCelsius();
Blynk.virtualWrite(V25, thermo);
}
BLYNK_READ(V26) {
// Read temperature as Celsius
t = dht.readTemperature();
Blynk.virtualWrite(V26, t);
last_UP_change = millis();
}
BLYNK_READ(V27) {
h = dht.readHumidity();
Blynk.virtualWrite(V27, h);
}
BLYNK_READ(V28) {
// Read temperature as Celsius
t = dht.readTemperature();
Blynk.virtualWrite(V28, t);
last_UP_change = millis();
}
BLYNK_READ(V29) {
h = dht.readHumidity();
Blynk.virtualWrite(V29, h);
}
Program to put data to EEPROM
#include <EEPROM.h>
const byte max_nbr_sensors = 6;
struct MyObject {
uint16_t this_node;
char room[9];
byte sensoren[max_nbr_sensors];
char auth[33];
char othauth [33];
};
void setup() {
int eeAddress = 0; //Location we want the data to be put.
/** Put is designed for use with custom structures also. **/
//Data to store: Node id (0 for base), 8 digits for room name, max. 6 sensors (referenced as 1-11),
//32 digits for auth token, 32 digits for bridge (other token)
// In this example node 1 in room office has sensors 1 (PIR sensor), 4 (DHT11 sensor), 2 (Relays) and 8 (Light sensor)
MyObject configuration = {1,"Office. ",1,4,2,8,0,0,"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"};
EEPROM.put(eeAddress, configuration);
}
void loop() {
/* Empty loop */
}