Create a distance sensor for your garage – Part 2/2 – Implement a proximity meter

We learned in the first part of this tutorial how to measure a distance with a HC-SR04 ultrasonic sensor. In this second part, we’ll get rid of the LCD display, and instead show the distance on a custom meter made with LEDs. The idea is to turn colored LEDs ON/OFF depending on how close the car is from the wall.

Why would we get rid of the LCD display

There are two main reasons why we want to remove the LCD display from the final version of this project. The first one is that printing text on the LCD display is using a lot of memory on the PIC for no real reason. Our code related to the LCD, on a PIC16F88, takes around 20% of the program memory. To compare, we’ll see how much memory our program uses at the end of this tutorial. With the LCD related code, it takes 17% of the data memory and 39% of the program memory.

mem_LCD
Memory with the LCD related code

The second reason is simply that it is not needed in the final product. Being able to print text on a LCD display was helpful when writing the logic for distance measuring, but it will not be useful in the end.

On a side note, there were other options that we could have used to debug our program during development. I chose this method because we already learned in a previous tutorial how to control a LCD display with a PIC, but we could also have used the UART interface of the PIC to output text on a serial console on our computer. See this tutorial to learn how to use the UART interface.

This is an important thing to keep in mind when working with embedded systems. The resources of the systems we work with are often very limited, and while it’s convenient to have a way to display data, it’s rarely needed in the final product.

Bill of materials

In addition to the components we used in the first part of this tutorial, we’ll need 4 LEDs and 4 resistors. You can use 2 green LEDs, an orange one and a red one. For the resistors, 330Ω is perfect.

Modifications to the circuit

Let’s take the circuit we built previously, remove the LCD display, and add the LEDs. I connected the LEDs to the pins RB0 to RB3 of the PIC. This allows us to still use the LCD display if needed, as it was not connected to those pins.

proximity_meter
Schematics of the proximity meter

Software

Determine the levels for the meter

The idea behind the proximity meter is simple. We have 4 LEDs that we’ll turn ON or OFF depending on the distance from the car to the wall. The colors of those LEDs will make it easy to quickly see how far we are from hitting the wall.

Knowing this, we can first determine the threshold distances we want to assign to each LED. For this, go in your garage with a tape measurer, and write down the limit distances for each of the following states. I’ll give the distances I chose for my car:

Distance to wall (cm) State LEDs
> 75 Too far all_led_off
65 – 75 Good one_green_on
55 – 65 Perfect 2_green_on
40 – 55 Too close orange_on
< 40 Back up, gonna hit the wall! red_on

Let’s add those values to our program. We’ll define them as #define, which will make it easier to change them later if needed; we’ll just need to change those #define instead of changing the value everywhere it’s used in the code.

The logic to control the proximity meter

We’ll write a function update_proximity_meter()  to take care of the meter. We’ll give it the distance in cm as a parameter, and it will turn each LED on or off depending on the distance.

As you see it’s very easy, we just compare the distance with each threshold and turn the LED on if the distance is smaller.

Main loop

Logic

We basically need to read the distance at regular intervals, and update the meter accordingly. But this is not very efficient; even when you’re not needing the system to tell you how close your car is, it will constantly be updating the meter.

There are many ways to make this more efficient. One of the best would be to use a PIR sensor to detect motion. When motion is detected, it would trigger an interrupt on the PIC and start the whole measuring / updating the meter process.

To keep it simple, and only use the components we’re already using, we’ll simply put the system to sleep after each reading. But we need to put the system in idle mode when the car is not in the garage, and when the car is parked but not moving anymore. In order to do this, we’ll use two different durations for the loop delay, and we’ll add a counter of identical distances:

Here is the logic we’ll use

  • If the distance is greater than the largest threshold, use DELAY_IDLE
  • If the distance has been the same for more than THRESHOLD_COUNT_IDENTICAL, use DELAY_IDLE
  • Otherwise, we need to update the proximity meter more frequently, and we’ll use DELAY_ACTIVE

In the first two cases, we want the LEDs to be OFF. We’ll just call  update_proximity_meter()  with a distance greater than the largest threshold.

Code

Here is the code for the main loop:

As you can see, the code for the main function is pretty small. This is because we encapsulated as many code as we could. If we still had the LCD display in the project, we would just need to call the function display_distance() that we wrote in the first part of this tutorial, and this would just add one line to the main function. It’s very important to keep your code as modular as possible; it greatly improves the readability and maintainability of your program. In this example, anyone can quickly understand what the program does, even if the inner working of each function is not known.

Filter the measures

If you’ve experimented a bit with the distance measurer, and it’s easier if you still have the LCD display attached, you probably noticed that the distance value sometimes jumps for one single read, even though the object has barely moved. There’s an easy way to fix this issue and make the system more reliable. We’re going to filter the values, by simply averaging the distances over a given number of measures.

Let’s modify our dist_measure.c and .h files. The function HCInit() will now take an argument, which will be the number of measures. We’ll limit it to 5 samples per measure, so getting a distance doesn’t take too much time. We’ll use a static variable n_samples, that will be accessible by all functions in this file, but not by any other files. Below is the modified code for the HCInit()  function:

Now we just need to loop n_sample times in HCCalculateDistance() , and calculate the average of the n_samples  values:

And that’s it, now the distances returned by HCCalculateDistance() will be smoother, and this should get rid of the wrong values.

Full code

The full code is available on my Github page.

Memory consumption

As promised, here is the memory used by this program. It is much smaller than before, and this is only due to us removing the code related to the LCD display. The size of the program memory is half of what it used to be. And we also added some code for the averaging and for the delay logic!

mem_no_lcd
Memory used by the program without the LCD code

Result

Here is the result when moving the system closer/further away from a wall:

Improvements

There are many ways we could improve this device. I’ll list some below, but feel free to experiment and implement your own ideas!

  • Use a PIR motion sensor to trigger the system ON/OFF. It would be a much better idea than the logic we currently have with our delays, and would reduce the power consumption of the system.
  • Add another level, when the car is much too close and about to hit the wall. You could blink the LEDs or emit a sound with a buzzer.
  • Power the device with a battery, and get rid of the power cable.

 

2 Trackbacks & Pingbacks

  1. Garage Distance Sensor Kicks Tennis Ball To Curb | Hackaday
  2. Garage Distance Sensor Kicks Tennis Ball To Curb – High Tech Newz
%d bloggers like this: