곽원석

Shock_detection_arduino_ver.1

File mode changed
1 +// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
2 +// for both classes must be in the include path of your project
3 +// 전처리부
4 +#include "I2Cdev.h"
5 +#include "MPU6050.h"
6 +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
7 + #include "Wire.h"
8 +#endif
9 +#define mpu_add 0x68
10 +#define Pin_Relay 13
11 +
12 +
13 +// 변수 및 상수부
14 +long ac_x, ac_y, ac_z, gy_x, gy_y, gy_z; //acc, gyro data (acc, gyro 계산 수식)
15 +double angle = 0, deg; // angle, deg data (각도계산)
16 +double dgy_x; // double type acc data
17 +long int normal_x, normal_y, normal_z, deltha_x[3], deltha_y[3], deltha_z[3], deltha; // 노말라이즈(정규화 데이터), 가속도 변화량 표시
18 +long int angle_value;
19 +const int mapping_value = 1000;
20 +const int Emergency_value = 1300; // 충격상태로 판단하는 값
21 +const int Emergency_angle = 25; // 충격상태로 판단하는 각도(기울기)
22 +const int Emergency_value2 = 1200;// 충격상태로 판단하는 값
23 +const int Emergency_angle2 = 9; // 충격상태로 판단하는 각도(기울기)
24 +boolean State_Parameter = false; // 충격상태
25 +const long int sum_count = 2; // 평균 내는 횟수
26 +
27 +
28 +/* 사용자지정함수부
29 +*/
30 +// 모듈초기화
31 +void mpu6050_init(){
32 + Wire.begin(); //I2C통신 시작
33 + Wire.beginTransmission(mpu_add) ; // 0x68(주소) 찾아가기
34 + Wire.write(0x6B) ; // 0x6B의 레지스트를 0으로 함으로써 Sleep에서 깨움
35 + Wire.write(0); // set to ZERO(WAKE UP THE MPU6050)
36 + Wire.endTransmission(true) ;
37 +}
38 +
39 +// 연산에 필요한 변수들을 초기화
40 +void value_init(){
41 + normal_x = 0;
42 + normal_y = 0;
43 + normal_z = 0;
44 +
45 + for(int i = 0; i < 3; i++){
46 + deltha_x[i]=0;
47 + deltha_y[i]=0;
48 + deltha_z[i] = 0;
49 + angle = 0;
50 + angle_value=0;
51 + }
52 +}
53 +
54 +// 가속도 연산 함수
55 +void accel_calculate() {
56 + ac_x = 0;
57 + ac_y = 0;
58 + ac_z = 0;
59 + normal_x = 0;
60 + normal_y = 0;
61 + normal_z = 0;
62 +
63 + Wire.beginTransmission(mpu_add) ; // 번지수 찾기
64 + Wire.write(0x3B) ; // 가속도 데이터 보내달라고 컨트롤 신호 보내기
65 + Wire.endTransmission(false) ; // 기달리고,
66 + Wire.requestFrom(mpu_add, 6, true) ; // 데이터를 받아 처리
67 +
68 + // Data SHIFT
69 + ac_x = Wire.read() << 8 | Wire.read() ;
70 + ac_y = Wire.read() << 8 | Wire.read() ;
71 + ac_z = Wire.read() << 8 | Wire.read() ;
72 +
73 + //맵핑화 시킨 것 - 즉 10000으로 맵핑시킴
74 + normal_x = map(int(ac_x), -16384, 16384, 0, mapping_value);
75 + normal_y = map(int(ac_y), -16384, 16384, 0, mapping_value);
76 + normal_z = map(int(ac_z), -16384, 16384, 0, mapping_value);
77 +
78 + //각도계산 deg -> 각도
79 + deg = atan2(ac_x, ac_z) * 180 / PI ; //rad to deg
80 + dgy_x = gy_y / 131. ; //16-bit data to 250 deg/sec
81 + angle = (0.95 * (angle + (dgy_x * 0.001))) + (0.05 * deg) ;
82 +}
83 +
84 +// 충격상태함수
85 +void Emergency_state_(){
86 + digitalWrite(Pin_Relay , HIGH); // 릴레이핀을 True값으로 바꿔 13번 핀의 LED를 ON시킨다.
87 + Serial.println("SHOCK!!!!!!!!!!!!!!!!!"); // Serial 모니터로 확인
88 +}
89 +
90 +void Shock_Sensing(){
91 + State_Parameter = false; // 충격상태 초기화
92 +
93 + //첫번째 센싱
94 + for (int i=0; i < sum_count; i++){
95 + accel_calculate();
96 + deltha_x[1] = deltha_x[1]+(normal_x);
97 + deltha_y[1] = deltha_y[1]+(normal_y);
98 + deltha_z[1] = deltha_z[1]+(normal_z);
99 + angle_value = angle_value + angle;
100 + }
101 + deltha_x[1] = int(deltha_x[1]/sum_count);
102 + deltha_y[1] = int(deltha_y[1]/sum_count);
103 + deltha_z[1] = int(deltha_z[1]/sum_count);
104 +
105 + //두번째 센싱
106 + for (int i=0; i < sum_count; i++){
107 + accel_calculate();
108 + deltha_x[2] = deltha_x[2]+(normal_x);
109 + deltha_y[2] = deltha_y[2]+(normal_y);
110 + deltha_z[2] = deltha_z[2]+(normal_z);
111 + angle_value = angle_value + angle;
112 + }
113 + deltha_x[2] = int(deltha_x[2]/sum_count);
114 + deltha_y[2] = int(deltha_y[2]/sum_count);
115 + deltha_z[2] = int(deltha_z[2]/sum_count);
116 +
117 + //3축 변화량 비교 - 가속도 변화량, 각도 평균 값
118 + deltha_x[0] = abs(deltha_x[1]-deltha_x[2]);
119 + deltha_y[0] = abs(deltha_y[1]-deltha_y[2]);
120 + deltha_z[0] = abs(deltha_z[1]-deltha_z[2]);
121 + deltha = deltha_x[0] + deltha_y[0] + deltha_z[0];
122 + angle_value = abs(int(angle_value/(sum_count)));
123 +
124 + // deltha : 가속도 변화량
125 + // angle_value : 각도 값(현재 각도 값)
126 + if (deltha > Emergency_value){
127 + State_Parameter=true;
128 + }
129 + if (angle_value > Emergency_angle){
130 + State_Parameter=true;
131 + }
132 + if ((deltha > Emergency_value2)&&(angle_value > Emergency_angle2)){
133 + State_Parameter=true;
134 + }
135 +
136 + // 충격상태체크
137 + if( State_Parameter == true ){
138 + Emergency_state_();
139 + }
140 + else {
141 + digitalWrite(Pin_Relay , LOW);
142 + }
143 +}
144 +
145 +
146 +
147 +
148 +
149 +/*main 함수부*/
150 +void setup() {
151 + mpu6050_init(); // 가속도 센서 초기 설정
152 +
153 + Serial.begin(9600); // 시리얼 속도
154 + pinMode(Pin_Relay, OUTPUT); // 핀모드사용, led로 육안확인 가능하게끔
155 + digitalWrite(Pin_Relay , LOW); // HIGH - LED on, LOW - LED off (DEFAULT : OFF)
156 +}
157 +
158 +void loop() {
159 + value_init(); //가속도-각도 관련 초기값 선언
160 + Shock_Sensing(); // 충격감지 함수
161 +}