Don’t forget you need to measure the time to and from the object so an object 1cm from the sonar has 2cm of travel for the ping. I use 58uS/cm.
The interrupt latency is a variable but I would expect it’s less than 2uS. I didn’t worry about it too much and assumed 1mm theoretical accuracy was enough for all practical purposes (ie. 6uS).
So I measured the sonar interrupt latency in ConVEX, from falling edge of the received echo to the interrupt is about 3uS with less than 1uS worst case jitter. Here is scope capture showing echo (yellow trace) to a pin set high then low in the interrupt code (blue trace). Obviously harder to do with PROS as you do not have access to the interrupt function. I time to uS accuracy, an interrupt is caused when the ping is sent (rising edge of the yellow trace) so the 3uS offset is effectively added to both start and end of the timing, ie. the only error left is the 1uS jitter, so the error in measurement will be 1/58 cm or 0.17mm. There’s probably going to be more noise, that is variation in echoes, than this.
Here’s the modified ConVEX irq callback, I was toggling digital out 2.
25uS is really slow, there must be other processing going on before you get into your handler. I didn’t even know that PROS had that function, guess I learn’t something today. As I said before, PROS is based on FreeRTOS. Usually when using FreeRTOS only certain calls are allowed in an interrupt, they usually end with “FromISR”, for example, to send to a queue you would use xQueueSendFromISR. I’m not sure what PROS allows in interrupts, I wonder if there is some glue code that wakes a high priority task or something rather than calling the irq handler directly, that may account for the long latency. Are you sure it was 25uS and not 2.5uS?
Thanks! I was able to find the definition of those macros in the FreeRTOS distribution. I think I may not need it, but if I test it anytime soon I can update the thread (if anyone cares to know).
For the sake of those following this thread, the only time you might need this is if you write your own Interrupt Handler, and then only under very specific circumstances. One case I can imagine is if the Handler updates multiple variables that it shares with another task. That task may assume the variables were updated at the same time, but in fact there is always a remote possibility of the Handler running again between the time you read one of the variables and the time you read the other. The following mechanism can prevent this:
// Enter critical section
// Perform an uninterruptible operation
v1 = firstDataValue; // set in Interrupt Handler
v2 = secondDataValue; // set in same Handler
// Exit critical section
// Continue processing
result = compareValues(v1, v2);
Keep in mind, disabling interrupts for too long can mess up system performance, so make it short and sweet. Or better yet, synchronize task/handler access using semaphores (http://en.wikipedia.org/wiki/Semaphore_%28programming%29). I think that’s what I’ll end up doing with my Sonar driver.