Posted 03/28/15
In my last post I described a change to the wall-following algorithm for Wall-E. However, when I tried this for real, I didn’t get the expected performance gains. In fact, it looked like performance had degraded rather than improved! ;-(.
So, I started thinking – again – about how to determine what’s really going on in the ping timing loop for Wall-E. I have a time check using the Arduino millisec() function that, supposedly, spaces pings at least 10 mSec apart. I can see from the left/right LED activity that the loop is executing at least several times/sec, but I can’t be sure *how many* times per second – could be happening too quickly and I’m still getting ping confusion, or it could be happening too slowly and I’m wasting time. As an experiment at one point I changed the minimum ping interval from 10 to 100 mSec, and the performance degraded dramatically and the left/right LED activity was also much slower, but again with no real numbers it’s hard to make an assessment.
So, today I dragged out my trusty Tektronix 2236 O’scope and looked directly at the ping timing for one of my three (left/right/front) ping sensors. As shown in the video below, the actual ping time spacing was about 37 mSec (shown by the digital period timer at the upper right of the scope screen) rather than the 10 mSec programmed into the code. I believe this means that the ping occurs every time through the Update loop, but it other processes were extending the overall time required by the loop
So, I started commenting out pieces of the update loop to see if I could understand where the ‘tall poles’ (if any) are in the program. First I commented out the code that manages the left/right ‘turn signal’ LEDs on the back of the robot, thinking maybe that was chewing up a lot of time.
This did reduce the loop time a bit, but nowhere near what I was expecting. Finally, I had everything commented out except the ping sensors themselves, and I was still getting some pretty big (and sometimes varying) numbers for the loop time – what was going on?
Finally, after a lot of research into the NewPing library I was using, I came up with the answer. The NewPing constructor for each sensor takes a MAX_DISTANCE_CM argument, and uses this number to cut off the ping receive routine after enough time has elapsed for the ping to get out to that distance and return, instead of waiting for up to one second for an echo to arrive. For the 200 cm (2 meter) max distance I had specified, this number is about 12 msec (4 meter round trip time divided by 334 m/sec speed of sound in air). The actual delay I was seeing was about 17-18 msec max delay per sensor. Since on average, two of the three sensors (left/right/front) would not have anything within range, that meant that the minimum loop time would be around 35 msec + actual round-trip delay from the ‘active’ sensor. I verified this by physically disconnecting all three sensors from the UNO and measuring the ping-ping interval of one of the three. The result, as shown in the photo below, is very close to 3 * 18 = 54 msec.
Leaving the ping sensors all disconnected (max ping delay) I then re-enabled all the rest of the processing (motor speed update, turn signals, etc). The result was less than 1 msec longer, indicating that all the rest of the processing takes an insignificant amount of time; its all down to the ping delays.
As an experiment, I commented out all the ping sensor stuff, and added a line or two to manually generate a ‘ping’ trigger on one of the ping sensor trigger lines – thus simulating the use of a ping sensor, but without the issue of the echo delay. When I did this, I got a ‘ping’ interval of almost exactly 10 msec – i.e. the programmed MIN_PING_INTERVAL_MSEC. Changing MIN_PING_INTERVAL_MSEC to 5 msec resulted in an interval of almost exactly 5 msec.
So, now I think I have (finally!) a good handle on the loop timing issues for the robot – the ping sensors themselves and their related (and unavoidable) max_distance delays are by far the tallest poles in the tent. All of the rest of the processing done in the normal wall-following loop, including all the turn signal stuff, takes less than 1% of the total loop time.
The good news is that all the worrying I was doing about the impacts of more sophisticated tracking algorithms was misplaced – I can do LOTS of math and it won’t materially affect the total loop time!
The bad news is that my idea of incorporating a second pair of left/right ping sensors angled at 45 degrees left and right of forward would probably result in a significant degradation of performance, just due to the unavoidable addition of at least 20 msec to the total loop. The only possible way to beat the max_ping_delay rap would be to go with NewPing’s timer-based functions that don’t block waiting for an echo. This might be a way to accommodate multiple left & right ping sensors, but it would come at the cost of a lot of additional complexity.
Frank