ESP32 S3 UNO - Motion Sensor

This ESP32 S3 Uno motion sensor tutorial shows you how to wire an HC-SR501 PIR sensor to the ESP32 S3 Uno form board and detect people with Arduino code. The HC-SR501 motion sensor sees the body heat of a moving person, and your sketch prints a message when motion starts and when it stops.

In this tutorial, you will:

  1. Learn how the HC-SR501 PIR sensor detects human movement
  2. Wire the HC-SR501 motion sensor to the ESP32 S3 Uno
  3. Read the sensor output with digitalRead() in the Arduino IDE
  4. Detect when motion starts and stops
  5. Tune the detection range, time delay and trigger mode
ESP32 S3 Uno motion sensor

Hardware Preparation

1×ESP32 S3 Uno-form Board
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×HC-SR501 Motion Sensor
1×Alternatively, AM312 Mini Motion Sensor
1×Jumper Wires

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Overview of HC-SR501 Motion Sensor

HC-SR501 Motion Sensor

The HC-SR501 is a PIR (passive infrared) sensor that notices when a person or an animal moves. You find this kind of sensor in automatic lights, self-opening doors, escalators that start when someone walks up, and intruder alarms.

Have you ever walked into a shop and seen the door open by itself, or a hallway light turn on as you pass? A small sensor like this one is usually behind it. In this guide you will see how it works, and then build the same idea yourself.

Pinout

The HC-SR501 has only three pins, so the wiring is simple. You power it, and it gives you one digital signal back.

GND pin

Connect it to GND (0V).

VCC pin

Connect it to 5V. The module has its own 3.3V regulator inside, so it runs well from the 5V header pin.

OUTPUT pin

This pin is LOW when there is no motion and HIGH when motion is detected. Connect it to a digital input pin on the ESP32 S3 Uno.

The board also has one jumper and two small potentiometers to change how the sensor behaves. Leave them at the default setting for now. The Advanced Uses section explains each one.

HC-SR501 Motion Sensor Pinout

How It Works

The sensor does not see objects. It sees changes in infrared light. To be detected, an object must do two things at the same time:

  1. Move
  2. Give off infrared energy (heat)

This has two results. A moving object with no body heat, like a robot or a toy car, is not detected. A warm person who stands perfectly still is not detected either. People and animals give off infrared all the time, so the sensor reacts when they move.

OUTPUT pin states

When nobody moves in the sensor's range, the OUTPUT pin stays LOW. When a person or animal moves into the range, the pin goes from LOW to HIGH, which means motion is detected. When they leave the range, the pin goes from HIGH back to LOW, which means motion has ended.

The video shows the basic idea. In a real project, the exact timing depends on the sensor settings, which you can change in the Advanced Uses section.

ESP32 S3 Uno - HC-SR501 Motion Sensor

The ESP32 S3 Uno only needs to read one digital signal here. When you set a pin as a digital input, the board can tell if that pin is LOW or HIGH.

Connect the sensor's OUTPUT pin to an ESP32 S3 Uno input pin. Your code then reads that pin over and over, and a change in its state tells you that motion started or stopped.

ESP32 S3 Uno Pinout

The image below shows the pinout diagram of the ESP32 S3 Uno form board. Use it to find the D2, 5V and GND header pins and their GPIO numbers before you wire the motion sensor.

ESP32 S3 Uno pinout diagram

Wiring Diagram

Power the sensor from the 5V and GND pins, and connect its OUTPUT pin to D2 (GPIO18), as shown below.

The wiring diagram between ESP32 S3 Uno Motion Sensor

This image is created using Fritzing. Click to enlarge image

HC-SR501 Pin ESP32 S3 Uno Pin
VCC 5V
GND GND
OUTPUT D2 (GPIO18)

※ NOTE THAT:

ESP32 S3 Uno pins work at 3.3V and are NOT 5V tolerant. The HC-SR501 is safe here: even when you power it from 5V, its OUTPUT pin gives about 3.3V for HIGH. If you use a different PIR module, check that its output is not 5V before you connect it.

Initial Setting

