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.
ESP8266 is single-core, so you can't run stuff simultaneously anyways.
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
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.
@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 :smile: I like s/w that is saying in plan text what the problem is :+1:
Krzysztof
@geoffreyhhh Hi, I recently found this article: https://www.hackster.io/feilipu/using-freertos-multi-tasking-in-arduino-ebc3cc?utm_source=Hackster.io+newsletter&utm_campaign=9665148c8a-2015_4_17_Top_projects4_16_2015&utm_medium=email&utm_term=0_6ff81e3e5b-9665148c8a-140388981 - but have not tried it with ESP yet.
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.
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.
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 Foundnn";
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.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();
}
I have to say, I still don't understand your problem. Are your loop2() and loop3() terribly slow, then?
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.
FYI: Github/Makuna/Task is a non-preemptive multitasking library support that cross Arduino compatible.
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.
+1 on this topic; I have a lot of use cases for cooperative multitasking on the ESP
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)
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' ?
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?
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
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.
@ 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?
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);
}
}
Is this supported on esp?
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. :(
@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.
@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 .
Thanks! Let me go there to take a look.
@anmaped i got compile errors for nodemcu 1.0
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 ;)
Most helpful comment
@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 :smile: I like s/w that is saying in plan text what the problem is :+1:
Krzysztof