Wednesday, 29 November 2017

Motion Detector using a PhotoResistor and Arduino

I recently brought two "WeMos D1 WiFi Uno ESP8266 ESP-12E Development Board" hoping to get my first connectivity of two arduino systems via wifi.

Getting the WeMos D1's working

The first task is to set up the arduinos. I could write out how in full, but there's no point in reinventing the wheel, especially when the instructables website does such a good job here:

Once we have this setup its important to understand how we get that connectivity to the internet, what code we need and what the errors and status codes we might see in order to handle them in the code. The best link I have found, or the simplest for Connecting Arduino to Wifi (including status codes) is the one below.

However, the easiest way to get something working straight away is to use: http://www.esp8266learning.com/wemos-webserver-example.php all that is needed is to set your wifi name and password, upload to your Arduino and your done. Follow the IP address that is printed on the serial monitor and you'll have a webpage where you can turn on and off the light of the arduino. 

Try it with any webpage viewable device connected to the same network and voila!

Do this with both Arduino's. One of the Arduino's will be used as a web server and the other will be used to send the sensor information to switch the light on, on the web server in order to "Alert" someone watching the server Arduino that someone has passed the sensor that could be in another room.

Setting up a sensor to output analog (Alert Arduino)

For this we will need;
 - 1 PhotoResistor
 - 3 Male to Male Jumper Cable
 - 1 Resistor
 - 1 Breadboard

We plug the PhotoResistor into the breadboard on one of the centre areas, one leg will be connected to a positive 5V charge from the Arduino. The other will have a resistor across it into a new line and also a male to male jumper cable into one of the analog pins. The final piece is to connect the other end of the resistor to GND (ground).
The sensor will be pointing off the table towards where you want to monitor
We need to add the variable for the photoResistor. 

Before the Setup Code we add:
int sensorPin = A0;    // select the input pin for the potentiometer
int sensorValue = 0;  // variable to store the value coming from the sensor
Within the loop:
sensorValue = analogRead(sensorPin);
Serial.println(sensorValue);

The information for this was taken from here: https://www.arduino.cc/en/Tutorial/AnalogInput
Once this runs we will start to see the unhindered sensor reading. In my case, this was around 355 - 380 and when covered by hand close and far the readings varied from 150 - 350. 

We can then add some code to the loop to turn the light on/off depending on the value returned by the sensor.
   if(sensorValue > 350){
      //turn light off
   }else{
      //turn light on
   }

Waiting for the Alert (Server Arduino)

We need to add the listener to turn on the light when the sensor is triggered.

In the "match request" section underneath the /LED we need to setup actions when the sensors alert.
  if (request.indexOf("/sensor=ON") != -1){
    digitalWrite(ledPin, HIGH);
    value = LOW;
  }
  if (request.indexOf("/sensor=OFF") != -1){
    digitalWrite(ledPin, LOW);
    value = LOW;
  }
Upload.

To test we can go to 
IPAddress:/sensor=ON
and then
 IPAddress:/sensor=OFF
on a network connected device. We should see the server Arduino's light turn on and then off. 

Posting an Alert when the sensor is triggered (Alert Arduino)

After a little google, the best Arduino POST example I could find using the examples we have was the answer by "stiff" on the following stack overflow question: https://stackoverflow.com/questions/3677400/making-a-http-post-request-using-arduino

Where we need to add;
   #include <ESP8266HTTPClient.h> 
   //inside the loop
   HTTPClient http;    //Declare object of class HTTPClient
   http.begin("http://IPAddress/sensor=OFF");      //Specify request destination
   http.addHeader("Content-Type", "text/plain");  //Specify content-type header
   int httpCode = http.POST("Message from ESP8266");   //Send the request
   String payload = http.getString();                  //Get the response payload

   Serial.println(httpCode);   //Print HTTP return code
   Serial.println(payload);    //Print request response payload
   http.end();  //Close connection
We can then use the:
 http.begin("http://IPAddress/sensor=ON");
with the sensorValue IF statement we made earlier.
if(sensorValue > 350){
   http.begin("http://IPAddress/sensor=OFF");      //Specify request destination
 }else{
   http.begin("http://IPAddress/sensor=ON");
  }
We have now completed the minimum viable product. I will share the full source code below as well as a video of the result. If you have any questions or would like the source code directly feel free to comment!
*UPDATE: below the original source code is an adapted piece of code which is much quicker and more responsive! enjoy!

Full Source Code: 

Alert Arduino: (With Sensor)

#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>

const char* ssid = "XXX";
const char* password = "YYY";

int ledPin = D5;
int sensorPin = A0;
int sensorValue = 0;