Before you test the code, set the sensor to a known starting point. This makes your first results match the ones shown in this tutorial.

Time Delay AdjusterTurn it fully anti-clockwise.
Detection Range AdjusterTurn it fully clockwise.
Repeat Trigger SelectorPlace the jumper as shown in the image.
ESP32 S3 Uno motion sensor initial setting

How To Program For Motion Sensor

Reading a PIR sensor takes only a few lines of code. The main idea is to compare the new reading with the last one, so you react only when the state changes.

  1. Set the ESP32 S3 Uno pin as a digital input with the pinMode() function.
pinMode(SENSOR_PIN, INPUT);
  1. Read the state of the sensor's OUTPUT pin with the digitalRead() function.
motion_state = digitalRead(SENSOR_PIN);
  1. Detect the start of motion, when the pin goes from LOW to HIGH.
prev_motion_state = motion_state; // Store the previous state of the pin motion_state = digitalRead(SENSOR_PIN); // Read the current state of the pin if (prev_motion_state == LOW && motion_state == HIGH) { // Check for transition from LOW to HIGH Serial.println("Motion detected!"); }
  1. Detect the end of motion, when the pin goes from HIGH to LOW.
prev_motion_state = motion_state; // Preserve the previous state of the pin motion_state = digitalRead(SENSOR_PIN); // Update the current state from sensor input if (prev_motion_state == HIGH && motion_state == LOW) { // Detect transition from HIGH to LOW Serial.println("Motion stopped!"); // Output message when motion stops }

ESP32 S3 Uno Code

The sketch below reads the HC-SR501 on GPIO18 (header D2) in a loop. It keeps the last state in a variable, so it prints a message only once when motion starts and once when motion stops.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-motion-sensor */ #define SENSOR_PIN 18 // The ESP32 S3 Uno pin GPIO18 (D2) connected to the output pin of the motion sensor int motion_state = LOW; // Initialize current pin state to LOW int prev_motion_state = LOW; // Initialize previous pin state to LOW void setup() { Serial.begin(9600); // Start serial communication at 9600 baud rate pinMode(SENSOR_PIN, INPUT); // Configure GPIO18 as an input for the sensor } void loop() { prev_motion_state = motion_state; // Assign the current pin state to the previous pin state for comparison motion_state = digitalRead(SENSOR_PIN); // Read the current state from the sensor output // Check for transition from LOW to HIGH which indicates motion detected if (prev_motion_state == LOW && motion_state == HIGH) { Serial.println("Motion detected!"); // Print message when motion is detected // Optional: Additional actions when motion is detected } // Check for transition from HIGH to LOW which indicates motion has stopped else if (prev_motion_state == HIGH && motion_state == LOW) { Serial.println("Motion stopped!"); // Print message when motion has stopped // Optional: Additional actions when motion stops } }

Detailed Instructions

Follow these steps in order:

  1. New to the ESP32 S3 Uno? Follow ESP32 S3 Uno - Getting Started first.
  2. Wire it up as shown in the diagram.
  3. Connect the board to your computer with a USB Type-C cable.
  4. Open Arduino IDE, choose the ESP32S3 Dev Module board and the correct COM port.
  5. Copy the code above and paste it into the Arduino IDE.
  6. Upload the sketch by clicking the Upload button.
  7. Open the Serial Monitor and set it to 9600 baud.
  8. Wave your hand in front of the sensor.
  9. Check the output on the Serial Monitor.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
Motion detected! Motion stopped! Motion detected! Motion stopped!
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2
  1. Tip: The HC-SR501 needs up to one minute to settle after power on. During that time it may give false triggers, so wait a moment before you test.

ESP32 S3 Uno with HC-SR501 Motion Sensor - Video Tutorial

Watch the video below to see this ESP32 S3 Uno project step by step.

