Wireless Fall Detection Device
Preface
As more and more people work hard in their careers, the national economy is beginning to take off. However, the aging of society will also deepen. Without the care of young people, life for the elderly is always difficult and dangerous.
Each year, one-third to one-half of all people age 65 and older experience a fall. Falls are the leading cause of injury in older adults and the leading cause of accidental death in those 75 and older. For a person to experience a fall unnoticed can be doubly dangerous. The distinct possibility of an initial injury may further exacerbate the possible consequences if not treated in a short period of time. Statistics show that the most serious consequences are not the direct result of a fall, but rather the result of a delay in assistance and treatment. The consequences of a fall can be greatly reduced if rescuers are alerted in a timely manner.
Many seniors live alone in apartments or smaller homes after their children have grown up and left home. After a fall, it is not uncommon for the elderly to be unable to get up on their own or summon help. Therefore, there is a need for an automatic fall detection system that can summon help even if the patient loses consciousness or is unable to get up after a fall.
Hardware
- Grove - 3-Axis Digital Accelerometer (LIS3DHTR)
- Wio RP2040 mini Dev Board to complete this project.
Grove - 3-Axis Digital Accelerometer (LIS3DHTR) can be used as a sensor to detect falls, and Wio RP2040 mini Dev Board can be used to process data and send distress information wirelessly. In addition, you need a computer and WiFi.
Wiring Diagram
Software
1. Install Thonny
Easy to get started. Thonny comes with Python 3.7 built-in, so just one simple installer is needed and you're ready to learn to program. First, click Thonny.org to enter the download page. In the upper right corner of the page, select the Thonny installation package according to your operating system to download. Double-click the installation package you downloaded to open it, and install it according to the steps.
Now that you have Thonny installed, open the application. You should see the main interface of Thonny:
The main interface of Thonny is very simple, divided into the following four parts:
Toolbar: basic common tools, such as new, open, save, run the current script, stop, etc.
Code editor: Thonny's core area, where we will write Python/MicroPython code.
Shell: We can run commands here, and the results of the commands will be displayed in the Shell immediately. We also can see outputs of our code in the Shell window.
Interpreter: Here you can select the type of interpreter to compile the program. Click Python 3.7.9, find MicroPython (Raspberry pi Pico) in the pop-up menu, and click OK to switch the interpreter to Pico interpreter. You can also click "Tools>>>Options>>>Interpreter" to select.
2.Connect Wio RP2040 mini Dev Board
Use the data cable to connect the development board to the computer, and then click the "Restart backend" button on the toolbar. If Wio RP2040 is successfully connected to the computer, you will see the MicroPython version information and device name in the Shell.
3.Code
In order to use 3-Axis Digital Accelerometer, we need to import the library file of the sensor into the memory of Wio RP2040. This is done as follows: Copy the following code, paste it into a new thorny editor window, then save it to the development board and rename it to "ACC_ Adxl345.py "
from machine import I2C
import time
ADXL345_DEVICE = (0x53)
""" ------- Register names ------- """
ADXL345_DEVID =0x00
ADXL345_RESERVED1 =0x01
ADXL345_THRESH_TAP =0x1d
ADXL345_OFSX =0x1e
ADXL345_OFSY =0x1f
ADXL345_OFSZ =0x20
ADXL345_DUR =0x21
ADXL345_LATENT =0x22
ADXL345_WINDOW =0x23
ADXL345_THRESH_ACT =0x24
ADXL345_THRESH_INACT =0x25
ADXL345_TIME_INACT =0x26
ADXL345_ACT_INACT_CTL =0x27
ADXL345_THRESH_FF =0x28
ADXL345_TIME_FF =0x29
ADXL345_TAP_AXES =0x2a
ADXL345_ACT_TAP_STATUS =0x2b
ADXL345_BW_RATE =0x2c
ADXL345_POWER_CTL =0x2d
ADXL345_INT_ENABLE =0x2e
ADXL345_INT_MAP =0x2f
ADXL345_INT_SOURCE =0x30
ADXL345_DATA_FORMAT =0x31
ADXL345_DATAX0 =0x32
ADXL345_DATAX1 =0x33
ADXL345_DATAY0 =0x34
ADXL345_DATAY1 =0x35
ADXL345_DATAZ0 =0x36
ADXL345_DATAZ1 =0x37
ADXL345_FIFO_CTL =0x38
ADXL345_FIFO_STATUS =0x39
ADXL345_BW_1600 =0xF # 1111
ADXL345_BW_800 =0xE # 1110
ADXL345_BW_400 =0xD # 1101
ADXL345_BW_200 =0xC # 1100
ADXL345_BW_100 =0xB # 1011
ADXL345_BW_50 =0xA # 1010
ADXL345_BW_25 =0x9 # 1001
ADXL345_BW_12 =0x8 # 1000
ADXL345_BW_6 =0x7 # 0111
ADXL345_BW_3 =0x6 # 0110
"""
Interrupt PINs
INT1: 0
INT2: 1
"""
ADXL345_INT1_PIN =0x00
ADXL345_INT2_PIN =0x01
"""Interrupt bit position"""
ADXL345_INT_DATA_READY_BIT =0x07
ADXL345_INT_SINGLE_TAP_BIT =0x06
ADXL345_INT_DOUBLE_TAP_BIT =0x05
ADXL345_INT_ACTIVITY_BIT =0x04
ADXL345_INT_INACTIVITY_BIT =0x03
ADXL345_INT_FREE_FALL_BIT =0x02
ADXL345_INT_WATERMARK_BIT =0x01
ADXL345_INT_OVERRUNY_BIT =0x00
ADXL345_DATA_READY =0x07
ADXL345_SINGLE_TAP =0x06
ADXL345_DOUBLE_TAP =0x05
ADXL345_ACTIVITY =0x04
ADXL345_INACTIVITY =0x03
ADXL345_FREE_FALL =0x02
ADXL345_WATERMARK =0x01
ADXL345_OVERRUNY =0x00
ADXL345_OK =1 # no error
ADXL345_ERROR =0 # indicates error is predent
ADXL345_NO_ERROR =0 # initial state
ADXL345_READ_ERROR =1 # problem reading accel
ADXL345_BAD_ARG =2 # bad method argument
class AccelerationAdxl345(object):
def __init__(self, i2c, addr=ADXL345_DEVICE, drdy=None):
self.i2c_device = i2c
time.sleep(0.1)
#self.rgbMatrixData = [0xFF]*64
def read(self, reg_base, reg, buf):
self.write(reg)
time.sleep(.001)
self.i2c_device.readfrom_into(59,buf)
def write(self, buf=None):
if buf is not None:
self.i2c_device.writeto(ADXL345_DEVICE, buf)
# i2c_device.writeto(0x58, bytearray([3,100,100,16,39]))
def writeTo(self,address, val):
dta_send = bytearray([address, val])
self.write(dta_send)
def readFrom(self, address, num):
data_0 = address & 0xff
dta_send = bytearray([data_0])
self.write(dta_send)
time.sleep(.001)
result=self.i2c_device.readfrom(ADXL345_DEVICE, num)
return result
def setRegisterBit(self, regAdress, bitPos, state):
bytes=self.readFrom(regAdress, 1)
for _b in bytes:
value = int(_b)
if (state):
value |= (1 << bitPos)
else:
value &= ~(1 << bitPos)
self.writeTo(regAdress, value)
def acc_adxl345_init(self):
#Turning on the ADXL345
self.writeTo(ADXL345_POWER_CTL, 0)
self.writeTo(ADXL345_POWER_CTL, 16)
self.writeTo(ADXL345_POWER_CTL, 8)
self.writeTo(ADXL345_THRESH_ACT, 75)
self.writeTo(ADXL345_THRESH_INACT, 75)
self.writeTo(ADXL345_TIME_INACT, 10)
#look of activity movement on this axes - 1 == on; 0 == off
self.setRegisterBit(ADXL345_ACT_INACT_CTL, 6, 1)
self.setRegisterBit(ADXL345_ACT_INACT_CTL, 5, 1)
self.setRegisterBit(ADXL345_ACT_INACT_CTL, 4, 1)
#look of inactivity movement on this axes - 1 == on; 0 == off
self.setRegisterBit(ADXL345_ACT_INACT_CTL, 2, 1)
self.setRegisterBit(ADXL345_ACT_INACT_CTL, 1, 1)
self.setRegisterBit(ADXL345_ACT_INACT_CTL, 0, 1)
self.setRegisterBit(ADXL345_TAP_AXES, 2, 0)
self.setRegisterBit(ADXL345_TAP_AXES, 1, 0)
self.setRegisterBit(ADXL345_TAP_AXES, 0, 0)
#set values for what is a tap, and what is a double tap (0-255)
#setTapThreshold(50); # 62.5mg per increment
self.writeTo(ADXL345_THRESH_TAP, 50)
self.writeTo(ADXL345_DUR, 15)
self.writeTo(ADXL345_LATENT, 80)
#setDoubleTapWindow(200); # 1.25ms per increment
self.writeTo(ADXL345_WINDOW, 200)
#set values for what is considered freefall (0-255)
self.writeTo(ADXL345_THRESH_FF, 7)
self.writeTo(ADXL345_TIME_FF, 45)
#setting all interrupts to take place on int pin 1
#I had issues with int pin 2, was unable to reset it
self.setRegisterBit(ADXL345_INT_MAP, ADXL345_INT_SINGLE_TAP_BIT, ADXL345_INT1_PIN)
self.setRegisterBit(ADXL345_INT_MAP, ADXL345_INT_DOUBLE_TAP_BIT, ADXL345_INT1_PIN)
self.setRegisterBit(ADXL345_INT_MAP, ADXL345_INT_FREE_FALL_BIT, ADXL345_INT1_PIN)
self.setRegisterBit(ADXL345_INT_MAP, ADXL345_INT_ACTIVITY_BIT, ADXL345_INT1_PIN)
self.setRegisterBit(ADXL345_INT_MAP, ADXL345_INT_INACTIVITY_BIT, ADXL345_INT1_PIN)
#register interrupt actions - 1 == on; 0 == off
self.setRegisterBit(ADXL345_INT_ENABLE, ADXL345_INT_SINGLE_TAP_BIT, 1)
self.setRegisterBit(ADXL345_INT_ENABLE, ADXL345_INT_DOUBLE_TAP_BIT, 1)
self.setRegisterBit(ADXL345_INT_ENABLE, ADXL345_INT_FREE_FALL_BIT, 1)
self.setRegisterBit(ADXL345_INT_ENABLE, ADXL345_INT_ACTIVITY_BIT, 1)
self.setRegisterBit(ADXL345_INT_ENABLE, ADXL345_INT_INACTIVITY_BIT, 1)
def acc_adxl345_read_xyz(self):
ADXL345_TO_READ = (6)
_buff = self.readFrom(ADXL345_DATAX0, ADXL345_TO_READ) #read the acceleration data from the ADXL345
if _buff[1] <= 0:
x=_buff[0]
else:
x=(_buff[0]-255)
if _buff[3] <= 0:
y=_buff[2]
else:
y=(_buff[2]-255)
if _buff[5] <= 0:
z=_buff[4]
else:
z=(_buff[4]-255)
#x = int(((_buff[1]) << 8) | _buff[0])
#y = int(((_buff[3]) << 8) | _buff[2])
#z = int(((_buff[5]) << 8) | _buff[4])
#print("%d, %d, %d\r\n", x, y, z)
return [x,y,z]
def acc_adxl345_read_acc(self):
__Gains = [0.00376390, 0.00376009, 0.00389265]
xyz=self.acc_adxl345_read_xyz()
ax = xyz[0] * __Gains[0]
ay = xyz[1] * __Gains[1]
az = xyz[2] * __Gains[2]
return [ax,ay,az]
def get_acc_adxl345_property(self,xyz):
axyz=self.acc_adxl345_read_acc()
if(xyz == 0):
return axyz[0]
if(xyz == 1):
return axyz[1]
if(xyz == 2):
return axyz[2]
"""
acceleration = AccelerationAdxl345()
acceleration.acc_adxl345_init()
acceleration.get_acc_adxl345_property(0)
acceleration.get_acc_adxl345_property(1)
acceleration.get_acc_adxl345_property(2)
"""
Then create a new program window to write the following code.
import network
import mqtt
from Acc_Adxl345 import AccelerationAdxl345
from machine import Pin,I2C
from time import sleep
i2c = I2C(0,sda = Pin(4),scl= Pin(5))
ax = AccelerationAdxl345(i2c)
ax.acc_adxl345_init()
N1 = network.WLAN_SPI(network.STA_IF)
N1.active(True)
N1.connect("CHCK","depot0510")
sleep(1)
print('network information:', N1.ifconfig())
led = Pin(13, Pin.OUT)
button = Pin(12,Pin.IN,Pin.PULL_UP)
led.value(1)
SERVER = 'mqtt.p2hp.com'
CLIENT_ID = 'Wio_RP2040'
TOPIC = 'Security_status'
def mqtt_callback(topic):
print('topic: {}'.format(topic[0]))
print('msg:{}'.format(topic[1]))
cl = mqtt.MQTTClient(CLIENT_ID, SERVER, mqtt_port = 1883)
cl.connect()
cl.set_callback(mqtt_callback)
val_last = 1
print("ready")
cl.publish(TOPIC,"ready")
while True:
a = ax.acc_adxl345_read_acc()
b = ax.acc_adxl345_read_acc()
for i in range(0,3):
a[0] = a[i] * a[i]
b[0] = b[i] * b[i]
if a[0] - b[0] > 0.4 or b[0] - a[0] > 0.4:
cl.publish(TOPIC,"help!")
Note that on line 12 of the program, change your correct WiFi name and password.
4.Setting up MQTT client
MQTT is a Client Server publish/subscribe messaging transport protocol. The client can work as a publisher or subscriber or both.
The publisher can create a topic with messages attached to the topic. For example, I can create a new topic "Today's Weather" and the message content is "25 degrees Celsius", and then sent the message to the Server. After receiving the topic message, the publisher distributes the information to any clients that have subscribed to that topic. That is, the subscriber will receive the message of "25 degrees Celsius" only if it subscribes to the topic "Today's Weather". If the subscriber does not subscribe to the topic of "Today's Weather", no matter what message the publisher sends, the subscriber will not receive the message.
Download the MQTTX server software and install it on the computer, and then configure the MQTT server.
We will use the free server of "mqtt.p2hp.com" in this project. Online server
- Address: mqtt.p2hp.com
- Ports: 1883 (TCP), 8083 (WebSocket)
- Type: EMQ
- MQTT V3.1.1/V5.0 compatible
Enter the MQTTX software to create a new connection, fill in the name, server, port, subject, and then click "Connect" to connect to the server.
After the connection is successful, there will be a pop-up in the upper right corner of the software.
Then set the topic and message below.
When data is received, the number of messages is displayed at the top. If you don't see the message, click on the subscription topic.
Here, the deployment of the MQTT client is completed. Let's go back to the Thorny editor to run the code, and then drop the 3-axis digital accelerator from a high place to observe whether the mqtt client has received the message.
Installation and testing
If you get the message successfully, congratulations you have done most of the work. Next, you just need to connect the battery to the development board and fix the device on a 5cm * 5cm cardboard.
Finally, put it into a cloth pocket. This simple fall detection device is complete! So far, this project is just a simple experimental prototype. There may be some mistouch in practical application. You can also give me feedback and we will optimize this project together.
Tech Support & Product Discussion
if you have any technical issue. submit the issue into our forum. Thank you for choosing our products! We are here to provide you with different support to ensure that your experience with our products is as smooth as possible. We offer several communication channels to cater to different preferences and needs.