void setup() {

  Serial.begin(115200);                 //Serial connection
 
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);   //WiFi connection

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

}

void loop() {
   sensorValue = analogRead(sensorPin);
   Serial.println(sensorValue);
   if(WiFi.status()== WL_CONNECTED){   //Check WiFi connection status

   HTTPClient http;    //Declare object of class HTTPClient
   if(sensorValue > 350){
   http.begin("http://
IPAddress/sensor=OFF");      //Specify request destination
   }else{
   http.begin("http://IPAddress/sensor=ON");
   }
   http.addHeader("Content-Type", "text/plain");  //Specify content-type header
   int httpCode = http.POST("Message from ESP8266");   //Send the request
   String payload = http.getString();                  //Get the response payload

   Serial.println(httpCode);   //Print HTTP return code
   Serial.println(payload);    //Print request response payload
   http.end();  //Close connection

 }else{

    Serial.println("Error in WiFi connection");

 }

  delay(10);

Server Arduino:

#include <ESP8266WiFi.h>

const char* ssid = "XXX";
const char* password = "YYY";

int ledPin = D5;
WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  delay(10);


  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.print("Use this URL : ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");

}

void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }

  // Read the first line of the request
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();

  // Match the request

  int value = LOW;
  if (request.indexOf("/LED=ON") != -1) {
    digitalWrite(ledPin, HIGH);
    value = HIGH;
  }
  if (request.indexOf("/LED=OFF") != -1){
    digitalWrite(ledPin, LOW);
    value = LOW;
  }
  if (request.indexOf("/sensor=ON") != -1){
    digitalWrite(ledPin, HIGH);
    value = LOW;
  }
  if (request.indexOf("/sensor=OFF") != -1){
    digitalWrite(ledPin, LOW);
    value = LOW;
  }



  // Return the response
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  do not forget this one
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");

  client.print("Led pin is now: ");

  if(value == HIGH) {
    client.print("On");
  } else {
    client.print("Off");
  }
  client.println("<br><br>");
  client.println("Click <a href=\"/LED=ON\">here</a> turn the LED on pin 5 ON<br>");
  client.println("Click <a href=\"/LED=OFF\">here</a> turn the LED on pin 5 OFF<br>");
  client.println("</html>");

  delay(1);
  Serial.println("Client disconnected");
  Serial.println("");

}
Results:


UPDATE: From the above video we can see that the response is pretty slow with the code we have. To fix this I have edited the "Alert Arduino" code. Below is the results of changes made (below that will be the code).


Video Links: https://www.youtube.com/watch?v=Pfqs-WN9OiQ
                      https://www.youtube.com/watch?v=iTQJmba_wcw

Updated Code:

Alert Arduino: (With Sensor)
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>

const char* ssid = "XXX";
const char* password = "YYY";

int ledPin = D5;
int sensorPin = A0;
int sensorValue = 0;
int sensorOn = 0;
int currentSensor = 0;

void setup() {

  Serial.begin(115200);                 //Serial connection
 
  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);   //WiFi connection

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

}

void loop() {
   sensorValue = analogRead(sensorPin);
   Serial.println(sensorValue);
   if(sensorValue > 350){
    sensorOn = 0;
   }else{
    sensorOn = 1;
   }
 
   if(WiFi.status()== WL_CONNECTED){   //Check WiFi connection status

   HTTPClient http;    //Declare object of class HTTPClient
 
   if(currentSensor == 1 && sensorOn == 0){
 
    currentSensor = 0;
    http.begin("http://IPAddress/sensor=OFF");      //Specify request destination
    http.addHeader("Content-Type", "text/plain");  //Specify content-type header
    int httpCode = http.POST("Message from ESP8266");   //Send the request
    http.end();  //Close connection
 
   }else if(currentSensor == 0 && sensorOn == 1){
 
    currentSensor = 1;
    http.begin("http://IPAddress/sensor=ON");
    http.addHeader("Content-Type", "text/plain");  //Specify content-type header
    int httpCode = http.POST("Message from ESP8266");   //Send the request
    http.end();  //Close connection
 
   }else{
 
    //do nothing
 
   }
   //String payload = http.getString();                  //Get the response payload
   //Serial.println(httpCode);   //Print HTTP return code
   //Serial.println(payload);    //Print request response payload

 }else{

    Serial.println("Error in WiFi connection");

 }

  delay(500);

}

1 comment:

  1. This is really interesting blog on Motion Sensor in Chennai, You are a very skilled blogger. I've joined your rss feed and look forward to seeking more of your excellent post. Also, I've shared your web site in my social networks! Thank You!!!

    ReplyDelete