Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does ESP8266 with Arduino IDE support multi-threading? #1870

Closed
geoffreyhhh opened this issue Apr 6, 2016 · 28 comments
Closed

Does ESP8266 with Arduino IDE support multi-threading? #1870

geoffreyhhh opened this issue Apr 6, 2016 · 28 comments

Comments

@geoffreyhhh
Copy link

geoffreyhhh commented Apr 6, 2016

Dears,
was wondering if ESP8266 with Arduino IDE supports multi-threading to run multiple tasks/functions simultaneously? If it does, please help to provide the working example code.

any advise is highly appreciated.

Geoffrey

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@WereCatf
Copy link
Contributor

WereCatf commented Apr 6, 2016

ESP8266 is single-core, so you can't run stuff simultaneously anyways.

@geoffreyhhh
Copy link
Author

Thanks for the advice.

wondering if ESP8266 with Arduino IDE supports allocating processing resources for a function for specific time before it runs next function.

// During the 5000ms allocation, processing resource should be available
void loop(){
loop1(); // e.g. allocate 5000ms before it runs loop2
loop2();
loop3();
}

any advise is highly appreciated.
Geoffrey

@WereCatf
Copy link
Contributor

WereCatf commented Apr 7, 2016

I'm not entirely sure what you're asking. You could do timestamps by tracking time spent with millis() and then running one or another function when a certain amount of time has passed, or you could use timers to set a flag when a certain amount of time has passed and just check whether the flag is true or flag in loop and run your functions accordingly -- the latter solution makes for cleaner code, even if there is no practical difference.

I might be able to offer more if you explained what you're trying to achieve.

@krzychb
Copy link
Contributor

krzychb commented Apr 7, 2016

@geoffreyhhh,

I guess you may be looking for a cooperative scheduler like this one prepared for Arduino sam and samd architectures.

Out of curiosity I made a quick check and sure enough MultipleBlinks sketch does not compile for ESP. It is complaining a lot about incompatibility of boards and by providing several other reasons it will not make it 😄 I like s/w that is saying in plan text what the problem is 👍

Krzysztof

@geoffreyhhh
Copy link
Author

Thanks for the inputs and sorry for the late reply.

Below is the portion of the code relating to the question. it's a code for demo purpose, loop1() is to demo turning on/off esp8266 onboard led through web browser.

ESP8266WebServer server(80);

void loop(){
loop1(); // e.g. allocate 5000ms before it runs loop2
loop2();
loop3();
}

void loop1(void){
server.handleClient();
}

when there's no loop2() loop3() in loop(), and loop1() code is in loop(), I used millis() to measure the time required to complete the code, it gave between 3second ~ 5second, each time is slightly different. in this way, the web browser can get complete response message from the esp8266.

when loop1() loop2() loop3() are in loop(), once web browser sends commands to esp8266, it's very hard to get complete response message from esp8266 to display in web browser the response message from esp8266.

the web browser will get the response message after 2nd or 3rd running of the loop1() after the web browser sends out the command to the esp8266.

that's why I was thinking to be able to allocate 5000ms to the loop1(), so that there's no need to wait for 2nd or 3rd running of the loop1() for the web browser to receive the response.

I tried to use delay(), which is not right way to do so since delay() holds processing resource.

Could you advise further to offer bit code example to illustrate your timer to resolve.

Thank you in advance.

@igrr
Copy link
Member

igrr commented Apr 9, 2016

when loop1() loop2() loop3() are in loop(), once web browser sends commands to esp8266, it's very hard to get complete response message from esp8266 to display in web browser the response message from esp8266.

This looks like the main issue here. Could you please post the minimal code sample which demonstrates the issue? Thanks.

@geoffreyhhh
Copy link
Author

Hello~
Thanks for asking and the support.

The minimal code relating to the question is as follows.

ESP8266WebServer server(80);

void handleRoot() {
server.send(200, "text/plain",
"\n/on: to turn onboard LED ON \n/off: to turn onboard LED OFF \n");

}

void handleNotFound(){
digitalWrite(led, 1);
digitalWrite(ext_led, 1);
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET)?"GET":"POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i=0; i<server.args(); i++){
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
digitalWrite(led, LOW);
digitalWrite(ext_led, LOW);
}