At the end of the video, the sensor is used to build an automatic door with a servo motor and a buzzer. The ESP32 S3 Uno version of that code is below. The servo signal goes to D5 (GPIO20) and the buzzer goes to D6 (GPIO3). It uses the ESP32Servo library by Kevin Harrington, because the normal Servo library does not work on the ESP32 S3 Uno.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-motion-sensor */ #include <ESP32Servo.h> #define SENSOR_PIN 18 // The ESP32 S3 Uno pin GPIO18 (D2) connected to the output pin of the motion sensor #define SERVO_PIN 20 // The ESP32 S3 Uno pin GPIO20 (D5) connected to the servo motor #define BUZZER_PIN 3 // The ESP32 S3 Uno pin GPIO3 (D6) connected to the buzzer Servo servo; int motion_state = LOW; // Initialize current pin state to LOW int prev_motion_state = LOW; // Initialize previous pin state to LOW void setup() { Serial.begin(9600); // Start serial communication at 9600 baud rate pinMode(SENSOR_PIN, INPUT); // Configure GPIO18 (D2) as an input for the sensor pinMode(BUZZER_PIN, OUTPUT); // Configure the buzzer pin as output servo.attach(SERVO_PIN); servo.write(0); noTone(BUZZER_PIN); } void beep() { for (int i = 0; i < 2; i++) { tone(BUZZER_PIN, 5000); delay(100); noTone(BUZZER_PIN); delay(100); } } void loop() { prev_motion_state = motion_state; // Assign the current pin state to the previous pin state for comparison motion_state = digitalRead(SENSOR_PIN); // Read the current state from the sensor output // Check for transition from LOW to HIGH which indicates motion detected if (prev_motion_state == LOW && motion_state == HIGH) { Serial.println("Motion detected!"); // Print message when motion is detected servo.write(180); beep(); // Optional: Additional actions when motion is detected } // Check for transition from HIGH to LOW which indicates motion has stopped else if (prev_motion_state == HIGH && motion_state == LOW) { Serial.println("Motion stopped!"); // Print message when motion has stopped servo.write(0); beep(); // Optional: Additional actions when motion stops } }

WARNING

D6 (GPIO3) is a boot strapping pin on the ESP32 S3 Uno. The board reads it at startup to pick the boot mode. A buzzer module usually does not cause trouble, but if the board does not boot or upload while the buzzer is connected, unplug the buzzer wire from D6, upload, and connect it again.

Advanced Uses

This section includes advanced information that may be overwhelming. If you are unsure about the content, feel free to skip it and move on to the next sections.

The jumper and the two potentiometers on the HC-SR501 let you change how far it sees, how long the output stays HIGH, and how it reacts to repeated motion. Small changes here can make your project feel much more natural.

Detection Range Adjuster

This potentiometer sets how far the sensor can detect motion, from about 3 meters to about 7 meters. Turn it fully clockwise for about 3 meters, or fully anti-clockwise for about 7 meters. Any position in between gives a range between these two values.

Motion Sensor Detection Range

Time Delay Adjuster

This potentiometer sets the time delay, which is how long the OUTPUT pin stays HIGH after motion. Turn it fully clockwise for about 5 minutes, or fully anti-clockwise for about 3 seconds. The next part shows how this delay works together with the trigger mode.

motion sensor adjust time delay

Repeat Trigger Selector

The jumper picks one of two trigger modes: single trigger or repeatable trigger.

motion sensor trigger selection

Call the time set by the Time Delay Adjuster time_delay. Now imagine you keep moving in front of the sensor for a long time, called motion_time, which is much longer than time_delay.

Single trigger mode

The OUTPUT pin switches between LOW and HIGH again and again. Each HIGH period lasts for "time_delay", and each LOW period lasts a fixed 3 seconds.

motion sensor single trigger mode

Repeatable trigger mode

The OUTPUT pin stays HIGH for the whole motion time plus the time delay.

motion sensor repeatable trigger mode

Testing

You can see the difference between the two modes with the same sketch. First, turn the Time Delay Adjuster fully anti-clockwise, so the delay is 3 seconds.

Test the single trigger mode:

  1. Set the jumper to single trigger mode.
  2. Keep waving your hand in front of the sensor for 10 seconds.
  3. Move your hand out of the sensor's range.
  4. Wait 3 seconds, then look at the Serial Monitor.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
Motion detected! Motion stopped! Motion detected! Motion stopped! Motion detected! Motion stopped!
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2

