Introduction: HomeKit HomeBridge Siri Enabled Arduino ESP8266 NodeMCU Based PIR Motion Sensor for HomeKit Automation
HomeKit HomeBridge Siri Enabled Arduino ESP8266 NodeMCU Based PIR Motion Sensor for HomeKit Automation
by Galen Wollenberg
Build custom Motion Sensors for home automation via Siri / HomeKit / HomeBridge using NodeMCU/ESP8266/arduino microcontroller, and a HC-SR501 PIR Motion Sensor.
I can put one of each of these in each room, and then use the iOs 'Eve' app to publish automatic HomeKit Automation rules and triggers. I.E.: "if is motion detected in the bedroom, automatically turn on the Bedroom lights".
This can be combined with my CurrentAmbientLighLevel plugin, and the DS18B20 or DHT11/DHT22 plugins (or HttpTemperatureHum plugin) to make a super room sensor for HomeKit / HomeBridge.
Step 1: Install HomeBridge for HomeKit on a Raspberry Pi
Install HomeBridge for HomeKit on a Raspberry Pi
Test that HomeBridge and HomeKit is working on your iPhone.
See: https://github.com/nfarina/homebridge
https://github.com/nfarina/homebridge/wiki/Runnin...
https://github.com/nfarina/homebridge
Ensure these plugin are installed. It may be installed by default in the newer versions:
https://github.com/lucacri/homebridge-http-temper...
https://github.com/lagunacomputer/homebridge-Motio...
sudo npm install -g https://www.npmjs.com/package/homebridge-MotionSensor
Step 2: Parts Needed:
Parts Needed:
1x HomeBridge installed on a Raspberry Pi and working.
1x NodeMCU module
1x HC-SR501 PIR motion sensor
1x DHT11 or DHT22 temp/humidity sensor.
1x 10k ohm Photocell resistor
1x 4.7 k resistor (5k potentiometer used here to adjust light input sensitivity)
1x 2"x1.5" perf board
1x small piece of wire
1x 5v USB charger (i find the iPhone adapters to be the smallest and best)
1x usb cable end with exposed wires
Step 3: Build It
Build it
Pictured above is a sample connection of the motion sensor and a NodeMCU. We want to use a different pin than pictured above (or change the Arduino IDE code). see below.
Pictured above is a few sensors I have made with the addition of a photocell and potientiometer to adjust the light sensor sensitivity. Also pictured is an optional DS18B20 temperature sensor module. See my other Instructables if you are interested in adding the other sensors.
HC-SR501 data pin goes to NodeMCU D4 pin. check the sample Arduino code to make sure it matches the pin used in the code. For the older code, NodeMCU Digital Pin 1, set the Arduino Code to "int pirpin = 5" . This is because the NodeMCU pins map out to different GPIO#'s in reality. Google Images search "nodemcu pinout" to see a chart with the correct PIN to GPIO mappings.
HC-SR501 data pin goes to NodeMCU D4 pin
USB cable +5 & HC-SR501 VCC goes to NodeMCU Vin pin
USB cable -GND & HC-SR501 GND goes to NodeMCU GND
Photocell to A0
Step 4: Edit the HomeBridge /var/homebridge/config.json File on the Raspberry Pi HomeBridge
Edit the HomeBridge /var/homebridge/config.json file on the Raspberry Pi HomeBridge
the file may alternatively be in /home/.homebridge or /root/home/./homebridge.
read the docs from the github link
https://github.com/nfarina/homebridge
Ensure this plugin is installed. It may be installed by default in the newer versions:
https://github.com/lagunacomputer/homebridge-Motio...
https://github.com/nfarina/homebridge https://github.com/lagunacomputer/homebridge-Curr...
Program the NodeMCU using the Arduino IDE.
Upon powering up (5V!) it should be seen on the network.
Try something like http://192.168.1.101/ .
You should get a webpage returned.
Assuming your NodeMCU pulls a DHCP ip of :192.168.1.101 (you should probably set a DHCP reservation on your router, for each ESP8266 you add) add this code to the config.json file.
( sudo nano /var/homebridge/config.json) etc:
{ "bridge": { "name": "HomeBridge", "username": "CC:22:3D:E3:CE:30", "port": 51826, "pin": "031-45-154" }, "description": "", "accessories": [ { "accessory": "Motion", "name": "Motion Sensor", "url": "http://192.168.1.101/?light", "sendimmediately": "", "http_method": "GET" } ] "platforms": [] }
mind the last comma, you may or may not need it if you have other accessories, or Homebridge is crashing on load.
Step 5: Program NodeMCU / ESP8266 / Arduino With Code
Program
*NEW IMPROVED CODE NodeMCU / ESP8266 / Arduino IDE ( faster, lighter, better, stronger):
Use digital Pin d4 for the motion sensor, D6 for DHT, and photocell=A0 with this code:
<p>#include <br>byte mac[] = { 0x5C, 0xCF, 0x7F, 0xC1, 0x1A, 0x33 };</p><p>int photocellPin = 0; // the cell and 10K pulldown are connected to a0 int photocellReading; // the analog reading from the analog resistor divider</p><p>#include #define DHT11Pin D6</p><p>///////////////////////////// //VARS //the time we give the sensor to calibrate (10-60 secs according to the datasheet) int calibrationTime = 30; </p><p>//the time when the sensor outputs a low impulse long unsigned int lowIn; </p><p>//the amount of milliseconds the sensor has to be low //before we assume all motion has stopped long unsigned int pause = 5000; </p><p>boolean lockLow = true; boolean takeLowTime; </p><p>int pirPin = 4; //the digital pin connected to the PIR sensor's output int ledPin = 13;</p><p>#include </p><p>IPAddress ip(192, 168, 1, 147); IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0);</p><p>const char* ssid = "IWILLSTEALYOURMONEY"; const char* password = "namnamnewnew";</p><p>// Create an instance of the server // specify the port to listen on as an argument WiFiServer server(80);</p><p>DHT dht(DHT11Pin, DHT11); unsigned long previousMillis = 0; // will store last temp was read const long interval = 2000; </p><p>///////////////////////////// //SETUP void setup(){ Serial.begin(9600); pinMode(pirPin, INPUT); pinMode(ledPin, OUTPUT); digitalWrite(pirPin, LOW);</p><p>WiFi.begin(ssid, password); //WiFi.config(ip, gateway, subnet); while (WiFi.status() != WL_CONNECTED) { delay(500); //WiFi.begin(ssid, password); //Serial.print("."); } //Serial.println(""); //Serial.println("WiFi connected"); // Start the server server.begin(); //Serial.println("Server started"); Serial.println(""); // Print the IP address Serial.println(WiFi.localIP());</p><p> //give the sensor some time to calibrate Serial.print("calibrating sensor "); for(int i = 0; i < calibrationTime; i++){ Serial.print("."); delay(1000); } Serial.println(" done"); Serial.println("SENSOR ACTIVE"); delay(50);</p><p> } </p><p> // get humidity float humidity = dht.readHumidity(); // get temperature as C float celsius = dht.readTemperature(); // get temperature as F float fahrenheit = dht.readTemperature(true);</p><p>// prepare a web page to be send to a client (web browser) String prepareHtmlPage() { //gettemperature(); String htmlPage = String("HTTP/1.1 200 OK\r\n") + "Content-Type: application/json;charset=utf-8\r\n" + "Connection: close\r\n" + // the connection will be closed after completion of the response "Refresh: 5\r\n" + // refresh the page automatically every 5 sec "\r\n" + //"" + //" " + "{" + "\"lightval\":" + String(analogRead(A0)) + "," + "\"pirval\":" + String(digitalRead(D4)) + "," + "\"temperature\":" + float(dht.readTemperature()) + "," + "\"fahrenheit\":" + float(dht.readTemperature(true)) + "," + "\"humidity\":" + float(dht.readHumidity()) + "}" + //"</p><p>" + "\r\n"; return htmlPage; }</p><p>//////////////////////////// //LOOP void loop(){</p><p>readPhotocell();</p><p>//delay(10000); // get humidity float humidity = dht.readHumidity(); // get temperature as C float celsius = dht.readTemperature(); // get temperature as F float fahrenheit = dht.readTemperature(true); // print results Serial.print("Humidity: "); Serial.print(humidity); Serial.print(" Celsius: "); Serial.print(celsius); Serial.print(" Fahrenheit: "); Serial.println(fahrenheit);</p><p> if(digitalRead(pirPin) == HIGH){ digitalWrite(ledPin, HIGH); //the led visualizes the sensors output pin state if(lockLow){ //makes sure we wait for a transition to LOW before any further output is made: lockLow = false; Serial.println("---"); Serial.print("motion detected at "); Serial.print(millis()/1000); Serial.println(" sec"); delay(50); } takeLowTime = true; } ////high</p><p> if(digitalRead(pirPin) == LOW){ digitalWrite(ledPin, LOW); //the led visualizes the sensors output pin state</p><p> if(takeLowTime){ lowIn = millis(); //save the time of the transition from high to LOW takeLowTime = false; //make sure this is only done at the start of a LOW phase } //if the sensor is low for more than the given pause, //we assume that no more motion is going to happen if(!lockLow && millis() - lowIn > pause){ //makes sure this block of code is only executed again after //a new motion sequence has been detected lockLow = true; Serial.print("motion ended at "); //output Serial.print((millis() - pause)/1000); Serial.println(" sec"); delay(50); } } //low</p><p> WiFiClient client = server.available(); // wait for a client (web browser) to connect if (client) { Serial.println("\n[Client connected]"); while (client.connected()) { // read line by line what the client (web browser) is requesting if (client.available()) { String line = client.readStringUntil('\r'); Serial.print(line); // wait for end of client's request, that is marked with an empty line if (line.length() == 1 && line[0] == '\n') { client.println(prepareHtmlPage()); break; } } } delay(1); // give the web browser time to receive the data</p><p> // close the connection: client.stop(); Serial.println("[Client disonnected]"); }</p><p> } //loop</p><p>void readPhotocell(){</p><p>photocellReading = analogRead(photocellPin); Serial.print(WiFi.localIP()); Serial.print(" Analog reading = "); Serial.print(photocellReading); // the raw analog reading</p><p> // We'll have a few threshholds, qualitatively determined if (photocellReading < 10) { Serial.println(" - Dark"); } else if (photocellReading < 200) { Serial.println(" - Dim"); } else if (photocellReading < 500) { Serial.println(" - Light"); } else if (photocellReading < 800) { Serial.println(" - Bright"); } else { Serial.println(" - Very bright"); } }</p><p>/* void gettemperature() { // Wait at least 2 seconds seconds between measurements. // if the difference between the current time and last time you read // the sensor is bigger than the interval you set, read the sensor // Works better than delay for things happening elsewhere also unsigned long currentMillis = millis(); if(currentMillis - previousMillis >= interval) { // save the last time you read the sensor previousMillis = currentMillis; // Reading temperature for humidity takes about 250 milliseconds! // Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor) humidity = dht.readHumidity(); // Read humidity (percent) celsius = dht.readTemperature(); // Read temperature as Fahrenheit fahrenheit = dht.readTemperature(true); // Read temperature as Fahrenheit // Check if any reads failed and exit early (to try again). if (isnan(humidity) || isnan(fahrenheit)) { Serial.println("Failed to read from DHT sensor!"); return; } } }</p><p>*/</p><br>
NodeMCU / ESP8266 / Arduino IDE Code version:
<p>#include <br>//#include </p><p>//byte mac[] = { 0x5C, 0xCF, 0x7F, 0x24, 0x84, 0x3D }; //physical mac address //byte mac[] = { 0x5C, 0xCF, 0x7F, 0x24, 0x84, 0x3D }; //physical mac address byte mac[] = { 0x5C, 0xCF, 0x7F, 0x24, 0x66, 0x69 }; //physical mac address //byte ip[] = { 192, 168, 1, 133 }; // ip in lan //byte gateway[] = { 192, 168, 1, 1 }; // internet access via router //byte subnet[] = { 255, 255, 255, 0 }; //subnet mask //EthernetServer server(80); //server port</p><p>String readString; </p><p>#include #include </p><p>/*-----( Declare Constants )-----*/ #define ONE_WIRE_BUS D4 /*-(Connect to Pin 2 )-*</p><p>*-----( Declare objects )-----*/ /* Set up a oneWire instance to communicate with any OneWire device*/ OneWire ourWire(ONE_WIRE_BUS);</p><p>/* Tell Dallas Temperature Library to use oneWire Library */ DallasTemperature sensors(&ourWire);</p><p>/*-----( Declare Variables )-----*</p><p>/////////////////////</p><p>int photocellPin = 0; // the cell and 10K pulldown are connected to a0 int photocellReading; // the analog reading from the analog resistor divider</p><p>boolean pirReading = false; //the time we give the sensor to calibrate (10-60 secs according to the datasheet) int calibrationTime = 30;</p><p>//the time when the sensor outputs a low impulse long unsigned int lowIn;</p><p>//the amount of milliseconds the sensor has to be low //before we assume all motion has stopped long unsigned int pause = 5000;</p><p>boolean lockLow = true; boolean takeLowTime; int pirPin = 4; //the digital pin connected to the PIR sensor's output</p><p>#include </p><p>IPAddress ip(192, 168, 1, 133); IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0);</p><p>const char* ssid = "IWILLSTEALYOURMONEY"; const char* password = "namnamnewnew";</p><p>// Create an instance of the server // specify the port to listen on as an argument WiFiServer server(80);</p><p>#include dht DHT; #define DHT11_PIN D6</p><p>void setup(){ Serial.begin(115200); pinMode(5, OUTPUT); //pin selected to control //start Ethernet //Ethernet.begin(mac, ip, gateway, gateway, subnet);</p><p>WiFi.begin(ssid, password); //WiFi.config(ip, gateway, subnet); while (WiFi.status() != WL_CONNECTED) { delay(500); //WiFi.begin(ssid, password); //Serial.print("."); } //Serial.println(""); //Serial.println("WiFi connected"); // Start the server server.begin(); //Serial.println("Server started");</p><p> // Print the IP address Serial.println(WiFi.localIP());</p><p> //server.begin(); //enable serial data print //Serial.begin(9600); </p><p>sensors.begin();</p><p> pinMode(pirPin, INPUT); ///PIR digitalWrite(pirPin, LOW); //give the sensor some time to calibrate Serial.print("calibrating sensor "); for(int i = 0; i < calibrationTime; i++){ Serial.print("."); delay(1000); } Serial.println(" done"); Serial.println("SENSOR ACTIVE"); delay(50); }</p><p>void loop(){ readPIR(); readPhotocell(); //int chk = DHT.read11(DHT11_PIN); //Serial.print(DHT.humidity);</p><p>float temperatureIndoor; float temperatureOutdoor; float humidity; sensors.requestTemperatures(); // Send the command to get temperatures temperatureIndoor = (sensors.getTempCByIndex(0)); delay(100); // Create a client connection //EthernetClient client = server.available(); WiFiClient client = server.available(); if (client) { while (client.connected()) { if (client.available()) { char c = client.read();</p><p> //read char by char HTTP request if (readString.length() < 100) {</p><p> //store characters to string readString += c; //Serial.print(c); } </p><p> //if HTTP request has ended if (c == '\n') {</p><p> /////////////// </p><p> /////original code for dht client.println("HTTP/1.1 200 OK"); client.println("Content-Type: application/json;charset=utf-8"); client.println("Server: Arduino"); client.println("Connnection: close"); client.println(); //sensors.requestTemperatures(); // Send the command to get temperatures //temperatureIndoor = (sensors.getTempCByIndex(0)); //temperatureOutdoor = (sensors.getTempFByIndex(0)); //Serial.print(sensors.getTempCByIndex(0));</p><p> humidity = (DHT.humidity); client.print("{"); client.print("\"temperature\":"); client.print(temperatureIndoor); client.print(","); client.print("\"humidity\":"); client.print(humidity); //client.print("}"); //client.println(); client.print(","); //client.print("{"); client.print("\"lightval\":"); client.print(photocellReading); client.print("}"); client.println(); original code for dht */</p><p> client.println("HTTP/1.1 200 OK"); client.println("Content-Type: application/json;charset=utf-8"); client.println("Server: Arduino"); client.println("Connnection: close"); client.println(); sensors.requestTemperatures(); // Send the command to get temperatures temperatureIndoor = (sensors.getTempCByIndex(0)); //temperatureOutdoor = (sensors.getTempFByIndex(0)); client.print("{"); client.print("\"temperature\":"); client.print(temperatureIndoor); client.print(","); //client.print("\"humidity\":"); //client.print(temperatureOutdoor); //client.print("}"); //client.println(); //client.print(","); //client.print("{"); client.print("\"lightval\":"); client.print(photocellReading); client.print(","); client.print("\"pirval\":"); client.print(pirReading); //client.print("True");</p><p> client.print("}"); client.println();</p><p> //stopping client client.stop();</p><p> ///////////////////// control arduino pin if(readString.indexOf("?on") >0)//checks for on { Serial.println(readString.indexOf("on")); digitalWrite(5, HIGH); // set pin 5 high Serial.println("Led On");</p><p> } if(readString.indexOf("?off") >0)//checks for off { Serial.println(readString.indexOf("off")); digitalWrite(5, LOW); // set pin 5 low Serial.println("Led Off"); } if(readString.indexOf("?temp") >0)//checks for off { Serial.println(readString.indexOf("temp"));</p><p> temperatureIndoor = (sensors.getTempCByIndex(0)); //digitalWrite(5, LOW); // set pin 5 low Serial.println("temp sent"); } if(readString.indexOf("?light") >0)//checks for off { Serial.println(readString.indexOf("light"));</p><p> //digitalWrite(5, LOW); // set pin 5 low Serial.println("light sent"); }</p><p> //clearing string for next read readString="";</p><p>//sensors.requestTemperatures(); // Send the command to get temperatures //Serial.print("Device 1 (index 0) = "); //Serial.print(sensors.getTempFByIndex(0)); //Serial.println(" Degrees F");</p><p> } ///c=n } //client available } //client connected } //if client } //loop</p><p>void readPhotocell(){</p><p>photocellReading = analogRead(photocellPin); Serial.print(WiFi.localIP()); Serial.print(" Analog reading = "); Serial.print(photocellReading); // the raw analog reading</p><p> // We'll have a few threshholds, qualitatively determined if (photocellReading < 10) { Serial.println(" - Dark"); } else if (photocellReading < 200) { Serial.println(" - Dim"); } else if (photocellReading < 500) { Serial.println(" - Light"); } else if (photocellReading < 800) { Serial.println(" - Bright"); } else { Serial.println(" - Very bright"); } }</p><p>void readPIR(){ Serial.println(pirReading); // the raw analog reading if (digitalRead(pirPin) == HIGH) { //digitalWrite(ledPin, HIGH); //the led visualizes the sensors output pin state if (lockLow) { //makes sure we wait for a transition to LOW before any further output is made: lockLow = false; Serial.println("---"); Serial.print("motion detected at "); Serial.print(millis() / 1000); Serial.println(" sec"); delay(50); } takeLowTime = true; pirReading = true; //alarmTriggered(); }</p><p> if (digitalRead(pirPin) == LOW) { //digitalWrite(ledPin, LOW); //the led visualizes the sensors output pin state pirReading = false; if (takeLowTime) { lowIn = millis(); //save the time of the transition from high to LOW takeLowTime = false; //make sure this is only done at the start of a LOW phase } //if the sensor is low for more than the given pause, //we assume that no more motion is going to happen if (!lockLow && millis() - lowIn > pause) { //makes sure this block of code is only executed again after //a new motion sequence has been detected lockLow = true; Serial.print("motion ended at "); //output Serial.print((millis() - pause) / 1000); Serial.println(" sec"); delay(50); } }</p><p>}</p> <br>
Arduino Mega with Ethernet Shield Code version:
<p>#include <br>//#include </p><p>//byte mac[] = { 0x5C, 0xCF, 0x7F, 0x24, 0x84, 0x3D }; //physical mac address byte mac[] = { 0x5C, 0xCF, 0x7F, 0x24, 0x66, 0x69 }; //physical mac address //byte ip[] = { 192, 168, 1, 101 }; // ip in lan //byte gateway[] = { 192, 168, 1, 1 }; // internet access via router //byte subnet[] = { 255, 255, 255, 0 }; //subnet mask //EthernetServer server(80); //server port</p><p>String readString; </p><p>#include #include </p><p>/*-----( Declare Constants )-----*/ #define ONE_WIRE_BUS D4 /*-(Connect to Pin 2 )-*</p><p>*-----( Declare objects )-----*/ /* Set up a oneWire instance to communicate with any OneWire device*/ OneWire ourWire(ONE_WIRE_BUS);</p><p>/* Tell Dallas Temperature Library to use oneWire Library */ DallasTemperature sensors(&ourWire);</p><p>/*-----( Declare Variables )-----*</p><p>/////////////////////</p><p>int photocellPin = 0; // the cell and 10K pulldown are connected to a0 int photocellReading; // the analog reading from the analog resistor divider</p><p>#include </p><p>IPAddress ip(192, 168, 1, 101); IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0);</p><p>const char* ssid = "IWILLSTEALYOURMONEY"; const char* password = "namnamnewnew";</p><p>// Create an instance of the server // specify the port to listen on as an argument WiFiServer server(80);</p><p>#include dht DHT; #define DHT11_PIN D6</p><p>void setup(){ Serial.begin(115200); pinMode(5, OUTPUT); //pin selected to control //start Ethernet //Ethernet.begin(mac, ip, gateway, gateway, subnet);</p><p>WiFi.begin(ssid, password); //WiFi.config(ip, gateway, subnet); while (WiFi.status() != WL_CONNECTED) { delay(500); //WiFi.begin(ssid, password); //Serial.print("."); } //Serial.println(""); //Serial.println("WiFi connected"); // Start the server server.begin(); //Serial.println("Server started");</p><p> // Print the IP address Serial.println(WiFi.localIP());</p><p> //server.begin(); //enable serial data print //Serial.begin(9600); </p><p>sensors.begin();</p><p> }</p><p>void loop(){</p><p>readPhotocell(); //int chk = DHT.read11(DHT11_PIN); //Serial.print(DHT.humidity);</p><p>float temperatureIndoor; float temperatureOutdoor; float humidity; sensors.requestTemperatures(); // Send the command to get temperatures temperatureIndoor = (sensors.getTempCByIndex(0)); delay(100); // Create a client connection //EthernetClient client = server.available(); WiFiClient client = server.available(); if (client) { while (client.connected()) { if (client.available()) { char c = client.read();</p><p> //read char by char HTTP request if (readString.length() < 100) {</p><p> //store characters to string readString += c; //Serial.print(c); } </p><p> //if HTTP request has ended if (c == '\n') {</p><p> /////////////// </p><p> client.println("HTTP/1.1 200 OK"); client.println("Content-Type: application/json;charset=utf-8"); client.println("Server: Arduino"); client.println("Connnection: close"); client.println(); //sensors.requestTemperatures(); // Send the command to get temperatures //temperatureIndoor = (sensors.getTempCByIndex(0)); //temperatureOutdoor = (sensors.getTempFByIndex(0)); //Serial.print(sensors.getTempCByIndex(0));</p><p> humidity = (DHT.humidity); client.print("{"); client.print("\"temperature\":"); client.print(temperatureIndoor); client.print(","); client.print("\"humidity\":"); client.print(humidity); //client.print("}"); //client.println(); client.print(","); //client.print("{"); client.print("\"lightval\":"); client.print(photocellReading); client.print("}"); client.println();</p><p> //stopping client client.stop();</p><p> ///////////////////// control arduino pin if(readString.indexOf("?on") >0)//checks for on { Serial.println(readString.indexOf("on")); digitalWrite(5, HIGH); // set pin 5 high Serial.println("Led On");</p><p> } if(readString.indexOf("?off") >0)//checks for off { Serial.println(readString.indexOf("off")); digitalWrite(5, LOW); // set pin 5 low Serial.println("Led Off"); } if(readString.indexOf("?temp") >0)//checks for off { Serial.println(readString.indexOf("temp"));</p><p> temperatureIndoor = (sensors.getTempCByIndex(0)); //digitalWrite(5, LOW); // set pin 5 low Serial.println("temp sent"); } if(readString.indexOf("?light") >0)//checks for off { Serial.println(readString.indexOf("light"));</p><p> //digitalWrite(5, LOW); // set pin 5 low Serial.println("light sent"); }</p><p> //clearing string for next read readString="";</p><p>//sensors.requestTemperatures(); // Send the command to get temperatures //Serial.print("Device 1 (index 0) = "); //Serial.print(sensors.getTempFByIndex(0)); //Serial.println(" Degrees F");</p><p> } ///c=n } //client available } //client connected } //if client } //loop</p><p>void readPhotocell(){</p><p>photocellReading = analogRead(photocellPin); Serial.print(WiFi.localIP()); Serial.print(" Analog reading = "); Serial.print(photocellReading); // the raw analog reading</p><p> // We'll have a few threshholds, qualitatively determined if (photocellReading < 10) { Serial.println(" - Dark"); } else if (photocellReading < 200) { Serial.println(" - Dim"); } else if (photocellReading < 500) { Serial.println(" - Light"); } else if (photocellReading < 800) { Serial.println(" - Bright"); } else { Serial.println(" - Very bright"); } }</p><br>
ok
Step 6: Test the New Accessory in IOS HomeKit App
Test the new Accessory in iOS HomeKit App
Test the new Accessory in iOS HomeKit App and Siri
Check out my Light Sensor plugin for HomeBridge / HomeKit !
Step 7: Create HomeKit Automation Rules and Triggers Within the IOS 'Eve' App From the App Store.
Create HomeKit Automation Rules and Triggers within the iOS 'Eve' app from the App Store.
You could create a Scene that uses the Motion Detected Trigger to turn on the Living Room Lamp.
Using the Triggers feature in the Eve iOS App (i assume you can do the same with an Apple TV4)
Step 8: Optional - Basic 3D Printable Box
Optional - Basic 3D Printable Box

