Arduino loop() function executes only once when connected to the WiFi!

I have come across a situation with Arduino loop() function when connected to the WiFi.
I would like to verify whether this is correct?

When the WiFi connection settings are included in an Arduino sketch does the loop() function execute only once? and waiting for any remote commands through wifi to execute the contents inside the loop() function?

In another words, I have a sketch to blink an LED every 200ms. This is working fine without including wifi setup into the sketch.

But when I included the wifi setup, it gets connected to the wifi and LED blinks (on and then off) only once. I have couple of HTML buttons and when I press one of those buttons the LED blinks again and that it. It is not continuously blinking (on and off) ?

Any idea or thoughts?

Cheers
Fernando

No that is not standard behavior, so you would need to show your code for anyone to tell you why. And a wiring diagram while you are at it. Please use the forum's standards to show that stuff (in the How to ... post.)

Hi,

Thank you for the response.

Please find the attached sketch.

It is getting connected to the wifi and I can make the LED ON and OFF through "Blink LED ON" and "Blink LED OFF" HTML buttons. However it is not continuously blinking, as it should do, when hit the "Blink LED ON". It ONLY make it ON once and stay ON until I hit the buttons again.

PIN 13 (configured as digital out) connected to LED via 400 Ohms resistor.

4 HTML buttons have been created with following names:
(1) Turn ON : to just switch LED on once.
(2) Turn Off : to just switch off LED once.
(3) Blink LED ON : to blink the LED On & OFF, with an interval 500ms, until "Blink LED OFF" button is pressed.
(4) Blink LED OFF : to switch OFF the blinking LED

