So you're a Noob? Post your questions here until you graduate! Don't be shy.

User avatar
By Warrik
#65408 Greetings All !

I am trying to control the NodeMCU from the web browser, via HTML buttons on a page served by the device while in Access Point Mode. The Access Point works as does the Web Server but my issue is with the functionality of the HTML buttons.

I would like to call an Arduino void function with each HTML button press.

If I use the HTML buttons for simple operations: just IF statements, they work just fine -- I am able to switch between the different functions. However the problem occurs when running a loop function as I am unable to control the device from the web interface anymore.

In short while in a loop function, the Web Buttons are rendered useless. I believe the issue here is the fact that I don't know how to implement a break call, triggered by the HTML Button action.

I am interested in a looping function as I am running a function to constantly determine the distance to a given object using HC-SR04 and maintain a constant distance to it.
If I call the function keepDistance from the HTML button, it runs fine but only once, not in a loop while anothre button is pressed. If I include a loop under the Button action, then I am unable to exit out of the loop when pressing any of the HTML buttons.

Could you please advise me on the best way to create a break call, that forfeits a looping function, the trigger being a HTML Button press ?

Thank you !

Code: Select all#include <ESP8266WiFi.h>

#define TRIGGER   13
#define ECHO      15
#define greenLED  5
#define yellowLED 12
#define boardLED  16

// Access point network Name and Password
const char* ssid = "TestTest";
const char* password = "test1234";
long distance;
WiFiServer server(80);

void setup() {
  pinMode(TRIGGER, OUTPUT);
  pinMode(ECHO, INPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);
  pinMode(boardLED, OUTPUT);
  Serial.begin(115200);
  delay(10);
  // Start the Access Point
  WiFi.softAP(ssid, password);
  Serial.println("");
  Serial.println("Access Point started");
  // Start the server
  server.begin();
  Serial.println("Server started");
}
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=TOGGLE") != -1)  {
    value = LOW;
    Serial.println(millis());
    Serial.println("Calling Led Toggle Function");
    ledToggle();
    Serial.println(millis());
    Serial.println("Exited: Led Toggle Function");
  }
  if (request.indexOf("/TOPSPEED=LIMIT") != -1)  {
    value = LOW;
    Serial.println(millis());
    Serial.println("Calling Set Top Speed Function");
    setTopSpeed();
    Serial.println(millis());
    Serial.println("Exited: Set Top Speed Function");
  }
  if (request.indexOf("/PILOT=OFF") != -1)  {
    value = LOW;
    Serial.println(millis());
    Serial.println("Pilot Off Pressed!");
  }
  if (request.indexOf("/PILOT=ON") != -1)  {
    value = HIGH;
    Serial.println(millis());
    Serial.println("Calling keepDistance function");
    keepDistance();
    delay(100);
    Serial.println(millis());
    Serial.println("Function executed : keepDistance");
  }
  // 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("Auto Pilot is now: ");
  if (value == HIGH) {
    client.print("On");
  } else {
    client.print("Off");
  }
  client.println("<br><br>");
  client.println("<a href=\"/LED=TOGGLE\"\"><button>Toggle Led </button></a>");
  client.println("<a href=\"/TOPSPEED=LIMIT\"\"><button>Limit Top Speed </button></a>");
  client.println("<a href=\"/PILOT=ON\"\"><button>Pilot ON </button></a>");
  client.println("<a href=\"/PILOT=OFF\"\"><button>Pilot OFF </button></a><br />");
  client.println("</html>");
  delay(1);
  Serial.println("Client disonnected");
  Serial.println("");
}

//Functions to deal with calculating the Distance
long getDistance() {
  // Returns distance to an object in Centimeters
  long duration;
  digitalWrite(TRIGGER, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIGGER, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGER, LOW);
  duration = pulseIn(ECHO, HIGH);
  distance = (duration / 2) / 29.1;
  return distance;
}
void printDistance() {
  // Prints the value of the distance
  distance = getDistance();
  Serial.println("");
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.print(" cm");
  Serial.println("");
  delay(250);
}
void keepDistance() {
  // Mantains the distance to a given object
  distance = getDistance();
  digitalWrite(greenLED, LOW);
  digitalWrite(yellowLED, LOW);
  if (distance > 17) {
    digitalWrite(greenLED, HIGH);
  }
  if (distance < 15) {
    digitalWrite(greenLED, LOW);
    digitalWrite(yellowLED, HIGH);
  }
}
void ledToggle(){
  digitalWrite(boardLED,!digitalRead(boardLED));
  Serial.println(millis());
  Serial.println("Currently running ledToggle function");
 
}
void setTopSpeed(){
  Serial.println(millis());
  Serial.println("Currently running setTopSpeed function");
}
User avatar
By Warrik
#65418 In the meantime I played around with the code and came up with the attached solution.
However it does not work as well as it should:

1. If I run the keepDistance() function in the loop() of the Arduino code, it works as expected in regards to keeping the distance but I am unable to turn off this mode.
2. If I run the keepDistance() withing a while() function within the posted code, the same behavior occurs, thus rendering the HTML buttons useless.

