I am new to IOT and have just been experimenting with Arduino and |ESP8266 for a few weeks now, so I am still very much an enthusiastic beginner!
I have a sketch which I previously rang on Arduino and now want to use ESP8266 to allow me access the system status via webpage / Blynk or similar. I have the sketch running on the ESP8266 using Arduino IDE.
Reading the eBook on Home Automation using ESP8266,I see that the web functionality is explained through LUA, whereas I am only familiar with Arduino IDE. Can I copy the LUA code and simply paste it into the Arduino IDE or are there significant differences?
The tutorial also uses interrupts for monitoring PIRs, whereas I have implemented a State Machine. What are the pros and cons of each method?
Can I display the current status of the State Machine on a web page or using Blynk? Can you offer me some simple suggestions to get this operational?
Here is the code I am using on the NODE MCU ESP8266:-
const int relay2 = D1; //drives linear actuator to close6 flap GPIO 5
const int relay1 = D2; //drives linear actuator to open flap GPIO 4
const int pIR2 = D5; //outputs HIGH signal when motion detected GPIO 14
const int pIR1 = D6; //outputs HIGH signal when motion detected GPIO 12
const int masterSwitch = D7; // manual switch to close flap GPIO13
const int doorSensor = D8; //outputs HIGH is closed – reed switch GPIO15
const unsigned long flapOpenTime = 30000; //in addition to timing of piR pot
unsigned long previousTime = 0;
int lastPIR1Status;
int lastPIR2Status;
byte doorSensorStatus;
byte masterSwitchStatus;
void turnOFF();
void openFlap();
void closeFlap();
enum _state_enum
{
IDLE,
MONITOR_MASTER_SWITCH,
MONITOR_DOOR_CLOSED,
CMD_OPEN_FLAP,
MONITOR_OPEN_FLAP,
CMD_CLOSE_FLAP,
};
_state_enum systemState = IDLE;
void setup() {
(30000); // wait for PIR modules to stabalize
pinMode(relay1, OUTPUT);// set pin as output for relay 1
pinMode(relay2, OUTPUT);// set pin as output for relay 2
pinMode(pIR1, INPUT);
pinMode(pIR2, INPUT);
pinMode(doorSensor, INPUT_PULLUP);
pinMode(masterSwitch,INPUT_PULLUP);
//turnOFF();
lastPIR1Status = digitalRead(pIR1);
lastPIR2Status = digitalRead(pIR2);
doorSensorStatus = digitalRead(doorSensor);
closeFlap();
Serial.begin(9600);// initialize serial monitor with 9600 baud
}
void loop() {
byte pIR1Status = digitalRead(pIR1);
byte pIR2Status = digitalRead(pIR2);
int doorSensorStatus = digitalRead(doorSensor);
int masterSwitchStatus = digitalRead(masterSwitch);
unsigned long currentTime = millis();
switch (systemState)
{
// Wait for motion
case IDLE:
Serial.println (“IDLE”);
Serial.print (“pIR1Status (last/Current)= “);
Serial.print (lastPIR1Status);
Serial.print (“/”);
Serial.println(pIR1Status);
Serial.print (“pIR2Status (last/Current)= “);
Serial.print (lastPIR2Status);
Serial.print (“/”);
Serial.println(pIR2Status);
Serial.print (“doorSensorStatus = “);
Serial.println(doorSensorStatus);
Serial.print (“MasterSwitchStatus = “);
Serial.println (masterSwitchStatus);
Serial.println (“***********************”);
// If either PIR sensor went from LOW to HIGH then open the flap, while door is closed and master switch is on.
if ((pIR1Status != lastPIR1Status
&& pIR1Status == 1
&& doorSensorStatus != 1
&& masterSwitchStatus != 1)
||
(pIR2Status != lastPIR2Status
&& pIR2Status == 1
&& doorSensorStatus != 1
&& masterSwitchStatus != 1))
{
systemState = CMD_OPEN_FLAP;
previousTime = currentTime;
}
break;
case MONITOR_MASTER_SWITCH:
Serial.println (“MASTER SWITCH OFF”);
if (masterSwitchStatus == 1)
{
systemState = CMD_CLOSE_FLAP;
}
break;
case MONITOR_DOOR_CLOSED:
Serial.println (“MONITOR_DOOR_CLOSED”);
if (doorSensorStatus == 0)
{
systemState = CMD_CLOSE_FLAP;
}
break;
case CMD_OPEN_FLAP:
Serial.println (“CMD_OPEN_FLAP”);
openFlap();
systemState = MONITOR_OPEN_FLAP;
break;
case MONITOR_OPEN_FLAP:
Serial.println (“MONITOR_OPEN_FLAP”);
Serial.print (“elapsed time = “);
Serial.println (currentTime – previousTime);
Serial.print (“pIR1Status (last/Current)= “);
Serial.print (lastPIR1Status);
Serial.print (“/”);
Serial.println (pIR1Status);
Serial.print (“pIR2Status (last/Current)= “);
Serial.print (lastPIR2Status);
Serial.print (“/”);
Serial.println(pIR2Status);
Serial.print (“doorSensorStatus = “);
Serial.println(doorSensorStatus);
Serial.print (“MasterSwitchStatus = “);
Serial.println (masterSwitchStatus);
Serial.println (“***********************”);
if ((pIR1Status == 0 && pIR2Status == 0) && (currentTime – previousTime >= flapOpenTime)
|| (masterSwitchStatus == 1 || doorSensorStatus == 1))
{
systemState = CMD_CLOSE_FLAP;
}
break;
case CMD_CLOSE_FLAP:
Serial.println (“CMD_CLOSE_FLAP”);
closeFlap();
systemState = IDLE;
break;
}
lastPIR1Status = pIR1Status;
lastPIR2Status = pIR2Status;
}
//
// when the actuator is pushed, it closes the flap
//
void openFlap()
{
digitalWrite(relay1, LOW);// turn relay 1 ON
digitalWrite(relay2, HIGH);// turn relay 2 OFF
}//openFlap()
void closeFlap()
{
digitalWrite(relay1, HIGH);// turn relay 1 OFF
digitalWrite(relay2, LOW);// turn relay 2 ON
}//closeFlap()
// void turnOFF()
// {
// digitalWrite(relay1, HIGH);// turn relay 1 OFF
// digitalWrite(relay2, HIGH);// turn relay 2 OFF
// }//turnOFF()
Hi.
Can you better explain what you want to do?
Your question is a bit confusing.
You can’t copy/past LUA code to Arduino IDE. It won’t work.
Which project would you like to build? Is it the door status monitor?
Regards,
Sara
Hi Sara. Thank you for your reply. Yes I want to build a dog flap in a back door. I had it running on Arduino Nano, and then I thought it would be good to have it wifi enabled, so I have built the unit with an ESP8286. There are 2 Pirs, each side of the door, a reed switch which checks if the door itself is closed, before allowing the flap to operate. The flap is operated by a linear actuator which is controlled by two relays. There is a master switch wired in series with the reed switch, so that a user can stop the flap from opening automatically.
So far it runs reasonably well, but the PIRs (3v3version) are quite erratic, which I understand is due to the HF from the ESP8266. Assuming I can get them to trigger reliably, I wanted to modify the sketch, so that I can:-
- View the status of the state machine on a web page
- Open & close the dog flap manually
- Extract the time of day from my router and use that to only allow the system run automatically during dat time.
My initial question was twofold:-
a) Your tutorial describes using interrupts to monitor the pirs, whereas I had implemented a state machine (upon recommendation from Arduino forum users) What are the pros and cons of each approach?
b) I understand now that the lua code can not be used in the Arduino IDE, so I was searching for a way to implement in Arduino IDE. Thank you for this clarification.
I have tried to experiment with combining some example code with my sketch, but I can’t figure out how to publish the current system state from the state machine to the webpage. Do I need to create a new state, which is monitoring the web page?
Start your code here
[code]
#include <ESP8266WiFi.h>
const char* ssid = “”;
const char* password = “”;
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Auxiliar variables to store the current output state
String relay2State = “off”;
String relay1State = “off”;
// Current time
unsigned long currentTime = millis();
// prior time for web timeout
unsigned long priorTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
const int relay2 = D1; //drives linear actuator to close flap GPIO 5
const int relay1 = D2; //drives linear actuator to open flap GPIO 4
const int pIR2 = D5; //outputs HIGH signal when motion detected GPIO 14
const int pIR1 = D6; //outputs HIGH signal when motion detected GPIO 12
const int masterSwitch = D7; // manual switch to close flap GPIO13
const int doorSensor = D8; //outputs HIGH is closed – reed switch GPIO15
const unsigned long flapOpenTime = 30000; //in addition to timing of piR pot
unsigned long previousTime = 0; //lasttime flap opened
int lastPIR1Status;
int lastPIR2Status;
byte doorSensorStatus;
byte masterSwitchStatus;
void turnOFF();
void openFlap();
void closeFlap();
enum _state_enum
{
IDLE,
MONITOR_MASTER_SWITCH,
MONITOR_DOOR_CLOSED,
CMD_OPEN_FLAP,
MONITOR_OPEN_FLAP,
CMD_CLOSE_FLAP,
};
_state_enum systemState = IDLE;
void setup() {
pinMode(relay1, OUTPUT);// set pin as output for relay 1
pinMode(relay2, OUTPUT);// set pin as output for relay 2
pinMode(pIR1, INPUT);
pinMode(pIR2, INPUT);
pinMode(doorSensor, INPUT_PULLUP);
pinMode(masterSwitch, INPUT_PULLUP);
//turnOFF();
lastPIR1Status = digitalRead(pIR1);
lastPIR2Status = digitalRead(pIR2);
doorSensorStatus = digitalRead(doorSensor);
closeFlap();
Serial.begin(115200);// initialize serial monitor
// Connect to Wi-Fi network with SSID and password
Serial.print(“Connecting to “);
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(“.”);
}
// Print local IP address and start web server
Serial.println(“”);
Serial.println(“WiFi connected.”);
Serial.println(“IP address: “);
Serial.println(WiFi.localIP());
server.begin();
}
void loop() {
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
Serial.println(“New Client.”); // print a message out in the serial port
String currentLine = “”; // make a String to hold incoming data from the client
currentTime = millis();
priorTime = currentTime;
while (client.connected() && currentTime – priorTime <= timeoutTime) { // loop while the client’s connected
currentTime = millis();
if (client.available()) { // if there’s bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == ‘\n’) { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that’s the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what’s coming, then a blank line:
client.println(“HTTP/1.1 200 OK”);
client.println(“Content-type:text/html”);
client.println(“Connection: close”);
client.println();
// turns the GPIOs on and off
if (header.indexOf(“GET /5/on”) >= 0) {
Serial.println(“Relay 2 on”);
relay2State = “on”;
digitalWrite(relay2, HIGH);
} else if (header.indexOf(“GET /5/off”) >= 0) {
Serial.println(“Relay 2 off”);
relay2State = “off”;
digitalWrite(relay2, LOW);
} else if (header.indexOf(“GET /4/on”) >= 0) {
Serial.println(“Relay 1 on”);
relay1State = “on”;
digitalWrite(relay1, HIGH);
} else if (header.indexOf(“GET /4/off”) >= 0) {
Serial.println(“Relay 1 off”);
relay1State = “off”;
digitalWrite(relay1, LOW);
}
// Display the HTML web page
client.println(“<!DOCTYPE html><html>”);
client.println(“<head><meta name=\”viewport\” content=\”width=device-width, initial-scale=1\”>”);
client.println(“<link rel=\”icon\” href=\”data:,\”>”);
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println(“<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}”);
client.println(“.button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;”);
client.println(“text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}”);
client.println(“.button2 {background-color: #77878A;}</style></head>”);
// Web Page Heading
client.println(“<body><h1>Dog Flap Status</h1>”);
// Display current state, and ON/OFF buttons for GPIO 5
client.println(“<p>Relay 2 – State ” + relay2State + “</p>”);
// If the relay2State is off, it displays the ON button
if (relay2State == “off”) {
client.println(“<p><a href=\”/5/on\”><button class=\”button\”>ON</button></a></p>”);
} else {
client.println(“<p><a href=\”/5/off\”><button class=\”button button2\”>OFF</button></a></p>”);
}
// Display current state, and ON/OFF buttons for GPIO 4
client.println(“<p>Relay 1 – State ” + relay1State + “</p>”);
// If the relay1State is off, it displays the ON button
if (relay1State == “off”) {
client.println(“<p><a href=\”/4/on\”><button class=\”button\”>ON</button></a></p>”);
} else {
client.println(“<p><a href=\”/4/off\”><button class=\”button button2\”>OFF</button></a></p>”);
}
client.println(“</body></html>”);
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = “”;
}
} else if (c != ‘\r’) { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = “”;
// Close the connection
client.stop();
Serial.println(“Client disconnected.”);
Serial.println(“”);
}
byte pIR1Status = digitalRead(pIR1);
byte pIR2Status = digitalRead(pIR2);
int doorSensorStatus = digitalRead(doorSensor);
int masterSwitchStatus = digitalRead(masterSwitch);
unsigned long currentTime = millis();
switch (systemState)
{
// Wait for motion
case IDLE:
Serial.println (“IDLE”);
client.println(“<p>System State – IDLE” “</p>”);
// If either PIR sensor went from LOW to HIGH then open the flap, while door is closed and master switch is on.
if ((pIR1Status != lastPIR1Status
&& pIR1Status == 1
&& doorSensorStatus != 1
&& masterSwitchStatus != 1)
||
(pIR2Status != lastPIR2Status
&& pIR2Status == 1
&& doorSensorStatus != 1
&& masterSwitchStatus != 1))
{
systemState = CMD_OPEN_FLAP;
previousTime = currentTime;
}
break;
case MONITOR_MASTER_SWITCH:
Serial.println (“MASTER SWITCH OFF”);
client.println(“<p>System State – MONITOR_MASTER_SWITCH” “</p>”);
if (masterSwitchStatus == 1)
{
systemState = CMD_CLOSE_FLAP;
}
break;
case MONITOR_DOOR_CLOSED:
Serial.println (“MONITOR_DOOR_CLOSED”);
client.println(“<p>System State – MONITOR_DOOR_CLOSED” “</p>”);
if (doorSensorStatus == 0)
{
systemState = CMD_CLOSE_FLAP;
}
break;
case CMD_OPEN_FLAP:
Serial.println (“CMD_OPEN_FLAP”);
client.println(“<p>System State – CMD_OPEN_FLAP” “</p>”);
openFlap();
systemState = MONITOR_OPEN_FLAP;
break;
case MONITOR_OPEN_FLAP:
Serial.println (“Monitor_Open_Flap”);
client.println(“<p>System State – MONITOR_OPEN_FLAP” “</p>”);
if ((pIR1Status == 0 && pIR2Status == 0) && (currentTime – previousTime >= flapOpenTime)
|| (masterSwitchStatus == 1 || doorSensorStatus == 1))
{
systemState = CMD_CLOSE_FLAP;
}
break;
case CMD_CLOSE_FLAP:
Serial.println (“CMD_CLOSE_FLAP”);
client.println(“<p>System State – CMD_CLOSE_FLAP” “</p>”);
closeFlap();
systemState = IDLE;
break;
}
lastPIR1Status = pIR1Status;
lastPIR2Status = pIR2Status;
}
//
// when the actuator is pushed, it closes the flap
//
void openFlap()
{
digitalWrite(relay1, LOW);// turn relay 1 ON
digitalWrite(relay2, HIGH);// turn relay 2 OFF
}//openFlap()
void closeFlap()
{
digitalWrite(relay1, HIGH);// turn relay 1 OFF
digitalWrite(relay2, LOW);// turn relay 2 ON
}//closeFlap()
// void turnOFF()
// {
// digitalWrite(relay1, HIGH);// turn relay 1 OFF
// digitalWrite(relay2, HIGH);// turn relay 2 OFF
// }//turnOFF()
[/code]
Hi.
There are many ways to build a web server with the ESP8266.
The method you’re using is not the best one if you want to have multiple things occurring besides the web server. Like checking the state of the PIRs and the door switch.
The best way is to use an asynchronous web server both to display the readings and control the door. See the eBook page: 252.
To be able to control the door from the web server and with a manual button, the best thing is to use websocket protocol with the asynchronous web server. Unfortunately, this subject is not covered in that eBook.
We cover these subjects in great detail in our new eBook: https://rntlab.com/product/build-web-servers-esp32-esp8266-ebook/
However, I recommend that you take a look at our free tutorials that address this subject. Here’s a few tutorials that might be useful:
- ESP8266 Async Web Server to Control Outputs
- ESP8266 Async Web Server With WebSocket
- ESP32/ESP8266: Control Outputs with Web Server and a Physical Button Simultaneously
I understand that this might be quite a lot of new things. However, after understanding how the asynchrnonous web server works, you’ll see how easy it can be to build your web servers.
I hope this helps.
Regards,
Sara
Thank you Sara. I will buy the eBook and see how I get on. No doubt I will be back!
Hi.
You don’t need to buy the eBook straight away.
I recommend that you first take a look at the free projects and only buy the eBook if you feel that’s necessary.
Regards,
Sara
Hi Sara – Happy to buy the eBooks as I appreciate your efforts to educate. I’ve been working through the tutorials in your eBook “Build Web Servers with the ESP32 and ESP8266”
I am working my way through the examples and have got the LittleFS system working using VS Code + PlatformIO, which is a steep learning curve.