Process the motion detected by the motion sensor HC-SR501 with Raspberry Pi 3 & Java

Introduction

Use the Raspberry Pi 3 to read the motion detection status of the motion sensor HC-SR501. The programming language uses Java.

HC-SR501
HC-SR501.png

This motion sensor detects the movement of infrared rays, and when there is a change, the output becomes a high level (3.3V), and when there is no change, it becomes a low level (0V).

There are two orange semi-fixed resistors on the side of the module, and if you turn the left side clockwise, the delay time after detection will be in the range of about 5 to 300 seconds, and if you turn the right side clockwise , The detection distance can be adjusted in the range of about 3 to 7 meters.

(Reference) HC-SR501 data sheet

Preparation

Use Pi4J to control the GPIO of the Raspberry Pi from Java. For the Pi4J environment, refer to "Installing Pi4J" in the following article.

Graph the sensor information of Raspberry Pi and prepare an environment that can be checked with a Web browser

When Pi4J is installed, various sample programs will be copied together under the directory / opt / pi4j / examples. You can use the source code in this sample to check the motion detection status.

Sample program

The motion detection state only looks at whether the output level is high or low, so you can use the same program logic as the switch.

If you want to do something according to the GPIO pin level status, you can loop around the program to check the pin level periodically, but the process is executed when the pin status changes. You can write so-called event-driven programs.

ListenGpioExample.java in / opt / pi4j / examples is the source code to do that.

To try out the program, connect the Raspberry Pi and the HC-SR501 as follows.

HC-SR501

The program implements the interface GpioPinListenerDigital and registers an instance of the anonymous class that overrides the listener handleGpioPinDigitalStateChangeEvent () method with the GPIO pin instance.

ListenGpioExample.Part of java (rewriting comments)



//Create a GpioController instance
final GpioController gpio = GpioFactory.getInstance();

//Specify the target pin as the input pin
final GpioPinDigitalInput myButton = gpio.provisionDigitalInputPin(RaspiPin.GPIO_02, PinPullResistance.PULL_DOWN);

//Register a listener to be called when the pin state changes
myButton.addListener(new GpioPinListenerDigital() {
    @Override
    public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
        //Show pin status on console
        System.out.println(" --> GPIO PIN STATE CHANGE: " + event.getPin() + " = " + event.getState());
    }
});

This will cause the above process to be called each time the pin state changes.

You can check the operation by copying ListenGpioExample.java to an appropriate directory and compiling with the following command.

pi@raspberrypi:~ $ pi4j -c ListenGpioExample.java
--------------------------------------------
Pi4J - Compiling: ListenGpioExample.java
--------------------------------------------
+ javac -classpath '.:classes:*:classes:/opt/pi4j/lib/*' -d . ListenGpioExample.java
pi@raspberrypi:~ $

After compiling, execute it with root privileges. Enter Ctrl + C to exit.

pi@raspberrypi:~ $ sudo pi4j ListenGpioExample
+ java -classpath '.:classes:*:classes:/opt/pi4j/lib/*' ListenGpioExample
<--Pi4J--> GPIO Listen Example ... started.
 ... complete the GPIO #02 circuit and see the listener feedback here in the console.
 --> GPIO PIN STATE CHANGE: "GPIO 2" <GPIO 2> = HIGH
 --> GPIO PIN STATE CHANGE: "GPIO 2" <GPIO 2> = LOW
 --> GPIO PIN STATE CHANGE: "GPIO 2" <GPIO 2> = HIGH
 --> GPIO PIN STATE CHANGE: "GPIO 2" <GPIO 2> = LOW
^Cpi@raspberrypi:~ $

It is a good idea to start the program with the delay time knob turned all the way counterclockwise so that you can read the state change immediately.

Demo program

In addition to the above motion sensor, I created a demo program that combines a 1602 LCD display with an I2C interface and a tact switch.

I2C 1602 LCD Tact switch
I2C 1602 LCD Tactswitch

This program works as follows.

・ When the program is started, the date and time are displayed on the LCD. ・ Each time the tact switch is pressed, the time display switches between 12-hour notation and 24-hour notation. ・ The LCD backlight turns on when a person approaches, and turns off when there is no movement.

To use the 1602 LCD, enable the I2C communication function of the Raspberry Pi. See the following articles for details on how to enable it and the program to use the 1602 LCD.

Display characters on I2C 1602 LCD with Raspberry Pi 3 & Java

The Raspberry Pi and each part were connected as follows.

HC-SR501 Demo

If you want to try out the demo program, modify the value of the variable i2cAddress to match the address assigned to the 1602 LCD (how to check the address is also mentioned in the article above).

As mentioned above, the processing structure of the switch and the motion sensor is exactly the same.

HC_SR501Demo.java


import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