void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
setup1();
}

void setup1(void){
pinMode(led, OUTPUT);
pinMode(ext_led, OUTPUT);
pinMode(buttonPin, INPUT); //connect to ESP8266 GPIO12
digitalWrite(led, 0);
digitalWrite(ext_led, 0);

server.on("/", handleRoot);

server.on("/on", {
digitalWrite(led, LOW); //BUILTIN_LED
digitalWrite(ext_led, HIGH); //external GPIO5 LED
msg1 += "LED ON; button status: ";
msg1 += buttonState;
msg1 += " sensorValue: ";
msg1 += sensorValue;
msg1 += "\n";
server.send(200, "text/plain", msg1);
});

server.on("/off", {
digitalWrite(led, HIGH); //BUILTIN_LED
digitalWrite(ext_led, LOW); //external GPIO5 LED
msg2 += "LED OFF; button status: ";
msg2 += buttonState;
msg2 += " sensorValue: ";
msg2 += sensorValue;
msg2 += "\n";
server.send(200, "text/plain", msg2);
});

server.onNotFound(handleNotFound);

server.begin();
Serial.println("HTTP server started");

//delay a moment,
//for terminal to receive inf, such as IP address
delay(1000);
// Serial.end();
pinMode(led, OUTPUT); //BUILTIN_LED
pinMode(ext_led, OUTPUT);
digitalWrite(led, 0);
}

void loop(){
loop1(); // e.g. allocate 5000ms before it runs loop2
loop2();
loop3();
}

void loop1(void){
server.handleClient();
}

@WereCatf
Copy link
Contributor

I have to say, I still don't understand your problem. Are your loop2() and loop3() terribly slow, then?

@baruch
Copy link
Contributor

baruch commented Apr 19, 2016

As for cooperative scheduling, the ESP8266 Arduino code already has the coroutine functions, I wonder if they can be exposed somehow to the users. I would love to make use of them for some of my code instead of the state machines I need to code now.

@Makuna
Copy link
Collaborator

Makuna commented Apr 23, 2016

FYI: Github/Makuna/Task is a non-preemptive multitasking library support that cross Arduino compatible.

@baruch
Copy link
Contributor

baruch commented Apr 23, 2016

While makuna/task does help a bit it isn't much different then having a set of loop functions and checking for triggers.

A coroutine approach is much more convenient and while it is not portable I don't really care that much about portability anyway in my project.

@malachib
Copy link

+1 on this topic; I have a lot of use cases for cooperative multitasking on the ESP

@mkeyno
Copy link

mkeyno commented May 11, 2016

its already done, unlike the AVR core, every modern core like ARM and extensa can prioritize its interrupts which is resulted to multi-threading task, but in old Arduino board which is base on ATMEGA core , many developer have to calculate precise timing sequence for multi tasking and in fact impossible because each event (interrupt) have nor priority over another event (interrupt)

@anmaped
Copy link

anmaped commented Nov 2, 2016

Take a look on https://github.com/anmaped/esp8266-scheduler it is a preemptive scheduler for esp8266 Arduino.

I have to submit the changes to Arduino esp8266 to weak the definition of some functions. It is not stable, but for now it is working very well.

@igrr Could I submit this pull resquest to weak the function 'esp_schedule', 'optimistic_yield', 'loop_task', and 'delay' ?

@Didix57
Copy link

Didix57 commented Feb 12, 2017

Let me get back to this thread.
The typical Webserver example has two handles: one to put an LED on and a second to put it off.

Example:

void handle_ledOff() {
  digitalWrite(ledPin, LOW);
  doHtmlPage();
}

Instead of just putting the LED on, I would like to do something that lasts forever - unless I stop it intentionally.
Example:

void handle_ledOn() {
  doHtmlPage();
  while (not interrupted) {
    digitalWrite(ledPin, HIGH);
    delay(100);
    digitalWrite(ledPin, LOW);
    delay(100);
  }
}

Well, do no just focus on blinking, it might be something more complex.