Test the repeatable trigger mode:

  1. Set the jumper to repeatable trigger mode.
  2. Keep waving your hand in front of the sensor for about 10 seconds.
  3. Move your hand out of the sensor's range.
  4. Wait 3 seconds, then look at the Serial Monitor.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
Motion detected! Motion stopped!
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2

With single trigger mode, the sensor fires two or three times for one long movement. With repeatable trigger mode, it fires only once.

※ NOTE THAT:

In the 3-second LOW period, the sensor is blind and cannot detect motion. In most projects this is not a problem.

The repeatable trigger mode is the better choice for most projects.

This matches how real devices behave:

  • A device usually turns on as soon as a person is detected nearby.
  • It does not turn off the moment the person leaves. It turns off after a delay.

Function References

FAQ

Can I power the HC-SR501 from the ESP32 S3 Uno 3.3V pin?

It is better to use the 5V pin. The HC-SR501 is made for 4.5V to 20V, and its internal regulator may not work well from 3.3V. The sensor's OUTPUT pin still gives about 3.3V, so it is safe for the ESP32 S3 Uno input.

Is the HC-SR501 output safe for ESP32 S3 Uno pins?

Yes. ESP32 S3 Uno pins are NOT 5V tolerant, unlike the UNO R4 pins, but the HC-SR501 output HIGH level is about 3.3V even when VCC is 5V. Other PIR modules may output 5V, so measure the output with a multimeter before you connect a new module.

Which ESP32 S3 Uno pin should I use for the motion sensor?

Any normal digital header pin works. This tutorial uses D2, which is GPIO18, so the code uses the number 18. Avoid D0 and D1, which are used for USB serial, and avoid D6 (GPIO3) and D9 (GPIO46) for inputs, because they are boot strapping pins.

Why does my motion sensor trigger by itself?

The HC-SR501 needs up to one minute to settle after power on, and it can give false triggers during that time. Heat sources, air from a fan or heater, and direct sunlight can also trigger it. Point it away from these and wait after power up.

Why does the sensor not detect me when I stand still?

A PIR sensor only reacts to a change in infrared light. If you do not move, the heat it sees does not change, so the output goes back to LOW after the time delay. This is normal behavior.

What if my project needs more pins than the Uno headers give?

The ESP32 S3 Uno has two extra rows of holes with more GPIOs. GPIO15 and GPIO16 support I/O, PWM and analog. GPIO45 and GPIO35 to GPIO42 support I/O and PWM. GPIO47 and GPIO48 are output only, with PWM. Solder pin headers to use them and write the GPIO number in your code. For extra motion sensors, GPIO35 to GPIO42 are a good choice. Never connect a sensor output to GPIO47 or GPIO48, because they cannot be inputs. Keep two warnings in mind. First, GPIO47 and GPIO48 may run at 1.8V instead of 3.3V on some modules (especially ones with "V" in the name, like R8V or R16V), so 3.3V devices can be damaged or act strangely. Second, GPIO0, GPIO3 (D6), GPIO45 and GPIO46 (D9) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code. Use the other extra pins first.

Troubleshooting

Problem Possible Cause Solution
No COM port shows up in Arduino IDE USB driver missing or board not in upload mode Install the CP210x or CH340 driver, use a data USB cable, or hold BOOT while pressing RESET
Nothing prints on the Serial Monitor Wrong baud rate Set the Serial Monitor to 9600 baud
Sensor never detects motion Loose wire, wrong pin, or no power Check VCC to 5V and GND, and that OUTPUT goes to D2 with GPIO18 in the code
Many false triggers after power on Sensor still warming up Wait about one minute after power on before testing
Random triggers with nobody around Heat source, moving air or sunlight in view Point the sensor away from heaters, fans and windows
Output stays HIGH for a long time Time delay set too long Turn the Time Delay Adjuster anti-clockwise
Motion detected and stopped several times for one movement Jumper in single trigger mode Move the jumper to repeatable trigger mode
Board does not boot with the door sketch Buzzer on boot strapping pin D6 Unplug the buzzer wire from D6 while uploading or resetting

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!