Note
Hello, welcome to the SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Community on Facebook! Dive deeper into Raspberry Pi, Arduino, and ESP32 with fellow enthusiasts.
Why Join?
Expert Support: Solve post-sale issues and technical challenges with help from our community and team.
Learn & Share: Exchange tips and tutorials to enhance your skills.
Exclusive Previews: Get early access to new product announcements and sneak peeks.
Special Discounts: Enjoy exclusive discounts on our newest products.
Festive Promotions and Giveaways: Take part in giveaways and holiday promotions.
👉 Ready to explore and create with us? Click [here] and join today!
19. Smart Trash Can¶
Welcome to our exciting project-based course where we’ll be building a Smart Trash Can! This course offers a practical approach to integrating an ultrasonic sensor with a servo motor to create a trash can that responds to your presence. By the end of this course, you’ll understand how to make everyday objects smarter and more interactive.
By the end of this lesson, you will be able to:
Understand and utilize ultrasonic sensors for distance measurement.
Integrate a servo to automate physical actions.
Program an Arduino to control device behavior based on sensor inputs.
Learn the Ultrasonic Module¶
Imagine you are in a dark room and can’t see the objects around you. In this situation, you could clap your hands to produce a sound that travels outward. When this sound hits a wall or another object, it bounces back as an echo. If you listen carefully, you can hear this echo. By calculating the time it takes for the sound to travel out and the echo to return, you can roughly estimate how far away the wall or object is. Ultrasonic sensors work in a similar way to “see” the world around them.
TRIG: Trigger Pulse Input
ECHO: Echo Pulse Output
GND: Ground
VCC: 5V Supply
The HC-SR04 ultrasonic distance sensor, providing non-contact measurement from 2 cm to 400 cm with a range accuracy of up to 3 mm. Included on the module is an ultrasonic transmitter, a receiver and a control circuit.
You only need to connect 4 pins: VCC (power), Trig (trigger), Echo (receive) and GND (ground) to make it easy to use for your measurement projects.
Principle
The basic principles are as follows:
Using IO trigger for at least 10us high level signal.
The module sends an 8 cycle burst of ultrasound at 40 kHz and detects whether a pulse signal is received.
Echo will output a high level if a signal is returned; the duration of the high level is the time from emission to return.
Distance = (high level time x velocity of sound (340M/S)) / 2
Note
This module should not be connected under power up, if necessary, let the module’s GND be connected first. Otherwise, it will affect the work of the module.
The area of the object to be measured should be at least 0.5 square meters and as flat as possible. Otherwise, it will affect results.
Build the Circuit¶
Components Needed
1 * Arduino Uno R3 |
1 * Servo |
1 * Ultrasonic Module |
1 * Breadboard Power Module |
1 * USB Cable |
1 * Breadboard |
Jumper Wires |
|
1 * 9V Battery |
1 * Battery Cable |
||
Building Step-by-Step
Follow the wiring diagram, or the steps below to build your circuit.
When using motors, servos, and other actuators, it’s recommended to use an external power supply to avoid damaging the main board. Insert the breadboard power module into the breadboard, then use a jumper wire to connect the negative rail of the breadboard to the GND of the Arduino Uno R3 to achieve a common ground.
Note
The order of the positive and negative terminals on the breadboard in the wiring diagram is reversed compared to the breadboard provided in the kit.
In actual wiring, you need to insert the breadboard power module from the higher number side (60~65) so that the “-” of the power module goes into the negative rail “-” of the breadboard, and the “+” into the positive rail “+”.
Use three short jumper wires to extend the three wires of your servo: connect the yellow wire to pin 9 of the Arduino Uno R3, the red wire to the positive rail of the breadboard, and the brown wire to the negative rail of the breadboard.
Insert the ultrasonic module into the breadboard.
Connect the VCC pin of the ultrasonic module to the positive side of the breadboard, the Trig pin to pin 8 on the Arduino board, the Echo pin to pin 7, and the GND to the negative side of the breadboard.
Code Creation - Read the Distance¶
Now, let’s see how to get the distance measurements from the ultrasonic module.
Open the Arduino IDE and start a new project by selecting “New Sketch” from the “File” menu.
Save your sketch as
Lesson19_Read_Distance
usingCtrl + S
or by clicking “Save”.Firstly, we need to define the pins on the Arduino that are connected to the ultrasonic module.
#define TRIGGER_PIN 8
#define ECHO_PIN 7
In the
setup()
function, we set the mode for each pin. The Trig pin needs to be set to output (as it sends the signal), the Echo pin is set to input (as it receives the signal).
void setup() {
pinMode(TRIGGER_PIN, OUTPUT); // Set the Trig pin as output
pinMode(ECHO_PIN, INPUT); // Set the Echo pin as input
Serial.begin(9600); // Start serial communication for debugging
}
Writing the
measureDistance()
Function:
The measureDistance()
function encapsulates the logic required to trigger the ultrasonic sensor and read the distance based on the echo received:
Triggering the Ultrasonic Pulse
Set the
TRIGGER_PIN
low initially to ensure a clean pulse.A short delay of 2 microseconds ensures the line is clear.
Send a 10-microsecond high pulse to the
TRIGGER_PIN
. This pulse tells the sensor to emit an ultrasonic sound wave.Set the
TRIGGER_PIN
back to low to end the pulse.long measureDistance() { digitalWrite(TRIGGER_PIN, LOW); // Ensure Trig pin is low before a pulse delayMicroseconds(2); digitalWrite(TRIGGER_PIN, HIGH); // Send a high pulse delayMicroseconds(10); // Pulse duration of 10 microseconds digitalWrite(TRIGGER_PIN, LOW); // End the high pulse }
Reading the Echo
The
pulseIn()
function is used on theECHO_PIN
to measure the duration of the incoming pulse. This function waits for the pin to goHIGH
, times how long it staysHIGH
, and then returns the duration in microseconds.This
duration
is the time taken for the ultrasonic pulse to travel to the object and back.long measureDistance() { digitalWrite(TRIGGER_PIN, LOW); // Ensure Trig pin is low before a pulse delayMicroseconds(2); digitalWrite(TRIGGER_PIN, HIGH); // Send a high pulse delayMicroseconds(10); // Pulse duration of 10 microseconds digitalWrite(TRIGGER_PIN, LOW); // End the high pulse long duration = pulseIn(ECHO_PIN, HIGH); // Measure the duration of high level on Echo pin }
Calculating the Distance
The speed of sound in air (approximately 340 m/s) is used here. The formula to calculate the distance is (duration * speed of sound) / 2. We divide by 2 because the sound wave travels to the object and back, so we only need half the distance for a one-way measurement.
In our code, 0.034 cm/us (speed of sound in cm/microsecond) is used as a conversion factor.
long measureDistance() { digitalWrite(TRIGGER_PIN, LOW); // Ensure Trig pin is low before a pulse delayMicroseconds(2); digitalWrite(TRIGGER_PIN, HIGH); // Send a high pulse delayMicroseconds(10); // Pulse duration of 10 microseconds digitalWrite(TRIGGER_PIN, LOW); // End the high pulse long duration = pulseIn(ECHO_PIN, HIGH); // Measure the duration of high level on Echo pin long distance = duration * 0.034 / 2; // Calculate the distance (in cm) return distance; }
In the
loop()
function, call themeasureDistance()
function to measure the distance, and then print it to the serial monitor.
void loop() {
long distance = measureDistance(); // Call the function to measure distance
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
delay(100); // Delay between measurements
}
Note
In previous lessons, we worked with int
and float
types of variables or constants. Now, let’s understand what long
and unsigned long
variables are about:
long
: Along
integer is an extended version of anint
. It is used to store larger integer values that exceed the capacity of standardint
. A long typically occupies 32 or 64 bits of memory, which allows it to hold much larger values, both positive and negative.unsigned long
: Anunsigned long
is similar to along
but can only represent non-negative values. It uses the bit normally reserved for the sign to extend the range of possible values it can hold, but strictly in the positive spectrum.
Here is your complete code. You can now click “Upload” to upload the code to the Arduino Uno R3.
#define TRIGGER_PIN 8
#define ECHO_PIN 7
void setup() {
pinMode(TRIGGER_PIN, OUTPUT); // Set the Trig pin as output
pinMode(ECHO_PIN, INPUT); // Set the Echo pin as input
Serial.begin(9600); // Start serial communication for debugging
}
void loop() {
long distance = measureDistance(); // Call the function to measure distance
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm");
delay(100); // Delay between measurements
}
long measureDistance() {
digitalWrite(TRIGGER_PIN, LOW); // Ensure Trig pin is low before a pulse
delayMicroseconds(2);
digitalWrite(TRIGGER_PIN, HIGH); // Send a high pulse
delayMicroseconds(10); // Pulse duration of 10 microseconds
digitalWrite(TRIGGER_PIN, LOW); // End the high pulse
long duration = pulseIn(ECHO_PIN, HIGH); // Measure the duration of high level on Echo pin
long distance = duration * 0.034 / 2; // Calculate the distance (in cm)
return distance;
}
Open the serial monitor, and you will see the printed distance values. You can move the object in front of the ultrasonic sensor to see if the printed distance changes. If it does, this indicates that the ultrasonic module is functioning correctly.
Distance: 30 cm
Distance: 29 cm
Distance: 28 cm
Distance: 27 cm
Distance: 26 cm
Distance: 25 cm
Distance: 25 cm
Finally, remember to save your code and tidy up your workspace.
Question
If you want the distance detected by this device to be more accurate to decimals, how should you modify the code?
Code Creation - Smart Trash Can¶
We already know how to measure the distance to objects using an ultrasonic module. Now, let’s write code to create a smart trash can. This trash can will automatically open its lid when the ultrasonic sensor detects an object closer than 20cm—indicating that you intend to dispose of trash. After the trash is thrown in, the lid will automatically close.
The lid’s movement is controlled by a servo:
At a servo angle of 90 degrees, the servo shaft is parallel to the servo, meaning the trash can lid is closed.
At 0 degrees, the servo shaft is perpendicular to the servo, lifting the lid open via a rod attached to the shaft.
Let’s explore how to implement this using code.
Open the sketch you saved earlier,
Lesson19_Read_Distance
. Hit “Save As…” from the “File” menu, and rename it toLesson19_Smart_Trashcan
. Click “Save”.To control the servo, we need to include the
Servo
library and create an instance of theServo
class to control the servo.
#include <Servo.h>
Servo myServo; // Create a Servo object
#define TRIGGER_PIN 8
#define ECHO_PIN 7
Let’s start by defining the servo pin, and create two variables
openAngle
andcloseAngle
to store the angles for opening and closing the trash can lid respectively.
#include <Servo.h>
Servo myServo; // Create a Servo object
#define TRIGGER_PIN 8
#define ECHO_PIN 7
// Set up the servo motor parameters
const int servoPin = 9;
const int openAngle = 0;
const int closeAngle = 90;
In the
void setup()
function, attach the servo object to the specified pin.
void setup() {
pinMode(TRIGGER_PIN, OUTPUT); // Set the Trig pin as output
pinMode(ECHO_PIN, INPUT); // Set the Echo pin as input
Serial.begin(9600); // Start serial communication for debugging
myServo.attach(servoPin);
}
Now we’ve reached the main program. First, comment out the code for the three serial print statements to avoid interfering with the program’s process.
void loop() {
long distance = measureDistance(); // Call the function to measure distance
// Serial.print("Distance: ");
// Serial.print(distance);
// Serial.println(" cm");
delay(100); // Delay between measurements
}
As planned, if the ultrasonic sensor detects a distance less than 20cm, the servo should rotate to 0 degrees to open the trash can lid. Otherwise, the servo should remain at 90 degrees to keep the lid closed.
delay(2000);
is used here to give you enough time to throw away the trash without the lid closing too quickly. You can adjust this timing as needed.In
if (distance > 2 && distance < 20)
, the conditiondistance > 2
is used to filter out invalid values. The effective detection range of the ultrasonic sensor is from 2cm to 400cm. Distances that are too far or too close will return invalid values of -1 or 0.
void loop() {
long distance = measureDistance(); // Call the function to measure distance
// Serial.print("Distance: ");
// Serial.print(distance);
// Serial.println(" cm");
if (distance > 2 && distance < 20) {
myServo.write(openAngle);
delay(2000);
} else {
myServo.write(closeAngle);
}
delay(100); // Delay between measurements
}
Your complete code is as follows. You can upload it and test to see if your trash can automatically opens and then closes after you’ve disposed of your trash.
#include <Servo.h>
Servo myServo; // Create a Servo object
#define TRIGGER_PIN 8
#define ECHO_PIN 7
// Set up the servo motor parameters
const int servoPin = 9;
const int openAngle = 0;
const int closeAngle = 90;
void setup() {
pinMode(TRIGGER_PIN, OUTPUT); // Set the Trig pin as output
pinMode(ECHO_PIN, INPUT); // Set the Echo pin as input
Serial.begin(9600); // Start serial communication for debugging
myServo.attach(servoPin);
}
void loop() {
long distance = measureDistance(); // Call the function to measure distance
// Serial.print("Distance: ");
// Serial.print(distance);
// Serial.println(" cm");
if (distance > 2 && distance < 20) {
myServo.write(openAngle);
delay(2000);
} else {
myServo.write(closeAngle);
}
delay(100); // Delay between measurements
}
// Function to read the sensor data and calculate the distance
long measureDistance() {
digitalWrite(TRIGGER_PIN, LOW); // Ensure Trig pin is low before a pulse
delayMicroseconds(2);
digitalWrite(TRIGGER_PIN, HIGH); // Send a high pulse
delayMicroseconds(10); // Pulse duration of 10 microseconds
digitalWrite(TRIGGER_PIN, LOW); // End the high pulse
long duration = pulseIn(ECHO_PIN, HIGH); // Measure the duration of high level on Echo pin
long distance = duration * 0.034 / 2; // Calculate the distance (in cm)
return distance;
}
Finally, remember to save your code and tidy up your workspace.
Summary
Today, we successfully built a smart trash can that opens its lid automatically when an object is within 20 cm. We explored how ultrasonic sensors work, similar to echolocation, and applied this technology to control a servo motor. We also discussed best practices in wiring and provided tips for effective Arduino programming. The interactive nature of the project provided hands-on experience with real-world applications of sensors and servo motors.