It's time to bounce that old tennis ball out of your garage, and up your game with this simple project that lets you know exactly where to stop when pulling in to your garage.
Distance sensors are great! They're generally a maker's first step towards creating a basic autonomous robot, but did you know that there are many other uses for them? It's true! Everything from Halloween props to annoying musical instruments to parking garage guidance systems can be made using distance sensors. So let's take ours off the workbench and out into the wild, and make something happen!
I've never had a tennis ball, boogie board or anything else hanging from my garage ceiling to let me know exactly when I should stop my car when pulling into the garage. However, now that I have a teenager who's about to start driving, I think maybe it's time. Now, I don't play tennis, but I do play electronics, so I'm going to use what I have available to me. My plan is to use a distance sensor and create a small stop light. When the car first pulls into the garage, a green LED will be illuminated. As the car gets closer, a yellow LED will light up, and when the car gets to the ideal stopping point, the driver will see a red LED. I'll design and 3D print a simple traffic light to use as the housing, so it will be aesthetically pleasing, too!
With so many distance/proximity sensors to choose from, how do you know which one is right for your project? There are a number of considerations, such as range, resolution, interface type, update rate and cost. Sometimes, you may need to decide which options have some flex (does it really need to update 635 times per second?), and which ones are must-haves (my professor said we have to use I2C components). My garage measures about twenty-six feet from the back wall to the garage door. While I could probably get away with one of our XL-MaxSonar Ultrasonic units, which are good up to about twenty five feet, for this build, I'm going to go with the TFMini - Micro LiDAR Module.
I'm using it with the Qwiic package, as that includes a boost board. Since the TFMini runs on 5V but communicates at 3.3V, the boost board that comes with the Qwiic package eliminates the need for logic level conversion if using a 5V board, or a split power supply if using a 3.3V board. By pairing this with the Sparkfun Blackboard, which has a built-in Qwiic connector, I can make the sensor half of this hookup a straightfoward plug and play design. Add a few Super Bright LEDs, resistors and a power supply, and we're good to go!
Here's the parts list for this project:
The Qwiic system really makes this build pretty simple. The TFMini Qwiic version comes with the boost board and a pair of cables. One cable runs from the module to the boost board, and the other from the boost board to the Qwiic connector on your Blackboard. The green, yellow and red LEDs run to pins 8, 9 and 10, respectively. For the code, I simply did a little tweaking to the LidarTest.ino sketch you can find on the TFMini Qwiic's Hookup Guide. Here's how it looks:
/*
TFMiniStopLight.ino
Rob Reynolds, November 19, 2018
This code is a small practical demonstration application
of the TFMini Lidar Module. The 3D files can be found in
the Github repository, here [ https://github.com/ThingsRobMade/TFMini_Stop_Light ]
Based heavily on the previous collaborative work done by
Nate Seidle and Benewake. The original example sketch for
the Qwiic Enabled TFMini can be found here:
(https://www.sparkfun.com/products/14786)
This code is free, but if you find it useful, and we meet someday, you can buy me a beer (Beerware license).
*/
#include <Wire.h>
uint16_t distance = 0; //distance
uint16_t strength = 0; // signal strength
uint8_t rangeType = 0; //range scale
/*Value range:
00 (short distance)
03 (intermediate distance)
07 (long distance) */
boolean valid_data = false; //ignore invalid ranging data
const byte sensor1 = 0x10; //TFMini I2C Address
// Define pins for LEDs
const int greenLED = 8;
const int yellowLED = 9;
const int redLED = 10;
int stopLimit = 160; //Change this number of cm to adjust stop distance
void setup()
{
Wire.begin();
Serial.begin(115200);
Serial.println("TFMini I2C Test"); //For testing using Serial Monitor
// Set LED pins as outputs
pinMode(redLED, OUTPUT);
pinMode(yellowLED, OUTPUT);
pinMode(greenLED, OUTPUT);
}
void loop()
{
if (readDistance(sensor1) == true)
{
if (valid_data == true) {
Serial.print("\stopLimit["); //These Serial.print lines remain for testing and adjustment purposes
Serial.print(stopLimit);
Serial.print("\tDist[");
Serial.print(distance);
Serial.println();
if (distance <= stopLimit) {
digitalWrite(redLED, HIGH);
digitalWrite(yellowLED, LOW);
digitalWrite(greenLED, LOW);
}
else if (distance > stopLimit && distance < (stopLimit + 200) ) { //change this number to increase distance yellow stays lit
digitalWrite(redLED, LOW);
digitalWrite(yellowLED, HIGH);
digitalWrite(greenLED, LOW);
}
else if (distance > (stopLimit + 199) ) { //change this number to adjust when yellow LED illuminates
digitalWrite(redLED, LOW);
digitalWrite(yellowLED, LOW);
digitalWrite(greenLED, HIGH);
}
}
// else {
// Serial.println("Read fail");
// }
delay(50); //Delay small amount between readings
}
}
//Write two bytes to a spot
boolean readDistance(uint8_t deviceAddress)
{
Wire.beginTransmission(deviceAddress);
Wire.write(0x01); //MSB
Wire.write(0x02); //LSB
Wire.write(7); //Data length: 7 bytes for distance data
if (Wire.endTransmission(false) != 0) {
return (false); //Sensor did not ACK
}
Wire.requestFrom(deviceAddress, (uint8_t)7); //Ask for 7 bytes
if (Wire.available())
{
for (uint8_t x = 0 ; x < 7 ; x++)
{
uint8_t incoming = Wire.read();
if (x == 0)
{
//Trigger done
if (incoming == 0x00)
{
//Serial.print("Data not valid: ");//for debugging
valid_data = false;
//return(false);
}
else if (incoming == 0x01)
{
Serial.print("Data valid: ");
valid_data = true;
}
}
else if (x == 2)
distance = incoming; //LSB of the distance value "Dist_L"
else if (x == 3)
distance |= incoming << 8; //MSB of the distance value "Dist_H"
else if (x == 4)
strength = incoming; //LSB of signal strength value
else if (x == 5)
strength |= incoming << 8; //MSB of signal strength value
else if (x == 6)
rangeType = incoming; //range scale
}
}
else
{
Serial.println("No wire data avail");
return (false);
}
return (true);
}
I also did a quick stop light model, and you can download that from the Github repository here.
GOTCHA WARNING! Because of the power needs of the TFMini, and the power management system on the SparkFun Blackboard, if you try to run your final project with a power supply using the barrel jack, it will freeze up, the green LED will remain illuminated, and your driver, basing their actions solely on your sweet new project, will drive right into the wall. However, powering it through the microUSB connector works without issue. So even though that big beautiful barrel jack is staring right at you, tempting you, don't give in! It will only lead to misery.
This build is about as quick and basic as they come, but it doesn't have to be. You've got the code, you've got the .STL files, now take them and run with them. Add some buttons to make it easier to adjust the optimal stopping distance. Create a better housing. Increase the number of LEDs to make it more visible. If you're feeling really ambitious, you might even swap out the Blackboard for a Raspberry Pi, and program this project in Python. Is there any advantage to using an SBC over a microcontroller for this project? Absolutely not. But why just kill a project when you can overkill it? Happy Hacking, friends!
Learn all about the different technologies distance sensors use and which products would work best for your next project.
Take me there!