3. Workaround 1 is to neglect detection when a new Client is connected and just read incoming messages from the client. This slows down the keepDistance() function terribly. I believe it runs once a second. It is too slow for avoiding impact by detecting the current distance with the HC-SR04 Sensor.

4. Workadound 2 is to add a while loop withing the code that runst the keepDistance() for let's say 10 seconds and then reads the message coming from the Client. This way the Sensor works fast (as expected) for 10 seconds at a time and then stutters for 1 seconds while checking for any HTML button press. Then runs fine for another 10 seconds and so on.

I am not sure how to get the sensor to work at full speed while still being able to enable or disable the keepDistance() function usage from the HTML interface.

Could it be by using Interrupts ? I am not familiar with that method at all.
Another idea I thought of is by connecting the sensor to another Arduino. Thus the loop runs on that other device and is triggered by a PIN's State that can be toggled from the HTML interface.

Could you please advise on this ?

Thank you !

Code: Select all#include <ESP8266WiFi.h>

#define TRIGGER   13
#define ECHO      15
#define greenLED  5
#define yellowLED 12
#define boardLED  16

// Access point network Name and Password
const char* ssid = "TestTest";
const char* password = "test1234";
long distance, starttime, endtime;
WiFiServer server(80);
int value = LOW;

void setup() {
  pinMode(TRIGGER, OUTPUT);
  pinMode(ECHO, INPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);
  pinMode(boardLED, OUTPUT);
  Serial.begin(115200);
  delay(10);
  // Start the Access Point
  WiFi.softAP(ssid, password);
  Serial.println("");
  Serial.println("Access Point started");
  // Start the server
  server.begin();
  Serial.println("Server started");
}
void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  // Read the first line of the request
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();
  // Match the request
  if (request.indexOf("/LED=TOGGLE") != -1)  {
    value = LOW;
    Serial.println(millis());
    Serial.println("Calling Led Toggle Function");
    ledToggle();
    Serial.println(millis());
    Serial.println("Exit: Led Toggle Function");
  }
  if (request.indexOf("/TOPSPEED=LIMIT") != -1)  {
    value = LOW;
    Serial.println(millis());
    Serial.println("Calling Set Top Speed Function");
    setTopSpeed();
    Serial.println(millis());
    Serial.println("Exit: Set Top Speed Function");
  }
  if (request.indexOf("/PILOT=OFF") != -1)  {
    value = LOW;
    autoOff();
    Serial.println(millis());
    Serial.println("Pilot Off Pressed!");
  }
  if ((request.indexOf("/PILOT=ON") != -1) || (value != LOW))  {
    value = HIGH;
    Serial.println(millis());
    Serial.println("Calling keepDistance function");
    //Run for 10 seconds then go back to loop
    starttime = millis();
    endtime = starttime;
    while ((endtime - starttime) <=10000) // do this loop for up to 10000mS
    {
    // code here
    keepDistance();
    //loopcount = loopcount+1;
    endtime = millis();
    }
    Serial.println(millis());
    Serial.println("Function executed : keepDistance");
  }
  // 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><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><style>table{width:100%;margin:auto;}td{border:solid black;text-align:center;background-color:black;}a{display:block;font-size:200%;text-decoration:none;color:white;}</style></head>");
  client.println("<body><table class=\"table\">");
  client.println("<tr><td><a><br><b>AutoPilot is: ");
  if (value == HIGH) {
    client.print("ON");
  } else {
    client.print("OFF");
  }
  client.println("</b><br><br></a></td></tr>");
  client.println("<tr><td><a href=\"/LED=TOGGLE\"\"><br>Toggle LED<br><br></a></td></tr>");
  client.println("<tr><td><a href=\"/PILOT=ON\"\"><br>AutoPilot ON<br><br></a></td></tr>");
  client.println("<tr><td><a href=\"/PILOT=OFF\"\"><br>AutoPilot OFF<br><br></a></td></tr>");
  client.println("</table></body></html>");
 
  delay(1);
  Serial.println("Exiting Loop().");
  Serial.println("");
}

//Functions to deal with calculating the Distance
long getDistance() {
  // Returns distance to an object in Centimeters
  long duration;
  digitalWrite(TRIGGER, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIGGER, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGER, LOW);
  duration = pulseIn(ECHO, HIGH);
  distance = (duration / 2) / 29.1;
  return distance;
}
void printDistance() {
  // Prints the value of the distance
  distance = getDistance();
  Serial.println("");
  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.print(" cm");
  Serial.println("");
  delay(250);
}
void keepDistance() {
  // Mantains the distance to a given object
  distance = getDistance();
  digitalWrite(greenLED, LOW);
  digitalWrite(yellowLED, LOW);
  if (distance > 20) {
    digitalWrite(greenLED, HIGH);
  }
  if (distance < 20) {
    digitalWrite(greenLED, LOW);
    digitalWrite(yellowLED, HIGH);
  }
}
void autoOff (){
  digitalWrite(greenLED, LOW);
  digitalWrite(yellowLED, LOW);
}
void ledToggle(){
  digitalWrite(boardLED,!digitalRead(boardLED));
  Serial.println(millis());
  Serial.println("Currently running ledToggle function");
 
}
void setTopSpeed(){
  Serial.println(millis());
  Serial.println("Currently running setTopSpeed function");
}