import com.pi4j.component.lcd.LCDTextAlignment;
import com.pi4j.component.lcd.impl.I2CLcdDisplay;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalInput;
import com.pi4j.io.gpio.Pin;
//import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.io.gpio.event.GpioPinDigitalStateChangeEvent;
import com.pi4j.io.gpio.event.GpioPinListenerDigital;

public class HC_SR501Demo {
    //Specifying the pin to which the switch is connected
    private static final Pin gpioTactSwitch = RaspiPin.GPIO_07;
    //Specifying the pin to which the motion sensor is connected
    private static final Pin gpioPirSensor = RaspiPin.GPIO_02;

    //Specifying the I2C bus number and address to which the I2C 1602 LCD module is connected
    private static final int i2cBus = 1;
    private static final int i2cAddress = 0x27;

    //Display format definition
    private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("y/MM/dd eee.", Locale.ENGLISH);
    private static final DateTimeFormatter timeFormatter12 = DateTimeFormatter.ofPattern("h:mm:ss a", Locale.ENGLISH);
    private static final DateTimeFormatter timeFormatter24 = DateTimeFormatter.ofPattern("HH:mm:ss");

    //Current time display format (true: 12 hours false:24hours)
    private static boolean timeFormat = true;

    public static void main(String[] args) throws Exception {
        //Creating objects for the I2C 1602 LCD module
        final I2CLcdDisplay lcd = new I2CLcdDisplay(2, 16, i2cBus, i2cAddress, 3, 0, 1, 2, 7, 6, 5, 4);

        //Creating a GpioController instance
        final GpioController gpio = GpioFactory.getInstance();

        //Set the pin to which the switch is connected as the input pin
        final GpioPinDigitalInput pinTactSwitch = gpio.provisionDigitalInputPin(gpioTactSwitch);
        //final GpioPinDigitalInput pinTactSwitch = gpio.provisionDigitalInputPin(gpioTactSwitch, PinPullResistance.PULL_DOWN);

        //Register a listener that will be called when the state of the pin to which the switch is connected changes
        pinTactSwitch.addListener(new GpioPinListenerDigital() {
            @Override
            public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
                //Switch the time display format each time the switch is pressed (pull-up)
                if (event.getState().isHigh()) timeFormat = !timeFormat;
            }
        });

        //Set the pin to which the motion sensor is connected as the input pin
        final GpioPinDigitalInput pinPirSensor = gpio.provisionDigitalInputPin(gpioPirSensor);
        //Set the initial state of the LCD backlight
        lcd.setBacklight(pinPirSensor.isHigh());

        //Register the listener that is called when the state of the pin to which the motion sensor is connected changes
        pinPirSensor.addListener(new GpioPinListenerDigital() {
            @Override
            public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
                //Turns on the LCD backlight when motion is detected (pull-up) and turns it off when it is not detected (pull-up).
                lcd.setBacklight(event.getState().isHigh());
            }
        });

        while (true) {
            //Get the current date and time
            LocalDateTime dateTime = LocalDateTime.now();

            //The date on the first line of the LCD and the time on the second line are centered.
            lcd.writeln(0, dateTime.format(dateFormatter), LCDTextAlignment.ALIGN_CENTER);
            lcd.writeln(1, dateTime.format(timeFormat ? timeFormatter12 : timeFormatter24), LCDTextAlignment.ALIGN_CENTER);
            Thread.sleep(100);
        }
    }
}

To run this program, put the above file in a directory of your choice and compile it.

pi@raspberrypi:~ $ pi4j -c HC_SR501Demo.java
--------------------------------------------
Pi4J - Compiling: HC_SR501Demo.java
--------------------------------------------
+ javac -classpath '.:classes:*:classes:/opt/pi4j/lib/*' -d . HC_SR501Demo.java
pi@raspberrypi:~ $

After compiling, execute it with root privileges. Enter Ctrl + C to exit.

pi@raspberrypi:~ $ sudo pi4j HC_SR501Demo
+ java -classpath '.:classes:*:classes:/opt/pi4j/lib/*' HC_SR501Demo
^Cpi@raspberrypi:~ $

If the backlight responds flickeringly, you can adjust it by turning the delay time knob slightly clockwise to get a good feeling.

Recommended Posts

Process the motion detected by the motion sensor HC-SR501 with Raspberry Pi 3 & Java
Display user-defined characters on the I2C 1602 LCD with Raspberry Pi 3 & Java
Graph the sensor information of Raspberry Pi in Java and check it with a web browser
Memo: [Java] Get Raspberry Pi data by SFTP
Display characters on I2C 1602 LCD with Raspberry Pi 3 & Java
Read temperature / humidity with Java from Raspberry Pi 3 & DHT11
[Java] Change the process according to the situation with the Strategy pattern
Read barometric pressure and temperature with Java from Raspberry Pi 3 & BMP180
[Java] Output by specifying the format with printf% s,% d,% f [Format specifier]
Check the domain by checking the MX record of the email address with java