However, the second routine blocks the webserver and clicking on the button at the html-page to trigger ledOff therefore does not show any result than waiting.

How could I overcome that?
How can I get 'interrupted' become TRUE?

Would Makuna/Task solve that problem?

@vicnevicne
Copy link
Contributor

In such a case, I would just do something like:

void handle_ledOff() {
  digitalWrite(ledPin, LOW);
  doHtmlPage();
  flashLed = 0;
}

void handle_ledOn() {
  doHtmlPage();
  flashLed = 1;
}

void loop() {
  if (flashLed) {
    digitalWrite(ledPin, HIGH);
    delay(100);
    digitalWrite(ledPin, LOW);
    delay(100);
  }
}

The idea is that the loop lets the code "breathe", and the handlers just set indicator variables that can be tested in the main loop.

Vicne

@Makuna
Copy link
Collaborator

Makuna commented Feb 13, 2017

And yes the makuna/task would handle this problem. It will take the example Vicne above to the next level and allow you to get rid of delay completely. For most Arduinos delay is blocking, so nothing else happens while you wait. If you are using the Async Html Server object for Esp8266, then this isn't a problem though.

Some reference reading Adafruit Multitasking that will help you understand the concept.

@Didix57
Copy link

Didix57 commented Feb 13, 2017

@ vicnevicne:
Where would you place 'server.handleClient()'?

@ Makuna:
Thanx, epecially for the link, too. This takes me further!

@ all:
I also stumbled over ESPAsyncWebServer
https://github.com/me-no-dev/ESPAsyncWebServer
Anybody experience with that approach?

Could anybody recommend me which path to follow?

@vicnevicne
Copy link
Contributor

Yeah, I omitted many things related to the server to make the case simpler.
server.handleClient() should be in the loop of course. Something along the lines:

void loop() {
  server.handleClient();
  if (flashLed) {
    digitalWrite(ledPin, HIGH);
    delay(100);
    digitalWrite(ledPin, LOW);
    delay(100);
  }
}

@Naguissa
Copy link

Is this supported on esp?

https://www.arduino.cc/en/Reference/Scheduler

@HugoSH
Copy link

HugoSH commented Oct 5, 2017

Any more discussions?
I am having the same issue ....
loop(){
server.handleclient();
function-do-sth-else();
}
The handleClient() is so ... slow ... to send html to client. :(

@devyte
Copy link
Collaborator

devyte commented Oct 5, 2017

@HugoSH try #3362 , it updates lwip to v2, while we're currently on 1.4. There have been several reports about improving the handleClient time.

@devyte
Copy link
Collaborator

devyte commented Oct 5, 2017

@geoffreyhhh et al
this firmware doesn't support concurrent multithreading, and afaik, the Arduino standard Scheduler also hasn't been ported. Doing that requires a rather huge effort in an old piece of code that has very high impact, because it affects yield and delay functions, and it's therefore very risky.
There are two esp-specific scheduler-like libs out there in gits, and there is also the FreeRTOS firmware, but they all have certain drawbacks.
You shouldn't need to do multithreading, there are round-robin methods with timing checks that can be just as good, and use less resources.
But this is not the right place to discuss these thing. Closing as off-topic, see #3655 .

@devyte devyte closed this as completed Oct 5, 2017
@HugoSH
Copy link

HugoSH commented Oct 5, 2017

Thanks! Let me go there to take a look.

@ozanhan
Copy link

ozanhan commented Oct 23, 2017

@anmaped i got compile errors for nodemcu 1.0

@MacLeod-D
Copy link

Here you can find a full blown up tutorial for multitasking with ESP8266:

Without WiFi:
https://github.com/MacLeod-D/CoopOS-Lessons-English

And a Demo with Wifi
https://github.com/MacLeod-D/ESP8266-Multitasking-CoopOS

Have fun ;)

@Sagar73594
Copy link

Here you can find a full blown up tutorial for multitasking with ESP8266:

Without WiFi:
https://github.com/MacLeod-D/CoopOS-Lessons-English

And a Demo with Wifi
https://github.com/MacLeod-D/ESP8266-Multitasking-CoopOS

Have fun ;)

Great Scott.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests