I first checked that video is still playing, then checked my speakers, then opened another video to check for a playback issue.. :D :D Anyway, great video! Subscribed.
extremely useful, thanks! I like how you go a bit deeper compared to other tutorials. "use volatile if you plan to update the variable from ISR" didn't give me much insights, but you explained that it will put it in RAM instead of registers
Thanks Dave, I recently wanted a day and a half grappling with the difference between ESP32 & ESP8266. You covered it in less than 5 minutes. Your blood is worth bottling!
Thanks for this tutorial. My ESP32 has a 40MHz crystal and this will help improve the reliability of catching a 10us falling edge delay on two external interrupts. I had a tough time doing this on the Arduino as the timing wasn't always repeatable.
An interrupt is an edge triggered event and so should be asynchronous, that is not dependent on clock speed or accuracy, are you sure the incoming signal is meeting the ESP32 logic requirements of a voltage they is above or below the input thresholds say 2.7v and 0.6v and that the edge transition is clean and not subject to any perturbations. Sometimes the addition of a low value (PF) capacitor can help to store enough energy and ensure reliable switching, either that or fit an input buffer to clean up the signal.
@@G6EJD I'd have to check. I was just comparing my scope capture to the values I was outputting onto the LCD. On the scope i was triggering off 3v and seemed to get pretty consistent results but the Uno seemed to vary. I don't have anything else really happening in the loop other than waiting for the two external triggers and the ISR only updates the volatile with the micros function so it should be quick. You're probably right that there's some perturbations causing false triggers. This is an IR sensor and there's 38KHz riding on top of my data, maybe I need some filtering or I need to clean up my jumble of wires.
The Arduino will have needed about 4.4v for a reliable trigger for the high state and about 0.7v for the low state. Nearly all CPU’s have a Schmitt input to stop slow input edges from causing the input stage going through a linear region and oscillating, it may be worth reviewing the data sheet for inputs that are designed for interrupt use. It may also help to enable either a pull-down or pull-up resistor on the cpu as this helps to clean up the input signal or support an open-source / collector sensor output stage. Some sensors use an open-source output so they can be wire-or’d together then any sensor can trigger an event with simple loop wiring.
Would it be feasible to use interrupts to capture and store a signal generated by a vibration. Imagine a esp32 setup for external interrupts with a vibration sensor (piezo disc module), connected to the interrupt pin; the ESP32 would remain in deep sleep while there is no vibration; then save the analog value coming from the piezo module to RAM. Not sure how to approach this or if possible.
You need an edge transition from 0-3.3v or 3.3-0v to wake the ESP32, it’s not possible to use an analogue signal for interrupts unless the value exceeds the input trigger threshold and it has a Schmitt input, tbh I don’t know if the ESP32 supports that function.
@@G6EJD I used an LM324 as an amplifier/comparator for the signal generated by the piezo. I wonder if I can use the digital HIGH from the comparator to trigger the interrupt and wake up the esp32, then have the amplified analog signal recorded through an ADC pin. (this is just for hobby stuff, Im learning as I go)
@@Friendroid an LM324 would give sufficient gain to convert low signal amplitudes to a fast rising edge, so that would work. However recording audio or varying amplitude signals is not easy. To have any value you’d need a certain number of ADC samples to recreate the waveform or get any meaningful meta data from it, let’s say you records a couple of seconds (you need to record at twice the maximum frequency) so say 1khz for a noisy like signal then that would require 2000 samples at 8-bit resolution or .2K of RAM leading to a fast consumption of memory. So it’s achievable but management will be the key to success, to me that means filtering out random triggering from noise or vibration spikes, then memory management to ensure there is enough TAM to enable the ESP32 to operate, so there would be need to be a regime to delete recordings if there were too many and so on. It’s just the need to think through all scenarios and have a way of coping with them. I’d start by recording some vibration events and see what the data is like as that will help determine the sampling frequency, that would simply be a loop to take an ADC sample, store it in an array then wait for the sampling frequency (time) then repeat until the sample is complete, then perhaps output the sample to the serial port for analysis, that would take about 10-lines of code, it would only need to be very basic, then having taken the samples how to get them off the ESP, there are a few ways, serial or write to SD card, but how to initiate a transfer maybe by push button and so on.
ed, it’s best to try a simple example and make sure you always preserve the programme variables using the correct method, without doing so, you will find your sketch will work with a low reliability level.
In short yes, note this is a data type just like say an integer. The reason for doing this is to stop the two cores from sharing the interrupt task, and when that happens core-1 may handle the interrupt for you, but if the source interrupts again, core-2 will handle the interrupt and then any variable manipulation in your routine will get modified by both cores and causes generally a core crash. To stop this you can lock the data to the core that handles the task with a flag aka semaphore to stop the other core from handling the interrupt. You can share an interrupt routine amongst peripherals and you need to handle all that in the same routine that is locked to the core given the task. A long answer that I hope explains the reason for doing this, perhaps I should produce another video at some stage to explain.
@@G6EJD thank you! I did some test on an ESP32 but it still didn't solve my question You have made it clear! I would love a video on this topic since I have found out that is not much good discussion on how to implement multiple ISR routines
One of the problems with freertos is you can’t stop interrupts to prevent the other core repeating the activity so semaphores are needed and you may need to test them during an interrupt response handler
@@G6EJD I don't have any problem yet but i want to implement more than 3 external interrupts, i have tried without using "portENTER_CRITICAL(&synch); portEXIT_CRITICAL(&synch);" and I guess if I use 5 or 6 interrupts I do need to use the portMUX_TYPE data type The main question was if every ISR needs a unique portMUX_TYPE variable and you have clarify that :)
Hi David! Excellent video. I'd like to ask you for some advice on a problem I'm facing with esp32 though. I'm trying to enable two external falling interrupts on my esp32. First of all, which 2 esp32 pins could I use to enable the interrupts with pullups (can't use 16,17,4,19 bc already used). And finally, should I have to replicate what's in 3:37 in this video for both interrupts to assure good functioning? What if one interrupt happens when processing the other, or any of this type of casuistry?
Hi, you can use any pin from 0-32 for an interrupt. If both pins are set to interrupt on low, then external timing will determine how they are handled, but when both occur you have to handle the priority, which is not easy to do, however both should occur albeit one will be handled followed by the other or vice-versa, what effects are you seeing? There is a small problem with the Arduino IDE is the interrupt process is not a true hardware solution ands it’s all managed with a software solution. The key to solving is knowing what your seeing as incorrect operating
Thanks for your answer. But could you confirm that I have to duplicate what's in 3:37 for both interrupts in my case? And if by default, if an interrupt is triggered when processing another one, the system will end processing the one it's already doing and then process the one that was triggered?
@@guillembalcells5376 sorry, yes each party n needs its own handler so just duplicate the ISR for each pin and decide what you want to do when it gets triggered. Don’t use serial.print statements inside the handlers
Another question Dave. I've seen several other esp32 interrupt sketches that use portMUX_TYPE mux and not synch. And also portENTER_CRITICAL_ISR(&mux) Care to explain the difference? My interrupts seem to run fine either way, but interested in your expert opinion. Cheers. Matt.
Hi Matt, the only method I have seen is that provided by Espressif in their Freertos documentation, my view is any other method (if that's what's being employed by the compiler - very important) is not a valid method. Noting the need to do this is to allow access to the programme variables without conflicting with the operation of the real-time operating system and it's use of the stack and variables during interrupt servicing. It's quite possible to use other directives only to find that the compiler is implementing either method in the same way and I suspect it is! The only way to determine this is to go through the ESP32 IDE add-ons to see what's done. Code size may be a indicator of the complier implementation for both methods, if identical then suspect no change in the final image regardless of method used.
@@G6EJD I think that I'll leave the clever stuff to clever blokes like yourself. 1) struggling to find the info and 2) understanding it as and when I do find it is a non starter. I should have paid more attention in school! And I'll definitely be paying more attention to your videos from now on :)
Are you using interrupts? If so make sure you are entering and exiting the ISR with the correct commands and also you are limited to what you can do in the ISR like no serial.println statements
After trawling through many videos and websites I've come to the conclusion that there's just way too much going on in the interrupt, so will try another route. Thanks for your reply
Just instead of critical sections that can actually corrupt whole execution - use taskDISABLE_INTERRUPTS() www.freertos.org/a00020.html#taskDISABLE_INTERRUPTS and by the way volatile keyword does not mean it is in ram but tells compiler to omit optimizations and modifications on it. It actually can be unused register
First of all, these videos are primarily for beginners/ novices and the principles I put over are basic, yes the compiler may make other decisions but usually and as recommended by Espressif IRAM is the only location that should be used, in fact they also recommend using DRAM for the ESP32 . I would never recommend using a disable interrupt function and even the documentation says that too: ‘Macro to enable microcontroller interrupts. ‘Normally this macro would not be called directly and taskENTER_CRITICAL() and taskEXIT_CRITICAL() should be used in its place.’
Thanks for these great videos, Dave. I subscribed to your channel. I have a related question. Will using a process inside the function pull all related functions into the IRAM? Example - from inside my IRAM_ATTR my code I call this process: unsigned char result = rotary.process(); I adapted an encoder library interrupt example from this article www.buxtronix.net/2011/10/rotary-encoders-done-properly.html and corresponding git github.com/buxtronix/arduino/tree/master/libraries/Rotary