Yeoh Wei Yee
Newbie level 1
I am fairly new to ARM processing and I tried using msTicks, which I did before.
The main idea is as long as the accelerometer (aka fall detection) remains a certain threshold, the counter starts counting. After 5 seconds, a SMS will be sent (which I used printf to simulate this).
However the msTicks isn't counting (INITIAL_TIME and CURRENT_TIME), please advise, TYVM
The main idea is as long as the accelerometer (aka fall detection) remains a certain threshold, the counter starts counting. After 5 seconds, a SMS will be sent (which I used printf to simulate this).
However the msTicks isn't counting (INITIAL_TIME and CURRENT_TIME), please advise, TYVM
Code:
#include "lpc17xx_pinsel.h"
#include "lpc17xx_gpio.h"
#include "lpc17xx_i2c.h"
#include "lpc17xx_ssp.h"
#include "lpc17xx_timer.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <acc.h>
#include <time.h>
//Definition
#define I2CDEV LPC_I2C2
#define ACCEL_I2C_ADDR (0x1E)
// LSM303 Accelerometer registry declaration
#define L3G4200D_CTRL_REG1 0x20
#define L3G4200D_CTRL_REG4 0x23
#define L3G4200D_OUT_X_L_A 0x28
#define LSM303_CTRL_REG1_A 0x20
#define LSM303_CTRL_REG2_A 0x21
#define LSM303_CTRL_REG4_A 0x23
//Accelerometer low and high for XYZ
// Expressed as 2's complement
#define LSM303_OUT_X_L_A 0x28
#define LSM303_OUT_X_H_A 0x29
#define LSM303_OUT_Y_L_A 0x2A
#define LSM303_OUT_Y_H_A 0x2B
#define LSM303_OUT_Z_L_A 0x2C
#define LSM303_OUT_Z_H_A 0x2D
#define LSM303_OUTXH_M 0x03
#define LSM303_MR_REG_M 0x02
//To be used for observing the min and max of data for scaling calculation
int minCurrentX = 0, minCurrentY = 0, minCurrentZ = 0;
int maxCurrentX = 0, maxCurrentY = 0, maxCurrentZ = 0;
// msTicks declaration
volatile uint32_t msTicks;
uint32_t INITIAL_TIME = 0;
uint32_t CURRENT_TIME = 0;
//Function Declaration
void SysTick_Handler(void);
uint32_t GetSysTick (void);
static int i2c_read(uint8_t addr, uint8_t* buf, uint32_t len);
static int i2c_write(uint8_t addr, uint8_t* buf, uint32_t len);
void init_i2c(void);
void accelInit();
void readAccel();
void fallDetection(void);
int fallFlag = 0;
//Accelerometer X, Y, Z declaration (Raw)
int currentX, previousX, deltaX;
int currentY, previousY, deltaY;
int currentZ, previousZ, deltaZ;
//Accelerometer X, Y, Z declaration (Fine)
int fineX;
int fineY;
int fineZ;
//Calibration Parameters
int offsetX = 0;
int offsetY = 0;
int offsetZ = 0;
//Scaling Factor
/*
* Offset = (max+min) / 2
* Scaling Factor = 19600 / (max-offset)
* Data would then be +- 9600~9900
*/
int scaleX = 2.404023;
int scaleY = 2.39;
int scaleZ = 1.93599;
int integralArea; //Total energy spike if the stick were to fall down
void SysTick_Handler(void)
{
msTicks++;
}
uint32_t GetSysTick (void)
{
return msTicks;
}
static int i2c_read(uint8_t addr, uint8_t* buf, uint32_t len)
{
I2C_M_SETUP_Type rxsetup;
rxsetup.sl_addr7bit = addr;
rxsetup.tx_data = NULL; // Get address to read at writing address
rxsetup.tx_length = 0;
rxsetup.rx_data = buf;
rxsetup.rx_length = len;
rxsetup.retransmissions_max = 3;
if (I2C_MasterTransferData(I2CDEV, &rxsetup, I2C_TRANSFER_POLLING) == SUCCESS)
{
return (0);
}
else
{
//print_line("I2C Read Error");
return (-1);
}
}
static int i2c_write(uint8_t addr, uint8_t* buf, uint32_t len)
{
I2C_M_SETUP_Type txsetup;
txsetup.sl_addr7bit = addr;
txsetup.tx_data = buf;
txsetup.tx_length = len;
txsetup.rx_data = NULL;
txsetup.rx_length = 0;
txsetup.retransmissions_max = 3;
if (I2C_MasterTransferData(I2CDEV, &txsetup, I2C_TRANSFER_POLLING) == SUCCESS)
{
return (0);
}
else
{
//print_line("I2C Write Error");
return (-1);
}
}
void init_i2c(void)
{
PINSEL_CFG_Type PinCfg;
/*Initialize I2C pin connect*/
PinCfg.Funcnum = 2;
PinCfg.Pinnum = 10; //p0.10 SDA2
PinCfg.Portnum = 0;
PINSEL_ConfigPin(&PinCfg);
PinCfg.Pinnum = 11;//p0.11 SCL2
PINSEL_ConfigPin(&PinCfg);
// Initialize I2C peripheral
I2C_Init(LPC_I2C2, 100000);
/* Enable I2C1 operation */
I2C_Cmd(LPC_I2C2, ENABLE);
}
void accelInit()
{
uint8_t buf[2];
buf[0] = LSM303_CTRL_REG1_A; //Registry 1
buf[1] = 0x37;
i2c_write(ACCEL_I2C_ADDR, buf, 2);
buf[0] = LSM303_CTRL_REG2_A; //Registry 2
buf[1] = 0x58;
i2c_write(ACCEL_I2C_ADDR, buf, 2);
}
void readAccel()
{
uint8_t buf[1];
int16_t data = 0;
//Read lower bits and push to data (X)
buf[0] = LSM303_OUT_X_L_A;
i2c_write(ACCEL_I2C_ADDR, buf, 1);
i2c_read(ACCEL_I2C_ADDR, buf, 1);
data = buf[0];
//Read upper bits and push to data (X)
buf[0] = LSM303_OUT_X_H_A;
i2c_write(ACCEL_I2C_ADDR, buf, 1);
i2c_read(ACCEL_I2C_ADDR, buf, 1);
data = (int16_t)(buf[0] << 8 | data);
currentX = data;
//Read lower bits and push to data (Y)
buf[0] = LSM303_OUT_Y_L_A;
i2c_write(ACCEL_I2C_ADDR, buf, 1);
i2c_read(ACCEL_I2C_ADDR, buf, 1);
data = buf[0];
//Read upper bits and push to data (Y)
buf[0] = LSM303_OUT_Y_H_A;
i2c_write(ACCEL_I2C_ADDR, buf, 1);
i2c_read(ACCEL_I2C_ADDR, buf, 1);
data = (int16_t)(buf[0] << 8 | data);
currentY = data;
//Read lower bits and push to data (Z)
buf[0] = LSM303_OUT_Z_L_A;
i2c_write(ACCEL_I2C_ADDR, buf, 1);
i2c_read(ACCEL_I2C_ADDR, buf, 1);
data = buf[0];
//Read upper bits and push to data (Z)
buf[0] = LSM303_OUT_Z_H_A;
i2c_write(ACCEL_I2C_ADDR, buf, 1);
i2c_read(ACCEL_I2C_ADDR, buf, 1);
data = (int16_t)(buf[0] << 8 | data);
currentZ = data;
//Fine data after processing
fineX = (currentX - offsetX) * scaleX / 2;
fineY = (currentY - offsetY) * scaleY / 2;
fineZ = (currentZ - offsetZ) * scaleZ / 2;
/*
* Temporary min/max Current XYZ
* Gets highest and lowest value for ease of sclaing calculation
*/
if(currentX > maxCurrentX)
{
maxCurrentX = currentX;
}
if(currentX < minCurrentX)
{
minCurrentX = currentX;
}
if(currentY > maxCurrentY)
{
maxCurrentY = currentY;
}
if(currentY < minCurrentY)
{
minCurrentY = currentY;
}
if(currentZ > maxCurrentZ)
{
maxCurrentZ = currentZ;
}
if(currentZ < minCurrentZ)
{
minCurrentZ = currentZ;
}
}
void fallDetection(void)
{
readAccel();
time_t now;
struct tm *info;
time(&now);
info = gmtime(&now);
//Get absolute value of difference
deltaX = fabs(fineX - previousX);
deltaY = fabs(fineY - previousY);
deltaZ = fabs(fineZ - previousZ);
//Integral area
integralArea = sqrt(pow(fineX,2)+pow(fineY,2)+pow(fineZ,2));
/*
*Set a max delta change, preferably for X as main delta.
*Set Y and/or Z as secondary spike of a min value delta change
*Set Integral Area of about 1185~2000
*/
//Fallen down conditions
//if(integralArea >= 1500 && (deltaX >= 500 || deltaY >= 500) && deltaZ <=500)
if( integralArea >= 1200 && deltaX >= 600 && (deltaY <= 700 || deltaZ <= 700) && fineX > -1000
&& previousX < fineX)
{
printf("FALLEN DOWN! \n");
//printf("%s\n\n",ctime(&now)); //Time zone not to SGT
printf("%2d:%02d hours\n\n", (info->tm_hour+8)%24, info->tm_min); //Time zone should be SGT now
fallFlag = 1;
INITIAL_TIME = msTicks;
}
//Push to previous data so that new data can be updated with currentXYZ
previousX = fineX;
previousY = fineY;
previousZ = fineZ;
if(fallFlag == 1)
{
[COLOR="#B22222"] while(fineX >= -1000) //While accelerometer is in lying down position
{
CURRENT_TIME = msTicks;
if((CURRENT_TIME - INITIAL_TIME) >= 5000)
{
printf("\nSMS sent\n");
fallFlag = 0;
break;
}
}[/COLOR]
}
}
int main (void)
{
init_i2c();
accelInit();
while(1)
{
fallDetection();
}
return 0;
}