곽원석

Shock_detection code update

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 <SoftwareSerial.h>
5 +#include "I2Cdev.h"
6 +#include "MPU6050.h"
7 +
8 +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
9 + #include "Wire.h"
10 +#endif
11 +
12 +#define mpu_add 0x68
13 +#define Pin_Relay 13
14 +#define BT_RXD 7
15 +#define BT_TXD 8
16 +MPU6050 mpu;
17 +
18 +
19 +// 변수 및 상수부
20 +long ac_x, ac_y, ac_z, gy_x, gy_y, gy_z; //acc, gyro data (acc, gyro 계산 수식)
21 +double angle = 0, deg; // angle, deg data (각도계산)
22 +double dgy_x; // double type acc data
23 +long int normal_x, normal_y, normal_z, deltha_x[3], deltha_y[3], deltha_z[3], deltha; // 노말라이즈(정규화 데이터), 가속도 변화량 표시
24 +long int angle_value;
25 +const int mapping_value = 1000;
26 +const int Emergency_value = 1300; // 충격상태로 판단하는 값
27 +const int Emergency_angle = 25; // 충격상태로 판단하는 각도(기울기)
28 +const int Emergency_value2 = 1200;// 충격상태로 판단하는 값
29 +const int Emergency_angle2 = 9; // 충격상태로 판단하는 각도(기울기)
30 +boolean State_Parameter = false; // 충격상태 판단
31 +unsigned short int shock_level; // 충격정도 상,중,하 char로 받을 생각
32 +const long int sum_count = 2; // 평균 내는 횟수
33 +const long interval = 500; // 충격을 감지후 다음 충격을 감지하는 최소 간극 시간 (ms)
34 +unsigned long previousMillis = 0; // 최초 시작시간
35 +
36 +
37 +/* 사용자지정함수부
38 +*/
39 +// 모듈초기화
40 +void mpu6050_init(){
41 + Wire.begin(); //I2C통신 시작
42 + Wire.beginTransmission(mpu_add) ; // 0x68(주소) 찾아가기
43 + Wire.write(0x6B) ; // 0x6B의 레지스트를 0으로 함으로써 Sleep에서 깨움
44 + Wire.write(0); // set to ZERO(WAKE UP THE MPU6050)
45 + Wire.endTransmission(true) ;
46 +}
47 +
48 +// 연산에 필요한 변수들을 초기화
49 +void value_init(){
50 + normal_x = 0;
51 + normal_y = 0;
52 + normal_z = 0;
53 +
54 + for(int i = 0; i < 3; i++){
55 + deltha_x[i] = 0;
56 + deltha_y[i] = 0;
57 + deltha_z[i] = 0;
58 + angle = 0;
59 + angle_value = 0;
60 + }
61 +}
62 +
63 +// 가속도 연산 함수
64 +void accel_calculate() {
65 + ac_x = 0;
66 + ac_y = 0;
67 + ac_z = 0;
68 + normal_x = 0;
69 + normal_y = 0;
70 + normal_z = 0;
71 +
72 + Wire.beginTransmission(mpu_add) ; // 번지수 찾기
73 + Wire.write(0x3B) ; // 가속도 데이터 보내달라고 컨트롤 신호 보내기
74 + Wire.endTransmission(false) ; // 기달리고,
75 + Wire.requestFrom(mpu_add, 6, true) ; // 데이터를 받아 처리
76 +
77 + // Data SHIFT
78 + ac_x = Wire.read() << 8 | Wire.read() ;
79 + ac_y = Wire.read() << 8 | Wire.read() ;
80 + ac_z = Wire.read() << 8 | Wire.read() ;
81 +
82 + //맵핑화 시킨 것 - 즉 10000으로 맵핑시킴
83 + normal_x = map(int(ac_x), -16384, 16384, 0, mapping_value);
84 + normal_y = map(int(ac_y), -16384, 16384, 0, mapping_value);
85 + normal_z = map(int(ac_z), -16384, 16384, 0, mapping_value);
86 +
87 + //각도계산 deg -> 각도
88 + deg = atan2(ac_x, ac_z) * 180 / PI ; //rad to deg
89 + dgy_x = gy_y / 131. ; //16-bit data to 250 deg/sec
90 + angle = (0.95 * (angle + (dgy_x * 0.001))) + (0.05 * deg) ;
91 +}
92 +
93 +// 충격상태함수
94 +void Emergency_state_(){
95 + digitalWrite(Pin_Relay , HIGH); // 릴레이핀을 True값으로 바꿔 13번 핀의 LED를 ON시킨다.
96 + Serial.print("SHOCK level : ");
97 + Serial.println(shock_level); // Serial 모니터로 확인
98 +}
99 +
100 +void Shock_Sensing(){
101 + State_Parameter = false; // 충격상태 초기화
102 + shock_level = 0; // 충격정도 초기화
103 + //첫번째 센싱
104 + for (int i=0; i < sum_count; i++){
105 + accel_calculate();
106 + deltha_x[1] = deltha_x[1]+(normal_x);
107 + deltha_y[1] = deltha_y[1]+(normal_y);
108 + deltha_z[1] = deltha_z[1]+(normal_z);
109 + angle_value = angle_value + angle;
110 + }
111 + deltha_x[1] = int(deltha_x[1]/sum_count);
112 + deltha_y[1] = int(deltha_y[1]/sum_count);
113 + deltha_z[1] = int(deltha_z[1]/sum_count);
114 +
115 + //두번째 센싱
116 + for (int i=0; i < sum_count; i++){
117 + accel_calculate();
118 + deltha_x[2] = deltha_x[2]+(normal_x);
119 + deltha_y[2] = deltha_y[2]+(normal_y);
120 + deltha_z[2] = deltha_z[2]+(normal_z);
121 + angle_value = angle_value + angle;
122 + }
123 + deltha_x[2] = int(deltha_x[2]/sum_count);
124 + deltha_y[2] = int(deltha_y[2]/sum_count);
125 + deltha_z[2] = int(deltha_z[2]/sum_count);
126 +
127 + //3축 변화량 비교 - 가속도 변화량, 각도 평균 값
128 + deltha_x[0] = abs(deltha_x[1]-deltha_x[2]);
129 + deltha_y[0] = abs(deltha_y[1]-deltha_y[2]);
130 + deltha_z[0] = abs(deltha_z[1]-deltha_z[2]);
131 + deltha = deltha_x[0] + deltha_y[0] + deltha_z[0];
132 + angle_value = abs(int(angle_value/(sum_count)));
133 +
134 + // deltha : 가속도 변화량
135 + // angle_value : 각도 값(현재 각도 값)
136 + if (deltha > Emergency_value){
137 + State_Parameter=true;
138 + }
139 +
140 + shock_level = deltha; // 추후 수정 예정
141 +
142 +/*
143 + if(deltha > 하){
144 + shock_level = 'a';
145 + if(deltha > 중){
146 + shock_level = 'b';
147 + if(deltha > 상){
148 + shock_level = 'c';
149 + }
150 + }
151 + }
152 +
153 +*/
154 +
155 +
156 + /*if (angle_value > Emergency_angle){
157 + State_Parameter=true;
158 + }
159 + if ((deltha > Emergency_value2)&&(angle_value > Emergency_angle2)){
160 + State_Parameter=true;
161 + }*/
162 +
163 + // 충격상태체크
164 + if( State_Parameter == true ){
165 + Emergency_state_();
166 + }
167 + else {
168 + digitalWrite(Pin_Relay , LOW);
169 + }
170 +}
171 +
172 +// BLUETOOTH TRANSACTION
173 +SoftwareSerial bluetooth(BT_RXD, BT_TXD); // 블루투스 모듈
174 +
175 +
176 +/*main 함수부*/
177 +void setup() {
178 + Serial.begin(9600); // 시리얼 속도 설정
179 + Serial.println("Initializing I2C devices...");
180 + bluetooth.begin(9600); // 블루투스 속도 설정
181 + Serial.println("Initializing Bluetooth devices...");
182 +
183 + mpu6050_init(); // 가속도 센서 초기화
184 + Serial.println("Testing device connections...");
185 + Serial.println(mpu.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
186 +
187 + pinMode(Pin_Relay, OUTPUT); // 핀모드사용, led로 육안확인 가능하게끔
188 + digitalWrite(Pin_Relay , LOW); // HIGH - LED on, LOW - LED off (DEFAULT : OFF)
189 +}
190 +
191 +void loop() {
192 + value_init(); //가속도-각도 관련 초기값 선언
193 + unsigned long currentMillis = millis();
194 +
195 + if(currentMillis - previousMillis >= interval){
196 + Shock_Sensing();
197 + if(State_Parameter == true){
198 + bluetooth.write(shock_level); // 블루투스로 충격정도 전송
199 + previousMillis = currentMillis;
200 + }
201 + }
202 +}