The first time I ran the vehicle under its own control, it moved about two meters, turned sharply into a wall, and stopped. I had been so focused on getting it to move that I hadn't seriously thought about what would happen when it encountered something it wasn't expecting.

Looking back, this was entirely predictable. But at the time, I had convinced myself that the sensor readings were reliable enough to catch anything in the vehicle's path. They weren't.

The first wrong assumption

I assumed ultrasonic sensors produced clean, consistent distance readings. They don't. The readings I was getting varied by 15–30% depending on the angle at which the sound waves reflected off the object. At certain angles — particularly when approaching walls at less than 45 degrees — the sensor would return nothing at all, because the reflected wave never made it back to the receiver.

My decision logic was: if distance reading < threshold → turn. But if the reading is sometimes zero or wildly incorrect, the vehicle is making navigation decisions on noise. This is exactly what happened.

The second problem: timing

Even when the sensors were giving correct readings, there was a lag between the reading and the motor response. I hadn't measured this — I'd assumed it was negligible. It wasn't. At the speeds I was running, the vehicle was already 20–30cm past an obstacle by the time the motor control signal reached the wheels.

The fix was straightforward in principle: run slower, or reduce the sensor read / control loop latency. But it made me understand something important — in embedded systems, timing is not an afterthought. It's part of the design.

The third problem: lighting

The computer vision component of the system — path detection from the camera — worked fine indoors under fluorescent lights. When I moved the vehicle near a window, the contrast changes broke the edge detection entirely.

I had tested in one environment and assumed the system would generalize. It didn't. The model I'd built (however simple) was overfit to the conditions I'd tested it in.

What I actually changed

I slowed the vehicle down significantly. I added a moving average filter to the sensor readings to reduce noise. I added a minimum time delay before trusting a new sensor reading after a sudden change (to catch spurious reflections). And I added indoor-only mode constraints, acknowledging that the vision system wasn't ready for variable lighting.

Version two worked better. Not perfectly — but better in ways I could explain and measure. That felt like real progress.

What this taught me

The most useful lesson wasn't technical. It was this: testing reveals assumptions you didn't know you were making. Every failure in this project was caused by something I had assumed without realizing I'd assumed it.

The practice of asking "what am I assuming here?" before and after a test is now the most valuable debugging habit I have.


← Full project write-up Next: Fall Detection →