We can select the best mists and thermal waters on the market to soothe the skin whenever necessary and add extra hydration for people with visual or mobility disabilities through this innovative device. The user only has to bring their faces in front of the person sensor and extend their hands closee the hand spray. The hand spray is automatically activated to spray the person's hands for three seconds. Afterwards the system gives you 5 seconds to leave this area. This is a useful application for people with mobility disabilities while traveling as it gives them comfort and hygiene.
In this application we can apply super effective instant hydration that we can use at any time of the day, not only when we do our morning and night facial care routine. They are a very good option not only to enhance the product that we are going to apply later. Use your device and take care of your facial skin in the most delicate moments by applying it in the simplest way: with two or three sprays at 10-15 cm. away from your hands.
Person Sensor With Raspberry PiThe Person Sensor from Useful Sensors is a small, low-cost hardware module that detects nearby peoples’ faces, and returns information about how many there are, where they are relative to the device, and performs facial recognition. It is designed to be used as an input to a larger system, for example to wake up a hand spray by means of a servo and a gripper. This is the case of my project.
Features:
- Qwiic connector for the I2C interface
- Operating Voltage - 3.3V
- 150mW power consumed
- 5mW LED power consumption
- I2C bus speeds of up to 400k baud
- Image Sensor - 110-degree FOV
- Image scan rate - 7Hz with no facial recognition
- Image scan rate - 5Hz with facial recognition active
- Module designed for privacy - resistant to allow access to raw image data, only metadata derived from each frame available.
- Pre-programmed microcontroller - firmware flashing & model updates not available.
More details can be found on the official site: https://github.com/usefulsensors/person_sensor_docs/tree/main
Raspberry Pi 4
- Broadcom BCM2711, Quad core Cortex-A72 (ARM v8) 64-bit SoC @ 1.8GHz
- 1GB, 2GB, 4GB or 8GB LPDDR4-3200 SDRAM (depending on model)
- 2.4 GHz and 5.0 GHz IEEE 802.11ac wireless, Bluetooth 5.0, BLE
- Gigabit Ethernet
- 2 USB 3.0 ports; 2 USB 2.0 ports.
- Raspberry Pi standard 40 pin GPIO header
- 2 × micro-HDMI® ports
- 2-lane MIPI DSI display port
- 2-lane MIPI CSI camera port
- 4-pole stereo audio and composite video port
- H.265 (4kp60 decode), H264 (1080p60 decode, 1080p30 encode)
- OpenGL ES 3.1, Vulkan 1.0
- Micro-SD card slot for loading operating system and data storage
- Power over Ethernet (PoE) enabled (requires separate PoE HAT)
- Operating temperature: 0 – 50 degrees C ambient
How does it works?
- If the face is pointing directly at the camera, then the person sensor board detects a user.
- Now the servo motor is activated via port 18, it rotates from 105 to 170 degrees approx with the gripper to press the water spray bottle for 3 seconds, then returns to the initial position of 105 degrees.
- Otherwise, the person sensor doesn't detect anyone and the servo remains in the original position.
- The qwiic pHat device acts as an interface between the Raspberry Pi and the Person Sensor. I have added or soldered 2 pins to facilitate the connection with the gripper servo.
Below I show you the gripper that we will use, as you can see it has a MG995 servo, which has a stall torque from 8.5 kgf·cm (4.8 V ) to 10 kgf·cm (6 V). Here the datasheet: https://www.electronicoscaldas.com/datasheet/MG995_Tower-Pro.pdf
The handheld water sprayer is a generic 250 ml.
I have mounted the devices on an old CD case, which is ideal since the water spray bottle doesn't stop the movement of the gripper when it works.
For STL files, below I show you module 1, which is an empty box on the inside and with the holes to insert the cables you need to connect a battery for example.
Here I show you a zoom of the handheld water sprayer mounted on the gripper using a single nylon strap.
Here's another view of the spray assembly.
Now it's time to connect the person sensor with the qwiic pHat interface, through the qwiic cable.
After mounting the previous module on the Raspberry Pi 4, I made a wooden box to detect the person's sensor on the face of the person who will be detected.
Finally I show you the entire device assembling, which will then be programmed and tested.
Here we have used Python version 3. You can run the following command to list all the devices found on the I2C bus:
i2cdetect -y 1
This command lists all the I2C addresses that have been found. The important one for the person sensor is 62, which is the hexadecimal address of the device.
The code is as follows:
person_sensor_raspberry.py
# AUTHOR: GUILLERMO PEREZ GUILLEN
# Example of accessing the Person Sensor from Useful Sensors on a Pi using
# Python. See https://usfl.ink/ps_dev for the full developer guide.
import io
import fcntl
import struct
import time
########## SERVO CONFIGURATION
import RPi.GPIO as GPIO
servoPIN = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(servoPIN, GPIO.OUT)
p = GPIO.PWM(servoPIN, 50) # GPIO 18 for PWM with 50Hz
p.start(7.5) # Initialization 5
# The person sensor has the I2C ID of hex 62, or decimal 98.
PERSON_SENSOR_I2C_ADDRESS = 0x62
# We will be reading raw bytes over I2C, and we'll need to decode them into
# data structures. These strings define the format used for the decoding, and
# are derived from the layouts defined in the developer guide.
PERSON_SENSOR_I2C_HEADER_FORMAT = "BBH"
PERSON_SENSOR_I2C_HEADER_BYTE_COUNT = struct.calcsize(
PERSON_SENSOR_I2C_HEADER_FORMAT)
PERSON_SENSOR_FACE_FORMAT = "BBBBBBbB"
PERSON_SENSOR_FACE_BYTE_COUNT = struct.calcsize(PERSON_SENSOR_FACE_FORMAT)
PERSON_SENSOR_FACE_MAX = 4
PERSON_SENSOR_RESULT_FORMAT = PERSON_SENSOR_I2C_HEADER_FORMAT + \
"B" + PERSON_SENSOR_FACE_FORMAT * PERSON_SENSOR_FACE_MAX + "H"
PERSON_SENSOR_RESULT_BYTE_COUNT = struct.calcsize(PERSON_SENSOR_RESULT_FORMAT)
# I2C channel 1 is connected to the GPIO pins
I2C_CHANNEL = 1
I2C_PERIPHERAL = 0x703
# How long to pause between sensor polls. 0.2
PERSON_SENSOR_DELAY = 3
i2c_handle = io.open("/dev/i2c-" + str(I2C_CHANNEL), "rb", buffering=0)
fcntl.ioctl(i2c_handle, I2C_PERIPHERAL, PERSON_SENSOR_I2C_ADDRESS)
while True:
try:
read_bytes = i2c_handle.read(PERSON_SENSOR_RESULT_BYTE_COUNT)
except OSError as error:
print("No person sensor data found")
print(error)
time.sleep(PERSON_SENSOR_DELAY)
continue
offset = 0
(pad1, pad2, payload_bytes) = struct.unpack_from(
PERSON_SENSOR_I2C_HEADER_FORMAT, read_bytes, offset)
offset = offset + PERSON_SENSOR_I2C_HEADER_BYTE_COUNT
(num_faces) = struct.unpack_from("B", read_bytes, offset)
num_faces = int(num_faces[0])
offset = offset + 1
faces = []
for i in range(num_faces):
(box_confidence, box_left, box_top, box_right, box_bottom, id_confidence, id,
is_facing) = struct.unpack_from(PERSON_SENSOR_FACE_FORMAT, read_bytes, offset)
offset = offset + PERSON_SENSOR_FACE_BYTE_COUNT
face = {
"box_confidence": box_confidence,
"box_left": box_left,
"box_top": box_top,
"box_right": box_right,
"box_bottom": box_bottom,
"id_confidence": id_confidence,
"id": id,
"is_facing": is_facing,
}
## TURN SPRAY ON
if is_facing == 1:
print("spray ON")
p.ChangeDutyCycle(12.5)
time.sleep(0.5)
p.ChangeDutyCycle(7.5)
time.sleep(0.5)
p.ChangeDutyCycle(12.5)
time.sleep(0.5)
p.ChangeDutyCycle(7.5)
time.sleep(0.5)
## TURN SPRAY OFF
else:
print("spray OFF")
p.ChangeDutyCycle(7.5)
time.sleep(0.5)
faces.append(face)
checksum = struct.unpack_from("H", read_bytes, offset)
print(num_faces, faces)
time.sleep(PERSON_SENSOR_DELAY)
I have modified the demo code shown here to add the servo: https://github.com/usefulsensors/person_sensor_rpi_python
If the Person Sensor detects a user, then it presses the hand spray twice, otherwise the servo doesn't press at all:
## TURN SPRAY ON
if is_facing == 1:
print("spray ON")
p.ChangeDutyCycle(12.5)
time.sleep(0.5)
p.ChangeDutyCycle(7.5)
time.sleep(0.5)
p.ChangeDutyCycle(12.5)
time.sleep(0.5)
p.ChangeDutyCycle(7.5)
time.sleep(0.5)
## TURN SPRAY OFF
else:
print("spray OFF")
p.ChangeDutyCycle(7.5)
time.sleep(0.5)
TestConclusion- This project is a useful innovation for people with motor disabilities, since they usually have busy their hands either holding the cane or maneuvering the wheelchair.
- You just have to bring your face close to the person sensor chamber and the hand spray will be pressed twice by the gripper.
- Then they place their hands in the correct direction and can use this device as a hand sanitizer, as well as moisturizing or some substance to soothe the skin with complete comfort al home or hotels while traveling.
Considering the experience gained in the development of this innovative prototype, I am now going to repeat the experience using the Arduino UNO board to demonstrate its functionality. All this will be explained in a simple chapter, below I show you the schematic diagram.
I have used as a reference the official documentation obtained at this link: https://github.com/usefulsensors/person_sensor_arduino
As you can see, in the schematic diagram I have modified a connector of the I2C Qwiic cable to be able to connect it to the Arduino UNO board.
I have printed a 3D piece to hold the personal sensor using 2 mini rubber bands as shown in the images below. Yo can get the STL file in the download section.
In the image below I show you the person sensor wired to the Arduino UNO board.
Below I show you the entire device ready for a test.
Code
person_sensor_arduino.ino
// Author: Guillermo Perez Guillen
#include <Wire.h>
#include <Servo.h> //servo
Servo servoMotor; //servo
#include "person_sensor.h"
// How long to wait between reading the sensor. The sensor can be read as
// frequently as you like, but the results only change at about 5FPS, so
// waiting for 200ms is reasonable.
const int32_t SAMPLE_DELAY_MS = 3000;
void setup() {
// You need to make sure you call Wire.begin() in setup, or the I2C access
// below will fail.
Wire.begin();
Serial.begin(9600);
servoMotor.attach(9);
}
void loop() {
person_sensor_results_t results = {};
// Perform a read action on the I2C address of the sensor to get the
// current face information detected.
if (!person_sensor_read(&results)) {
Serial.println("No person sensor results found on the i2c bus");
delay(SAMPLE_DELAY_MS);
return;
}
Serial.println("********");
Serial.print(results.num_faces);
Serial.println(" faces found");
for (int i = 0; i < results.num_faces; ++i) {
const person_sensor_face_t* face = &results.faces[i];
Serial.print("Face #");
Serial.print(i);
Serial.print(": ");
Serial.print(face->box_confidence);
Serial.print(" confidence, (");
Serial.print(face->box_left);
Serial.print(", ");
Serial.print(face->box_top);
Serial.print("), (");
Serial.print(face->box_right);
Serial.print(", ");
Serial.print(face->box_bottom);
Serial.print("), ");
if (face->is_facing) {
Serial.println("facing");
} else {
Serial.println("not facing");
}
}
//servo
if(results.num_faces == 1){
// SPRAY ON
servoMotor.write(160);
delay(500);
servoMotor.write(100);
delay(500);
servoMotor.write(160);
delay(500);
servoMotor.write(100);
delay(500);
}
else{
// SPRAY OFF
servoMotor.write(100);
delay(500);
}
delay(SAMPLE_DELAY_MS);
}
As in the example with the Raspberry Pi, I have added a 3 second delay so that the person has time to leave once the Hand Spray is activated, but you can modify it if you need it.
Test
Below I show you the test done with this device. This prototype worked as well on the Arduino UNO board as it did on the Raspberry Pi.
Comments