6

Short version: I have a program that connects my ESP8266 to WIFI so I can control a relay connected to it over the internet or a button. I also have a sensor for my door. This software works perfectly, if I add a light dependent resistor to it (which is connected correctly since I do get readings from it) and start reading data I lose my WIFI connection. Has anyone got any idea why this is happening?

Long version:

So I have this program running on my Esp8266

#include <ESP8266WiFi.h>

IPAddress ip(192, 168, 0, 150);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);

const char* ssid = "mySSID";
const char* password = "myPSW";
const char* host = "192.168.0.228";

const int buttonPin = 0;
const int relayPin =  4;
const int doorPin = 5;
const int ldrPin = A0;


//int ldrState;
//int serialCount = 0;
//int ldrMin = 0;
//int ldrMax = 1024;
int buttonState = 0;
int doorState = 0;
byte Main_Light_State_Begin;
bool Main_Light_State;
bool doorNotified = false;
bool button_action_taken = false;
bool Main_Light_DBR = true;
String HTTP_Get_Response;

WiFiServer server(80);

//Functions
String HTTP_Get(char* Adress, String URL, bool Last_Line_Bool) {
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(Adress, httpPort)) {
    Serial.println("connection failed");
    return "Failed";
  }

  Serial.print("Requesting URL: ");
  Serial.println(URL);
  Serial.println("at adress");
  Serial.println(Adress);
  client.print(String("GET ") + URL + " HTTP/1.1\r\n" +
               "Host: " + Adress + "\r\n" +
               "Connection: close\r\n\r\n");
  delay(10);

  String Response;
  String Last_Line;

  while (client.available()) {
    String line = client.readStringUntil('\r');
    Serial.print(line);
    Response = Response + line;
  }
  return Response;

  Serial.println();
  Serial.println("closing connection");

}

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

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);



  WiFi.begin(ssid, password);
  WiFi.config(ip, gateway, subnet);

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

  server.begin(); -
  Serial.println("Server started");

  Serial.println(WiFi.localIP());
  pinMode(relayPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  pinMode(doorPin, INPUT);
//  pinMode(ldrPin, INPUT);
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Wifi NOT Connected");
  }
  //Sensors
  buttonState = digitalRead(buttonPin);
  doorState = digitalRead(doorPin);
  //ldrState = map(analogRead(ldrPin), ldrMin, ldrMax, 0, 100);
  //Serial.println(analogRead(ldrPin));
//  if (serialCount == 1000) {
//    Serial.println(ldrState);
//    serialCount = 0;
//  } else {
//    serialCount ++;
//  }

  //Doorsensor
  if (doorState == HIGH) {
    if (doorNotified == false) {
      Serial.println("DOOR");
      HTTP_Get_Response = HTTP_Get("192.168.0.228", "/index.php/?door_opened=true", false);
      doorNotified = true;
    }
  } else if (doorState == LOW) {
    if (doorNotified == true) {
      doorNotified = false;
      delay(500);
    }
    else {
      doorNotified = false;
    }
  }

  //Button
  if (buttonState == LOW) {
    if (button_action_taken == false) {
      if (Main_Light_State == true) {
        Serial.println("SWITCH");
        Main_Light_State = false;
        digitalWrite(relayPin, HIGH);
        delay(500);
        Main_Light_DBR = false;
      }
      else if (Main_Light_State == false) {
        Serial.println("SWITCH");
        Main_Light_State = true;
        digitalWrite(relayPin, LOW);
        delay(500);
        Main_Light_DBR = false;
      }
      button_action_taken = true;
    }
  } else if (buttonState == HIGH) {
    if (button_action_taken == true) {
      button_action_taken = false;
      delay(500);
    }
    else {
      button_action_taken = false;
    }

  }
  //Main_Light_State
  if (Main_Light_State == true) {
    digitalWrite(relayPin, LOW);
    if (Main_Light_DBR == false) {
      HTTP_Get_Response = HTTP_Get("192.168.0.228", "/index.php/?main_light_on_dbr=true", false);
      Main_Light_DBR = true;
    }

  } else if (Main_Light_State == false) {
    digitalWrite(relayPin, HIGH);
    if (Main_Light_DBR == false) {
      HTTP_Get_Response = HTTP_Get("192.168.0.228", "/index.php/?main_light_off_dbr=true", false);
      Main_Light_DBR = true;
    }
  }

  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  Serial.println("new client");
  while (!client.available()) {
    delay(1);
  }

  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();

  if (req.indexOf("/main_light/on") != -1) {
    Main_Light_State = true;
    Main_Light_DBR = false;
  } else if (req.indexOf("/main_light/off") != -1) {
    Main_Light_State = false;
    Main_Light_DBR = false;
  } else if (req.indexOf("/main_light/switch") != -1) {
    Serial.println("SWITCH");
    if (Main_Light_State == true) {
      Main_Light_State = false;
    }
    else if (Main_Light_State == false) {
      Main_Light_State = true;
    }
    Main_Light_DBR = false;
  } else if (req.indexOf("/main_light/state") != -1) {

  } else {
    Serial.println("invalid request");
    client.stop();
    return;
  }

  client.flush();

  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
  s += (Main_Light_State) ? "1" : "0";

  client.print(s);
  delay(1);
  Serial.println("Client disonnected");
}

