Posted 08/04/2015
In my last post (http://gfpbridge.com/2015/07/emi-problems-with-lidar-and-wall-e/) I described my efforts to track down and suppress an apparent EMI problem with Wall-E. After successfully (I hope) killing off the EMI problem, I added navigation code back into the mix, and did some initial tracking tests on a long, straight wall. The results were not encouraging at all – it appeared that Wall-E was having quite a bit of difficulty deciding which way to steer; it appeared to be correctly measuring the distance and angle to the nearest obstacle (the wall), but wasn’t adjusting wheel speed to compensate for nose-in or nose-out conditions.
As it turned out, there was a very obvious reason Wall-E wasn’t adjusting the wheel speeds; at some point I had overridden the wheel speed setting logic and arbitrarily pegged the wheel speeds at 50 and 50 – oops! Unfortunately, while I was figuring this out, I discovered something even more disturbing. Apparently, all this time Wall-E has been servicing only about half (9 vs 18) of the LIDAR tach wheel interrupts! I hadn’t noticed this up until now because although I had previously looked at the the contents of the 18-element distance/time/angle array, there was apparently enough ‘creep’ in the interrupt numbers that Wall-E *did* service that the array looked normal. However, some of the instrumentation code I put in place this time made it painfully obvious that only 9 interrupt calls were being made. As a double-check, I changed the code to turn the red laser ON during interrupt service routine (ISR) calls, and OFF at all other times. Then I made a surround screen from several sheets of paper and looked at the pattern made by the laser. In the following time-lapse image (0.5 sec or about 1 full revolution), 4 laser pulses (ISR calls) are visible in about 1/2 full circle. In the following video, there are only 9 laser pulses visible per revolution.
Then I went into the code, and commented out the call to GetMeasurement(). GetMeasurement() is where the Pulsed Light LIDAR measurement delay occurs, and this is the obvious suspect for missing ISR calls. As the following time-lapse photo and companion video shows, this indeed allowed all 18 ISR calls per revolution. Comparing the two photos, it is obvious that the one without the GetMeasurement() call exhibits twice as many laser pulses (ISR calls) and each pulse is much shorter, denoting less time spent in the ISR.
So, what to do? In the first place, I’m still not sure why interrupts are being skipped. If you believe that the laser ON time represents the duration of a particular ISR call, then the fact that there are times when the laser is OFF should indicate that the system can service another interrupt – why doesn’t it?
So, back to the drawing board. I drug out my trusty O’Scope and started poking around. I have one of the Uno’s digital lines set up to show the duration of GetMeasurement() and another one set to show the duration of the ISR. Then I did a series of tests, starting with GetMeasurement() turned ON as normal, but with the call to PulsedIn() (the actual LIDAR measurement function) commented out and replaced with delays of 10, 20, and 30 msec. The following captioned photos show the results:
Conclusions:
- The PulseIn() call in GetMeasurement() is definitely the culprit. Not surprising, as this is the call that interfaces with the spinning LIDAR unit to get the actual distance measurement. The only question is how long does/should it take the LIDAR to return the distance measurement.
- Delays up to 20 msec in place of the PulseIn() do not adversely affect operation. Both the O’Scope and laser pattern presentations clearly show that interrupt servicing is proceeding normally.
- A 30 msec delay is too large, but not by much. There is some evidence in the O’Scope photo that occasionally the next interrupt is not skipped.
The above conclusions track reasonably well with the known physics of the setup. The spinning LIDAR rotates about 2 times/sec, or about 500 msec/rev. Interrupts are spaced out 1/20 rev apart, except for the index plug where 2 interrupts are missing. (500 msec/rev) times (1/20 rev/interrupt) = 25 msec/interrupt. So, 10msec delay should be no problem, 20 should also fit, but 30 is too long. The fact that there is some evidence that 30 is almost short enough is probably due to the rotation speed being slower than estimated; 30 msec/interrupt –> 600msec/rev or about 20% slower than nominal.
In any case, it is clear that the current setup can’t support an interrupt interval of 25 msec. I’m either going to have to slow down the spinning LIDAR (which I do not want to do) or speed up the measurement delay (which I don’t know how to do – yet).
There are two methodologies for interfacing with the Pulsed Light LIDAR. One (the one I’m using now) is pretty simple but involves the PulseIn() call with it’s known issues. The other one is via the I2C channel, which I have not tried because I thought would be harder to do, and there wasn’t any real evidence that it was any faster. Now that I’m convinced that PulseIn() won’t work, I’m going to have to take another look at the I2C interface technique – EEK!!
Stay tuned,
Frank
Pingback: I2C Interface Testing for the LIDAR-Lite V1 - Paynter's Palace