Participated in the
IoT Builders Contest

Participated in the
Circuits Contest 2016
35 Comments
Question 3 years ago
Hey,
First of all I would like to say thank you for this instruction.
I tried to make it too and after evenings of struggling with the Arduino IDE I finally got it working except for one crucial part:
HomeKit integration
I m able to send GET requests via http in a browser and I m receiving responds too.
But in Apple's Home app the device shows a refresh state for about 3 seconds and then it goes to the 'not answering' state.
I also increased the sensor timeout by editing the index.js of the Homebridge plugin MotionSensor but that did not helped. Do you have any idea what could be the reason?
The sensor and the WiFi connectivity is working (tested both separately with a simple
Sketch).
Reply 3 years ago
rob, my original code was 'updated' by some others and it may have broke it. Go check out the newer (actually older) arduino code i posted a few days ago https://github.com/lagunacomputer/homebridge-MotionSensor
Reply 3 years ago
Thanks for your reply.
A few days ago I decided to switch to MQTT and the diy motion sensor works now like a charm.
Also it was difficult to find the correct settings on the HC-SR501 (jumper on L-position, delay, sensitivity).
However Your instruction was a good inspiration for me to get into the topic ESP8266.
I already have made a diy temperature and humidity sensor based on a Genuino101. In comparison I will stay at ESP8266 because it’s much cheaper and it connects via WiFi.
Reply 3 years ago
Please post or reply with a link to your improved MQTT code, thanks sir
Reply 3 years ago
this is the homebridge plugin i m using:
https://www.npmjs.com/package/homebridge-mqtt-moti...
don't forget to customize the char values.
also it is very important to use the correct board settings in the Arduino IDE:
NodeMCU 1.0, 115200, 80Mhz, Flash, Disabled, 4M, v2 Lower Memory, Disabled, None, Only Sketch and the correct serial port of course.
char* ssid = "Auenland"; //Wi-Fi AP Name
char* password = "xxxxxxxx"; //Wi-Fi Password
char* mqtt_server = "192.168.2.102"; //MQTT Server IP
char* mqtt_name = "Wohnzimmer Bewegungssensor"; //MQTT device name
char* mqtt_topic = "home/livingroom/sensors/motion"; //MQTT topic for communication
int pirPin = 13; //set the GPIO which you will connect the PIR sensor
bool lowPower = false; //set to true if you want low power use
int delayTime = 2000; //ONLY FOR LOW POWER - how long motion detected should be active
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <PubSubClient.h>
WiFiClient mainESP;
PubSubClient MQTT(mainESP);
char* mqtt_maintopic = mqtt_topic;
void setup() {
pinMode(pirPin, INPUT_PULLUP);
Serial.begin(115200);
}
void loop() {
if (!lowPower && WiFi.status() != WL_CONNECTED) startWiFi();
Serial.println(digitalRead(pirPin));
if ((digitalRead(pirPin)) == 0) delay(250);
else {
if (WiFi.status() != WL_CONNECTED) startWiFi();
MQTT.loop();
if (!MQTT.connected()) reconnect();
MQTT.publish(mqtt_topic, "1");
Serial.println("Message Published: TRUE");
while (digitalRead(pirPin) == 1) {
if (!MQTT.connected()) reconnect();
MQTT.publish(mqtt_topic, "1");
Serial.println("Message Published: TRUE");
delay(5000);
}
if (!MQTT.connected()) reconnect();
if (lowPower) delay(delayTime);
MQTT.publish(mqtt_topic, "0");
Serial.println("Message Published: FALSE");
MQTT.loop();
delay(5000);
}
if (lowPower) {
WiFi.disconnect();
WiFi.mode(WIFI_OFF);
WiFi.forceSleepBegin();
delay(1);
}
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
void reconnect() {
while (!MQTT.connected()) {
Serial.print("Attempting MQTT connection...");
if (MQTT.connect(mqtt_name)) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(MQTT.state());
Serial.println(" try again in 5 seconds");
for (int i = 0; i < 5000; i++) {
delay(1);
}
}
}
}
void startWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(1000);
ESP.restart();
}
WiFi.hostname(mqtt_name);
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
MQTT.setServer(mqtt_server, 1883);
MQTT.setCallback(callback);
}
Reply 2 years ago
Thank you Rob, your code works excellent. I've just installed Mosquitto to my RPi and it started working right away.
Question 2 years ago
Hello!
I have errors with the code.
My esp8266 is sending de Pir data to the http web server but it was impossible to communicate the homebridge with the server, any idea?
What do I have to write on the config.json on url?
The output says: method GET, timeout 3000
HTTP bad responde ("myipadress"): read ENCONNRESET
Thanks a lot.
3 years ago
Im wondering the same thing.. I have Homekit Apple TV, Hue lights etc.. do i need Raspberry Pi or not to get this to work?
Reply 3 years ago
At least a running instance of Homebridge. That can run as service an a Raspberry but also an a always on MacMini f.e.
4 years ago
Hello. That link for temperature sensor plugin is dead as well that one :
https://github.com/lagunacomputer/homebridge-Curre...
Please update - wanted to start project but don't know which one plugin is suitable for ur ESP code.
Cheers. Nice project. Looking as well for code for CarbonOxide sensor - just for detecting signal on GPIO from sensor. And proper display in Homekit App.
Reply 4 years ago
Sensors are working well when i connect. I use dht11 and for light sensor i used more accurate photodiode from sparkFun.
https://www.sparkfun.com/products/8688
working very good and i getting proper readings on com port log.
when i connect DHT it working well ( before i connected but forgot about pullup resistor and had readings only 10-15 seconds but after put in pullup 4.7kohm
everything working well) except motion. I getting motion detected and motion ended in com log but something is wrong in connection to homebridge.
Ill connect everything tommorow and check it out again.
Let u know the results.
Thx for help :)
Regards
Reply 4 years ago
The HomeBridge install version has likely changed/updated by now, you may want to try an older version.
Reply 4 years ago
try https://github.com/lagunacomputer/
4 years ago
Hello.
I don't know why there is so big difference - when i compiled code with selected board Wemos D1 i had many errors as below and when selected generic 8266 i stil have errors but much less. But still can not compile.
Arduino Log:
WARNING: Category '' in library OneWire is not valid. Setting to 'Uncategorized'
Build options changed, rebuilding all
MotionSensor:28: error: 'D4' was not declared in this scope
#define ONE_WIRE_BUS D4 /*-(Connect to Pin 2 )-*/
^
/Users/jerry/Documents/Arduino/MotionSensor/MotionSensor.ino:32:17: note: in expansion of macro 'ONE_WIRE_BUS'
OneWire ourWire(ONE_WIRE_BUS);
^
MotionSensor:19: error: 'D6' was not declared in this scope
#define DHT11Pin D6
^
/Users/jerry/Documents/Arduino/MotionSensor/MotionSensor.ino:85:9: note: in expansion of macro 'DHT11Pin'
DHT dht(DHT11Pin, DHT11);
^
Multiple libraries were found for "OneWire.h"
Used: /Users/jerry/Documents/Arduino/libraries/OneWire
Not used: /Users/jerry/Documents/Arduino/libraries/DallasTemperature
exit status 1
'D4' was not declared in this scope
Reply 4 years ago
try fixing this:
Multiple libraries were found for "OneWire.h"
Used: /Users/jerry/Documents/Arduino/libraries/OneWire
Not used: /Users/jerry/Documents/Arduino/libraries/DallasTemperature
Reply 4 years ago
Thanks for help.
I succesfully solved problem with libraries which was differtent each other - i dont know why. With one of these i compiled succesfully.
Now another problem:
i ve put in my config these lines:
{
"accessory": "Motion",
"name": "Motion Sensor",
"url": "http://192.168.1.101/?light",
"sendimmediately": "",
"http_method": "GET"
}
the result in my homebridhe log:
[Test Motion Sensor] Requesting motion on "http://192.168.0.30/?light", method GET, timeout 3000
[2018-2-18 17:47:05] [Test Motion Sensor] HTTP successful response: {"lightval":8,"pirval":0,"temperature":nan,"fahrenheit":nan,"humidity":nan}
[2018-2-18 17:47:05] [Test Motion Sensor] Received value is not valid. Returning "false"
[2018-2-18 17:52:02] [Test Motion Sensor] Requesting motion on "http://192.168.0.30/?light", method GET, timeout 3000
[2018-2-18 17:52:03] [Test Motion Sensor] HTTP successful response: {"lightval":14,"pirval":0,"temperature":nan,"fahrenheit":nan,"humidity":nan}
[2018-2-18 17:52:03] [Test Motion Sensor] Received value is not valid. Returning "false
I dont have currently connected any sensors ( i had for few minutes but it changed nothing ).
I have only wire which i do short to vcc. It looks that it works good in hardwarte side. Led is responsing to sensor state and even in log the 'value "pirval" getting "0" when motion is detected and "1" when doesn't.
On iphone see sensor icon but never was activated.
I think over :
"url": "http://192.168.0.30/?light"
why "?light" - in similar plugin example is:
"url": "http://192.168.1.220/motionEndpoint?json=true"
or
"url": "http://192.168.1.210/motionEndpoint",
i know that its depend plugin requirement.
Anyway homebridge for some reason doesn't see motion activity.
Where is the problem???
Regards! Good job anyway!
Reply 4 years ago
I would start a new basic sketch and make sure you can get your DHT11 or DHT22 sensor working first.
'nan' means you are not getting a sensor value from the sensor yet.
Start with a basic sketch that reads the DHT value only correctly first, then port it over to your homebridge code.
https://playground.arduino.cc/Main/DHT11Lib
http://www.circuitbasics.com/how-to-set-up-the-dht...
http://howtomechatronics.com/tutorials/arduino/dht...
4 years ago
Hello. Arduino compiler showing many errors during compilation so compilation is impossible .
Maybe the reason for that is some new library versions. Anyway i cannot overcome that. All needed libraries installed. What library versions did u use for build that project?
Log window look like:
WARNING: Category '' in library OneWire is not valid. Setting to 'Uncategorized'
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::depower()':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:163: multiple definition of `OneWire::reset()'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:143: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::search(unsigned char*, bool)':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:197: multiple definition of `OneWire::write_bit(unsigned char)'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:177: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::read_bit()':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:225: multiple definition of `OneWire::read_bit()'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:205: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::write(unsigned char, unsigned char)':
Multiple libraries were found for "OneWire.h"
Used: /Users/jerry/Documents/Arduino/libraries/OneWire
Not used: /Users/jerry/Documents/Arduino/libraries/DallasTemperature
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:249: multiple definition of `OneWire::write(unsigned char, unsigned char)'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:229: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::write_bytes(unsigned char const*, unsigned short, bool)':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:263: multiple definition of `OneWire::write_bytes(unsigned char const*, unsigned short, bool)'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:243: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::read()':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:277: multiple definition of `OneWire::read()'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:257: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::read_bytes(unsigned char*, unsigned short)':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:287: multiple definition of `OneWire::read_bytes(unsigned char*, unsigned short)'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:267: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::select(unsigned char const*)':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:296: multiple definition of `OneWire::select(unsigned char const*)'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:276: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::skip()':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:308: multiple definition of `OneWire::skip()'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:288: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::depower()':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:314: multiple definition of `OneWire::depower()'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:293: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::reset_search()':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:328: multiple definition of `OneWire::reset_search()'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:308: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::OneWire(unsigned char)':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:145: multiple definition of `OneWire::OneWire(unsigned char)'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:125: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::OneWire(unsigned char)':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:145: multiple definition of `OneWire::OneWire(unsigned char)'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:125: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::target_search(unsigned char)':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:343: multiple definition of `OneWire::target_search(unsigned char)'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:323: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::crc8(unsigned char const*, unsigned char)':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:526: multiple definition of `OneWire::crc8(unsigned char const*, unsigned char)'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:502: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::crc16(unsigned char const*, unsigned short, unsigned short)':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:568: multiple definition of `OneWire::crc16(unsigned char const*, unsigned short, unsigned short)'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:540: first defined here
libraries/DallasTemperature/OneWire.cpp.o: In function `OneWire::check_crc16(unsigned char const*, unsigned short, unsigned char const*, unsigned short)':
/Users/jerry/Documents/Arduino/libraries/DallasTemperature/OneWire.cpp:562: multiple definition of `OneWire::check_crc16(unsigned char const*, unsigned short, unsigned char const*, unsigned short)'
libraries/OneWire/OneWire.cpp.o:/Users/jerry/Documents/Arduino/libraries/OneWire/OneWire.cpp:534: first defined here
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board WeMos D1 R2 & mini.
4 years ago
Hi there!
Thanks for this nice instructable.
I was looking for a solution to connect a WeMos D1 mini with a HC-SR501 PIR motion sensor to a Raspberry Pi 3 running Homebridge.
So, actually pretty much what the title of this instructable says, but all the plugins and programs include temperature and light sensors related code. The required hardware also includes a temperature sensor and a photocell resistor. (confusing, as your previous instructable was about those sensors)
I just need the motion sensor in Homebridge/Home-Kit and don't want to hook up additional sensors to the Arduino or install any unrelated plugins in Homebridge.
How would the plugin, program and homebridge config look like just for a motion sensor setup?
Could you please provide examples/sample code for the PIR motion sensor only?
Thanks again,
Dan
Reply 4 years ago
Dan, I'm pretty sure you can just ignore the temp and light sensor parts, code and hardware. It will just return 0 for values for those. Then can have the Arduino/ESP8266 code just call out for shorter http get request, i.e. Just one ?motion= In the get request . I will check the code in a few hours and see if I can send you a stripped down version. So basically chop the Arduino code to only make one request, and forget about installing the other plugins.