This is the final part of the 3-part series about the Parkonator, a device that overlays parking sensor information on top of any RCA backup camera.

Video Overlay

Now that we can get the sensor data to the second Arduino that has control of the Video Experimenter shield, we can start displaying the data. First things first, however. The camera I have picked already draws some sort of alignment lines to help with parking. The trick is to overlay the sensor information in such a way as to “highlight” the objects on camera where they actually are. For this, I’ve set up a test rig.

Basically, I pinned the parking sensors (mounted in fancy cardboard) to a wall as if they were mounted in my car’s bumper. I have some advice about that: mine are hanging too low. I didn’t realize this until I mounted them in the car. The problem is, the sensors use ultrasound to detect the distance to an object. Evidently, carpet isn’t all that great at reflecting sound waves, so I never noticed any issues during my testing. However, concrete and other paved surfaces will cause your sensors to get a lot of false signals from the sound waves bouncing off harder surfaces. Mine are mounted fairly low in my car, as a result I’ve noticed some noise every now and then (as you can see in the videos below).

Another important thing is we want to align the data in such a way as to give the user the perception of “tracking” an object. So, looking through the camera as you’re getting closer to something, objects that are far should move slower on the screen than objects which are close. It’s hard to put into words, but check out this graph that shows the Y-coordinate (in pixels) on the screen compared to the distance at which the object is standing from the camera (in cm).

On the Y axis is the screen pixel. On the X axis is the distance an object would have to be standing away from the camera to show at that pixel. Notice it’s non-linear. My first gut instinct was to approximate this thing with a polynomial. However, I later opted for a simple table and an interpolation algorithm because even on paper you could see that it would be much faster to interpolate. In code it looks something like this:

// Pixel and distance information related to guide lines drawn by camera.
// Super-far, kinda-far, 1st green line, 2nd green line, yellow line, red line, bottom
#define MARKERS 7
int pixel[MARKERS] = {32,37,44,51,55,63,H-1};
int distance[MARKERS] = {253,253,253,190,150,110,80};

This allowed me to accurately match the sensor information with the objects on camera. Check out this test with boxes!

Next there was the issue of expiring old values. When the sensors don’t detect anything, they just don’t send any signal. So your image appears “frozen” after the object goes out of range. As a result, there needs to be an algorithm that expires old values if they haven’t been updated for some time.

To complicate things, the sensors send updates with different intervals at different distances. For example, if the object is really far, you might get an update every 4-5 seconds. If the object is within a meter or so, the updates are much more frequent, close to 3 times a second or about every 350 milliseconds. When the object gets really close, the updates slow down again to about once a second. The graph below shows the approximate update interval in relation to distance:

The sensors don’t really have a range much beyond 190 cm (about 2 meters). But that’s still plenty. In code, it looks something like this (snippet):


// Sensor value ranges
#define MAX_DIST 191
#define MIN_DIST 23

// How long until the sensor value is set to out of range.
#define TTL_CLOSE 750
#define TTL_MED 350
#define TTL_FAR 150
#define TTL_REALLY_FAR 1500

#define VALUE_CLOSE 50
#define VALUE_MED 90
#define VALUE_FAR 140

volatile byte values[2][4];
volatile boolean valueChanged[2][4];
volatile unsigned long timestamps[2][4];
unsigned int group;
unsigned int id;
unsigned long lastExpired;

// If not heard from sensor in TTL ms, set value as out of range.
boolean expireOldValues() {
boolean expired = false;
if (millis() - lastExpired < TTL_FAR) {
return expired;
}
lastExpired = millis();
for (group = 0; group < 2; group++) {
for (id = 0; id < 4; id++) {
long ttl = TTL_REALLY_FAR;
if (values[group][id] <= VALUE_CLOSE) {
ttl = TTL_CLOSE;
} else if (values[group][id] >= VALUE_CLOSE && values[group][id] <= VALUE_MED) {
ttl = TTL_MED;
} else if (values[group][id] >= VALUE_MED && values[group][id] <= VALUE_FAR) {
ttl = TTL_FAR;
}
if (millis() - timestamps[group][id] > ttl && values[group][id] != OUT_OF_RANGE) {
values[group][id] = OUT_OF_RANGE;
valueChanged[group][id] = true;
beep();
expired = true;
}
}
}
return expired;
}

So that’s that. I’ll attach the Arduino sketch at the bottom of this page. Next, let’s move on to installing the thing into the car.

Car Install and Calibration

As I mentioned earlier, I mounted my sensors far too low, because I wanted them to be in the black plastic part of my bumper and not the yellow area. As a result, I do pick up occasional noise. That’s something I’m going to try and filter out at a later time.

Anyway, if you’re using an aftermarket backup camera like I was, you’ll want to align the camera’s guide lines with the real world so you can have a somewhat accurate representation of your car’s dimensions. It honestly would have been better if I could just draw my own, but whatever. Best way to do this alignment is with laser guides as you see in the picture on the right.

Once aligned, you need a large object, like a box, to move around and re-calibrate the distance to pixel tables. If your camera draws lines for you, this shouldn’t take long as you just need to place the large object on a line and enter the value you get from the sensors. Easy enough. With that done, I added some additional display elements (like a bar graph) to aid in parking really close to things (where you can’t see much except a wall through a camera). The results? See for yourself:

Wall Test

Car Test

You can see the sensor noise really manifest itself in this one. It doesn’t usually happen this bad.

Source Code

The complete source code can be had here:

Arduino Mini (for sensor data gathering)

Arduino Uno (for overlaying the data)

Hope you found this somewhat interesting and maybe even useful. Personally, this is one of the most useful things I’ve built in a long time. I’ve been driving with it for about 2 weeks now and I have to say, backing into parking spots is my favorite part of the drive now πŸ˜€ If you have any questions related to the code, I’d be happy to clear those up! PS: here’s the final layout of all the connections: