capstonedesign2.ino
7.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#include <CoDrone.h> // 코드론 라이브러리
#define ShockLed 12 // 충격 상태 확인을 위한 LED 핀번호
#define buzzer 7 // 피에조 버저 핀번호
#define LeftVib 27 // 왼쪽 진동자 핀번호
#define RightVib 28 // 오른쪽 진동자 핀번호
// 변수 및 상수부
long ac_x, ac_y, ac_z, gy_x, gy_y, gy_z; //acc, gyro data (acc, gyro 계산 수식)
double angle = 0, deg; // angle, deg data (각도계산)
double dgy_x; // double type acc data
long int normal_x, normal_y, normal_z, deltha_x[3], deltha_y[3], deltha_z[3], deltha; // 노말라이즈(정규화 데이터), 가속도 변화량 표시
long int angle_value;
const int mapping_value = 5000;
const int Emergency_value = 10000; // 충격상태로 판단하는 값
const int Emergency_angle = 25; // 충격상태로 판단하는 각도(기울기)
const int Emergency_value2 = 1200;// 충격상태로 판단하는 값
const int Emergency_angle2 = 9; // 충격상태로 판단하는 각도(기울기)
boolean State_Parameter = false; // 충격상태 판단
unsigned short int shock_level; // 충격정도 상,중,하 char로 받을 생각
const long int sum_count = 4; // 평균 내는 횟수
const long interval = 50; // 충격을 감지후 다음 충격을 감지하는 최소 간극 시간 (ms)
unsigned long previousMillis = 0; // 최초 시작시간
long shock_sum = 0; // 누적 충격값
//사용자지정 함수부
void value_init()
{
normal_x = 0;
normal_y = 0;
normal_z = 0;
for(int i = 0; i < 3; i++){
deltha_x[i] = 0;
deltha_y[i] = 0;
deltha_z[i] = 0;
angle = 0;
angle_value = 0;
}
}
// 가속도 연산 함수
void accel_calculate()
{
ac_x = 0;
ac_y = 0;
ac_z = 0;
normal_x = 0;
normal_y = 0;
normal_z = 0;
/* MPU 6050 전용
Wire.beginTransmission(mpu_add) ; // 번지수 찾기
Wire.write(0x3B) ; // 가속도 데이터 보내달라고 컨트롤 신호 보내기
Wire.endTransmission(false) ; // 기달리고,
Wire.requestFrom(mpu_add, 6, true) ; // 데이터를 받아 처리
*/
// Data SHIFT From CoDrone Accelerometer
ac_x = CoDrone.ImuAccX / 2;
ac_y = CoDrone.ImuAccY / 2;
ac_z = CoDrone.ImuAccZ / 2;
//맵핑화 시킨 것 - 즉 10000으로 맵핑시킴
normal_x = map(int(ac_x), -16384, 16384, -5000, mapping_value);
normal_y = map(int(ac_y), -16384, 16384, -5000, mapping_value);
normal_z = map(int(ac_z), -16384, 16384, -5000, mapping_value);
//normal_z = map(int(ac_z), -16384, 16384, -1000, mapping_value);
//각도계산 deg -> 각도
deg = atan2(ac_x, ac_z) * 180 / PI ; //rad to deg
dgy_x = gy_y / 131. ; //16-bit data to 250 deg/sec
angle = (0.95 * (angle + (dgy_x * 0.001))) + (0.05 * deg) ;
}
// 충격상태함수
void Emergency_state_()
{
digitalWrite(ShockLed , HIGH); // 릴레이핀을 True값으로 바꿔 13번 핀의 LED를 ON시킨다.
}
// 충격 감지함수
void Shock_Sensing()
{
State_Parameter = false; // 충격상태 초기화
shock_level = 0; // 충격정도 초기화
//첫번째 센싱
for (int i=0; i < sum_count; i++){
accel_calculate();
deltha_x[1] = deltha_x[1]+(normal_x);
deltha_y[1] = deltha_y[1]+(normal_y);
deltha_z[1] = deltha_z[1]+(normal_z);
angle_value = angle_value + angle;
}
deltha_x[1] = int(deltha_x[1]/sum_count);
deltha_y[1] = int(deltha_y[1]/sum_count);
deltha_z[1] = int(deltha_z[1]/sum_count);
//두번째 센싱
for (int i=0; i < sum_count; i++)
{
accel_calculate();
deltha_x[2] = deltha_x[2]+(normal_x);
deltha_y[2] = deltha_y[2]+(normal_y);
deltha_z[2] = deltha_z[2]+(normal_z);
angle_value = angle_value + angle;
}
deltha_x[2] = int(deltha_x[2]/sum_count);
deltha_y[2] = int(deltha_y[2]/sum_count);
deltha_z[2] = int(deltha_z[2]/sum_count);
//3축 변화량 비교 - 가속도 변화량, 각도 평균 값
deltha_x[0] = abs(deltha_x[1]-deltha_x[2]);
deltha_y[0] = abs(deltha_y[1]-deltha_y[2]);
deltha_z[0] = abs(deltha_z[1]-deltha_z[2]);
deltha = deltha_x[0] + deltha_y[0] + deltha_z[0];
angle_value = abs(int(angle_value/(sum_count)));
// deltha : 가속도 변화량
// angle_value : 각도 값(현재 각도 값)
if (deltha > Emergency_value){
State_Parameter=true;
}
shock_level = deltha; // 추후 수정 예정
/*
if(deltha > 하){
shock_level = 'a';
if(deltha > 중){
shock_level = 'b';
if(deltha > 상){
shock_level = 'c';
}
}
}
*/
/*if (angle_value > Emergency_angle){
State_Parameter=true;
}
if ((deltha > Emergency_value2)&&(angle_value > Emergency_angle2)){
State_Parameter=true;
}*/
// 충격상태체크
if( State_Parameter == true )
{
Emergency_state_();
}
else
{
digitalWrite(ShockLed , LOW);
}
}
// 진동함수
void vibrate()
{
// if 충격값이 왼쪽인지 오른쪽인지 대소비교로 판단
// 판단되면 그위치에 나눈것만큼의 진동을 나눠서 크기별로 부여
// analogWrite();
}
// Main 함수부
void setup()
{
// 부속 하드웨어 제어
pinMode(LeftVib,OUTPUT);
pinMode(RightVib,OUTPUT);
pinMode(ShockLed,OUTPUT); // 핀모드사용, led로 육안확인 가능하게끔
pinMode(buzzer,OUTPUT);
digitalWrite(ShockLed,LOW); // HIGH - LED on, LOW - LED off (DEFAULT : OFF)
digitalWrite(buzzer,LOW);
CoDrone.begin(115200); // 드론 플러그의 통신 개시 (115200bps)
CoDrone.AutoConnect(NearbyDrone); // 가장 가까운 위치의 드론과 연결
CoDrone.DroneModeChange(Flight); // 드론을 플라이트 모드로 설정
}
void loop()
{
value_init(); //가속도-각도 관련 초기값 선언
byte bt1 = digitalRead(11); // ■ □ □ □ □ □ □ 밑면 적외선 센서를 입력으로 사용
byte bt4 = digitalRead(14); // □ □ □ ■ □ □ □ 밑면 적외선 센서를 입력으로 사용
byte bt8 = digitalRead(18); // □ □ □ □ □ □ ■ 밑면 적외선 센서를 입력으로 사용
if (bt1 && !bt4 && !bt8) // 밑면 센서 가장 끝 11번 센서에 손을 대면 실행합니다.
{
CoDrone.FlightEvent(Stop); // 드론을 정지시킵니다.
}
if (!bt1 && !bt4 && bt8) // 밑면 센서 가장 끝 18번 센서에 손을 대면 실행합니다.
{
CoDrone.FlightEvent(Landing); // 드론을 착륙시킵니다.
}
Shock_Sensing();
if(State_Parameter == true)
{
shock_sum += deltha;
//currentMillis = millis();
}
if(State_Parameter == false && shock_sum != 0)
{
//bluetooth.write(char_maker(shock_sum)); // 블루투스로 충격정도 전송 (shock_maker 라는 char 리턴함수를 통해 진동강도 전송)
shock_sum = 0; // 충격의 지속이 끝났으니 원래값인 0으로 초기화
}
if(PAIRING == true) // 연결(페어링)이 성공한 경우에만 실행
{
YAW = -1 * CoDrone.AnalogScaleChange(analogRead(A3)); // 아날로그 3번 핀의 값을 YAW 값으로 사용합니다. - 좌우회전
THROTTLE = CoDrone.AnalogScaleChange(analogRead(A4)); // 아날로그 4번 핀의 값을 THROTTLE 값으로 사용합니다. - 승하강
ROLL = -1 * CoDrone.AnalogScaleChange(analogRead(A5)); // 아날로그 5번 핀의 값을 ROLL 값으로 사용합니다. - 좌우이동
PITCH = CoDrone.AnalogScaleChange(analogRead(A6)); // 아날로그 6번 핀의 값을 PITCH 값으로 사용합니다. - 전후진
CoDrone.Control(SEND_INTERVAL); // 제어 신호를 보냅니다. 통신이 안정하게 가도록 시간을 두고 보냄 (최소 50ms)
}
}