I have build a controller for my garage door using an ESP8266 for wifi connection, a relay that replaces a push button for the motor control and an ultrasonic distance sensor to find out the state of the garage door so I can have dedicated open/close commands. It has been working stable and well for a couple of weeks now, but what bothers me are quite some delays in the response.
Can anybody see what - for example - causes a delay of nearly a second until the status command returns the distance read via telnet? Or is it just the ESP8266 that isn't very fast?
#include <SoftwareSerial.h>
SoftwareSerial softSerial(10, 11); // RX, TX
#define SSID "MYSSID"
#define PASS "MYPASSWD"
#define WIFI_Serial Serial
#define Debug_Serial softSerial
#define DEBUG true
String inString = "";
String message = "";
const int trigPin = 2;
const int echoPin = 4;
const int relayPin = 6;
long sensorReadTime = 0;
const long sensorReadInterval = 2000;
long gateDistance = 0;
void setup()
{
WIFI_Serial.begin(9600);
WIFI_Serial.setTimeout(5000);
Debug_Serial.begin(9600);
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin,HIGH);
for(int i=0;i<10;i++)
{
delay(1000);
Debug_Serial.println(i);
}
Debug_Serial.println("Starting up");
WIFI_Serial.println("AT+RST");
delay(5000);
while(WIFI_Serial.available())
{
WIFI_Serial.read();
}
WIFI_Serial.println("AT+CWMODE=1");
delay(1000);
if(checkForOK())
{
Debug_Serial.println("Module is ready");
}
else
{
Debug_Serial.println("Module has no response.");
while(1);
}
//connect to the wifi
boolean connected=false;
for(int i=0;i<10;i++)
{
if(connectWiFi())
{
connected = true;
break;
}
}
if (!connected){
while(1);
}
//print the ip addr
WIFI_Serial.println("AT+CIFSR");
delay(1000);
Debug_Serial.println("ip address:");
while (WIFI_Serial.available())
Debug_Serial.write(WIFI_Serial.read());
//set multiple connection mode
WIFI_Serial.println("AT+CIPMUX=1");
delay(1000);
Debug_Serial.println("multiple connection mode:");
while (WIFI_Serial.available())
Debug_Serial.write(WIFI_Serial.read());
//set server mode
WIFI_Serial.println("AT+CIPSERVER=1,23");
delay(1000);
Debug_Serial.println("server mode:");
while (WIFI_Serial.available())
Debug_Serial.write(WIFI_Serial.read());
}
void loop()
{
if(millis()>(sensorReadTime+sensorReadInterval))
{
gateDistance = getGateDistance();
Debug_Serial.print("Distance: ");
Debug_Serial.println(gateDistance);
sensorReadTime=millis();
}
if(WIFI_Serial.available())
{
if(WIFI_Serial.find("+IPD,"))
{
delay(100);
Debug_Serial.println("Connection");
int connectionId = WIFI_Serial.read()-48; // subtract 48 because the read() function returns
// the ASCII decimal value and 0 (the first decimal number) starts at 48
int length = 0;
WIFI_Serial.read(); //Komma
while (WIFI_Serial.available() > 0)
{
int inChar = WIFI_Serial.read();
if (isDigit(inChar))
{
inString += (char)inChar;
}
if (inChar == ':')
{
length = inString.toInt();
inString = "";
break;
}
}
for(int i = 0;i<length-2;i++)
{
int inChar = WIFI_Serial.read();
inString += (char)inChar;
}
WIFI_Serial.read();
WIFI_Serial.read();//Line ending
Debug_Serial.println(inString);
if (inString == "status")
{
String distance = String(gateDistance);
String cipSend = "AT+CIPSEND=";
cipSend += connectionId;
cipSend += ",";
cipSend +=distance.length();
cipSend +="\r\n";
sendData(cipSend,1000,DEBUG);
sendData(distance+"\r\n",1000,DEBUG);
}
else if (inString == "close")
{
if (gateDistance<15)
{
digitalWrite(relayPin,LOW);
delay(1000);
digitalWrite(relayPin,HIGH);
message="OK";
}
else
{
message="ISCLOSED";
}
String cipSend = "AT+CIPSEND=";
cipSend += connectionId;
cipSend += ",";
cipSend +=message.length();
cipSend +="\r\n";
sendData(cipSend,1000,DEBUG);
sendData(message+"\r\n",1000,DEBUG);
}
else if (inString == "open")
{
if (gateDistance>40)
{
digitalWrite(relayPin,LOW);
delay(1000);
digitalWrite(relayPin,HIGH);
message="OK";
}
else
{
message="ISOPEN";
}
String cipSend = "AT+CIPSEND=";
cipSend += connectionId;
cipSend += ",";
cipSend +=message.length();
cipSend +="\r\n";
sendData(cipSend,1000,DEBUG);
sendData(message+"\r\n",1000,DEBUG);
}
String closeCommand = "AT+CIPCLOSE=";
closeCommand+=connectionId; // append connection id
closeCommand+="\r\n";
sendData(closeCommand,3000,DEBUG);
inString="";
}
}
}
String sendData(String command, const int timeout, boolean debug)
{
String response = "";
WIFI_Serial.print(command); // send the read character to the esp8266
long int time = millis();
while( (time+timeout) > millis())
{
while(WIFI_Serial.available())
{
// The esp has data so display its output to the serial window
char c = WIFI_Serial.read(); // read the next character.
response+=c;
}
}
if(debug)
{
Debug_Serial.print(response);
}
return response;
}
boolean connectWiFi()
{
String cmd="AT+CWJAP=\"";
cmd+=SSID;
cmd+="\",\"";
cmd+=PASS;
cmd+="\"";
Debug_Serial.println(cmd);
WIFI_Serial.println(cmd);
delay(10000);
if(checkForOK())
{
Debug_Serial.println("OK, Connected to WiFi.");
return true;
}
else
{
Debug_Serial.println("Can not connect to the WiFi.");
return false;
}
}
long getGateDistance()
{
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration;
// The sensor is triggered by a HIGH pulse of 10 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(trigPin, OUTPUT);
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Read the signal from the sensor: a HIGH pulse whose
// duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(echoPin, INPUT);
duration = pulseIn(echoPin, HIGH);
// convert the time into a distance
return microsecondsToCentimeters(duration);
}
boolean checkForOK()
{
char inChar;
boolean oLast=false;
boolean returnV = false;
while (WIFI_Serial.available())
{
inChar=WIFI_Serial.read();
Debug_Serial.print(inChar);
if(oLast && inChar == 'K')
returnV=true;
else if (inChar == 'O')
oLast = true;
else
oLast = false;
}
Debug_Serial.println();
return returnV;
}
long microsecondsToInches(long microseconds)
{
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}