However, the 1st two buttons (Turn On and Turn Off) do not do anything now as I have made
digital write to the pin command in active (// digitalWrite(ledPin, HIGH):wink:

So only buttons 3 & 4 are active.
There is a sub-routine with the name Blink_LED(boolean VALUE) which takes care of blinking the LED (On and OFF), simply toggling the digitalwrite HIGH and LOW. The Blink_LED(boolean VALUE) is inside the loop() function, and when the Boolean argument "VALUE" is true the LED should blink until the "Blink LED OFF" is pressed. "Blink LED ON" button is to set the Boolean VALUE to true. "Blink LED OFF" will set it false and make digitalWrite(ledPin, LOW).

I tested the Blink_LED(boolean VALUE) function as a separate sketch without WiFi and it is working as it should be.

I feel like although loop() should continuously loop(), it doesn't work like that when connected to WiFi due to some reason!

Any thoughts and suggestions are very much appreciated as I spent more than 4 days to find the reason for this behaviour without much success.

[code]
#include <ESP8266WiFi.h>

const char* ssid = "My_SSID"; 
const char* password = "My_passward1234";

int ledPin = 13; // GPIO13
WiFiServer server(80);

boolean LEDsw = false;
boolean LEDblink = false;
long previous_time = 0;
long interval = 500;


//following modes: WIFI_AP = access point,
//WIFI_STA = client, WIFI_AP_STA = (AP and client) or WIFI_OFF.

void setup() {

  Serial.begin(115200);
  delay(10);

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  void Blink_LED(boolean VALUE);


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

  //***
  WiFi.mode(WIFI_AP_STA);
  //***
  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 to connect: ");
  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 for LED
  Serial.printf("LEDblink Status = %d", LEDblink);
  Serial.println("");

  // Get the LED ON
  if ((request.indexOf("/LED=ON") != -1) && LEDsw == false) {
    //digitalWrite(ledPin, HIGH);
    Serial.println("");
    Serial.print("REQUEST Index LED=ON:");
    Serial.println(request.indexOf("/LED=ON"));
    LEDsw = true;
  }

  //Get the LED OFF
  if ((request.indexOf("/LED=OFF") != -1) && LEDsw == HIGH) {
    //digitalWrite(ledPin, LOW);
    Serial.println("");
    Serial.print("REQUEST Index LED=OFF:");
    Serial.println(request.indexOf("/LED=OFF"));
    LEDsw = LOW;
  }

  
  //Get the LED Blink with 500ms interval
  if ((request.indexOf("/LED=BLINK_ON") != -1 ) ) {
    LEDblink = true;
    Serial.println("REQUEST Index Blink_ON:");
    Serial.print(request.indexOf("/LED=BLINK_ON"));
  }

  if ((request.indexOf("/LED=BLINK_OFF") != -1) ) {
    LEDblink = false;
    Serial.println("");
    Serial.printf("Index BLINK OFF = %d", request.indexOf("/LED=BLINK_OFF"));
    digitalWrite(ledPin, LOW);
  }

  Serial.println("");
  Serial.printf("LEDblink Status = %d", LEDblink);
  Blink_LED(LEDblink);
  
  // Set ledPin according to the request
  //digitalWrite(ledPin, value);

  // 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 (LEDsw == HIGH) {
    client.print("On");
  } else {
    client.print("Off");
  }
  client.println("
"); //Line break
  client.println("<a href=\"/LED=ON\"\"><button>Turn On </button></a>");
  client.println("<>");
  client.println("<a href=\"/LED=OFF\"\"><button>Turn Off </button></a>
");
  client.println("
");
  client.println("<a href=\"/LED=BLINK_ON\"\"><button> Blink LED ON </button></a>");
  client.println("<>");
  client.println("<a href=\"/LED=BLINK_OFF\"\"><button> Blink LED OFF </button></a>
");
  client.println("</html>");

  delay(50); //10
  Serial.println("");
  Serial.println("Client disonnected");
  Serial.println("");
}


void Blink_LED(boolean VALUE) {
  Serial.println("");
  unsigned long current_time = millis();
  Serial.printf("Current time =%d", current_time );
  Serial.println("");

  if (VALUE && ((current_time - previous_time) > interval) ) {
    Serial.printf("Blink interval [ms] =%d", (current_time - previous_time));
    digitalWrite(ledPin, !digitalRead(ledPin));
    previous_time = current_time;
  }
}

[/code]

WiFi_ESP8266_LED-CONTROL_6.ino.ino (3.93 KB)

Hi,

Thank you for the response.

Please find the attached (included) sketch.

It is getting connected to the wifi and I can make the LED ON and OFF through "Blink LED ON" and "Blink LED OFF" HTML buttons. However it is not continuously blinking, as it should do, when hit the "Blink LED ON". It ONLY make it ON once and stay ON until I hit the buttons again.

PIN 13 (configured as digital out) connected to LED via 400 Ohms resistor.

4 HTML buttons have been created with following names:
(1) Turn ON : to just switch LED on once.
(2) Turn Off : to just switch off LED once.
(3) Blink LED ON : to blink the LED On & OFF, with an interval 500ms, until "Blink LED OFF" button is pressed.
(4) Blink LED OFF : to switch OFF the blinking LED

However, the 1st two buttons (Turn On and Turn Off) do not do anything now as I have made
digital write to the pin command in active (// digitalWrite(ledPin, HIGH):wink:

So only buttons 3 & 4 are active.
There is a sub-routine with the name Blink_LED(boolean VALUE) which takes care of blinking the LED (On and OFF), simply toggling the digitalwrite HIGH and LOW. The Blink_LED(boolean VALUE) is inside the loop() function, and when the Boolean argument "VALUE" is true the LED should blink until the "Blink LED OFF" is pressed. "Blink LED ON" button is to set the Boolean VALUE to true. "Blink LED OFF" will set it false and make digitalWrite(ledPin, LOW).

I tested the Blink_LED(boolean VALUE) function as a separate sketch without WiFi and it is working as it should be.

I feel like although loop() should continuously loop(), it doesn't work like that when connected to WiFi due to some reason!

Any thoughts and suggestions are very much appreciated as I spent more than 4 days to find the reason for this behaviour without much success.

[code]
#include <ESP8266WiFi.h>

const char* ssid = "My_SSID"; 
const char* password = "My_passward1234";

int ledPin = 13; // GPIO13
WiFiServer server(80);

boolean LEDsw = false;
boolean LEDblink = false;
long previous_time = 0;
long interval = 500;


//following modes: WIFI_AP = access point,
//WIFI_STA = client, WIFI_AP_STA = (AP and client) or WIFI_OFF.

void setup() {

  Serial.begin(115200);
  delay(10);

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  void Blink_LED(boolean VALUE);


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

  //***
  WiFi.mode(WIFI_AP_STA);
  //***
  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 to connect: ");
  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 for LED
  Serial.printf("LEDblink Status = %d", LEDblink);
  Serial.println("");

  // Get the LED ON
  if ((request.indexOf("/LED=ON") != -1) && LEDsw == false) {
    //digitalWrite(ledPin, HIGH);
    Serial.println("");
    Serial.print("REQUEST Index LED=ON:");
    Serial.println(request.indexOf("/LED=ON"));
    LEDsw = true;
  }

  //Get the LED OFF
  if ((request.indexOf("/LED=OFF") != -1) && LEDsw == HIGH) {
    //digitalWrite(ledPin, LOW);
    Serial.println("");
    Serial.print("REQUEST Index LED=OFF:");
    Serial.println(request.indexOf("/LED=OFF"));
    LEDsw = LOW;
  }

  
  //Get the LED Blink with 500ms interval
  if ((request.indexOf("/LED=BLINK_ON") != -1 ) ) {
    LEDblink = true;
    Serial.println("REQUEST Index Blink_ON:");
    Serial.print(request.indexOf("/LED=BLINK_ON"));
  }

  if ((request.indexOf("/LED=BLINK_OFF") != -1) ) {
    LEDblink = false;
    Serial.println("");
    Serial.printf("Index BLINK OFF = %d", request.indexOf("/LED=BLINK_OFF"));
    digitalWrite(ledPin, LOW);
  }

  Serial.println("");
  Serial.printf("LEDblink Status = %d", LEDblink);
  Blink_LED(LEDblink);
  
  // Set ledPin according to the request
  //digitalWrite(ledPin, value);

  // 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 (LEDsw == HIGH) {
    client.print("On");
  } else {
    client.print("Off");
  }
  client.println("
"); //Line break
  client.println("<a href=\"/LED=ON\"\"><button>Turn On </button></a>");
  client.println("<>");
  client.println("<a href=\"/LED=OFF\"\"><button>Turn Off </button></a>
");
  client.println("
");
  client.println("<a href=\"/LED=BLINK_ON\"\"><button> Blink LED ON </button></a>");
  client.println("<>");
  client.println("<a href=\"/LED=BLINK_OFF\"\"><button> Blink LED OFF </button></a>
");
  client.println("</html>");

  delay(50); //10
  Serial.println("");
  Serial.println("Client disonnected");
  Serial.println("");
}


void Blink_LED(boolean VALUE) {
  Serial.println("");
  unsigned long current_time = millis();
  Serial.printf("Current time =%d", current_time );
  Serial.println("");

  if (VALUE && ((current_time - previous_time) > interval) ) {
    Serial.printf("Blink interval [ms] =%d", (current_time - previous_time));
    digitalWrite(ledPin, !digitalRead(ledPin));
    previous_time = current_time;
  }
}

[/code]

What is the actual output from the sketch? Try to call "client.flush()" and "client.stop()" after the last "client.println()".

move call of Blink_LED() to the first line of loop

The line "void Blink_LED(boolean VALUE);" in "setup()" makes no sense - remove it :slight_smile:

Hi All,

Many thanks for the responses. It started worked (blinking). Following is the summary what I did after replies.

  1. Added client.stop() and client.flush() at the end of loop() function and it did not help.

  2. removed void Blink_LED(boolean VALUE) from setup and it did not work too.

BY The way I was tolled that the functions that are to be called (invoked) in the main() (in this case loop() ) should be declared in the setup. However I noticed that even without declaring the functions in the setup it still works.

What would be the correct way to do? The functions should be declared in the setup or not?

  1. I moved the Blink_LED() to the first line in the loop() and it started working. Many thanks @ Juraj!

I wish to learn bit more about this with wifi. Why it is working when moved the function before wifi methods execution? and why the loop() function is not looping after wifi setup execution?

AND the big question is what would be the correct way to do?
Move all functions before wifi methods in the loop() or Move functions that are needed to be called repeatedly to the beginning of the loop() ( before wifi methods) ?

Any references or links to learn bit more about this would be appreciated.

Many thanks again for you time!

you don't see why it helped?
you have if (!client) return;

Hi,

As I have understood if the following client condition has been met ( that is no client was found), then shouldn't it execute the rest of the lines(statements) in the loop() ? or should it exit the loop() and wait for client instructions (e.g. HTML button pressed etc.)?

if (!client) {
return;
}

Cheers

The "return;" statement immediately and prematurely ends any function, and loop() is a function. But loop() is called repeatedly by code we cannot see. So if ended, it just starts over again.

Many thanks for the answers and they helped me to understand better about wifi stuff.

I have a few questions to understand wifi client connections bit better.

I did two experiments by moving Blink_LED(LEDblink),

  1. to the 1st line of loop(). And it worked fine.

  2. I also moved it to inside the if statement instruction before the return. As shown below. And it also worked.

if (!client) {
Blink_LED(LEDblink)
return;
}

  1. Does this if (!client) { return; } necessary?
    Since the loop() is anyway looping continuously why we need to exit the loop if client is un-available?

  2. When it get connected to wifi isn't it the connection remains continuously?

  3. What are the differences between these two?

( !client ) and ( !client.available() )

  1. Is it necessary or good practice to declare any sub-routines (that are going to use in the loop() ) in the setup () ? in my case is it pointless to declare Blink_LED(LEDblink) in the setup?

Thanks again for any feedback!

Cheers
Fernando

  1. Does this if (!client) { return; } necessary?

No, you could (and I would) use

if(client)
{
   // Process client request here
}

Since the loop() is anyway looping continuously why we need to exit the loop if client is un-available?

Your ENTIRE loop() function is designed to process client requests, doing nothing else. If you developed a processClient() function, your loop would look like:

void loop()
{
   if(!client)
      return;
   processClient();
}

Or,

void loop()
{
   if(client)
   {
      processClient();
   }
}
  1. When it get connected to wifi isn't it the connection remains continuously?

The connection is "permanent". That is not what is being checked.

  1. What are the differences between these two?

( !client ) and ( !client.available() )

The if(client) (or if not client) is determining whether or not there is a client with a request. The client.available() tells how much of the client's request remains to be read.

Suppose you are a ticket seller, at a movie theater. You finish with a buyer, and look to see if there is anyone else wanting a ticket (or more than one). A buyer might want one ticket, to see one movie, or might want 12 pairs of tickets, to see several different movies. if(client) tells you whether there is a ticket buyer in line. if(client.available()) tells you how many of the tickets needs have been satisfied.

  1. Is it necessary or good practice to declare any sub-routines (that are going to use in the loop() ) in the setup () ? in my case is it pointless to declare Blink_LED(LEDblink) in the setup?

You can NOT declare a function inside another function. You can CALL a function from another function.

You can CALL Blink_LED() from setup() or from loop(). Whether it makes sense to do that, or not, is not for us to say.

the forward declarations of functions are not necessary in Arduino sketch (with some exceptions). a forward declaration of a function goes outside functions (before setup(), not inside setup() {})

Hi All,

Thank you again for all your answers. They helped me to understand operations much better.

OK, please let me know whether I have understood this correctly (with my explanation below)!

So, Once it received a client request, it passes to the next instruction to be executed and then waits for another request. If no request it then exit the loop(). And then repeats?

And also, while the following code is being executed (waiting for client requests), one can do other work with the MCU (micro-controller) ? That is, while the MCU is waiting for the wifi related operations to execute one can do other work such as blinking or lighting an LED or reading a Button pressed etc?

void loop(){
   if(!client)
      return;
 }

If it is ok to run other functions (while waiting for wifi), then where is the best place in the loop() to call the those functions digitalWrite(), digitalread(), analogread() etc. ?

At the beginning of the loop() (before wifi stuff) or inside the if(!client) instruction? eg as shown below?

   if(!client){
      return;
    analogRead(PIN)
   }

processClient();

means only wifi related client operations or any other hardware (button pressed) or software processes?

When it is needed for forward declaration of functions?

Thanks again for any input.

And also, while the following code is being executed (waiting for client requests), one can do other work with the MCU (micro-controller) ? That is, while the MCU is waiting for the wifi related operations to execute one can do other work such as blinking or lighting an LED or reading a Button pressed etc?

No, you can NOT do anything else, with that code, if there is no client to deal with.

It is stupid to return from loop() if there is no client to deal with. It is far better to do something like this:

void loop()
{
   if(client)
   {
      // Process the client request
   }


   // Do other stuff here
}

At the beginning of the loop() (before wifi stuff) or inside the if(!client) instruction? eg as shown below?

Read what the return statement does. It's a bit like pressing the back button, and then trying to read the rest of the page that you were looking at.

means only wifi related client operations or any other hardware (button pressed) or software processes?

It means that you are calling a function whose name suggests that it will ONLY process the client request.

   processClientAndSoASh*tloadOfOtherStuff();

is going to be a VERY difficult function to understand and debug.

When it is needed for forward declaration of functions?

Always. But the IDE usually does that for you. You need to be concerned only when the IDE can't properly construct the function prototypes for you, because the function uses structs or pass-by-reference or a few other special cases.

I just A mistake in my previous posts with the sample codes.

First one:

if(!client){
return;
analogRead(PIN)
}

THIS SHOULD BE:

 if(!client){
      analogRead(PIN)
      return;  
   }

THIS SHOULD BE:

No, it shouldn't be.

There is no reason to call analogRead() if you don't care what the return value is.

There is no way to have a statement without a semicolon on the end.

Thanks Paul.

There is no reason to call analogRead() if you don't care what the return value is.

This is what I wanted to know.

I was able to blink a LED by placing the Blink_LED(bool value) at the beginning of the loop() (before the wifi stuff) and as well as inside

if(!client){
      Blink_LED(bool vale);
      return;
   }

Both worked. But I wanted to know what would be the correct way of doing and whether there is any sense in calling Blink_LED(bool vale) inside (!if client).

So, simply, if I want to call other functions that are not related to internet and wifi, then I should call these functions right at the start of the loop() before the wifi stuff. Is that correct?

it is your algorithm. you decide when what happens. if you want to test if a incoming connection is available test it. (you must if you want to do something with that connection). if you want to blink a led independent from client connection do it so. if you want to blink it only if client is not available, do it so. if you want to blink the led only if client is available, do it so.