Detecting Human Falls with a 3-Axis Digital Accelerometer Foreword Besides senior citizens, there are many other conditions and activities for which an immediate alert to a possible fall, especially from substantial height, would be quite helpful—for example mountaineers, construction workers, window washers, painters, and roofers. In light of this need to warn of falls, the development of devices for detection and prediction of all types of falls has become a hot topic. In recent years, technological advances in microelectromechanical-system (MEMS) acceleration sensors have made it possible to design fall detectors based on a 3-axis integrated MEMS (iMEMS®) accelerometer. The technique is based on the principle of detecting changes in motion and body position of an individual, wearing a sensor, by tracking acceleration changes in three orthogonal directions. The data is continuously analyzed algorithmically to determine whether the individual’s body is falling or not. If an individual falls, the device can employ GPS and a wireless transmitter to determine the location and issue an alert in order to get assistance. The core element of fall detection is an effective, reliable detection principle and algorithm to judge the existence of an emergency fall situation. This article, based on research into the principles of fall detection for an individual body, proposes a new solution for detection of fall situations utilizing the ADXL345,1 a 3-axis accelerometer from Analog Devices. The ADXL345 iMEMS
Accelerometer The recently introduced ADXL345 is an iMEMS 3-axis accelerometer with digital output. It features a selectable ±2-g, ±4-g, ±8-g, or ±16-g measurement range; resolution of up to 13 bits; fixed 4-mg/LSB sensitivity; a tiny 3-mm × 5-mm × 1-mm package; ultralow power consumption (25 µA to 130 µA); standard I2C® and SPI serial digital interfacing; and 32-level FIFO storage. A variety of built-in features, including motion-status detection and flexible interrupts, greatly simplify implementation of the algorithm for fall detection. As you will see, this combination of features makes the ADXL345 an ideal accelerometer for fall-detector applications. The fall-detection solution proposed here takes full advantage of these internal functions, minimizing the complexity of the algorithm—with little requirement to access the actual acceleration values or perform any other computations. Interrupt System
Figure 1. ADXL345 system block diagram and pin designations. The ADXL345 features two programmable interrupt pins—INT1 and INT2—with a total of eight interrupt functions available. Each interrupt can be enabled or disabled independently, with the option to map to either the INT1 or INT2 pin. All functions can be used simultaneously—the only limiting feature is that some functions may need to share interrupt pins. The eight functions are: DATA_READY, SINGLE_TAP, DOUBLE_TAP, ACTIVITY, INACTIVITY, FREE_FALL, WATERMARK, and OVERRUN. Interrupts are enabled by setting the appropriate bit in the INT_ENABLE register and are mapped to either the INT1 or INT2 pins, based on the contents of the INT_MAP register. The interrupt functions are defined as follows:
Figure 2 illustrates the valid SINGLE_TAP and DOUBLE_TAP interrupts.
Figure 2. SINGLE_TAP and DOUBLE_TAP interrupts.
Acceleration-Change
Characteristics While Falling Figure 3 illustrates changes in acceleration that occur when (a) walking downstairs, (b) walking upstairs, (c) sitting down, and (d) standing up from a chair. The fall detector is mounted to a belt on the individual’s body. The red trace is the Y-axis (vertical) acceleration; it is –1 g at equilibrium. The black and yellow traces are the respective X-axis (forward) and Z-axis (sideways) accelerations. They are both 0 g at equilibrium. The green trace is the vector sum magnitude, 1 g at equilibrium.
a. Walking downstairs. b. Walking upstairs.
c. Sitting down. d. Standing up. Figure 3. Accelerometer responses to different types of motion. Because the movement of elderly people is comparatively slow, the acceleration change will not be very conspicuous during the walking motions. The most pronounced acceleration is a 3-g spike in Y (and the vector sum) at the instant of sitting down. The accelerations during falling are completely different. Figure 4 shows the acceleration changes during an accidental fall. By comparing Figure 4 with Figure 3, we can see four critical differences characteristic of a falling event that can serve as the criteria for fall detection. They are marked in the red boxes and explained in detail as follows:
Figure 4. Acceleration change curves during the process of falling.
The combination of these qualifications forms the entire fall-detection algorithm, which, when exercised, can cause the system to raise an appropriate alert that a fall has occurred. Of course, the time interval between interrupts has to be within a reasonable range. Normally, the time interval between FREE_FALL interrupt (weightlessness) and ACTIVITY interrupt (impact) is not very long unless one is falling from the top of a very high building! Similarly, the time interval between ACTIVITY interrupt (impact) and INACTIVITY interrupt (essentially motionless) should not be very long. A practical example will be given in the next section with a set of reasonable values. The related interrupt detection threshold and time parameters can be flexibly set as needed. If a fall results in serious consequences, such as unconsciousness, the human body will remain motionless for an even longer period of time, a status that can still be detected by the INACTIVITY interrupt, so a second critical alert could be sent out if the inactive state was detected to continue for a defined long period of time after a fall. Typical Circuit
Connection Other MCU or processor types could be used to access the ADXL345, with similar circuit connections to Figure 5, but the ADuC7026 also provides a data-acquisition facility including multichannel analog-to-digital and digital-to-analog conversion. The ADXL345 data sheet describes SPI-mode applications to achieve higher data rates.
Figure 5. Typical circuit connection between the ADXL345 and microcontroller. Table 1. ADCL345 Registers Function Descriptions
Using the ADXL345
to Simplify Fall Detection Some of the registers in Table 1 will have two values. This indicates that the algorithm switches between these values for different aspects of detection. Figure 6 is an algorithm flow chart.
Figure 6. Algorithm flow chart. Each interrupt threshold, and the related time parameter in the algorithm, is as described below.
This algorithm is developed in C language to be executed on the ADuC7026 microcontroller (See Appendix). A test case is also presented with the proposed solution to verify the algorithm. Each position, including falling forward, falling backward, falling to the left, and falling to the right is tested 10 times. Table 2 presents the test results. Check marks (P) indicate each condition that is satisfied. Table 2. Test Results
This experiment shows that falling status can be effectively detected with the proposed solution, based on the ADXL345. This is only a simple experiment. More comprehensive, effective, and long-term experimentation will be required to verify the reliability of the proposed solution. Conclusion APPENDIX—An Example
of the Code // Include header files #include "FallDetection.h" void IRQ_Handler() __irq // IRQ interrupt { unsigned char i; if((IRQSTA & GP_TIMER_BIT)==GP_TIMER_BIT) //TIMER1 Interrupt, interval 20ms { T1CLRI = 0; // Clear Timer1 interrupt if(DetectionStatus==0xF2) // Strike after weightlessness is detected, waiting for stable { TimerWaitForStable++; if(TimerWaitForStable>=STABLE_WINDOW) // Time out, restart { IRQCLR = GP_TIMER_BIT; // Disable ADuC7026's Timer1 interrupt DetectionStatus=0xF0; putchar(DetectionStatus); ADXL345Registers[XL345_THRESH_ACT]=STRIKE_THRESHOLD; ADXL345Registers[XL345_THRESH_INACT]=NOMOVEMENT_THRESHOLD; ADXL345Registers[XL345_TIME_INACT]=STABLE_TIME; ADXL345Registers[XL345_ACT_INACT_CTL]=XL345_INACT_Z_ENABLE | XL345_INACT_Y_ENABLE | XL345_INACT_X_ENABLE | XL345_INACT_AC | XL345_ACT_Z_ENABLE | XL345_ACT_Y_ENABLE | XL345_ACT_X_ENABLE | XL345_ACT_DC; xl345Write(4, XL345_THRESH_ACT, &ADXL345Registers[XL345_THRESH_ACT]); } } else if(DetectionStatus==0xF1) // Weightlessness is detected, waiting for strike { TimerWaitForStrike++; if(TimerWaitForStrike>=STRIKE_WINDOW) // Time out, restart { IRQCLR = GP_TIMER_BIT; // Disable ADuC7026's Timer1 interrupt DetectionStatus=0xF0; putchar(DetectionStatus); ADXL345Registers[XL345_THRESH_ACT]=STRIKE_THRESHOLD; ADXL345Registers[XL345_THRESH_INACT]=NOMOVEMENT_THRESHOLD; ADXL345Registers[XL345_TIME_INACT]=STABLE_TIME; ADXL345Registers[XL345_ACT_INACT_CTL]=XL345_INACT_Z_ENABLE | XL345_INACT_Y_ENABLE | XL345_INACT_X_ENABLE | XL345_INACT_AC | XL345_ACT_Z_ENABLE | XL345_ACT_Y_ENABLE | XL345_ACT_X_ENABLE | XL345_ACT_DC; xl345Write(4, XL345_THRESH_ACT, &ADXL345Registers[XL345_THRESH_ACT]); } } } if((IRQSTA&SPM4_IO_BIT)==SPM4_IO_BIT) // External interrupt form ADXL345 INT0 { IRQCLR = SPM4_IO_BIT; // Disable ADuC7026's external interrupt xl345Read(1, XL345_INT_SOURCE, &ADXL345Registers[XL345_INT_SOURCE]); if((ADXL345Registers[XL345_INT_SOURCE]&XL345_ACTIVITY)==XL345_ACTIVITY) // Activity interrupt asserted { if(DetectionStatus==0xF1) // Waiting for strike, and now strike is detected { DetectionStatus=0xF2; // Go to Status "F2" putchar(DetectionStatus); ADXL345Registers[XL345_THRESH_ACT]=STABLE_THRESHOLD; ADXL345Registers[XL345_THRESH_INACT]=NOMOVEMENT_THRESHOLD; ADXL345Registers[XL345_TIME_INACT =STABLE_TIME; ADXL345Registers[XL345_ACT_INACT_CTL]=XL345_INACT_Z_ENABLE | XL345_INACT_Y_ENABLE | XL345_INACT_X_ENABLE | XL345_INACT_AC | XL345_ACT_Z_ENABLE | XL345_ACT_Y_ENABLE | XL345_ACT_X_ENABLE | XL345_ACT_AC; xl345Write(4, XL345_THRESH_ACT, &ADXL345Registers[XL345_THRESH_ACT]); IRQEN|=GP_TIMER_BIT; // Enable ADuC7026's Timer1 interrupt TimerWaitForStable=0; } else if(DetectionStatus==0xF4) // Waiting for long time motionless, but a movement is detected { DetectionStatus=0xF0; // Go to Status "F0", restart putchar(DetectionStatus); ADXL345Registers[XL345_THRESH_ACT]=STRIKE_THRESHOLD; ADXL345Registers[XL345_THRESH_INACT]=NOMOVEMENT_THRESHOLD; ADXL345Registers[XL345_TIME_INACT]=STABLE_TIME; ADXL345Registers[XL345_ACT_INACT_CTL]=XL345_INACT_Z_ENABLE | XL345_INACT_Y_ENABLE | XL345_INACT_X_ENABLE | XL345_INACT_AC | XL345_ACT_Z_ENABLE | XL345_ACT_Y_ENABLE | XL345_ACT_X_ENABLE | XL345_ACT_DC; xl345Write(4, XL345_THRESH_ACT, &ADXL345Registers[XL345_THRESH_ACT]); } } else if((ADXL345Registers[XL345_INT_SOURCE]&XL345_INACTIVITY)==XL345_INACTIVITY) // Inactivity interrupt asserted { if(DetectionStatus==0xF2) // Waiting for stable, and now stable is detected { DetectionStatus=0xF3; // Go to Status "F3" IRQCLR = GP_TIMER_BIT; putchar(DetectionStatus); xl345Read(6, XL345_DATAX0, &ADXL345Registers[XL345_DATAX0]); DeltaVectorSum=0; for(i=0;i<3; i++) { Acceleration[i]=ADXL345Registers[XL345_DATAX1+i*2]&0x1F; Acceleration[i]=(Acceleration[i]<<8)|ADXL345Registers[XL345_DATAX0+i*2]; if(Acceleration[i]<0x1000) { Acceleration[i]=Acceleration[i]+0x1000; } else //if(Acceleration[i]>=4096) { Acceleration[i]=Acceleration[i]-0x1000; } if(Acceleration[i]>InitialStatus[i]) { DeltaAcceleration[i]=Acceleration[i]-InitialStatus[i]; } else { DeltaAcceleration[i]=InitialStatus[i]-Acceleration[i]; } DeltaVectorSum=DeltaVectorSum+DeltaAcceleration[i]*DeltaAcceleration[i]; } if(DeltaVectorSum>DELTA_VECTOR_SUM_THRESHOLD // The stable status is different from the initial status { DetectionStatus=0xF4; // Valid fall detection putchar(DetectionStatus); ADXL345Registers[XL345_THRESH_ACT]=STABLE_THRESHOLD; ADXL345Registers[XL345_THRESH_INACT]=NOMOVEMENT_THRESHOLD; ADXL345Registers[XL345_TIME_INACT]=NOMOVEMENT_TIME; ADXL345Registers[XL345_ACT_INACT_CTL]=XL345_INACT_Z_ENABLE | XL345_INACT_Y_ENABLE | XL345_INACT_X_ENABLE | XL345_INACT_AC | XL345_ACT_Z_ENABLE | XL345_ACT_Y_ENABLE | XL345_ACT_X_ENABLE | XL345_ACT_AC; xl345Write(4, XL345_THRESH_ACT, &ADXL345Registers[XL345_THRESH_ACT]); } else // Delta vector sum is not exceed the threshold { DetectionStatus=0xF0; // Go to Status "F0", restart putchar(DetectionStatus); ADXL345Registers[XL345_THRESH_ACT]=STRIKE_THRESHOLD; ADXL345Registers[XL345_THRESH_INACT]=NOMOVEMENT_THRESHOLD; ADXL345Registers[XL345_TIME_INACT]=STABLE_TIME; ADXL345Registers[XL345_ACT_INACT_CTL]=XL345_INACT_Z_ENABLE | XL345_INACT_Y_ENABLE | XL345_INACT_X_ENABLE | XL345_INACT_AC | XL345_ACT_Z_ENABLE | XL345_ACT_Y_ENABLE | XL345_ACT_X_ENABLE | XL345_ACT_DC; xl345Write(4, XL345_THRESH_ACT, &ADXL345Registers[XL345_THRESH_ACT]); } } else if(DetectionStatus==0xF4) // Wait for long time motionless and now it is detected { DetectionStatus=0xF5; // Valid critical fall detection putchar(DetectionStatus); ADXL345Registers[XL345_THRESH_ACT]=STRIKE_THRESHOLD; ADXL345Registers[XL345_THRESH_INACT]=NOMOVEMENT_THRESHOLD; ADXL345Registers[XL345_TIME_INACT]=STABLE_TIME; ADXL345Registers[XL345_ACT_INACT_CTL]=XL345_INACT_Z_ENABLE | XL345_INACT_Y_ENABLE | XL345_INACT_X_ENABLE | XL345_INACT_AC | XL345_ACT_Z_ENABLE | XL345_ACT_Y_ENABLE | XL345_ACT_X_ENABLE | XL345_ACT_DC; xl345Write(4, XL345_THRESH_ACT, &ADXL345Registers[XL345_THRESH_ACT]); DetectionStatus=0xF0; // Go to Status "F0", restart putchar(DetectionStatus); } } else if((ADXL345Registers[XL345_INT_SOURCE]&XL345_FREEFALL)==XL345_FREEFALL) // Free Fall interrupt asserted { if(DetectionStatus==0xF0) // Waiting for weightless, and now it is detected { DetectionStatus=0xF1; // Go to Status "F1" putchar(DetectionStatus); ADXL345Registers[XL345_THRESH_ACT]=STRIKE_THRESHOLD; ADXL345Registers[XL345_THRESH_INACT]=NOMOVEMENT_THRESHOLD; ADXL345Registers[XL345_TIME_INACT]=STABLE_TIME; ADXL345Registers[XL345_ACT_INACT_CTL]=XL345_INACT_Z_ENABLE | XL345_INACT_Y_ENABLE | XL345_INACT_X_ENABLE | XL345_INACT_AC | XL345_ACT_Z_ENABLE | XL345_ACT_Y_ENABLE | XL345_ACT_X_ENABLE | XL345_ACT_DC; xl345Write(4, XL345_THRESH_ACT, &ADXL345Registers[XL345_THRESH_ACT]); IRQEN|=GP_TIMER_BIT; // Enable ADuC7026's Timer1 interrupt TimerWaitForStrike=0; TimerFreeFall=0; } else if(DetectionStatus==0xF1) // Waiting for strike after weightless, and now a new free fall is detected { if(TimerWaitForStrike<FREE_FALL_INTERVAL) // if the Free Fall interrupt is continuously assert within the time of "FREE_FALL_INTERVAL", { // then it is consider as a continuous free fall TimerFreeFall=TimerFreeFall+TimerWaitForStrike; } else // Not a continuous free fall { TimerFreeFall=0; } TimerWaitForStrike=0; if(TimerFreeFall>=FREE_FALL_OVERTIME) // if the continuous time of free fall is longer than "FREE_FALL_OVERTIME" { // consider that a free fall from high place is detected DetectionStatus=0xFF; putchar(DetectionStatus); ADXL345Registers[XL345_THRESH_ACT =STRIKE_THRESHOLD; ADXL345Registers[XL345_THRESH_INACT]=NOMOVEMENT_THRESHOLD; ADXL345Registers[XL345_TIME_INACT]=STABLE_TIME; ADXL345Registers[XL345_ACT_INACT_CTL]=XL345_INACT_Z_ENABLE | XL345_INACT_Y_ENABLE | XL345_INACT_X_ENABLE | XL345_INACT_AC | XL345_ACT_Z_ENABLE | XL345_ACT_Y_ENABLE | XL345_ACT_X_ENABLE | XL345_ACT_DC; xl345Write(4, XL345_THRESH_ACT, &ADXL345Registers[XL345_THRESH_ACT]); DetectionStatus=0xF0; putchar(DetectionStatus); } } else { TimerFreeFall=0; } } IRQEN |=SPM4_IO_BIT; // Enable ADuC7026's external interrupt } } void main(void) { ADuC7026_Initiate(); // ADuC7026 initialization ADXL345_Initiate(); // ADXL345 initialization DetectionStatus=0xF0; // Clear detection status, Start InitialStatus[0]=0x1000; // X axis=0g, unsigned short int, 13 bit resolution, 0x1000 = 4096 = 0g, +/-0xFF = +/-256 = +/-1g InitialStatus[1]=0x0F00; // Y axis=-1g InitialStatus[2]=0x1000; // Z axis=0g IRQEN =SPM4_IO_BIT; // Enable ADuC7026's external interrupt, to receive the interrupt from ADXL345 INT0 while(1) // Endless loop, wait for interrupts { ; } } References 2www.analog.com/en/analog-microcontrollers/analog-microcontrollers/ADuC7026/products/product.html.
Copyright 1995-
Analog
Devices, Inc. All rights reserved. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||