If anyone gets bootloop with message: 'Debug exception reason: Stack canary watchpoint triggered esp32 core..." make sure you increase the stack (the 1000 in task init), 8192 worked for me. This 5 year old article was a great guide. Thanks Andreas.
Hi Andreas! Thanks for the great quality videos. I have a mechanical engineering background and I am moving my first steps towards mechatronics as an hobby and your material has high educational value to me! Thanks for sharing!
One of your best videos to date, Andreas. I expected you to achieve asynchronous tasks, but explaining semaphores and using them to achieve synchronous (procedural) execution, and the persistence of global variables across cores was an added bonus I wasn't expecting. Fantastic work, thank you and keep it up!
I don't know how you and others like Great Scott, Kevin Darrah upload content which is just so relevant to my current studies. I swear, a couple of times, I've been scouring the web for something I've wanted to learn, and then POOF : A video by one of you to help me with exactly that. I've had to pinch myself, if I'm being honest. Oh and before I forget, YES, I AM studying RTOS right now! For the ARM7 processors, though. All hail RUclips and people like you!
Andreas, you're a TRUE star (complete with your ubiquitous 'Swiss Accent'). I always enjoy your videos. I haven't yet done anything much with ESP32 boards as I've tended to concentrate more effort on ARM based SBCs (OLinuxuinos, Beagle, OrangePi, BananaPi, RaspPi etc), but my soldering iron is beginning to show 'twitching' signs of neglect. As soon as I can muster up some form of project to suit it, I'm sure I'll have the flux flowing... Thanx dude (from a guy with a Kiwi Accent... LOL)
Never visited your country so far... Maybe I can change that when I stop working. I strongly suggest you try this part of electronics. It enhances the useability of the part you are using now.
Great video as always! :-) Thanks for keeping your videos still simple, straight forward and easy to understand (e.g. using Arduino IDE), instead of getting more and more theoretically. This really is an outstanding advantage of your videos, if I compare it to other electronic channels. Your channel is way more valuable for me than any other...
Wasn't too complicated at all Andreas, fantastic job explaining it quickly and concisely. I wrote Hackster's article on "Multithreading" an Arduino. I might have to write one for ESP32 now and reference your video!
@@AndreasSpiess No, this is great! Your balance is for me perfect, and with the great advantage (compared to many RUclipsrs) is your stringent editing where you do not waist words/time. Pausing and looping back in a video is so much better than fast forwarding to get past blablabla! I am a proud to be a Patreon supporter, and I just bought you a coffee as a special thank you for this video. (I am finally about to transit from ESP8266 to ESP32, and your videos is the obvious starting point.)
This is fantastic! I've already forwarded this link on to friends (even though it's two in the morning here)! I'm also creating a dual-threaded process where one core monitors sensors and the other does display and uploading of data (which are passed via global scope variables). This is absolutely great, Andreas! I will henceforth use your framework for all my ESP32 projects!
It works! I created a typedef struct definition and instantiated a global scope variable - this is used to transfer data between cores. Core 0 polls an attached SI7021 temperature and humidity sensor, loads the data into the global scope variable, and then delay()s to control the timing. Core 1 reads the data buffer struct, displays the data on an OLED, and then uploads the data to adafruit.io (which is Adafruit's IoT/cloud offering.) Works like a charm! I couldn't have done it without your guidance, though! [Oh, and this is running on the Adafruit ESP32 Feather.]
Hello Andreas! First I need to say that I enjoy all of your videos due to your skill in explaining the concepts involved and walking us through your engineering based approach. I am very interested in the ESP 32 however and really enjoyed this example on how to utilize the three cores and learn the basics of RTOS! I didn’t even realize Freertos was ported to the ESP 32. So useful to me, can’t wait to try it on my own devices. Time for me to become a patron!As always keep up the interesting work on all the things you are interested in.
Hi Andreas, Awesome video! .. as always.... You describe it correct, that you have to use semaphores to protect access to shared variables, but in your code I think you use it *outside* of the protected block. counter++ should be inside that block. Otherwise you can introduce very very hard to find errors, especially in more complex scenarios. The synchronization of the starting point of the tasks itself does not neccessary fulfil that!
7 лет назад+4
Luckily the blink delay is different by 200ms, so the increment are never at the same time. But you're right: counter++ should be between the take and give...
+Walter Steinchen I know the problem but not the solution in this scenario (how to define protected variables). However I think, using semaphores can be used to prevent a double update. But I am still looking for a definition like "volatile"
Andreas, excellent video, but access to the global variable isn't exactly being controlled by the semaphore. At least not the way the video explains it. In the code it seems more like a side effect rather than proper handling. As long as folks know that more work needs to be done on the subject they can resolve the 'heisenbugs' (I like that name).
For the main loop(), "vTaskDelete(NULL); " I believe is a good solution - it will immediately stop execution of the "main" thread. You could even use it at the end of setup() to never enter loop()
Happy Sunday Morning Andreas 😀😀😀😀😀 Another very welcome addition to the ESP32, dual cores, cooooool. Still very much enjoying your new format😀 Your the magician that shows us all the tricks ✅ Bravo ✌️
HI Andreas! What a coincidence that you covered RTOS as I was just starting to play with RTOS on the Arduino Mega (because I ran out of memory on the Nano) for my ping pong led cube. Now that I learned from you that the ESP32 supports RTOS and I won't have to leave the comfort of the Arduino IDE, I certainly would use the ESP32 instead of the Mega. Thanks Andreas! Great content as usual!
I definitively would go for the ESP32 if it has enough pins for your application because it is much faster than a Mega and I think, also more memory. And maybe you can remotely control your cube?
Hari Wiguna be careful if you want to use digitalWrite though - the ESP32 can be slower than the classic Arduino, or at least not as fast as one thinks. I might have learned that in one of Andreas's videos.
Excellent video once again. I have been using ESP8266 modules commercially since the documentation was only in Chinese and personally experienced the frustration that the community was going through where the background WiFi functionality was causing delays and inconsistency in certain routines, especially ones that used PWM. In response to this Espressif came up with the idea to add a second core to do all this stuff while the first was left alone to do reliable networking. This was deliberate and hence the ESP32 solved many problems that we had to learn to work around on the ESP8266. I think that this needs to be kept in mind when assigning tasks to Core0 and only short, non-essential code should be used there. That being said. Thanks for expanding our knowledge with handy, practical tips. Cheers.
Thanks for your reply Andreas. No I don't know more. I think you are much more up to date with the ESP32 than I am. I am simply stating the historical basis for the second core and went by what Espressif were saying at the time. I was unaware that the new Arduino interface for the ESP32 was layered on top of RTOS. If the default for WiFi and user-defined are both core 1 then that would kind of defeat the purpose of the second core unless RTOS has already taken the balancing of tasks into account.
I learnt something today :). It would be good one day to have some kind of beginners masterclass for code architecture in this wonderful new world to reduce blocking and waiting. I'm sure some design patterns will be tidier than others!
Wow - totally cool! Thanks, Andreas, I had no idea that it was possible to access the two cores as simply as this. Fun playtimes ahead! Regards, David (UK)
I've been a firmware engineer for a considerable time now, and I have some very good experience with FreeRTOS, semaphores, and IPC in general. This opens up a whole new world for me with the ESP32 boards, and since winter is coming, I very much want to play. Thank you kind sir.
Andreas you are brilliant because you every time i have a question you answer it in your videos like you are sitting in my head :) so thank you very much.
This is really really interesting! I'm now working in Arduino/AVR worlds and still there's a lot to learn in AVR programming. I also have ESP8266 modules that haven't work with until now, moving to this new ESP32 is a huge improvement for me.
@@AndreasSpiess wow I'm just imagining that new world 😊 now I just to write my C library of the nrf24l01. But with the ESP modules, the WiFi is built-in so that's more juice. I know it won't be easy to work with the nrf24l01 modules. But the work you do in calibration and testing modules is so much interesting.
GREAT tutorial Andreas !!!! Thanks ! This will move some people to the right direction (including myself) Hope to see more dual core tutorials from you Awesome !
I've just remembered that I did some work on parallel programming for control some years ago. I found that in many simpler applications, there was no need for software synchronisation (e.g. via semaphores); the synchronisation came via sensor feedback in the real world. That means that there are many practical applications one can code up for twin cores without having to use semaphores at all. Hope that's helpful, regards, David
I'll second that - in spades. If you really have a good understanding of what you're doing - or can "be the computer(s)" in your head, oftentimes you don't need to block on semaphores or mutexes or even spin-busy on a shared boolean. My outfit wrote quite a bit of "very high 9's" software for some telecom manufs using this trick - and some of it hasn't crashed since started in the 1990s. But! You'd better darn well comment in unmistakable ways "the wires that aren't there because they don't need to be" - why you can do this without all those moving parts. Because someday, someone else is going to touch that code and since it looks easy - will not bother to undertake a full understanding, and that's when your phone rings at 3 am...Of course, that other person might be future you who has forgotten the plan. But it's still worth it - even though they take awhile to type - comments run VERY FAST! They also don't take up a lot of space in the runtime(!).
almost 5 years later, still an excellent video. 2 comments: (1) changing the counter on both tasks can cause a collision. I would recommend adding it to the semaphore stage, so it is guaranteed to be safe. (2) Why using delay() function? this is bad practice, especially when interrupts are used. I recommend use the millis() command.
Thanks for the video Andreas, lots of great info. I got a MAX7219 Led Matrix display being scrolled on one core (using a task, core 0) while the other core fetched the data (just using the loop). It's great because you can now scroll without any interruption!
You should always take the baton before accessing global variables, and give it back after accessing them. This includes writing access and reading access. If two tasks are writing at the same time the outcome is undefined. And if one is writing and another one is reading the data may be inconsistent, the writer may have started changing the data but not finished when the reader starts reading. Nice video as always, many thanks.
You are right. I used the sketch for parallel blinking as the example for the counter. The serial blinking example had the right order of the commands to protect the counter variable.
An explanatory video like this in such a good tempo is fascinating. No wonder to see so many positive reactions. But certainly you spend time to produce. Thanks, Andreas, for that. I have a question that will make using both cores even more interesting. What about interrupts and ISR's? Which core is handling interrupts? Say we have a process that produces many interrupts, you could think of an Rotary Encoder. Pololu has motors equipped with an Encoder. So I was thinking of using the Encoder info for a feedback to control the speed of such motor - now Pololu is offering very expensive motor controller boards from RoboClaw to perform such task. Would be nice if we could do this with an ESP32 for less then 10 $. My idea is: - one Core is handling all interrupts from the encoder and shares the shaft position info with the task running on the other core - other Core uses this position info to calculate if motor runs to slow/fast and corrects the speed of the motor For a project with 22 motors that have to run at the same speed this will be a money saver. Thanks if you will think about this, Jop The Netherlands
Hi Andreas. You asked for comments on global variable from different threads. Generally, updating a shared variable should be done from within locked section (only while process has the batton), never outside it. In general, counter++ is three assembly instructions - fetch the value from ram to processor, increase, then save back to memory. The reason why it worked for you so far is that probability is very low at 240 MHZ for one core to change the variable between steps 1 and 3 of the other core.
I was looking for how the OS supports the concept you describe. I assume that RTOS has a particular way of protecting variables which does exactly what you describe without programmer intervention.
I doubt that RTOS will just magically prevent simultaneous access without explicit locking. In a full-featured OS you still have to use mutexes and semaphores and FreeRTOS is a barebones operating system, more like a threading library. If your code were to read the value, wait one second then change and write it to memory, from OS point of view you are doing same thing as counter++ but with a bigger delay and bigger chance that something will change the value between your read and write. How would OS know in which case you want protection and in which not? In this case probability is millions to one that your code will work without locking. In general case, you should use semaphores for shared data.
I just know how we deal with this during interrupts: We switch the interrupt off before we do the change and switch it on afterward. This prevents another interrupt with a higher priority corrupting this "logical unit of work". I was looking for a similar concept to tell the OS that it must not interrupt for a moment.
Hi Andreas, If you decide to do a follow up on proper inter process communication it is worth checking out the concept of read/write memory barriers. In these comments I see a lot of people assuming guarding a section by a lock/semaphore is sufficient for communication using global variables, however in some cases the compiler can rearrange instructions in such a way that they end up outside of the lock if there are no memory barriers. I am not sure if this would be an issue in this environment (arduino/rtos). In general though people that are smart enough to write proper multi threaded code tend to use higher level constructs like queues/messages if possible, because writing/debugging it low level is hard.
@@AndreasSpiess Yes, you can do __atomic_add(mem, value) as with atomicity.h in esp32. So incrementing would just be __atomic_add(counter, 1). It will do the add and store all in one unit so that no other tasks can interfere during the operation.
Andreas, eres un súper mega chingón!!!! Esta información es muy útil. Muchas gracias por compartir, eres un mega máster. Te mando un cordial saludo desde la ciudad de México!!!! Un abrazo!!!! Víctor Murcio Mansilla
*Use queues for communication between tasks.* They are one of the core principles of parallel running programs. All the semaphore handling is done for you. You just have to write into and read out of the queue. It can also be inherently synchronizing (a write blocks while the queue is full, a read blocks if the queue is empty). In simple cases you transfer a value. In more complex (and flexible) cases you send a structure, you define, e. g. containing a command and a value. It is a different concept than reading and writing a single variable, so queues are not a 1:1 replacement. The programs have to structured differently. But it is the way to go in parallel tasks for the very common "producer-consumer" pattern of programs (like the very typical "sensor-to-display" programs you run on micros).
Definitely the way to go with coordinating the operation of different tasks. There's still a use for semaphores and indeed volatile global variables. The latter when you have e.g. only one task setting variables and others only reading ... And there is no need for coherence between variables ... or if any task can set a flag upon which others must also act... Such as a shutdown in the event of a crtical system fault.
Using them with Arduino seem to be easy (and is on the same site you already linked to ;) ): techtutorialsx.com/2017/09/13/esp32-arduino-communication-between-tasks-using-freertos-queues/
Btw. the special thing about an RTOS is not that it can run multiple tasks. Pretty much any OS can do that (there even are some for AVRs). But an RTOS usually has a guaranteed maximum time until a task gets processor time, so it won't be "starved" by other tasks. You don't even need multiple cores for that.
I saw the queues, but thought, this would be too much for this video and maybe is something for an entire one. But unfortunately it still does not solve the issue with global variables
I really got into using the ESP32 for wifi radio. I have built several versions now, all based on the little powerhouse. My latest are now being built into old amps for apple phones and iPads.. I have been locating the 5 volts inside and building the units inside the case, hook them up so the aux will switch them on. They play wonderfully, I left off the ability to change stations locally and still use my cell phone for tuning in the channels should I ever wish to listen to something. I picked up a couple of different brands of these devices 2 of the 3 that I have had room inside to stuff the ESP and the decoder. To protect the ESP inside the case I soldered all the wires then used a heavy duty heat shrink tube to cover it and shrink it down . This way there is little chance o it shorting out
Thanks for the video. It is very structured and clear. RTOS is about being "real time". The RTOS guarantees execution of the command at that specific time. This is essential for real time control. Conversely non real time OS such as Windows, does not guarantee that an instruction will be executed exactly at the programmed time. For example, In Sleep(1); Print("now"); Print statement may not be executed exactly after a sleep of 1 msec in non RTOS. This is because non RTOS drivers for example filesystem and network drivers may take longer than 1 msec before returning control back to the OS. In real time control systems, this unpredictability is disastrous. Hence RTOS is about "real time" and it is a big deal, very big deal. RTOS are expensive. Hope this is useful. I am sure you can explain it much better than I can, thanks.
Hi Andreas, this is a very good educational video! But are you planning to make upcoming videos about how to use ULP co-processor in near future? I haven't found any resources that explain to me how to use ULP in Arduino IDE yet. Thank you!
ULP is programmed by an assembler language and I doubt that it will be programmable by the Arduino IDE soon. You have to go the extra mile to achieve that.
Hello, ExpressIF has created some C macros that allow to program the assembly of the ULP using C (see github.com/espressif/arduino-esp32/blob/master/tools/sdk/include/ulp/esp32/ulp.h). This means that you can program it even on the Arduino IDE. There's not very much around, except this working example: gist.github.com/tomtor/99e2a33bfa404ff99454aa94fc0df804 It would be great if Andreas could dedicate a video to it ! (this is not an easy one !)
Excellent video! I used it and it's working fine. Core_0 to manage wifi, RTC and automation and Core_1 to manage Telegram Bot messages (chat bot). Although I had to change the _Stack size of task_ from 1000 to 8192, to stop getting _stack canary watchpoint triggered_ error.
Thank you Andreas! So far, Espressif is very responsive to bug reports against the Arduino IDE core, but the esp-idf is Espressif's preferred development framework. Problems get solved on esp-idf first. For example, Bluetooth works very well from esp-idf. Bluetooth didn't work at all from Arduino last time I tried.
You are right. But for the moment, most of my viewers want to stay with the Arduino IDE. So, we have to take what we get (and create some push on Espressif by using their chips).
To properly handle a scenario where two functions might access the same variable at the same time, (as in 10:50) I believe you'll want to declare it as "volatile" in the IDE. For example: volatile uint8_t counter = 0; In the past, this has solved situations on AVRs where I had a variable which was accessed occasionally in the loop, and very often in an ISR. Without declaring as "volatile", the ISR would have a chance of interrupting the "write" process of a variable in the loop, and would be unable to read it in the interrupt due to the corruption. I think "volatile" declarations force reads and writes to totally complete before anything can interrupt it.
I am not sure if this concept works for two processors. I know it works for one. But this problem is much easier to solve as you just can prohibit an interrupt for a short time.
Yeah, maybe not. I've got an ESP32 coming in the mail soon that I feel will kick me in the butt trying to fully understand it. I've been on your channel for about an hour watching ESP32 and LoRa videos to study it - keep up the great work Andreas!
Defining variable as 'volatile' is definitely a step in the right direction, but isn't quite the ENTIRE answer. The reasoning behind 'volatile' was more for the purposes of variables that could be altered in either the normal flow of a process, or perhaps in some ISR (Interrupt Service Routine), but this is still on a uniprocessor setup albeit with two distinct 'threads' of operation.. Thus, the 'volatile' definition was / is a 'hint' to the compiler that it should not 'cache' the value of a variable as it could quite possibly change BETWEEN sequential instructions in the normal flow if an interrupt had occurred. What's required is a second step of mutual exclusivity (often called a 'spinlock') that guarantees exclusive access to the variable(s) in question. The goal of a 'spinlock' supercedes ANY other asynchronous event (whether it is an interrupt, or perhaps even an entirely different CPU core), from modifying some fundamentally exclusive piece of data. Concepts such as spinlocks become VITAL when you start developing non-trivial software (eg: The Linux kernel). In the OLD days, much of the Linux kernel revolved around a single HUGE spinlock that was known as the BKL (Big Kernel Lock) which inhibited almost every other possible thread from execution. Now that the kernel has significantly 'matured', the 'granularity' of spinlocks has been significantly improved such that threads are far less likely to be 'blocked' waiting for the release of the BKL from some totally independent mutual exclusion. (Imagine having to 'stall' every single core of your 28 core beast simply because ONE of those cores wanted exclusive access to the UART ringbuffer. That's how it was actually done in 'the good old days')
Hi Andreas, I noticed that in your examples, xTaskCreatePinnedToCore is used in the setup. What if I want to enable and disable the task running on core 0 throughout my main loop? For example, I want to use core 0 to monitor an encoder while core 1 is driving a motor. I do not want core 0 retrieving values from the encoder when the motor is not running as I am using a shared SPI bus with the encoder and other sensors that are being monitors on core 1.
Nice video Andreas.....Cool.....have you run an video on how to prepare the Arduino IDE environment to program these devices. Remember a video from around a year back but then the libraries were not mature yet
Great video. I must say though that I’m getting more into programming the ESP32 in eclipse using FreeRtos and Its very nice. You get to use tasks like you did but with autocomplete
Hi, knowing about your obsession with battery efficient projects I have expected you will cover usage of ULP co-processor first. I hope the next video will be about how ESP32 can run on coin cell "forever" ;-) Million thanks.
Wow, ESP company did a lot of work building the RTOS and Semaphore. Really difficult to figure out. Very good example. Like you said Global Variables pass between Cores easily enough although the variable is susceptible to data corruption. Creating a class to pass Variables using pointers would be the normal way of securing the data as the address is what is passed not the data. Although there are also security issues with this as well. Because if the pointer is changed your reading the wrong data. Setting up the stack properly and ensuring the function doesn't exceed the stack size would probably secure this better. But just thinking out loud. Wondering if you can demo using ADC and seeing how sensor data can be read and Transmitted to another ESP32 using the dual core would be neat. Have a great week and thanks for the upload.
"Here is the guy with the Swiss accent...again..." - I always enjoy hearing that intro - it's your signature trademark. My wife gets a kick out of it too (sometimes she listens to my youtube tutorials LOL). Thank you for this video. I've been using the ESP8266 exclusively since the ESP32 software arduino support seemed to be very much in alpha/beta release. Based on your recent videos on the ESP32 it seems it's slowly starting to stabilize and become very useful (still missing bluetooth though). I like the intro on RTOS and the simple example - not so intimidating after all. Do you think it's possible to control two different GPIO pins in a task running on different cores?
1. I am glad to hear, that your wife increases the share of female viewers of this channel 2. If nobody uses a software, the supplier has no need to improve it. Typical catch 22. Maybe my videos help to change that. 3. Maybe you just try with the GPIOs. I assume, with synchronization of the tasks it should work.
Another awesome video. The ESP-32 is displacing our beloved ESP-12 as the go-to IOT module. Have you had any success accessing the third (low-power) core? Perhaps the biggest problem with the Expressif chips is their power requirement. If you are polling for an activity (pin pulled low, for example), could you deep sleep the two "fast" processors and just watch with the "slow" processor? Then wake the fast processors to do the processing?
Love this. Using this on my LED clock - bought 0.8" LED display and the core0 just refreshes the display, core1 does the logic. All of it is done using 1 ESP32, 4 resistors (100ohm) and 1 LED display. Btw, I had a watchdog problem with core0 in Arduino. I had to add these 3 lines to the for(;;) loop: TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0;
A much simpler way is to use ESP32's Ticker Function. I tested, the attached ticker function is run on Core 0. Which is good for scheduled tasks. And it's easier to implement in self-made classes or libraries. And if you want to make something like loop() without delay(), just set the ticker time to 0. eg: myTicker.attach(0, functionName) Thanks, Andreas. I use ticker sometimes but not for the second core only for scheduled tasks, and lately, I want to use the second core of ESP32 and watched this video. And got the trick of Serial.println(xPortGetCoreID()); and I thought maybe Ticker is a TaskHandle_t, too. Cause TaskHandle_t can be seen in a lot of ESP32 Arduino's attached libraries. And I tested the Ticker example, Ticker is run on Core 0! Test sketch: #include #include #define LED_PIN 2 Ticker blinker; void blink() { digitalWrite(LED_PIN, !digitalRead(LED_PIN)); Serial.print("Blink Task runs on Core: "); Serial.println(xPortGetCoreID()); } void setup() { Serial.begin(115200); Serial.print("Serial freeHeap: "); Serial.println(ESP.getFreeHeap()); pinMode(LED_PIN, OUTPUT); blinker.attach(1, blink); //blinker.attach(0, blink); Serial.print("Setup freeHeap: "); Serial.println(ESP.getFreeHeap()); Serial.print("Setup Task runs on Core: "); Serial.println(xPortGetCoreID()); } void loop() { delay(60000); } ====================================================================================================== One big difference between Ticker and Task is that the Ticker management seems to be One Single Task on Core 0, so Tickers are processed one by one. Ticker1(){delay(1000);} Ticker2(){delay(1000);} They both attached with interval 0. Ticker1 and Ticker2 will be triggered every 2 seconds. Tickers are get queued just like the normal loop(){}; And if create Task1 and Task2 both on Core 0. They will be triggered every 1 second. That means Tasks are really independent to each other. So Ticker is a simpler method to use Core 0 like the loop(). And Task is a more advanced tech indeed.
The most useful tutorial I've ever run into. Good work... But I was wondering about what we can do for the watchdog timer and how to solve its errors... Big thumbs up 👍👍
Awesome thank you! This will help with my current project I will have one core listening for bluetooth instructions and the main core runs the main block of code. As an aside, anyone who listens to the amp hour podcast should remember a few episodes ago the talked to Jeroen Domburg who now works at espressif who told us that it runs freertos and is multi core...although looking it up I know realize that was actually not that long ago but anyway yea...
Peter S - lol Peter S! I did not expect to find you on this side of the internet! it's funny how we're both interested in politics and electronics 😄 P.S. your profile picture is easy to notice 😂
Hello Daniel, I'm an EE who designs and manufactures building automation gear and I've been a hopeless nerd since the early 1970s. My computing career started on IBM punch-cards which were legacy at the time but still in common useage around Silicon Valley, where I grew up. Previously I was director of engineering for a $200M/yr Macintosh peripheral manufacturer where I was designing and building Thunderbolt II / USB 3.0 RAID enclosures most of the week but that got old because I was working for a hardcore conservative CEO/owner with 200+ conservative employees and had to live in conservative Texas. I am a San Francisco Hippy and Texas is not my thing even if BBQ is some of the best food in the world and their craft beer is amazing. His mother was dying of stage 4 cancer after surviving cancer twice before and I introduced him to the data about cannabis killing cancer cells without harming healthy ones. Her doctors had given up and left her for dead but he confirmed the data I gave him and she started cannabis flower extract oil treatment. She went from terminally ill to cancer free within 18 months and I permanently shook my CEO's faith in conservative thinking. When I quit the guy had removed cannabis from his company drug testing and he supported gay marriage while his wife was still an obvious bigot. He told me he was pissed off that he had been lied to by the people who taught him his conservative values. It took the hopelessness of his mother's mortality for him to finally realize this. His wife even asked him if he was becoming a liberal after I had worked on him for a year. That opened the door for him to start telling other conservative people that they had been programmed by lies and he told me he has since spread his story to well over 100 other medium to large corporate CEO types. I'll also add that I've been a very vocal proponent of medical cannabis for over 20 years with a couple years of tabling at events for TexasNORML where I performed outreach using a large base of peer reviewed data to back my arguments and I am most likely the first person in the Western Hemisphere to put bar codes on retail cannabis which happened at a San Francisco dispensary I wrote the point of sale system for back in 1999. So anyway... now you have a better idea of who I am than 99.9% of the people on the political channels. I'm not a big fan of politics but they affect me and I must do what I can to better all people. I'm far more interested in research concerning the endocannabinoid system, embedded processing, and mountain biking. Best wishes, -Peter
Peter S - Wow, That's an amazing background story :D I really don't have much to tell, I'm a 22 year old guy that has been programing videogames on game maker since I was 13. Graduated from one of the best engineering high-schools in Mexico with my own developed wireless comunication (like Bluetooth) system and then came to the US (legally) to finish my degree. I currently finished developing a text based operating system on my own. Now I'm integrating it into any microcontroller that can handle the code. (an arduino uno or better) The proof of concept is in my smartwatch based on the esp32 (if your interested, I could make a video presenting showing my operating system working and explaining the impact this could have in the WHOLE microcontroller industry). I'm planing to show it at some fancy company and get hired in any development type area. I am struggling to get the first step because I lack of any contacts that can hook me up.
Wow! That's very cool. I started by programming games too. That's an excellent path. The tools these days are so amazing, they allow you to really set your creativity free. My first home computer was an Apple ][ back in 1978 with 16K of RAM and a 1MHz CPU that was over $2000 in 1978 dollars. Now a $10 ESP32 can do so much more that it's almost silly. I am envious of your generation in many ways but I'm also grateful I got to listen to 1980s music as it was being made. Anybody who can design an RF communications system is very impressive to me, as are people who can speak more than one language, so you are doubly impressive. Americans are probably the least linguistically knowledgeable people on Earth so being bilingual is an excellent and valuable skill to many development companies. Developing an operating system is also impressive so make that you are triply impressive. I appreciate your offer of an explanation video however at the moment I am in the middle of designing a system for a client based on 12 different ARM Cortex M4 nodes on CAN-bus and my head is so full that it's leaking so I must decline your offer, but I encourage you to make such videos and place them on RUclips because they can be a very powerful tool for getting a job. I also encourage you to make them several times over a few months like each is practice for the making the next and get feedback from your peers to help with refinement. Most of the time people make documentation only once and it's like the 1st time a musician plays a song, no matter how good it sounds, you know that the 100th time will sound better because of practice. Your 4th video about a subject will typically be far better than the 1st. I pay attention to how creative people are when I hire and my last hire got their job by showing examples of building guitar sound processing circuits she had developed and others she built from designs on the net. Showing examples of what you can build is more powerful than most things you can see written in ink. For most positions I deal with, to me a physical example of something you designed and built is far more powerful than a degree from anywhere. Einstein did not possess a degree in Relativity Theory and he was reportedly a very poor student. There are some positions where a deep education is necessary but most positions from my experience require somebody who is capable and enthusiastic and able to adapt to the needs of the moment rather than somebody with a piece of paper. Once you make it into a development lab, somebody like you will naturally advance so don't worry about entering as a technician as long as the pay is acceptable. I wish you the best and perhaps the best advice I could give you is to be very persistent and get your resume out to lots of potential places because it's a numbers game, but above all make sure you're happy where you work because you cannot buy happiness, you can only generate it.
Thanks for that great video, really helped me a lot in a project :) I would also be interested in some information how to switch the second core (and other sub modules I don't need) completely off to save more energy and how to set the clock frequency of a core. Cheers!
Maestro, the quality of this video exceeds even your usual high standard. Superb job sir!
Thank you for your nice words!
HOLY CRAP!!!! Brilliant! This is going to to be one of your most classic videos Andreas!
I hope so ;-) Thanks for your compliment!
RIP arduino. We had a good run
As always.. to the point and amazing... Always learning new thing with your videos... You are a blessing Andreas.. 😀
Thank you!
I agree
This is one of the coolest videos you have ever made in my opinion! Great job!
I was astonished about the reactions on this video. I thought, it is too hardcore for RUclips and expected only a few viewers...
If anyone gets bootloop with message: 'Debug exception reason: Stack canary watchpoint triggered esp32 core..." make sure you increase the stack (the 1000 in task init), 8192 worked for me. This 5 year old article was a great guide. Thanks Andreas.
Thanks for the additional information!
Hi Andreas! Thanks for the great quality videos. I have a mechanical engineering background and I am moving my first steps towards mechatronics as an hobby and your material has high educational value to me! Thanks for sharing!
I tried the other way round when I bought my milling machine. It was hard for me ;-)
One of your best videos to date, Andreas. I expected you to achieve asynchronous tasks, but explaining semaphores and using them to achieve synchronous (procedural) execution, and the persistence of global variables across cores was an added bonus I wasn't expecting. Fantastic work, thank you and keep it up!
Thank you for your feedback. I think, without semaphores, two cores are not very useful ;-)
You are right.
I don't know how you and others like Great Scott, Kevin Darrah upload content which is just so relevant to my current studies. I swear, a couple of times, I've been scouring the web for something I've wanted to learn, and then POOF : A video by one of you to help me with exactly that. I've had to pinch myself, if I'm being honest. Oh and before I forget, YES, I AM studying RTOS right now! For the ARM7 processors, though. All hail RUclips and people like you!
Glad to be of help. I also learn a lot through RUclips!
I was thinking the same thing. I just got the itch to explore ESP32 bluetooth again and Andreas posted a video the day before!
The guy with the Swiss accent is kicking some serious ass -- great job!
:-)
Great video, as always! I'm still using the 8266 everywhere, but videos like this are really encouraging! I'll make the switch eventually!
I also use the ESP8266 for normal jobs, because I still have a few laying around...
Andreas, you're a TRUE star (complete with your ubiquitous 'Swiss Accent').
I always enjoy your videos.
I haven't yet done anything much with ESP32 boards as I've tended to concentrate more effort on ARM based SBCs (OLinuxuinos, Beagle, OrangePi, BananaPi, RaspPi etc), but my soldering iron is beginning to show 'twitching' signs of neglect.
As soon as I can muster up some form of project to suit it, I'm sure I'll have the flux flowing...
Thanx dude (from a guy with a Kiwi Accent... LOL)
Never visited your country so far... Maybe I can change that when I stop working. I strongly suggest you try this part of electronics. It enhances the useability of the part you are using now.
Fast, to the point, very didactic and very entertaining. You belong in the hall of fame of youtube of engineering Andreas. Cheers
Thank you for your nice words!
Great video as always! :-) Thanks for keeping your videos still simple, straight forward and easy to understand (e.g. using Arduino IDE), instead of getting more and more theoretically. This really is an outstanding advantage of your videos, if I compare it to other electronic channels. Your channel is way more valuable for me than any other...
Sometimes I think, my content is too complicated (for example for this video). But then, the feedback seems to be ok...
At least for me it's perfect :-)
Wasn't too complicated at all Andreas, fantastic job explaining it quickly and concisely. I wrote Hackster's article on "Multithreading" an Arduino. I might have to write one for ESP32 now and reference your video!
@@AndreasSpiess No, this is great! Your balance is for me perfect, and with the great advantage (compared to many RUclipsrs) is your stringent editing where you do not waist words/time. Pausing and looping back in a video is so much better than fast forwarding to get past blablabla!
I am a proud to be a Patreon supporter, and I just bought you a coffee as a special thank you for this video. (I am finally about to transit from ESP8266 to ESP32, and your videos is the obvious starting point.)
This is fantastic! I've already forwarded this link on to friends (even though it's two in the morning here)! I'm also creating a dual-threaded process where one core monitors sensors and the other does display and uploading of data (which are passed via global scope variables). This is absolutely great, Andreas! I will henceforth use your framework for all my ESP32 projects!
+Philip Moyer Please come back with your learnings. This is still new technology.
It works! I created a typedef struct definition and instantiated a global scope variable - this is used to transfer data between cores. Core 0 polls an attached SI7021 temperature and humidity sensor, loads the data into the global scope variable, and then delay()s to control the timing. Core 1 reads the data buffer struct, displays the data on an OLED, and then uploads the data to adafruit.io (which is Adafruit's IoT/cloud offering.) Works like a charm! I couldn't have done it without your guidance, though! [Oh, and this is running on the Adafruit ESP32 Feather.]
Thanks for the update. Cool!
Oops. I take that partially back. It works for a while, and then produces nonsense data, and then stops working altogether. Debug time!
+Philip Moyer As I mentioned: I also had some issues to solve....
Hello Andreas! First I need to say that I enjoy all of your videos due to your skill in explaining the concepts involved and walking us through your engineering based approach. I am very interested in the ESP 32 however and really enjoyed this example on how to utilize the three cores and learn the basics of RTOS! I didn’t even realize Freertos was ported to the ESP 32. So useful to me, can’t wait to try it on my own devices. Time for me to become a patron!As always keep up the interesting work on all the things you are interested in.
Thank you for your nice comment. So far, I am not on Patreon. But this might change if I cross the 50'000 subscribers...
Hi Andreas, Awesome video! .. as always.... You describe it correct, that you have to use semaphores to protect access to shared variables, but in your code I think you use it *outside* of the protected block. counter++ should be inside that block. Otherwise you can introduce very very hard to find errors, especially in more complex scenarios. The synchronization of the starting point of the tasks itself does not neccessary fulfil that!
Luckily the blink delay is different by 200ms, so the increment are never at the same time. But you're right: counter++ should be between the take and give...
I second this; nobody likes to search for those "heisenbugs" that this could lead to.
+Walter Steinchen I know the problem but not the solution in this scenario (how to define protected variables). However I think, using semaphores can be used to prevent a double update. But I am still looking for a definition like "volatile"
Andreas, excellent video, but access to the global variable isn't exactly being controlled by the semaphore. At least not the way the video explains it. In the code it seems more like a side effect rather than proper handling. As long as folks know that more work needs to be done on the subject they can resolve the 'heisenbugs' (I like that name).
+Neil Cherry Msxbe the solution is already there and I only do not know it...
I'm stunned by the perfection of this content
Thank you!
For the main loop(), "vTaskDelete(NULL); " I believe is a good solution - it will immediately stop execution of the "main" thread. You could even use it at the end of setup() to never enter loop()
Thank you for the tip!
at 4:42 , isn't that delay(1000) supposed to increase time instead of decreasing it? since the void loop() also is getting exceuted..
@@RakshithPrakash I think that RTOS handles this and does other stuff while the loop is in the delay
@@sasodoma Thats what appears to happen, but it would be better as mentioned above to just stop the loop entirely
Happy Sunday Morning Andreas 😀😀😀😀😀
Another very welcome addition to the ESP32, dual cores, cooooool.
Still very much enjoying your new format😀
Your the magician that shows us all the tricks ✅
Bravo ✌️
If I would be a real magician, I probably would not show you the tricks. Would be bad for business ;-)
Andreas Spiess your the best, you show all your apprentices how to wave a magic wand🤗
:-)
HI Andreas! What a coincidence that you covered RTOS as I was just starting to play with RTOS on the Arduino Mega (because I ran out of memory on the Nano) for my ping pong led cube. Now that I learned from you that the ESP32 supports RTOS and I won't have to leave the comfort of the Arduino IDE, I certainly would use the ESP32 instead of the Mega. Thanks Andreas! Great content as usual!
I definitively would go for the ESP32 if it has enough pins for your application because it is much faster than a Mega and I think, also more memory. And maybe you can remotely control your cube?
IoT LED Cubes! Sounds awesome.
Hari Wiguna be careful if you want to use digitalWrite though - the ESP32 can be slower than the classic Arduino, or at least not as fast as one thinks. I might have learned that in one of Andreas's videos.
afaik our beloved ESP8266 also uses FreeRTOS for its sdk ;-)
The question that comes to mind here is. What am I going to do with all the Arduino boards I have, nano, Uno, Mega.....
Excellent video once again. I have been using ESP8266 modules commercially since the documentation was only in Chinese and personally experienced the frustration that the community was going through where the background WiFi functionality was causing delays and inconsistency in certain routines, especially ones that used PWM. In response to this Espressif came up with the idea to add a second core to do all this stuff while the first was left alone to do reliable networking. This was deliberate and hence the ESP32 solved many problems that we had to learn to work around on the ESP8266.
I think that this needs to be kept in mind when assigning tasks to Core0 and only short, non-essential code should be used there.
That being said. Thanks for expanding our knowledge with handy, practical tips.
Cheers.
Another viewer did some testing and wrote, that Wi-Fi runs on core 1. Do you know more?
Thanks for your reply Andreas. No I don't know more. I think you are much more up to date with the ESP32 than I am. I am simply stating the historical basis for the second core and went by what Espressif were saying at the time. I was unaware that the new Arduino interface for the ESP32 was layered on top of RTOS. If the default for WiFi and user-defined are both core 1 then that would kind of defeat the purpose of the second core unless RTOS has already taken the balancing of tasks into account.
Thanks a lot Andreas for this amazing introduction. Great tutorial, as usual.
You are welcome!
Why all of your video always come when i need it the most😍
Truly magical~
God Bless you Mr. Andreas
Thank oyu! But this one is quite old ;-) So it came too early.
very good, ESP 32 is becoming the workhorse of IOT.
I can't wait to see what Expressif's next big thing is ------ ESP 64 maybe ?????? That'd be nice :-)
+Roy: I think, I have enough to do to learn how to work with what we have with the ESP32 ;-)
You make the best and most informative content on RUclips. A good diversion from all the cat videos... :)
Even if on some of my videos our cat appears ;-) Thank you!
I learnt something today :). It would be good one day to have some kind of beginners masterclass for code architecture in this wonderful new world to reduce blocking and waiting. I'm sure some design patterns will be tidier than others!
We will see where these new possibilities lead us...
This is probably most useful and important video about programming ESP32 I've seen.
I also like this concept of tasks.
Wow - totally cool! Thanks, Andreas, I had no idea that it was possible to access the two cores as simply as this. Fun playtimes ahead! Regards, David (UK)
I also discovered this possibility quite late.
Bravo. I feel much indebted to your brilliant and most useful take on low-end microcontrollers. It is helping me with a lot of DSP applications.
Glad to be able to help.
I've been a firmware engineer for a considerable time now, and I have some very good experience with FreeRTOS, semaphores, and IPC in general. This opens up a whole new world for me with the ESP32 boards, and since winter is coming, I very much want to play.
Thank you kind sir.
Enjoy! I am sure this is a new dimension for Makers...
Andreas you are brilliant because you every time i have a question you answer it in your videos like you are sitting in my head :) so thank you very much.
You are welcome! These are maybe common wishes?
@@AndreasSpiess Yes i think so :)
Brilliant work! You've excelled yourself in this video Andreas! Well done.
Thank you! I was not sure when I did the video. The stuff is quite complicated...
This is really really interesting! I'm now working in Arduino/AVR worlds and still there's a lot to learn in AVR programming. I also have ESP8266 modules that haven't work with until now, moving to this new ESP32 is a huge improvement for me.
And the Wi-Fi connection opens a whole new world of possibilities...
@@AndreasSpiess wow I'm just imagining that new world 😊 now I just to write my C library of the nrf24l01. But with the ESP modules, the WiFi is built-in so that's more juice. I know it won't be easy to work with the nrf24l01 modules. But the work you do in calibration and testing modules is so much interesting.
This is the first of your videos I saw. I am very well impressed about it. Congratulations and Thank you very much
Welcome to the channel!
Great break down of how the ESP32 Dual Cores actually work. Thanks for making me smarter quicker!
Glad to help!
GREAT tutorial Andreas !!!! Thanks !
This will move some people to the right direction (including myself)
Hope to see more dual core tutorials from you
Awesome !
Thank you! We will see where these possibilities lead us...
Hi Andreas, what amazing explanations and examples you did!
Congratulations from Brazil!
Thank you!
Well what can I say, great as always. Looking forward to some Christmas themed videos.
We will see if I find the time...
I've just remembered that I did some work on parallel programming for control some years ago. I found that in many simpler applications, there was no need for software synchronisation (e.g. via semaphores); the synchronisation came via sensor feedback in the real world. That means that there are many practical applications one can code up for twin cores without having to use semaphores at all. Hope that's helpful, regards, David
Thanks for the tip!
I'll second that - in spades. If you really have a good understanding of what you're doing - or can "be the computer(s)" in your head, oftentimes you don't need to block on semaphores or mutexes or even spin-busy on a shared boolean. My outfit wrote quite a bit of "very high 9's" software for some telecom manufs using this trick - and some of it hasn't crashed since started in the 1990s. But! You'd better darn well comment in unmistakable ways "the wires that aren't there because they don't need to be" - why you can do this without all those moving parts. Because someday, someone else is going to touch that code and since it looks easy - will not bother to undertake a full understanding, and that's when your phone rings at 3 am...Of course, that other person might be future you who has forgotten the plan. But it's still worth it - even though they take awhile to type - comments run VERY FAST! They also don't take up a lot of space in the runtime(!).
Tight video, clear and to the point. I like that you don't confuse us with race condition.
Thanks!
This video is great!! and quite useful to get the most from the ESP32!
Thank you!
Andreas gets better and better. One of five top Arduino RUclips channels!
Thank you!
almost 5 years later, still an excellent video. 2 comments: (1) changing the counter on both tasks can cause a collision. I would recommend adding it to the semaphore stage, so it is guaranteed to be safe. (2) Why using delay() function? this is bad practice, especially when interrupts are used. I recommend use the millis() command.
The delay in this scenario is ok because it is handled by RTOS. I agree with the semaphore.
Thanks for the video Andreas, lots of great info.
I got a MAX7219 Led Matrix display being scrolled on one core (using a task, core 0) while the other core fetched the data (just using the loop). It's great because you can now scroll without any interruption!
Thanks for the feedback! Interesting. So it works!
Yup! I had it running for maybe 30 mins or so and it was working fine (I know not a conclusive test, but promising for sure!)
You should always take the baton before accessing global variables, and give it back after accessing them. This includes writing access and reading access. If two tasks are writing at the same time the outcome is undefined. And if one is writing and another one is reading the data may be inconsistent, the writer may have started changing the data but not finished when the reader starts reading.
Nice video as always, many thanks.
You are right. I used the sketch for parallel blinking as the example for the counter. The serial blinking example had the right order of the commands to protect the counter variable.
Awesome video it truly is a different animal the pwm change still gets me I guess I'm use to the original approach but one does get use to the change
Thank you!
Another great video Mr. Spiess. I'll be rewatching and following along with my esp32 😊
Thank you!
Hi, a very interesting video,
I never thought that this was possible on the ESP32
Keep on making such video's!!
I knew it is possible, but not using the Arduino IDE...
Grüezi aus dem Aargau. Late to the party, but I just stumbled on this topic. Comes handyfor my next project!
Good to know. Hope it helps!
Absolutely brilliant. Thanks for opening some more doors into the world of the ESP32.
Thank you for your nice words! We will see what we can do with these new possibilities...
An explanatory video like this in such a good tempo is fascinating. No wonder to see so many positive reactions. But certainly you spend time to produce. Thanks, Andreas, for that.
I have a question that will make using both cores even more interesting. What about interrupts and ISR's? Which core is handling interrupts?
Say we have a process that produces many interrupts, you could think of an Rotary Encoder.
Pololu has motors equipped with an Encoder. So I was thinking of using the Encoder info for a feedback to control the speed of such motor - now Pololu is offering very expensive motor controller boards from RoboClaw to perform such task. Would be nice if we could do this with an ESP32 for less then 10 $.
My idea is:
- one Core is handling all interrupts from the encoder and shares the shaft position info with the task running on the other core
- other Core uses this position info to calculate if motor runs to slow/fast and corrects the speed of the motor
For a project with 22 motors that have to run at the same speed this will be a money saver.
Thanks if you will think about this,
Jop
The Netherlands
So far I never used interrupts with RTOS. So you have to dig into its documentation yourself. I am sure it will be possible.
Hi Andreas. You asked for comments on global variable from different threads. Generally, updating a shared variable should be done from within locked section (only while process has the batton), never outside it. In general, counter++ is three assembly instructions - fetch the value from ram to processor, increase, then save back to memory. The reason why it worked for you so far is that probability is very low at 240 MHZ for one core to change the variable between steps 1 and 3 of the other core.
I was looking for how the OS supports the concept you describe. I assume that RTOS has a particular way of protecting variables which does exactly what you describe without programmer intervention.
I doubt that RTOS will just magically prevent simultaneous access without explicit locking. In a full-featured OS you still have to use mutexes and semaphores and FreeRTOS is a barebones operating system, more like a threading library. If your code were to read the value, wait one second then change and write it to memory, from OS point of view you are doing same thing as counter++ but with a bigger delay and bigger chance that something will change the value between your read and write. How would OS know in which case you want protection and in which not?
In this case probability is millions to one that your code will work without locking. In general case, you should use semaphores for shared data.
I just know how we deal with this during interrupts: We switch the interrupt off before we do the change and switch it on afterward. This prevents another interrupt with a higher priority corrupting this "logical unit of work". I was looking for a similar concept to tell the OS that it must not interrupt for a moment.
Hi Andreas, If you decide to do a follow up on proper inter process communication it is worth checking out the concept of read/write memory barriers. In these comments I see a lot of people assuming guarding a section by a lock/semaphore is sufficient for communication using global variables, however in some cases the compiler can rearrange instructions in such a way that they end up outside of the lock if there are no memory barriers. I am not sure if this would be an issue in this environment (arduino/rtos). In general though people that are smart enough to write proper multi threaded code tend to use higher level constructs like queues/messages if possible, because writing/debugging it low level is hard.
@@AndreasSpiess Yes, you can do __atomic_add(mem, value) as with atomicity.h in esp32. So incrementing would just be __atomic_add(counter, 1). It will do the add and store all in one unit so that no other tasks can interfere during the operation.
Awesome episode on a very interesting and powerfull topic! Thank you very much, Andreas!
You are welcome!
No way I will digg Up My old Uno now. Love the videos
Thank you!
I think the like to dislike ratio speaks for itself, what an amazingly structured and informative video.
Thank you!
This is amazing. You found 2 extra cores where nobody else was looking!
I think we were aware that they existed. But I did not know how to use both inside the Arduino IDE
Andreas, eres un súper mega chingón!!!! Esta información es muy útil. Muchas gracias por compartir, eres un mega máster. Te mando un cordial saludo desde la ciudad de México!!!! Un abrazo!!!! Víctor Murcio Mansilla
Gracias!
@Andreas Spiess... : You are Rocking man... This is Super Practical Video...
Thank you!
*Use queues for communication between tasks.* They are one of the core principles of parallel running programs. All the semaphore handling is done for you. You just have to write into and read out of the queue. It can also be inherently synchronizing (a write blocks while the queue is full, a read blocks if the queue is empty). In simple cases you transfer a value. In more complex (and flexible) cases you send a structure, you define, e. g. containing a command and a value. It is a different concept than reading and writing a single variable, so queues are not a 1:1 replacement. The programs have to structured differently. But it is the way to go in parallel tasks for the very common "producer-consumer" pattern of programs (like the very typical "sensor-to-display" programs you run on micros).
Thanks for your explanation. I have to find out how RTOS (and Arduino IDE) supports that...
Definitely the way to go with coordinating the operation of different tasks.
There's still a use for semaphores and indeed volatile global variables. The latter when you have e.g. only one task setting variables and others only reading ... And there is no need for coherence between variables ... or if any task can set a flag upon which others must also act... Such as a shutdown in the event of a crtical system fault.
Using them with Arduino seem to be easy (and is on the same site you already linked to ;) ):
techtutorialsx.com/2017/09/13/esp32-arduino-communication-between-tasks-using-freertos-queues/
Btw. the special thing about an RTOS is not that it can run multiple tasks. Pretty much any OS can do that (there even are some for AVRs). But an RTOS usually has a guaranteed maximum time until a task gets processor time, so it won't be "starved" by other tasks. You don't even need multiple cores for that.
I saw the queues, but thought, this would be too much for this video and maybe is something for an entire one. But unfortunately it still does not solve the issue with global variables
I really got into using the ESP32 for wifi radio. I have built several versions now, all based on the little powerhouse. My latest are now being built into old amps for apple phones and iPads.. I have been locating the 5 volts inside and building the units inside the case, hook them up so the aux will switch them on. They play wonderfully, I left off the ability to change stations locally and still use my cell phone for tuning in the channels should I ever wish to listen to something. I picked up a couple of different brands of these devices 2 of the 3 that I have had room inside to stuff the ESP and the decoder. To protect the ESP inside the case I soldered all the wires then used a heavy duty heat shrink tube to cover it and shrink it down . This way there is little chance o it shorting out
Sounds like this project is getting better and better!
this is sooo exciting... i just got an esp32 now it is time for my little r&d hobby stuff...:/ thanks loads...:)
Have fun!
nice video! have two of those puppies waiting for their first mission
So enjoy!
Thanks for the video. It is very structured and clear. RTOS is about being "real time". The RTOS guarantees execution of the command at that specific time. This is essential for real time control. Conversely non real time OS such as Windows, does not guarantee that an instruction will be executed exactly at the programmed time. For example,
In Sleep(1); Print("now");
Print statement may not be executed exactly after a sleep of 1 msec in non RTOS. This is because non RTOS drivers for example filesystem and network drivers may take longer than 1 msec before returning control back to the OS. In real time control systems, this unpredictability is disastrous.
Hence RTOS is about "real time" and it is a big deal, very big deal.
RTOS are expensive.
Hope this is useful. I am sure you can explain it much better than I can, thanks.
Thanks for your clarification.
Outstanding!! Such a helpful illustration. Thank you.
You are welcome!
Hi Andreas, this is a very good educational video! But are you planning to make upcoming videos about how to use ULP co-processor in near future? I haven't found any resources that explain to me how to use ULP in Arduino IDE yet. Thank you!
That would make a great topic. @ukrit have you looked at the code for rtos?
ULP is programmed by an assembler language and I doubt that it will be programmable by the Arduino IDE soon. You have to go the extra mile to achieve that.
Hello, ExpressIF has created some C macros that allow to program the assembly of the ULP using C (see github.com/espressif/arduino-esp32/blob/master/tools/sdk/include/ulp/esp32/ulp.h). This means that you can program it even on the Arduino IDE. There's not very much around, except this working example: gist.github.com/tomtor/99e2a33bfa404ff99454aa94fc0df804
It would be great if Andreas could dedicate a video to it ! (this is not an easy one !)
Excellent video!
I used it and it's working fine. Core_0 to manage wifi, RTC and automation and Core_1 to manage Telegram Bot messages (chat bot). Although I had to change the _Stack size of task_ from 1000 to 8192, to stop getting _stack canary watchpoint triggered_ error.
Thanks for your feedback. It is encouraging to see that it works...
Please give me a hint how you did this to solve the same issue... Thanks
Can you be more specific?
Thank you Andreas! So far, Espressif is very responsive to bug reports against the Arduino IDE core, but the esp-idf is Espressif's preferred development framework. Problems get solved on esp-idf first. For example, Bluetooth works very well from esp-idf. Bluetooth didn't work at all from Arduino last time I tried.
You are right. But for the moment, most of my viewers want to stay with the Arduino IDE. So, we have to take what we get (and create some push on Espressif by using their chips).
Agreed, thank you for sticking with Arduino for these types of things. It is much more accessible than ESP-IDF for now.
Dear Maestro, thanks for this great, great video! It is fantastic! Saludos from the south of the world! ;-)
You are welcome!
Thank's for your videos Andreas! Really enjoy them, very good info.
Now i really must buy an ESP32 board.
You are welcome!
To properly handle a scenario where two functions might access the same variable at the same time, (as in 10:50) I believe you'll want to declare it as "volatile" in the IDE. For example:
volatile uint8_t counter = 0;
In the past, this has solved situations on AVRs where I had a variable which was accessed occasionally in the loop, and very often in an ISR. Without declaring as "volatile", the ISR would have a chance of interrupting the "write" process of a variable in the loop, and would be unable to read it in the interrupt due to the corruption.
I think "volatile" declarations force reads and writes to totally complete before anything can interrupt it.
I am not sure if this concept works for two processors. I know it works for one. But this problem is much easier to solve as you just can prohibit an interrupt for a short time.
Yeah, maybe not. I've got an ESP32 coming in the mail soon that I feel will kick me in the butt trying to fully understand it. I've been on your channel for about an hour watching ESP32 and LoRa videos to study it - keep up the great work Andreas!
Defining variable as 'volatile' is definitely a step in the right direction, but isn't quite the ENTIRE answer.
The reasoning behind 'volatile' was more for the purposes of variables that could be altered in either the normal flow of a process, or perhaps in some ISR (Interrupt Service Routine), but this is still on a uniprocessor setup albeit with two distinct 'threads' of operation..
Thus, the 'volatile' definition was / is a 'hint' to the compiler that it should not 'cache' the value of a variable as it could quite possibly change BETWEEN sequential instructions in the normal flow if an interrupt had occurred.
What's required is a second step of mutual exclusivity (often called a 'spinlock') that guarantees exclusive access to the variable(s) in question.
The goal of a 'spinlock' supercedes ANY other asynchronous event (whether it is an interrupt, or perhaps even an entirely different CPU core), from modifying some fundamentally exclusive piece of data.
Concepts such as spinlocks become VITAL when you start developing non-trivial software (eg: The Linux kernel).
In the OLD days, much of the Linux kernel revolved around a single HUGE spinlock that was known as the BKL (Big Kernel Lock) which inhibited almost every other possible thread from execution. Now that the kernel has significantly 'matured', the 'granularity' of spinlocks has been significantly improved such that threads are far less likely to be 'blocked' waiting for the release of the BKL from some totally independent mutual exclusion.
(Imagine having to 'stall' every single core of your 28 core beast simply because ONE of those cores wanted exclusive access to the UART ringbuffer. That's how it was actually done in 'the good old days')
Semaphores and MUTEX 101 primer in a few minutes... Another great video !
:-)
Well, this solves a problem of mine. Excellent Andreas.
:-)
Hi Andreas, I noticed that in your examples, xTaskCreatePinnedToCore is used in the setup. What if I want to enable and disable the task running on core 0 throughout my main loop? For example, I want to use core 0 to monitor an encoder while core 1 is driving a motor. I do not want core 0 retrieving values from the encoder when the motor is not running as I am using a shared SPI bus with the encoder and other sensors that are being monitors on core 1.
I am not an RTOS specialist. Maybe you google in their description on how to enable or kill tasks. AFAIK the ESP32 runs standard RTOS
Nice video Andreas.....Cool.....have you run an video on how to prepare the Arduino IDE environment to program these devices. Remember a video from around a year back but then the libraries were not mature yet
Maybe you watch video #147
SO much great info in this video! Thanks, as always, for sharing with us!
You are welcome!
Awesome! Thank you for you very systematic videos. Much appreciated. Long time fan :)
Thank you for your feedback!
Great job. Now I more interested to buy an ESP32 board. Thank you for all good videos you making.
You are welcome!
Great video. I must say though that I’m getting more into programming the ESP32 in eclipse using FreeRtos and Its very nice. You get to use tasks like you did but with autocomplete
Good to know. So far I did not try this route...
I'm thinking about putting a course together that will go over this. I'll keep you posted on my progress
Hi Andreas, Great video as always. You are the master!
Thank you!
Incredibly interesting video!
Thanks again Andreas
You are welcome!
Hi, knowing about your obsession with battery efficient projects I have expected you will cover usage of ULP co-processor first. I hope the next video will be about how ESP32 can run on coin cell "forever" ;-) Million thanks.
The ULP seems to be quite hard and I do not know yet when I will find the time to dig into it...
Excellent video! Really good stuff here!
Thank you!
Wow, ESP company did a lot of work building the RTOS and Semaphore. Really difficult to figure out. Very good example. Like you said Global Variables pass between Cores easily enough although the variable is susceptible to data corruption. Creating a class to pass Variables using pointers would be the normal way of securing the data as the address is what is passed not the data. Although there are also security issues with this as well. Because if the pointer is changed your reading the wrong data. Setting up the stack properly and ensuring the function doesn't exceed the stack size would probably secure this better. But just thinking out loud. Wondering if you can demo using ADC and seeing how sensor data can be read and Transmitted to another ESP32 using the dual core would be neat. Have a great week and thanks for the upload.
If I remember right this was done by viewers. I never did it myself.
"Here is the guy with the Swiss accent...again..." - I always enjoy hearing that intro - it's your signature trademark. My wife gets a kick out of it too (sometimes she listens to my youtube tutorials LOL). Thank you for this video. I've been using the ESP8266 exclusively since the ESP32 software arduino support seemed to be very much in alpha/beta release. Based on your recent videos on the ESP32 it seems it's slowly starting to stabilize and become very useful (still missing bluetooth though). I like the intro on RTOS and the simple example - not so intimidating after all. Do you think it's possible to control two different GPIO pins in a task running on different cores?
1. I am glad to hear, that your wife increases the share of female viewers of this channel
2. If nobody uses a software, the supplier has no need to improve it. Typical catch 22. Maybe my videos help to change that.
3. Maybe you just try with the GPIOs. I assume, with synchronization of the tasks it should work.
I also miss hearing your original intro "Swiss accent *again*". Feels like something is missing now :)
Super useful info again, thanks Andreas!
You are welcome!
Another awesome video. The ESP-32 is displacing our beloved ESP-12 as the go-to IOT module.
Have you had any success accessing the third (low-power) core? Perhaps the biggest problem with the Expressif chips is their power requirement. If you are polling for an activity (pin pulled low, for example), could you deep sleep the two "fast" processors and just watch with the "slow" processor? Then wake the fast processors to do the processing?
I did not experiment with the ULP so far.
Fantastic video! Extremely clear examples.
Glad you think so!
Master!!! Master!!! I learn a lot with your videos Andreas! Dankeschön!
Bitteschön!
Love this. Using this on my LED clock - bought 0.8" LED display and the core0 just refreshes the display, core1 does the logic. All of it is done using 1 ESP32, 4 resistors (100ohm) and 1 LED display.
Btw, I had a watchdog problem with core0 in Arduino.
I had to add these 3 lines to the for(;;) loop:
TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
TIMERG0.wdt_feed=1;
TIMERG0.wdt_wprotect=0;
Thank you for the information! Good to know.
A much simpler way is to use ESP32's Ticker Function. I tested, the attached ticker function is run on Core 0. Which is good for scheduled tasks. And it's easier to implement in self-made classes or libraries. And if you want to make something like loop() without delay(), just set the ticker time to 0. eg: myTicker.attach(0, functionName)
Thanks, Andreas.
I use ticker sometimes but not for the second core only for scheduled tasks, and lately, I want to use the second core of ESP32 and watched this video. And got the trick of Serial.println(xPortGetCoreID()); and I thought maybe Ticker is a TaskHandle_t, too. Cause TaskHandle_t can be seen in a lot of ESP32 Arduino's attached libraries. And I tested the Ticker example, Ticker is run on Core 0!
Test sketch:
#include
#include
#define LED_PIN 2
Ticker blinker;
void blink()
{
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
Serial.print("Blink Task runs on Core: ");
Serial.println(xPortGetCoreID());
}
void setup()
{
Serial.begin(115200);
Serial.print("Serial freeHeap: ");
Serial.println(ESP.getFreeHeap());
pinMode(LED_PIN, OUTPUT);
blinker.attach(1, blink);
//blinker.attach(0, blink);
Serial.print("Setup freeHeap: ");
Serial.println(ESP.getFreeHeap());
Serial.print("Setup Task runs on Core: ");
Serial.println(xPortGetCoreID());
}
void loop()
{
delay(60000);
}
======================================================================================================
One big difference between Ticker and Task is that the Ticker management seems to be One Single Task on Core 0, so Tickers are processed one by one.
Ticker1(){delay(1000);}
Ticker2(){delay(1000);}
They both attached with interval 0.
Ticker1 and Ticker2 will be triggered every 2 seconds. Tickers are get queued just like the normal loop(){};
And if create Task1 and Task2 both on Core 0. They will be triggered every 1 second. That means Tasks are really independent to each other.
So Ticker is a simpler method to use Core 0 like the loop(). And Task is a more advanced tech indeed.
I think, tasks are a more universal concept but need RTOS. Tickers exist also on platforms without "operating system".
The most useful tutorial I've ever run into.
Good work...
But I was wondering about what we can do for the watchdog timer and how to solve its errors...
Big thumbs up 👍👍
Thank you! We will see in the future...
Amazing video, as always :)
Thanks!
Absolutely excellent Content presented at a comfortable rate. Thank you very very much.
Thank you for your feedback!
Awesome thank you! This will help with my current project I will have one core listening for bluetooth instructions and the main core runs the main block of code. As an aside, anyone who listens to the amp hour podcast should remember a few episodes ago the talked to Jeroen Domburg who now works at espressif who told us that it runs freertos and is multi core...although looking it up I know realize that was actually not that long ago but anyway yea...
Good luck with your project. Seems to run not only at the "Leading edge" but probably at the "bleeding edge"...
Awesome video. Now I going to have to change my plans and play with this. 😁
The same happened to me when I discovered that it is possible ;-)
👏👏👏👏👏 Outstanding! Thank you for this excellent video tutorial!
Peter S - lol Peter S! I did not expect to find you on this side of the internet!
it's funny how we're both interested in politics and electronics 😄
P.S. your profile picture is easy to notice 😂
Hello Daniel, I'm an EE who designs and manufactures building automation gear and I've been a hopeless nerd since the early 1970s. My computing career started on IBM punch-cards which were legacy at the time but still in common useage around Silicon Valley, where I grew up. Previously I was director of engineering for a $200M/yr Macintosh peripheral manufacturer where I was designing and building Thunderbolt II / USB 3.0 RAID enclosures most of the week but that got old because I was working for a hardcore conservative CEO/owner with 200+ conservative employees and had to live in conservative Texas. I am a San Francisco Hippy and Texas is not my thing even if BBQ is some of the best food in the world and their craft beer is amazing. His mother was dying of stage 4 cancer after surviving cancer twice before and I introduced him to the data about cannabis killing cancer cells without harming healthy ones. Her doctors had given up and left her for dead but he confirmed the data I gave him and she started cannabis flower extract oil treatment. She went from terminally ill to cancer free within 18 months and I permanently shook my CEO's faith in conservative thinking. When I quit the guy had removed cannabis from his company drug testing and he supported gay marriage while his wife was still an obvious bigot. He told me he was pissed off that he had been lied to by the people who taught him his conservative values. It took the hopelessness of his mother's mortality for him to finally realize this. His wife even asked him if he was becoming a liberal after I had worked on him for a year. That opened the door for him to start telling other conservative people that they had been programmed by lies and he told me he has since spread his story to well over 100 other medium to large corporate CEO types. I'll also add that I've been a very vocal proponent of medical cannabis for over 20 years with a couple years of tabling at events for TexasNORML where I performed outreach using a large base of peer reviewed data to back my arguments and I am most likely the first person in the Western Hemisphere to put bar codes on retail cannabis which happened at a San Francisco dispensary I wrote the point of sale system for back in 1999. So anyway... now you have a better idea of who I am than 99.9% of the people on the political channels. I'm not a big fan of politics but they affect me and I must do what I can to better all people. I'm far more interested in research concerning the endocannabinoid system, embedded processing, and mountain biking. Best wishes, -Peter
Peter S - Wow, That's an amazing background story :D
I really don't have much to tell, I'm a 22 year old guy that has been programing videogames on game maker since I was 13. Graduated from one of the best engineering high-schools in Mexico with my own developed wireless comunication (like Bluetooth) system and then came to the US (legally) to finish my degree.
I currently finished developing a text based operating system on my own. Now I'm integrating it into any microcontroller that can handle the code. (an arduino uno or better)
The proof of concept is in my smartwatch based on the esp32 (if your interested, I could make a video presenting showing my operating system working and explaining the impact this could have in the WHOLE microcontroller industry). I'm planing to show it at some fancy company and get hired in any development type area. I am struggling to get the first step because I lack of any contacts that can hook me up.
+ Peter S: I am proud of my viewers if I read your story! Thank you for writing it down!
Wow! That's very cool. I started by programming games too. That's an excellent path. The tools these days are so amazing, they allow you to really set your creativity free. My first home computer was an Apple ][ back in 1978 with 16K of RAM and a 1MHz CPU that was over $2000 in 1978 dollars. Now a $10 ESP32 can do so much more that it's almost silly. I am envious of your generation in many ways but I'm also grateful I got to listen to 1980s music as it was being made. Anybody who can design an RF communications system is very impressive to me, as are people who can speak more than one language, so you are doubly impressive. Americans are probably the least linguistically knowledgeable people on Earth so being bilingual is an excellent and valuable skill to many development companies. Developing an operating system is also impressive so make that you are triply impressive. I appreciate your offer of an explanation video however at the moment I am in the middle of designing a system for a client based on 12 different ARM Cortex M4 nodes on CAN-bus and my head is so full that it's leaking so I must decline your offer, but I encourage you to make such videos and place them on RUclips because they can be a very powerful tool for getting a job. I also encourage you to make them several times over a few months like each is practice for the making the next and get feedback from your peers to help with refinement. Most of the time people make documentation only once and it's like the 1st time a musician plays a song, no matter how good it sounds, you know that the 100th time will sound better because of practice. Your 4th video about a subject will typically be far better than the 1st. I pay attention to how creative people are when I hire and my last hire got their job by showing examples of building guitar sound processing circuits she had developed and others she built from designs on the net. Showing examples of what you can build is more powerful than most things you can see written in ink. For most positions I deal with, to me a physical example of something you designed and built is far more powerful than a degree from anywhere. Einstein did not possess a degree in Relativity Theory and he was reportedly a very poor student. There are some positions where a deep education is necessary but most positions from my experience require somebody who is capable and enthusiastic and able to adapt to the needs of the moment rather than somebody with a piece of paper. Once you make it into a development lab, somebody like you will naturally advance so don't worry about entering as a technician as long as the pay is acceptable. I wish you the best and perhaps the best advice I could give you is to be very persistent and get your resume out to lots of potential places because it's a numbers game, but above all make sure you're happy where you work because you cannot buy happiness, you can only generate it.
very nice video - the only thing to add would be deadlock prevention
Of course you have to do that in your programs.
This is my favourite of your videos
Glad you like it!
Thanks for that great video, really helped me a lot in a project :)
I would also be interested in some information how to switch the second core (and other sub modules I don't need) completely off to save more energy and how to set the clock frequency of a core.
Cheers!
I had to reduce the speed in one of my videos. It is possible. I do not know if you can switch a core off. Video #161