With the lines I commented like above everything works fine. I have a light dependant resistor connected (correctly, I get correct measurements from it) to A0. From the moment on I uncomment the lines involving this LDR and thus start reading data from it I lose my wifi connection. Has anyone got any idea why this is? Thank you!

  • Which ESP8266? There are many versions each with different abilities and facilities. – Majenko Jan 21 '16 at 0:05
  • @Majenko The one with a serial chip and power regulator on board. (Diymall NodeMCU Devkit 1.0 CP2102 IIC SPI for Apple's MAC OS amazon.co.uk/dp/B00XJG7GEK/ref=cm_sw_r_other_awd_UnhOwbBSFS1GS) – JanG Jan 21 '16 at 6:00
  • I came across this while looking for info on analogRead problems. I think the "more elegant solution" may have a couple of problems. Problem 1. If the sensor read and processing takes less than 1 ms, the loop may return and you will get multiple executions of analogRead within the same millisecond - not the desired result. Considering that analogRead(A0) itself only takes about 70 microseconds, if the processing is quick you could easily have 10 or so executions of analogRead(A0) in that millisecond. Problem 2. If there are other things goind on which take multiple millieconds to complete (eg – farmerkeith Oct 16 '17 at 9:23
5

I have found that this was caused by reading the analog pin to many times in a short period of time. I replaced

  ldrState = map(analogRead(ldrPin), ldrMin, ldrMax, 0, 100);
  Serial.println(analogRead(ldrPin));
  if (serialCount == 1000) {
    Serial.println(ldrState);
    serialCount = 0;
  } else {
    serialCount ++;
  }

with this:

if (serialCount == 10000) {
  ldrState = map(analogRead(ldrPin), ldrMin, ldrMax, 0, 100);
  Serial.println(ldrState);
  serialCount = 0;
} else {
  serialCount ++;
}

Although I thought of this approach before, my mistake was that I was still reading the sensor every time the code loops, I just wasn't printing it to the serial monitor until each 100th loop.

This still gives me a reading several times per second, which is way more then I need. Anyway, now I know that I can't read my ESP8266 Analog pin to many times per second or the wifi will disconnect (at least when using it with the Arduino IDE)

5

This is an old question that has been answered, but I would like to offer a slightly more elegant solution (IMO!):

In my method which reads the analog data, I check and only read every 50 milliseconds:

void readAnalogSensor() {
   if( millis() % 50 != 0 )
       return;
   .
   .  // Do your sensor read and processing here
   .
}

This avoids having to keep a loop count and seems more deterministic - the loop count value will not necessarily increase in a consistent fashion depending on what else is going on in the loop. Having the millis values available is also useful if you need to implement some button debounce code.

  • 1
    Wow this has indeed been a while, man I should pick this project back up! This is indeed a more elegant solution, thank you! – JanG May 31 '17 at 18:53
1

Here is what I usually do to give repetition at fixed intervals:

void readAnalogSensor(){
  if (millis()<taskTime) return; // time is not expired yet
  taskTime += 50; // set time for the following execution
  // .... more code for the task that is done every 50 ms
}

This requires an unsigned long variable taskTime. You may also use a constant instead of the 50.
taskTime should be set to some value close to millis() at the end of setup(), otherwise there will be a rapid sequence of executions while taskTime catches up with millis().

  • 1
    Almost correct. You forgot the Timing Rollover (playground.arduino.cc/Code/TimingRollover). Every 49 days, millis() rollover to zero and your will comparing a very low value (millis) against a very large one (taskTime). The right ways is always compare the difference between millis() against the interval duration in milliseconds. – user31481 Oct 16 '17 at 9:46
  • Thank you. I wanted to avoid doing the arithmetic at every pass of the loop, but it seems this is not possible without causing the rollover error. – farmerkeith Oct 17 '17 at 12:00
  • You have lot of time to spent. Don't forget that yours is the only program running. There is no reason to save cycles if you are already waiting. – user31481 Oct 17 '17 at 12:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.