달력

1

« 2025/1 »

  • 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

'분류 전체보기'에 해당되는 글 168

  1. 2016.02.08 롤 제어
  2. 2016.02.08 호버링 제어
  3. 2016.02.08 조립 후 테스트
  4. 2016.02.08 하드웨어 조립
  5. 2016.02.08 부품 테스트 - 배터리
  6. 2016.02.08 부품테스트 ESC 및 BEC
  7. 2016.02.08 부품 테스트 - 센서
  8. 2016.02.08 부품 주문
  9. 2016.02.08 링크
  10. 2016.02.08 인터넷 check sum 함수의 구현
2016. 2. 8. 02:29

롤 제어 작품/쿼드콥터2016. 2. 8. 02:29

쿼드 콥터는 X자형이냐 +자형이냐에 따라 제어 방법이 다릅니다.

저는 +자형 쿼드 콥터를 만들기 때문에 롤 제어는 다음과 같이 합니다.

롤 제어 방법은 한 축의 두 개의 모터는 균형을 규지하면서 나머지 다른 축의 모터의 기울기를 통하여 비행하는 기울기를 결정합니다.



제가 테스트한 동영상의 방법은 일단 무선 조종기가 없었기 때문에 아두이노 IDE에서 시리얼 디버깅 창을 띄워놓고

한 쪽 축의 목표 기울기 값을 컴퓨터를 통하여 아두이노에 전송하여 기울기 방향을 정하였습니다.

동영상을 자세히 보면 기체가 한 쪽 방향으로 기울인 뒤 그 방향으로 움직이는 것을 볼 수 있어요.


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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
#include "SoftwareSerial.h"
#include "Servo.h"
 
/////////////////BLDC Motor/////////////////
#define MAX_THROTTLE 179
#define MIN_THROTTLE 0
#define MAX_PWM 100
#define MIN_PWM 20
#define MOTOR1  //motor pin number
#define MOTOR2  //motor pin number
#define MOTOR3 10  //motor pin number
#define MOTOR4 //motor pin number
 
int motor1Power, motor3Power; // Motors on the X axis
//=>; changing their speeds will affect the pitch
int motor2Power, motor4Power; // Motors on the Y axis
//=>; changing their speeds will affect the roll
  
Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;
////////////////////////////////////////////
 
 
/////////////////IMU Sensor/////////////////
#define DATANUM 12 //6
#define ACC_X_OFFSET 0.18
#define ACC_Y_OFFSET 0.01
#define ACC_Z_OFFSET -0.77
//IMU Sensor Serial
SoftwareSerial SensorSerial(2,4);//Rx Tx
//IMU Sensor variable
typedef union {
  signed short value;
  unsigned char byte[2];
} S2BYTE;
 
S2BYTE data_word;
 
unsigned char SBuf[100];
int SCnt=0;
double  DegRoll, DegPitch, DegYaw;
double Acc_x, Acc_y, Acc_z;
////////////////////////////////////////////
 
 
/////////////////PID Conrtroll/////////////////
#define MINhover 0
#define INIThover  20
 
#define INITROLLKp 0.38
#define INITROLLKi 0.000287 
#define INITROLLKd 33
 
#define INITPITCHKp 0.29
#define INITPITCHKi 0.000287 
#define INITPITCHKd 33
 
#define INITYAWKp 0.29 //0.38
#define INITYAWKi 0.000287 
#define INITYAWKd 33
 
#define MAXSPEED  3
#define MINSPEED  100
 
#define INITROLLSETPOINT -1.532
#define INITPITCHSETPOINT -0.516
 
 
double roll_setpoint = INITROLLSETPOINT, pitch_setpoint = INITPITCHSETPOINT, yaw_setpoint = 0;
int hover = INIThover;
double roll_Kp = INITROLLKp, roll_Ki = INITROLLKi, roll_Kd = INITROLLKd;
double pitch_Kp = INITPITCHKp, pitch_Ki = INITPITCHKi, pitch_Kd = INITPITCHKd;
double yaw_Kp = INITYAWKp, yaw_Ki = INITYAWKi, yaw_Kd = INITYAWKd;
double roll_p, roll_i, roll_d, roll_val;
double pitch_p, pitch_i, pitch_d, pitch_val;
double yaw_p, yaw_i, yaw_d, yaw_val;
int rollControll, pitchControll, yawControll;
 
int initial = 0;
////////////////////////////////////////////
 
/////////////////Serial Monitor/////////////////
int Serial_print_sig=1;
int roll_print = 1, pitch_print =0, yaw_print=0, hover_print=0;
////////////////////////////////////////////
 
 
//---------------------------------------------------------------------//
//
//                              funtions
//
//--------------------------------------------------------------------//
 
//esc조절 하기
void callibration(void)
{
  
  Serial.println("Calibrate ESC? 'y' or 'n'.");
    
  while (!Serial.available());
  char cali = Serial.read();
  if(cali == 'y'){  
   Serial.println("send max throttle");
    
    motor1.attach(MOTOR1);
    motor2.attach(MOTOR2);
    motor3.attach(MOTOR3);
    motor4.attach(MOTOR4);
    motor1.write(MAX_THROTTLE);
    motor2.write(MAX_THROTTLE);
    motor3.write(MAX_THROTTLE);
    motor4.write(MAX_THROTTLE);
   
    delay(5000);
 
    Serial.println("send min throttle");
    motor1.attach(MOTOR1);
    motor2.attach(MOTOR2);
    motor3.attach(MOTOR3);
    motor4.attach(MOTOR4);
    motor1.write(MIN_THROTTLE);
    motor2.write(MIN_THROTTLE);
    motor3.write(MIN_THROTTLE);
    motor4.write(MIN_THROTTLE);
 
    delay(2000);
    
    Serial.println("callibration complete");
    
  }else if(cali == 'n'){
    motor1.attach(MOTOR1);
    motor2.attach(MOTOR2);
    motor3.attach(MOTOR3);
    motor4.attach(MOTOR4);
    motor1.write(MIN_THROTTLE);
    motor2.write(MIN_THROTTLE);
    motor3.write(MIN_THROTTLE);
    motor4.write(MIN_THROTTLE);
   
  }
  Serial.println("If you want Program keep going. Press any key.");
  while (!Serial.available());
}
 
//------------------------------------------------------------------------//
//센서값을 읽어서 roll,pitch,yaw 값을 알아낸다.
int recieve_data(void)
{
    static int step_=0, check_all_recieve=0;
    unsigned char data1byte;
    int n;
 
    data1byte = SensorSerial.read();
    
    switch(step_)
    {
        case 0:
           if(data1byte==0x55) {step_=1, check_all_recieve=0;}
        break;
 
        case 1:
           if(data1byte==0x55) { step_=2;  SCnt=0;}
           else step_=0;
        break;
 
        case 2:
           SBuf[SCnt++= (unsigned char)data1byte;
           if(SCnt==DATANUM+2)  // roll(2byte),pitch(2byte),yaw(2byte),checksum(2byte) 
             {   
                step_=0;
                SCnt=0;
                check_all_recieve = 1;
             }
        break;
 
        default:
        break;
     }
   
    return check_all_recieve;
}
 
static int trans_data_to_degree(unsigned char *sdata)  // sdata : roll(2)+pitch(2)+yaw(2)+chk(2)
{
  int n;
  unsigned short chk=0;
 
  ///////////// checksum /////////////////
  chk=0x55+0x55;
  for(n=0;n<DATANUM;n++) chk+=sdata[n]; 
  if(chk != get_data_word(&sdata[DATANUM])) 
  {
    Serial.println("checksum error!");
    return 0//   
  }
  ////////////////////////////////////////
 
  DegRoll  = get_data_word(&sdata[0]) / 100.;
  DegPitch = get_data_word(&sdata[2]) / 100. * -1;
  DegYaw   = get_data_word(&sdata[4]) / 100.;
 
  Acc_x = get_data_word(&sdata[6]) / 100. + ACC_X_OFFSET;
  Acc_y = get_data_word(&sdata[8]) / 100. + ACC_Y_OFFSET;
  Acc_z = get_data_word(&sdata[10]) / 100. + ACC_Z_OFFSET;
 
  return 1;
}
 
static signed short get_data_word(unsigned char *dat)
{
  // little endian..
  data_word.byte[0]=dat[1];  
  data_word.byte[1]=dat[0];  
 
  return data_word.value;
}
 
//--------------------------------------------------------------------------------//
//각도 값을 받아서 PID제어값 출력
double roll_pid(double setpoint, double degree)
{
    double val_out;
    static double roll_p_err_prv, roll_p_err, roll_i_err, roll_d_err;
 
    roll_p_err = setpoint-degree;
    roll_i_err += roll_p_err;
    roll_d_err = roll_p_err - roll_p_err_prv;
    
    roll_p_err_prv = roll_p_err;
    val_out = (roll_Kp*roll_p_err) + (roll_Ki*roll_i_err) + (roll_Kd*roll_d_err);
 
    roll_p = roll_Kp*roll_p_err;
    roll_i = roll_Ki*roll_i_err;
    roll_d = roll_Kd*roll_d_err;
    roll_val = val_out;
    
    return val_out;
}
 
double pitch_pid(double setpoint, double degree)
{
    double val_out;
    static double pitch_p_err_prv, pitch_p_err, pitch_i_err, pitch_d_err;
 
    pitch_p_err = setpoint-degree;
    pitch_i_err += pitch_p_err;
    pitch_d_err = pitch_p_err - pitch_p_err_prv;
    
    pitch_p_err_prv = pitch_p_err;
    val_out = (pitch_Kp*pitch_p_err) + (pitch_Ki*pitch_i_err) + (pitch_Kd*pitch_d_err);
    
    pitch_p = pitch_Kp*pitch_p_err;
    pitch_i = pitch_Ki*pitch_i_err;
    pitch_d = pitch_Kd*pitch_d_err;
    pitch_val = val_out;
    
    return val_out;
}
 
double yaw_pid(double setpoint, double degree)
{
    double val_out;
    static double yaw_p_err_prv, yaw_p_err, yaw_i_err, yaw_d_err;
 
    yaw_p_err = setpoint-degree;
    yaw_i_err += yaw_p_err;
    yaw_d_err = yaw_p_err - yaw_p_err_prv;
    
    yaw_p_err_prv = yaw_p_err;
    val_out = (yaw_Kp*yaw_p_err) + (yaw_Ki*yaw_i_err) + (yaw_Kd*yaw_d_err);
    
    yaw_p = yaw_Kp*yaw_p_err;
    yaw_i = yaw_Ki*yaw_i_err;
    yaw_d = yaw_Kd*yaw_d_err;
    yaw_val = val_out;
    
    return val_out;
}
//------------------------------------------------------------------------
//제어값을 받어서 모터 구동
void run_motors(int throttle, int rollOffset, int pitchOffset, int yawOffset)
{
  motor1Power = throttle + pitchOffset - yawOffset;
  motor2Power = throttle + rollOffset + yawOffset;
  motor3Power = throttle - pitchOffset  - yawOffset;
  motor4Power = throttle - rollOffset + yawOffset;
  
  limit_max_min(motor1Power);
  limit_max_min(motor2Power);
  limit_max_min(motor3Power);
  limit_max_min(motor4Power);
 
  motor1.write(motor1Power);motor3.write(motor3Power);
  motor2.write(motor2Power);motor4.write(motor4Power);
}
 
void limit_max_min(int pwm)
{
  if(pwm>MAX_PWM)
  pwm = MAX_PWM;
  else if(pwm<MIN_PWM)
  pwm = MIN_PWM;
}
//-------------------------------------------------------------------------------//
void Serial_Monitor(void)
{
  if(Serial_print_sig ==){
    if(roll_print == 1){
      Serial.print("Roll=> ");Serial.print(DegRoll);Serial.print(", ");Serial.print(roll_p); Serial.print(", ");Serial.print(roll_i); Serial.print(", ");Serial.print(roll_d);Serial.print(", ");Serial.print(roll_val);Serial.print(", ");Serial.print(motor2Power);Serial.print(", ");Serial.println(motor4Power);
    }else if(pitch_print == 1){
      Serial.print("Pitch=> ");Serial.print(DegPitch);Serial.print(", ");Serial.print(pitch_p); Serial.print(", ");Serial.print(pitch_i); Serial.print(", ");Serial.print(pitch_d);Serial.print(", ");Serial.print(pitch_val);Serial.print(", ");Serial.print(motor1Power);Serial.print(", ");Serial.println(motor3Power);
    }else if(yaw_print == 1){
      Serial.print("Yaw=> ");Serial.print(DegYaw);Serial.print(", ");Serial.print(yaw_p); Serial.print(", ");Serial.print(yaw_i); Serial.print(", ");Serial.print(yaw_d);Serial.print(", ");Serial.println(yaw_val); 
    }
  } 
 
  if(Serial_print_sig == 0){
    if(hover_print == 1){
      Serial.print("hover = ");Serial.println(hover);
      hover_print =0;
    }else if(roll_print == 1){
      Serial.print("roll_Kp = ");Serial.print(roll_Kp);Serial.print(", roll_Ki = ");Serial.print(roll_Ki*10000);Serial.print(", roll_Kd = ");Serial.println(roll_Kd);
      roll_print = 0;
    }else if(pitch_print == 1){
      Serial.print("pitch_Kp = ");Serial.print(pitch_Kp);Serial.print(", pitch_Ki = ");Serial.print(pitch_Ki*10000);Serial.print(", pitch_Kd = ");Serial.println(pitch_Kd);
      pitch_print = 0;
    }else if(yaw_print == 1){
      Serial.print("yaw_Kp = ");Serial.print(yaw_Kp);Serial.print(", yaw_Ki = ");Serial.print(yaw_Ki*10000);Serial.print(", yaw_Kd = ");Serial.println(yaw_Kd);
      yaw_print = 0;
    }
  }
}
 
//------------------------------------------------------------------------------//
void from_computer(void)
{
    char c = Serial.read();
    //hover debuging
    if(c=='1'){
      hover += 1;
      Serial.print("hover = ");Serial.println(hover);
    }else if(c=='2'){
      hover -= 1;
      Serial.print("hover = ");Serial.println(hover);
    }else if(c=='3'){
      hover= INIThover;
      Serial.print("hover = ");Serial.println(hover);
    }else if(c=='4'){
      hover= MINhover;
      Serial.print("hover = ");Serial.println(hover);
    }else if(c=='5'){
      roll_setpoint += 0.1;
      Serial.print("roll_setpoint = ");Serial.println(roll_setpoint);
    }else if(c=='6'){
      roll_setpoint -= 0.1;
      Serial.print("roll_setpoint = ");Serial.println(roll_setpoint);
    }else if(c=='7'){
      roll_setpoint = INITROLLSETPOINT;
      Serial.print("roll_setpoint = ");Serial.println(roll_setpoint);
    }
 
    
    
    //roll debuging
    else if(c=='q'){
      roll_Kp += 0.01;
      Serial.print("roll_Kp = ");Serial.println(roll_Kp);
    }else if(c=='w'){
      roll_Kp -= 0.01;
      Serial.print("roll_Kp = ");Serial.println(roll_Kp);
    }else if(c=='e'){
      roll_Kp= INITROLLKp;
      Serial.print("roll_Kp = ");Serial.println(roll_Kp);
    }else if(c=='a'){
      roll_Ki += 0.000001;
      Serial.print("roll_Ki = ");Serial.println(roll_Ki*10000);
    }else if(c=='s'){
      roll_Ki -= 0.000001;
      Serial.print("roll_Ki = ");Serial.println(roll_Ki*10000);
    }else if(c=='d'){
      roll_Ki = INITROLLKi;
      Serial.print("roll_Ki = ");Serial.println(roll_Ki*10000);
    }else if(c=='z'){
      roll_Kd += 1;
      Serial.print("roll_Kd = ");Serial.println(roll_Kd);
    }else if(c=='x'){
      roll_Kd -= 1;
      Serial.print("roll_Kd = ");Serial.println(roll_Kd);
    }else if(c=='c'){
      roll_Kd = INITROLLKd;
      Serial.print("roll_Kd = ");Serial.println(roll_Kd);
    }
    
    
    
    //pitch debuging
    else if(c=='r'){
      pitch_Kp += 0.01;
      Serial.print("pitch_Kp = ");Serial.println(pitch_Kp);
    }else if(c=='t'){
      pitch_Kp -= 0.01;
      Serial.print("pitch_Kp = ");Serial.println(pitch_Kp);
    }else if(c=='y'){
      pitch_Kp= INITPITCHKp;
      Serial.print("pitch_Kp = ");Serial.println(pitch_Kp);
    }else if(c=='f'){
      pitch_Ki += 0.000001;
      Serial.print("pitch_Ki = ");Serial.println(pitch_Ki*10000);
    }else if(c=='g'){
      pitch_Ki -= 0.000001;
      Serial.print("pitch_Ki = ");Serial.println(pitch_Ki*10000);
    }else if(c=='h'){
      pitch_Ki = INITPITCHKi;
      Serial.print("pitch_Ki = ");Serial.println(pitch_Ki*10000);
    }else if(c=='v'){
      pitch_Kd += 1;
      Serial.print("pitch_Kd = ");Serial.println(pitch_Kd);
    }else if(c=='b'){
      pitch_Kd -= 1;
      Serial.print("pitch_Kd = ");Serial.println(pitch_Kd);
    }else if(c=='n'){
      pitch_Kd = INITPITCHKd;
      Serial.print("pitch_Kd = ");Serial.println(pitch_Kd);
    }
 
    //yaw debuging
    else if(c=='u'){
      yaw_Kp += 0.01;
      Serial.print("yaw_Kp = ");Serial.println(yaw_Kp);
    }else if(c=='i'){
      yaw_Kp -= 0.01;
      Serial.print("yaw_Kp = ");Serial.println(yaw_Kp);
    }else if(c=='o'){
      yaw_Kp= INITYAWKp;
      Serial.print("yaw_Kp = ");Serial.println(yaw_Kp);
    }else if(c=='j'){
      yaw_Ki += 0.000001;
      Serial.print("yaw_Ki = ");Serial.println(yaw_Ki*10000);
    }else if(c=='k'){
      yaw_Ki -= 0.000001;
      Serial.print("yaw_Ki = ");Serial.println(yaw_Ki*10000);
    }else if(c=='l'){
      yaw_Ki = INITYAWKi;
      Serial.print("yaw_Ki = ");Serial.println(yaw_Ki*10000);
    }else if(c=='m'){
      yaw_Kd += 1;
      Serial.print("yaw_Kd = ");Serial.println(yaw_Kd);
    }else if(c==','){
      yaw_Kd -= 1;
      Serial.print("yaw_Kd = ");Serial.println(yaw_Kd);
    }else if(c=='.'){
      yaw_Kd = INITYAWKd;
      Serial.print("yaw_Kd = ");Serial.println(yaw_Kd);
    }
 
    else if(c=='p'){
      Serial_print_sig = !(Serial_print_sig);
    }else if(c=='/'){
      roll_print = !(roll_print);
    }else if(c=='*'){
      pitch_print = !(pitch_print);
    }else if(c=='-'){
      yaw_print = !(yaw_print);
    }else if(c=='+'){
      hover_print = !(hover_print);
    }
    
}
 
//---------------------------------------------------------------------//
//
//                                main
//
//--------------------------------------------------------------------//
void setup() {
  Serial.begin(115200); 
  SensorSerial.begin(57600); 
  callibration();
}
 
void loop() {
 
  
  if(SensorSerial.available()){ //데이터 받기.
   if(recieve_data()==1)  //데이터 다 받음?
   {   
     if(trans_data_to_degree(SBuf)==1//센서값. 
     {
      if(initial == 0){
      yaw_setpoint = DegYaw;
      initial = 1;
      //Serial.println(yaw_setpoint);
      }
             
       rollControll = roll_pid(roll_setpoint, DegRoll); //PID.
       pitchControll = pitch_pid(pitch_setpoint, DegPitch);
       yawControll = yaw_pid(yaw_setpoint, DegYaw);
    
       run_motors(hover, rollControll, pitchControll, yawControll); //MOTOR
 
       //Serial_Monitor(); //Serial.print.
       Serial.print(Acc_x);Serial.print(", ");Serial.print(Acc_y);Serial.print(", ");Serial.println(Acc_y);
      }
    } 
  }
 
   if(Serial.available()){ //통신입력?
    from_computer(); //입력받기.
   }
}
 
 
 
cs



'작품 > 쿼드콥터' 카테고리의 다른 글

아두이노 메가2560으로 MCU를 교체하다  (0) 2016.02.08
무선 조종기와 카메라 테스트  (0) 2016.02.08
호버링 제어  (0) 2016.02.08
조립 후 테스트  (0) 2016.02.08
하드웨어 조립  (0) 2016.02.08
:
Posted by youjin.A
2016. 2. 8. 02:06

호버링 제어 작품/쿼드콥터2016. 2. 8. 02:06

1. PID 테스트

날개 4개 중에서 한 축인 2개의 모터만 돌려서 우선 균형을 잡을 수 있는 지 PID 테스트를 해보았습니다.

PID 제어란 목표인 입력값과 현재 상태인 결과 사이의 차이(Error)에 비례, 적분, 미분의 기법을 써서 구동부를 제어하는 방법입니다.

기본적인 PID 제어 방법과 코드는 아래와 같아요.


기초: PID 제어


#define Kp (2) // configurable value.

#define Ki (1) // configurable value.

#define Kd (1) // configurable value.

#define dt   0.01



double pid(int degree)

{

 static double P_err_prv; // Prev P error to get D_err.

 double P_err, I_err, D_err; // Basic Error values.


 P_err = SETPOINT - degree;

 I_err += P_err * dt;

 D_err = (P_err - P_err_prv) / dt;


 P_err_prv = P_err; // backup P_err.

 val_out = (Kp * P_err) + (Ki * I_err) + (Kd * D_err);

 return val_out; // Calculated.

}


균형을 잡는 지 저희 쿼드콥터로 테스트 하기 위해서 디버깅 환경을 다음과 같이 꾸몄습니다.




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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
#include "SoftwareSerial.h"
#include "Servo.h"
 
/////////////////BLDC Motor/////////////////
#define MAX_THROTTLE 179
#define MIN_THROTTLE 0
#define MAX_PWM 100
#define MIN_PWM 20
#define MOTOR0  //motor pin number
#define MOTOR1  //motor pin number
#define MOTOR2 10  //motor pin number
#define MOTOR3 //motor pin number
 
Servo motor0;
Servo motor1;
Servo motor2;
Servo motor3;
int mspeed=0;
int pwm=0, Cpwm=0;
////////////////////////////////////////////
 
 
/////////////////IMU Sensor/////////////////
//IMU Sensor Serial
SoftwareSerial SensorSerial(2,4);//Rx Tx
//IMU Sensor variable
char data[40];
int i = 0;
double  roll, pitch, yaw;
////////////////////////////////////////////
 
 
/////////////////PID Conrtroll/////////////////
#define SETPOINT  0
#define INITfitpoint  30
#define INITKp  0.38
#define INITKi 0.000287
#define INITKd 33
#define MAXSPEED  3
#define MINSPEED  100
 
int fitpoint = INITfitpoint;
double Kp = INITKp, Ki = INITKi, Kd = INITKd;
double last_t;
////////////////////////////////////////////
 
 
//---------------------------------------------------------------------//
//
//                              funtions
//
//--------------------------------------------------------------------//
 
//esc조절 하기
void callibration(void)
{
  
  Serial.println("Calibrate ESC? 'y' or 'n'.");
    
  while (!Serial.available());
  char cali = Serial.read();
  if(cali == 'y'){  
    Serial.println("send max throttle");
    
    motor0.attach(MOTOR0);
    motor1.attach(MOTOR1);
    motor2.attach(MOTOR2);
    motor3.attach(MOTOR3);
    motor0.write(MAX_THROTTLE);
    motor1.write(MAX_THROTTLE);
    motor2.write(MAX_THROTTLE);
    motor3.write(MAX_THROTTLE);
   
    delay(4000);
 
     Serial.println("send min throttle");
    motor0.attach(MOTOR0);
    motor1.attach(MOTOR1);
    motor2.attach(MOTOR2);
    motor3.attach(MOTOR3);
    motor0.write(MIN_THROTTLE);
    motor1.write(MIN_THROTTLE);
    motor2.write(MIN_THROTTLE);
    motor3.write(MIN_THROTTLE);
 
    delay(2000);
    
    Serial.println("callibration complete");
    
  }else if(cali == 'n'){
    motor0.attach(MOTOR0);
    motor1.attach(MOTOR1);
    motor2.attach(MOTOR2);
    motor3.attach(MOTOR3);
    motor0.write(MIN_THROTTLE);
    motor1.write(MIN_THROTTLE);
    motor2.write(MIN_THROTTLE);
    motor3.write(MIN_THROTTLE);
   
  }
  Serial.println("If you want Program keep going. Press any key.");
  while (!Serial.available());
}
 
//------------------------------------------------------------------------//
//센서값을 읽어서 roll,pitch,yaw 값을 알아낸다.
//IMU 센서에서 받아온 아스키코드 값을 잘라서 숫자로 저장하는 함수
//trans_ascii_to_num(저장할 버퍼 배열, 롤값 저장할 변수, 피치값 저장할 변수, 요값 저장할 변수)
void trans_ascii_to_num(char * SBuf, double * roll_ptr, double * pitch_ptr, double * yaw_ptr)
{  
  int value, value2;
  
  value=FindComma(SBuf);// ',' 위치(인덱스 값)을 반환?
  SBuf[value]='\0';// ','를 NULL(\0)값으로 바꾸어주어 하나의 스트링배열로 만들어주는듯?(NULL은 스트링의 마지막 값이니까)
  *roll_ptr=atof(SBuf); 
  //atof()는 스트링을 double형으로 바꾸어주는 함수, 소수점도 알아서 인식하고 바꾸어준다.
        
  value++;
  value2=FindComma(&SBuf[value]);
  SBuf[value+value2]='\0';
  *pitch_ptr=atof(&SBuf[value]);
    
  value=value+value2+1;
  value2=FindComma(&SBuf[value]);
  SBuf[value+value2]='\0';
  *yaw_ptr=atof(&SBuf[value]);
 
}
 
int FindComma(char * buf)
{
   int n;
   for(n=0;n<40;n++)
    {
     if(buf[n]==','break;
    }
 
   return n;
}
 
//--------------------------------------------------------------------------------//
//각도 값을 받아서 PID제어값 출력
double pid(double degree)
{
    double val_out;
    static double p_err_prv, p_err, i_err, d_err;
 
    p_err = SETPOINT-degree;
    i_err += p_err;
    d_err = p_err - p_err_prv;
    
    p_err_prv = p_err;
    val_out = (Kp*p_err) + (Ki*i_err) + (Kd*d_err);
    
    Serial.print((Kp*p_err)); Serial.print(", ");Serial.print((Ki*i_err)); Serial.print(", ");Serial.print((Kd*d_err));Serial.print(", ");Serial.print(val_out); 
    return val_out;
}
 
//------------------------------------------------------------------------
//제어값을 받어서 모터 구동
void run_motors(int speed1, int speed2)
{
  pwm = speed1 + speed2; 
  Cpwm = speed1 - speed2;
  
  if(pwm>MAX_PWM)
  pwm = MAX_PWM;
  else if(pwm<MIN_PWM)
  pwm = MIN_PWM;
 
  if(Cpwm>MAX_PWM)
  Cpwm = MAX_PWM;
  else if(Cpwm<MIN_PWM)
  Cpwm = MIN_PWM;
 
  motor1.write(pwm); 
  motor3.write(Cpwm);
 
  Serial.print(", ");Serial.print(pwm);Serial.print(", ");Serial.print(Cpwm);Serial.println("");
}
 
//------------------------------------------------------------------------------//
//pid 계수의 값을 바꾼다.
void modify_pid_val(void)
{
   if(Serial.available()){
    char c = Serial.read();
    if(c=='r'){
      fitpoint += 1;
      Serial.print("fitpoint = ");Serial.println(fitpoint);
    }else if(c=='t'){
      fitpoint -= 1;
      Serial.print("fitpoint = ");Serial.println(fitpoint);
    }else if(c=='y'){
      fitpoint= INITfitpoint;
      Serial.print("fitpoint = ");Serial.println(fitpoint);
    }else if(c=='q'){
      Kp += 0.01;
      Serial.print("Kp = ");Serial.println(Kp);
    }else if(c=='w'){
      Kp -= 0.01;
      Serial.print("Kp = ");Serial.println(Kp);
    }else if(c=='e'){
      Kp= INITKp;
      Serial.print("Kp = ");Serial.println(Kp);
    }else if(c=='a'){
      Ki += 0.000001;
      Serial.print("Ki = ");Serial.println(Ki*10000);
    }else if(c=='s'){
      Ki -= 0.000001;
      Serial.print("Ki = ");Serial.println(Ki*10000);
    }else if(c=='d'){
      Ki = INITKi;
      Serial.print("Ki = ");Serial.println(Ki*10000);
    }else if(c=='z'){
      Kd += 1;
      Serial.print("Kd = ");Serial.println(Kd);
    }else if(c=='x'){
      Kd -= 1;
      Serial.print("Kd = ");Serial.println(Kd);
    }else if(c=='c'){
      Kd = INITKd;
      Serial.print("Kd = ");Serial.println(Kd);
    }else if(c=='p'){
      Serial.print("Kp = ");Serial.print(Kp);Serial.print(", Ki = ");Serial.print(Ki*10000);Serial.print(", Kd = ");Serial.println(Kd);   
    }
  } 
}
 
//---------------------------------------------------------------------//
//
//                                main
//
//--------------------------------------------------------------------//
void setup() {
  Serial.begin(115200); 
  SensorSerial.begin(57600); 
  callibration();
}
 
void loop() {
  if(SensorSerial.available()){
    data[i]= SensorSerial.read();
    i++;
   
    if(data[i-1== 0x0A)
    data[i-1= ',';
    
    if(data[i-1== '*'){//데이터 다받음.
     i=0;
     
     trans_ascii_to_num(data, &roll, &pitch, &yaw);//센서값을 읽어서 roll,pitch,yaw 값을 알아낸다. 
     Serial.print(roll);Serial.print(", ");
     mspeed = pid(roll);//각도 값을 받아서 PID제어값 출력
     run_motors(fitpoint, mspeed);//제어값을 받어서 모터 구동
     
    }
   }
 
    modify_pid_val();
}
  
 
cs



2. 호버링 제어

다음으로 위의 PID 코드를 수정하여 두 축의 균형을 잡을 수 있도록 소스를 수정 한 후 모터 4개를 모두 돌려서 테스트 하였습니다.

기체가 균형을 잡는지, 공중에 뜨는 지를 확인 하였는데 생각보다 안정적이지 않았습니다.






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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
#include "SoftwareSerial.h"
#include "Servo.h"
 
/////////////////BLDC Motor/////////////////
#define MAX_THROTTLE 179
#define MIN_THROTTLE 0
#define MAX_PWM 100
#define MIN_PWM 20
#define MOTOR1  //motor pin number
#define MOTOR2  //motor pin number
#define MOTOR3 10  //motor pin number
#define MOTOR4 //motor pin number
 
Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;
////////////////////////////////////////////
 
 
/////////////////IMU Sensor/////////////////
//IMU Sensor Serial
SoftwareSerial SensorSerial(2,4);//Rx Tx
//IMU Sensor variable
typedef union {
  signed short value;
  unsigned char byte[2];
} S2BYTE;
 
S2BYTE data_word;
 
unsigned char SBuf[100];
int SCnt=0;
double  DegRoll, DegPitch, DegYaw;
////////////////////////////////////////////
 
 
/////////////////PID Conrtroll/////////////////
#define MINhover 0
#define INIThover  20
 
#define INITROLLKp 0.38
#define INITROLLKi 0.000287 
#define INITROLLKd 33
 
#define INITPITCHKp 0.29
#define INITPITCHKi 0.000287 
#define INITPITCHKd 33
 
#define INITYAWKp 0.29 //0.38
#define INITYAWKi 0.000287 
#define INITYAWKd 33
 
#define MAXSPEED  3
#define MINSPEED  100
 
#define INITROLLSETPOINT -1.532
#define INITPITCHSETPOINT -0.516
 
 
double roll_setpoint = INITROLLSETPOINT, pitch_setpoint = INITPITCHSETPOINT, yaw_setpoint = 0;
int hover = INIThover;
double roll_Kp = INITROLLKp, roll_Ki = INITROLLKi, roll_Kd = INITROLLKd;
double pitch_Kp = INITPITCHKp, pitch_Ki = INITPITCHKi, pitch_Kd = INITPITCHKd;
double yaw_Kp = INITYAWKp, yaw_Ki = INITYAWKi, yaw_Kd = INITYAWKd;
int rollControll, pitchControll, yawControll;
 
int initial = 0;
////////////////////////////////////////////
 
 
//---------------------------------------------------------------------//
//
//                              funtions
//
//--------------------------------------------------------------------//
 
//esc조절 하기
void callibration(void)
{
  
  Serial.println("Calibrate ESC? 'y' or 'n'.");
    
  while (!Serial.available());
  char cali = Serial.read();
  if(cali == 'y'){  
   Serial.println("send max throttle");
    
    motor1.attach(MOTOR1);
    motor2.attach(MOTOR2);
    motor3.attach(MOTOR3);
    motor4.attach(MOTOR4);
    motor1.write(MAX_THROTTLE);
    motor2.write(MAX_THROTTLE);
    motor3.write(MAX_THROTTLE);
    motor4.write(MAX_THROTTLE);
   
    delay(5000);
 
    Serial.println("send min throttle");
    motor1.attach(MOTOR1);
    motor2.attach(MOTOR2);
    motor3.attach(MOTOR3);
    motor4.attach(MOTOR4);
    motor1.write(MIN_THROTTLE);
    motor2.write(MIN_THROTTLE);
    motor3.write(MIN_THROTTLE);
    motor4.write(MIN_THROTTLE);
 
    delay(2000);
    
    Serial.println("callibration complete");
    
  }else if(cali == 'n'){
    motor1.attach(MOTOR1);
    motor2.attach(MOTOR2);
    motor3.attach(MOTOR3);
    motor4.attach(MOTOR4);
    motor1.write(MIN_THROTTLE);
    motor2.write(MIN_THROTTLE);
    motor3.write(MIN_THROTTLE);
    motor4.write(MIN_THROTTLE);
   
  }
  Serial.println("If you want Program keep going. Press any key.");
  while (!Serial.available());
}
 
//------------------------------------------------------------------------//
//센서값을 읽어서 roll,pitch,yaw 값을 알아낸다.
int recieve_data(void)
{
    static int step_=0, check_all_recieve=0;
    unsigned char data1byte;
    int n;
 
    data1byte = SensorSerial.read();
    
    switch(step_)
    {
        case 0:
           if(data1byte==0x55) {step_=1, check_all_recieve=0;}
        break;
 
        case 1:
           if(data1byte==0x55) { step_=2;  SCnt=0;}
           else step_=0;
        break;
 
        case 2:
           SBuf[SCnt++= (unsigned char)data1byte;
           if(SCnt==8)  // roll(2byte),pitch(2byte),yaw(2byte),checksum(2byte) 
             {   
                step_=0;
                SCnt=0;
                check_all_recieve = 1;
             }
        break;
 
        default:
        break;
     }
   
    return check_all_recieve;
}
 
static int trans_data_to_degree(unsigned char *sdata)  // sdata : roll(2)+pitch(2)+yaw(2)+chk(2)
{
  int n;
  unsigned short chk=0;
 
  ///////////// checksum /////////////////
  chk=0x55+0x55;
  for(n=0;n<6;n++) chk+=sdata[n]; 
  if(chk != get_data_word(&sdata[6])) 
  {
    Serial.println("checksum error!");
    return 0//   
  }
  ////////////////////////////////////////
 
  DegRoll  = get_data_word(&sdata[0]) / 100.;
  DegPitch = get_data_word(&sdata[2]) / 100. * -1;
  DegYaw   = get_data_word(&sdata[4]) / 100.;
 
  return 1;
}
 
static signed short get_data_word(unsigned char *dat)
{
  // little endian..
  data_word.byte[0]=dat[1];  
  data_word.byte[1]=dat[0];  
 
  return data_word.value;
}
 
//--------------------------------------------------------------------------------//
//각도 값을 받아서 PID제어값 출력
double roll_pid(double setpoint, double degree)
{
    double val_out;
    static double roll_p_err_prv, roll_p_err, roll_i_err, roll_d_err;
 
    roll_p_err = setpoint-degree;
    roll_i_err += roll_p_err;
    roll_d_err = roll_p_err - roll_p_err_prv;
    
    roll_p_err_prv = roll_p_err;
    val_out = (roll_Kp*roll_p_err) + (roll_Ki*roll_i_err) + (roll_Kd*roll_d_err);
    
    Serial.print((roll_Kp* roll_p_err)); Serial.print(", ");Serial.print((roll_Ki* roll_i_err)); Serial.print(", ");Serial.print((roll_Kd* roll_d_err));Serial.print(", ");Serial.print(val_out); 
    return val_out;
}
 
double pitch_pid(double setpoint, double degree)
{
    double val_out;
    static double pitch_p_err_prv, pitch_p_err, pitch_i_err, pitch_d_err;
 
    pitch_p_err = setpoint-degree;
    pitch_i_err += pitch_p_err;
    pitch_d_err = pitch_p_err - pitch_p_err_prv;
    
    pitch_p_err_prv = pitch_p_err;
    val_out = (pitch_Kp*pitch_p_err) + (pitch_Ki*pitch_i_err) + (pitch_Kd*pitch_d_err);
    
    //Serial.print((pitch_Kp* pitch_p_err)); Serial.print(", ");Serial.print((pitch_Ki* pitch_i_err)); Serial.print(", ");Serial.print((pitch_Kd* pitch_d_err));Serial.print(", ");Serial.print(val_out); 
    return val_out;
}
 
double yaw_pid(double setpoint, double degree)
{
    double val_out;
    static double yaw_p_err_prv, yaw_p_err, yaw_i_err, yaw_d_err;
 
    yaw_p_err = setpoint-degree;
    yaw_i_err += yaw_p_err;
    yaw_d_err = yaw_p_err - yaw_p_err_prv;
    
    yaw_p_err_prv = yaw_p_err;
    val_out = (yaw_Kp*yaw_p_err) + (yaw_Ki*yaw_i_err) + (yaw_Kd*yaw_d_err);
    
    //Serial.print((yaw_Kp*yaw_p_err)); Serial.print(", ");Serial.print((yaw_Ki*yaw_i_err)); Serial.print(", ");Serial.print((yaw_Kd*yaw_d_err));Serial.print(", ");Serial.print(val_out); 
    return val_out;
}
//------------------------------------------------------------------------
//제어값을 받어서 모터 구동
void run_motors(int throttle, int rollOffset, int pitchOffset, int yawOffset)
{
  int motor1Power, motor3Power; // Motors on the X axis
  //=>; changing their speeds will affect the pitch
  int motor2Power, motor4Power; // Motors on the Y axis
  //=>; changing their speeds will affect the roll
 
  motor1Power = throttle + pitchOffset - yawOffset;
  motor2Power = throttle + rollOffset + yawOffset;
  motor3Power = throttle - pitchOffset  - yawOffset;
  motor4Power = throttle - rollOffset + yawOffset;
  
  limit_max_min(motor1Power);
  limit_max_min(motor2Power);
  limit_max_min(motor3Power);
  limit_max_min(motor4Power);
 
  motor1.write(motor1Power);motor3.write(motor3Power);
  motor2.write(motor2Power);motor4.write(motor4Power);
 
  //Serial.print(", ");Serial.print(motor1Power);Serial.print(", ");Serial.print(motor3Power);
  Serial.print(", ");Serial.print(motor2Power);Serial.print(", ");Serial.print(motor4Power);
}
 
void limit_max_min(int pwm)
{
  if(pwm>MAX_PWM)
  pwm = MAX_PWM;
  else if(pwm<MIN_PWM)
  pwm = MIN_PWM;
}
//------------------------------------------------------------------------------//
//pid 계수의 값을 바꾼다.
void modify_pid_val(void)
{
   if(Serial.available()){
    
    char c = Serial.read();
    //hover debuging
    if(c=='1'){
      hover += 1;
      Serial.print("hover = ");Serial.println(hover);
    }else if(c=='2'){
      hover -= 1;
      Serial.print("hover = ");Serial.println(hover);
    }else if(c=='3'){
      hover= INIThover;
      Serial.print("hover = ");Serial.println(hover);
    }else if(c=='4'){
      hover= MINhover;
      Serial.print("hover = ");Serial.println(hover);
    }
    
    
    //roll debuging
    else if(c=='q'){
      roll_Kp += 0.01;
      Serial.print("roll_Kp = ");Serial.println(roll_Kp);
    }else if(c=='w'){
      roll_Kp -= 0.01;
      Serial.print("roll_Kp = ");Serial.println(roll_Kp);
    }else if(c=='e'){
      roll_Kp= INITROLLKp;
      Serial.print("roll_Kp = ");Serial.println(roll_Kp);
    }else if(c=='a'){
      roll_Ki += 0.000001;
      Serial.print("roll_Ki = ");Serial.println(roll_Ki*10000);
    }else if(c=='s'){
      roll_Ki -= 0.000001;
      Serial.print("roll_Ki = ");Serial.println(roll_Ki*10000);
    }else if(c=='d'){
      roll_Ki = INITROLLKi;
      Serial.print("roll_Ki = ");Serial.println(roll_Ki*10000);
    }else if(c=='z'){
      roll_Kd += 1;
      Serial.print("roll_Kd = ");Serial.println(roll_Kd);
    }else if(c=='x'){
      roll_Kd -= 1;
      Serial.print("roll_Kd = ");Serial.println(roll_Kd);
    }else if(c=='c'){
      roll_Kd = INITROLLKd;
      Serial.print("roll_Kd = ");Serial.println(roll_Kd);
    }
    
    
    
    //pitch debuging
    else if(c=='r'){
      pitch_Kp += 0.01;
      Serial.print("pitch_Kp = ");Serial.println(pitch_Kp);
    }else if(c=='t'){
      pitch_Kp -= 0.01;
      Serial.print("pitch_Kp = ");Serial.println(pitch_Kp);
    }else if(c=='y'){
      pitch_Kp= INITPITCHKp;
      Serial.print("pitch_Kp = ");Serial.println(pitch_Kp);
    }else if(c=='f'){
      pitch_Ki += 0.000001;
      Serial.print("pitch_Ki = ");Serial.println(pitch_Ki*10000);
    }else if(c=='g'){
      pitch_Ki -= 0.000001;
      Serial.print("pitch_Ki = ");Serial.println(pitch_Ki*10000);
    }else if(c=='h'){
      pitch_Ki = INITPITCHKi;
      Serial.print("pitch_Ki = ");Serial.println(pitch_Ki*10000);
    }else if(c=='v'){
      pitch_Kd += 1;
      Serial.print("pitch_Kd = ");Serial.println(pitch_Kd);
    }else if(c=='b'){
      pitch_Kd -= 1;
      Serial.print("pitch_Kd = ");Serial.println(pitch_Kd);
    }else if(c=='n'){
      pitch_Kd = INITPITCHKd;
      Serial.print("pitch_Kd = ");Serial.println(pitch_Kd);
    }
 
    //yaw debuging
    else if(c=='u'){
      yaw_Kp += 0.01;
      Serial.print("yaw_Kp = ");Serial.println(yaw_Kp);
    }else if(c=='i'){
      yaw_Kp -= 0.01;
      Serial.print("yaw_Kp = ");Serial.println(yaw_Kp);
    }else if(c=='o'){
      yaw_Kp= INITYAWKp;
      Serial.print("yaw_Kp = ");Serial.println(yaw_Kp);
    }else if(c=='j'){
      yaw_Ki += 0.000001;
      Serial.print("yaw_Ki = ");Serial.println(yaw_Ki*10000);
    }else if(c=='k'){
      yaw_Ki -= 0.000001;
      Serial.print("yaw_Ki = ");Serial.println(yaw_Ki*10000);
    }else if(c=='l'){
      yaw_Ki = INITYAWKi;
      Serial.print("yaw_Ki = ");Serial.println(yaw_Ki*10000);
    }else if(c=='m'){
      yaw_Kd += 1;
      Serial.print("yaw_Kd = ");Serial.println(yaw_Kd);
    }else if(c==','){
      yaw_Kd -= 1;
      Serial.print("yaw_Kd = ");Serial.println(yaw_Kd);
    }else if(c=='.'){
      yaw_Kd = INITYAWKd;
      Serial.print("yaw_Kd = ");Serial.println(yaw_Kd);
    }
    
    
  } 
}
 
//---------------------------------------------------------------------//
//
//                                main
//
//--------------------------------------------------------------------//
void setup() {
  Serial.begin(115200); 
  SensorSerial.begin(57600); 
  callibration();
}
 
void loop() {
 
  
  if(SensorSerial.available()){
   if(recieve_data()==1)  //roll(2byte),pitch(2byte),yaw(2byte),checksum(2byte) 모든 데이터 받았음
    {   
     if(trans_data_to_degree(SBuf)==1//센서값을 읽어서 roll,pitch,yaw 값을 알아낸다. 
     {
      if(initial == 0){
      yaw_setpoint = DegYaw;
      initial = 1;
      //Serial.println(yaw_setpoint);
      }
 
       Serial.print(DegRoll);Serial.print(", ");
       //Serial.print(DegPitch);Serial.print(", ");
       //Serial.print(DegYaw); Serial.print(", ");
             
       rollControll = roll_pid(roll_setpoint, DegRoll);//각도 값을 받아서 PID제어값 출력
       pitchControll = pitch_pid(pitch_setpoint, DegPitch);
       yawControll = yaw_pid(yaw_setpoint, DegYaw);
    
       run_motors(hover, rollControll, pitchControll, yawControll);//제어값을 받어서 모터 구동
       Serial.print(", hover = ");Serial.print(hover);
       
       Serial.print(", roll_Kp = ");Serial.print(roll_Kp);Serial.print(", roll_Ki = ");Serial.print(roll_Ki*10000);Serial.print(", roll_Kd = ");Serial.println(roll_Kd);
 
       //Serial.print(", pitch_Kp = ");Serial.print(pitch_Kp);Serial.print(", pitch_Ki = ");Serial.print(pitch_Ki*10000);Serial.print(", pitch_Kd = ");Serial.println(pitch_Kd);
 
       //Serial.print(", yaw_Kp = ");Serial.print(yaw_Kp);Serial.print(", yaw_Ki = ");Serial.print(yaw_Ki*10000);Serial.print(", yaw_Kd = ");Serial.println(yaw_Kd);
      }
    } 
  }
 
 
    modify_pid_val();
}
 
 
 
cs


'작품 > 쿼드콥터' 카테고리의 다른 글

무선 조종기와 카메라 테스트  (0) 2016.02.08
롤 제어  (0) 2016.02.08
조립 후 테스트  (0) 2016.02.08
하드웨어 조립  (0) 2016.02.08
부품 테스트 - 배터리  (0) 2016.02.08
:
Posted by youjin.A
2016. 2. 8. 01:33

조립 후 테스트 작품/쿼드콥터2016. 2. 8. 01:33

아두이노를 넣은 초록색 보드까지 프레임에 장착한 후 모든 모터가 제대로 작동하는 지 테스트 해 보았습니다.

블루투스를 이용하여 각각의 모터를 선택하고 또한 모터의 출력을 높이거나 낮출 수 있도록 하였습니다.



위 동영상의 코드 아래에...

 

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
#include <SoftwareSerial.h>
 
#define T 20000
#define MOTORNUM 4
 
//PWM : OC0A, OC0B, 
 
//pinNumber:5 , digitalPinNumber:3 , OC2B
//pinNumber:11 , digitalPinNumber:5 , OC0B
//pinNumber:15 , digitalPinNumber:9 , OC1A
//pinNumber:16 , digitalPinNumber:10 , OC2A
 
SoftwareSerial mySerial(13,11);//Rx, Tx 
 
int sig = 140, count = 0;
int ESC[MOTORNUM] = {59103};
char c;
int emergency=0;
int motor_set = 0;
 
void BLDCcont(int object,int val)
{
  digitalWrite(object, HIGH);
  delayMicroseconds(val);
  digitalWrite(object, LOW);
  delayMicroseconds(T-val);
}
 
void BLDCall(int val)
{
  /*
  digitalWrite(ESC[1], HIGH);
  delayMicroseconds(val);
  digitalWrite(ESC[1], LOW);
  digitalWrite(ESC[2], HIGH);
  delayMicroseconds(val);
  digitalWrite(ESC[2], LOW);
  digitalWrite(ESC[0], HIGH);
  delayMicroseconds(val);
  digitalWrite(ESC[0], LOW);
  
  digitalWrite(ESC[3], HIGH);
  delayMicroseconds(val);
  digitalWrite(ESC[3], LOW);
   
  delayMicroseconds(T-(val*4));
  */
 
 
}
  
void setup()  
{
  int i;
  
  for(i=0; i<MOTORNUM; i++)
    pinMode(ESC[i], OUTPUT);
  
  mySerial.begin(115200);//115200 not work
  Serial.begin(115200);
   mySerial.println(sig);
 
 TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);
 TCCR0B = _BV(CS01)|_BV(CS00);
 
}
 
void loop() 
{
  if (mySerial.available()){
    
    //read
    c = mySerial.read();
    Serial.println(c);
 
    //motor set?
    if(isdigit(c)){
      motor_set=c-'0';
      sig = 140;
    }
    else{//PWM set?
      if(c == 'u'){
       emergency = 0;
       sig +=10;
       if(sig>180)
          sig = 180;
       mySerial.println(sig);
      }
      else if(c == 'd'){
       emergency = 0;
       sig -=10;
       if(sig<140)
          sig = 140;
        mySerial.println(sig);
      }
      else if(c == 'e'){
       emergency = 1;
      }
    }
  
  }
 
  //emergency
  if(emergency == 1){
    count++;
    if(count == 20){
    sig-=10;
    if(sig<140){
        sig = 140;
        emergency=0;
    }
    mySerial.println(sig);
    count=0;
    }
  }
 
  //output
  if(motor_set == 0)
   analogWrite(ESC[0], sig);
  if(motor_set == 1)
    analogWrite(ESC[1], sig);
  if(motor_set == 2)
   analogWrite(ESC[2], sig);
  if(motor_set == 3)
   analogWrite(ESC[3], sig);
  if(motor_set == 4){
  analogWrite(ESC[0], sig);
  analogWrite(ESC[1], sig);
  analogWrite(ESC[2], sig);
  analogWrite(ESC[3], sig);}
}
cs

 


모터 4개가 동시에 출력되어도 아무 문제가 없었습니다.

그리하여 이번에는 모터가 회전했을 때 힘이 아래방향으로 밀어내도록 모터의 회전 방향을 조정하였습니다.

코드는 위의 코드를 이용하였습니다.





이번에는 모터4개를 동시에 돌리면서 센서를 동작시킬 때 센서에 Roll, Pitch, Yaw 값이 제대로 나오는 지 확인해 보았습니다.

"SerialChart"라는 프로그램을 이용하여 센서의 값을 그래프로 그려서 테스트해 봤는데 

모터와 센서를 동시에 동작시켜도 잘 동작하는 것을 확인할 수 있었습니다.




위 영상의 코드는 아래에..

 

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
#include <SoftwareSerial.h>
 
 
#define T 20000
#define MOTORNUM 4
 
//PWM : OC0A, OC0B, 
 
//pinNumber:5 , digitalPinNumber:3 , OC2B
//pinNumber:11 , digitalPinNumber:5 , OC0B
//pinNumber:15 , digitalPinNumber:9 , OC1A
//pinNumber:16 , digitalPinNumber:10 , OC2A
 
SoftwareSerial bluetoothSerial(13,11);//Rx, Tx 
SoftwareSerial sensorSerial(2,4);//Rx Tx
 
 
int sig = 140, count = 0;
int ESC[MOTORNUM] = {59103};
char c;
int emergency=0;
int motor_set = 0;
char data[40];
int i = 0;
double  roll, pitch, yaw;
 
void printAll(char* ch)
{
  int n;
  
  for(n=0; n<i; n++){
    Serial.print(ch[n]);
  }
    Serial.println("");
}
 
void trans_ascii_to_num(char * SBuf, double * DegRoll, double * DegPitch, double * DegYaw)
{  
  int value, value2;
  
  value=FindComma(SBuf);
  //Serial.print(value);
  SBuf[value]='\0';
  *DegRoll=atof(SBuf);
        
  value++;
  value2=FindComma(&SBuf[value]);
  SBuf[value+value2]='\0';
  *DegPitch=atof(&SBuf[value]);
    
  value=value+value2+1;
  value2=FindComma(&SBuf[value]);
  SBuf[value+value2]='\0';
  *DegYaw=atof(&SBuf[value]);
 
 Serial.print(*DegRoll); Serial.print(", ");Serial.print(*DegPitch); Serial.print(", ");Serial.println(*DegYaw); 
}
 
int FindComma(char * buf)
{
   int n;
   for(n=0;n<40;n++)
    {
     if(buf[n]==','break;
    }
 
   return n;
}
 
void BLDCcont(int object,int val)
{
  digitalWrite(object, HIGH);
  delayMicroseconds(val);
  digitalWrite(object, LOW);
  delayMicroseconds(T-val);
}
 
void BLDCall(int val)
{
  /*
  digitalWrite(ESC[1], HIGH);
  delayMicroseconds(val);
  digitalWrite(ESC[1], LOW);
  digitalWrite(ESC[2], HIGH);
  delayMicroseconds(val);
  digitalWrite(ESC[2], LOW);
  digitalWrite(ESC[0], HIGH);
  delayMicroseconds(val);
  digitalWrite(ESC[0], LOW);
  
  digitalWrite(ESC[3], HIGH);
  delayMicroseconds(val);
  digitalWrite(ESC[3], LOW);
   
  delayMicroseconds(T-(val*4));
  */
 
 
}
  
void setup()  
{
  int i;
  
  for(i=0; i<MOTORNUM; i++)
    pinMode(ESC[i], OUTPUT);
    
  sensorSerial.begin(57600);//115200 not work
  //bluetoothSerial.begin(115200);
 
  Serial.begin(115200);
  
 //bluetoothSerial.println(sig);
 
 TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);
 TCCR0B = _BV(CS01)|_BV(CS00);
 
}
 
void loop() 
{
  
 
  if(sensorSerial.available()){
   
    data[i]= sensorSerial.read();
    i++;
   
    if(data[i-1== 0x0A)
      data[i-1= ',';
    
    if(data[i-1== '*'){
     // printAll(data);
      trans_ascii_to_num(data, &roll, &pitch, &yaw);
      i=0;
    }
  }
 
 
  if (Serial.available()){
   
    //read
    c = Serial.read();
    //Serial.println(c);
 
    //motor set?
    if(isdigit(c)){
      motor_set=c-'0';
      sig = 140;
    }
    else{//PWM set?
      if(c == 'u'){
       emergency = 0;
       sig +=10;
       if(sig>180)
          sig = 180;
       //Serial.println(sig);
      }
      else if(c == 'd'){
       emergency = 0;
       sig -=10;
       if(sig<140)
          sig = 140;
        //Serial.println(sig);
      }
      else if(c == 'e'){
       emergency = 1;
      }
    }
  
  }
 
  //emergency
  if(emergency == 1){
    count++;
    if(count == 20){
    sig-=10;
    if(sig<140){
        sig = 140;
        emergency=0;
    }
    //Serial.println(sig);
    count=0;
    }
  }
 
  //output
  if(motor_set == 0)
   analogWrite(ESC[0], sig);
  if(motor_set == 1)
    analogWrite(ESC[1], sig);
  if(motor_set == 2)
   analogWrite(ESC[2], sig);
  if(motor_set == 3)
   analogWrite(ESC[3], sig);
  if(motor_set == 4){
    analogWrite(ESC[0], sig);
    analogWrite(ESC[1], sig);
    analogWrite(ESC[2], sig);
    analogWrite(ESC[3], sig);
  }
}
cs



 

도중에 같은 코드로 동작을 시켰는 데도 모터의 한 쪽 출력이 이상하게 느려지면서 이상해 지는 경우가 있었습니다.

그 원인은 ESC에 배터리를 한번 연결시켜줬을 때 초기에 ESC에 최대PWM과 최소PWM의 범위를 설정하는 단계가 있었는데

저희가 그걸 모르고 그냥 건너 뛴거였죠..

그 단계를 ESC callibration이라고 하는데 callibration을 위한 코드는 아래의 코드를 이용했습니다.

 

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
#include <Servo.h>
 
#define MAX_THROTTLE 179
#define MIN_THROTTLE 0
#define MOTOR0 5
#define MOTOR1 3
#define MOTOR2 9
#define MOTOR3 10
 
Servo motor0;
Servo motor1;
Servo motor2;
Servo motor3;
 
int mspeed;
 
void setup() {
  mspeed = 0;
  
  Serial.begin(115200);
  Serial.println("Program begin...");
  //Serial.println("This program will calibrate the ESC.");
 
  motor0.attach(MOTOR0);
  motor1.attach(MOTOR1);
  motor2.attach(MOTOR2);
  motor3.attach(MOTOR3);
 
  Serial.println("CAUTION!:If YOU STILL CONNECTED BATTERY, NEVER CHOOSE SAY YES!");
  Serial.print("Calibrate ESC? 'y' or 'n'");
  
  while (!Serial.available());
  char cali = Serial.read();
  
  if(cali == 'y'){
    Serial.println("Now writing maximum output.");
    Serial.println("Turn on power source, then wait 2 seconds and press any key.");
    motor0.write(MAX_THROTTLE);
    motor1.write(MAX_THROTTLE);
    motor2.write(MAX_THROTTLE);
    motor3.write(MAX_THROTTLE);
 
    // Wait for input
    while (!Serial.available());
    //Serial.read();
 
    // Send min output
    Serial.println("Sending minimum output");
    motor0.write(MIN_THROTTLE);
    motor1.write(MIN_THROTTLE);
    motor2.write(MIN_THROTTLE);
    motor3.write(MIN_THROTTLE);
 
    Serial.println("When beep on the ESC, Sned any data");
    // Wait for input
    while (!Serial.available());
    //Serial.read();
 
    Serial.println("Finish calibrating the ESC");
  }else {
    Serial.println("Program keep going");
  }
}
 
void loop() { 
  Serial.println(mspeed);
  
  if(Serial.available()){
    char c = Serial.read();
    if(c=='u'){
      mspeed += 1;
      motor0.write(mspeed); motor1.write(mspeed); motor2.write(mspeed); motor3.write(mspeed);
    }else if(c=='d'){
      mspeed -= 1;
      motor0.write(mspeed); motor1.write(mspeed); motor2.write(mspeed); motor3.write(mspeed);
    }else if(c=='e'){
      mspeed = 0;
      motor0.write(mspeed); motor1.write(mspeed); motor2.write(mspeed); motor3.write(mspeed);
    }
  }
}
cs





참고

-아두이노 PWM 제어 레지스터

https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM


-ATMEGA328 DATASHEET

http://www.atmel.com/images/doc8161.pdf


'작품 > 쿼드콥터' 카테고리의 다른 글

롤 제어  (0) 2016.02.08
호버링 제어  (0) 2016.02.08
하드웨어 조립  (0) 2016.02.08
부품 테스트 - 배터리  (0) 2016.02.08
부품테스트 ESC 및 BEC  (0) 2016.02.08
:
Posted by youjin.A
2016. 2. 8. 01:32

하드웨어 조립 작품/쿼드콥터2016. 2. 8. 01:32


멀티콥터 조립 자료.pdf


하드웨어에서 프레임은 설명서를 보고 조립을 하였습니다.


   


   


   

프레임을 다 조립한 후에 컨트롤러인 아두이노를 포함하여 센서와 블루투스가 장착되어 있는 보드를 만들었습니다.


 

'작품 > 쿼드콥터' 카테고리의 다른 글

호버링 제어  (0) 2016.02.08
조립 후 테스트  (0) 2016.02.08
부품 테스트 - 배터리  (0) 2016.02.08
부품테스트 ESC 및 BEC  (0) 2016.02.08
부품 테스트 - 센서  (0) 2016.02.08
:
Posted by youjin.A
2016. 2. 8. 01:29

부품 테스트 - 배터리 작품/쿼드콥터2016. 2. 8. 01:29

배터리는 11.1V, 4500mAh, 30~60C 리튬 폴리머 배터리를 씁니다.

 


전원 부분에 커넥터를 납땜하려고 하다가 실수로 아주 잠깐 쇼트가 났는 데..

그 후로는 계속 0V가 떴습니다. 

10만원 짜리라 어떻게든 살리기 위해서 내부를 살펴보았습니다.


 


살펴보니 쇼트 때문에 내부에 퓨즈가 끊켜 있더군요.

그 부분을 연결해주니 배터리가 잘 작동하였습니다.

'작품 > 쿼드콥터' 카테고리의 다른 글

조립 후 테스트  (0) 2016.02.08
하드웨어 조립  (0) 2016.02.08
부품테스트 ESC 및 BEC  (0) 2016.02.08
부품 테스트 - 센서  (0) 2016.02.08
부품 주문  (0) 2016.02.08
:
Posted by youjin.A
2016. 2. 8. 01:25

부품테스트 ESC 및 BEC 작품/쿼드콥터2016. 2. 8. 01:25

변속기 모델은 iPeaka 22A ESC 입니다.


변속기는 아래와 같이 모터에 전력을 공급해주기 위해서 쓰는 부품입니다.

아두이노의 신호로는 모터를 돌릴 에너지가 없기 때문에 변속기(ESC)에 배터리를 연결하여 아두이노는 오직 신호로만 사용하고 

외부 배터리의 에너지로 모터를 돌리는 겁니다. 



위 그림처럼 아두이노, ESC, 배터리, 모터를 연결하고 조종을 위해서 블루투스를 연결하여 ESC 테스트를 해 보았습니다.


 


위 동영상의 코드는 아래와 같습니다.


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
#include <SoftwareSerial.h>
 
#define T 20000
 
SoftwareSerial mySerial(13,11);//Rx, Tx 
 
int sig = 1100, count = 0;
int ESC = 5;
char c;
int emergency=0;
 
 
void setup()  
{
  pinMode(ESC, OUTPUT);
  mySerial.begin(115200);//115200 not work
  Serial.begin(115200);
   mySerial.println(sig);
}
 
void loop() 
{
  if (mySerial.available()){
    
    //read
    c = mySerial.read();
    Serial.println(c);
 
    //case
    if(c == 'u'){
      emergency = 0;
      sig +=50;
      if(sig>1700)
         sig = 1700;
      mySerial.println(sig);
    }
    else if(c == 'd'){
      emergency = 0;
      sig -=50;
      if(sig<1100)
        sig = 1100;
      mySerial.println(sig);
    }
    else if(c == 'e'){
      emergency = 1;
    }
  
  }
 
  //emergency
  if(emergency == 1){
    count++;
    if(count == 20){
    sig-=50;
    if(sig<1100){
        sig = 1100;
        emergency=0;
    }
    mySerial.println(sig);
    count=0;
    }
  }
 
  //output
  digitalWrite(ESC, HIGH);
  delayMicroseconds(sig);
  digitalWrite(ESC, LOW);
  delayMicroseconds(T); 
}
 

cs

 



BEC는 아두이노에 안정적으로 전원을 공급하기 위하여 사용하는 장치입니다.


 


아래 그림에서 RECEIVER를 아두이노라고 생각하고 연결하면 됩니다.

그러면 11.1V의 리튬 폴리머 배터리를 연결하면 BEC를 통해 아두이노에 5V가 공급됩니다.  



BEC에 11.1V를 공급했을 때 5V가 나오는지 테스트 해 보았습니다.


 








참고 사이트

ESC 사용 방법 코드

http://wjs890204.tistory.com/670

 


'작품 > 쿼드콥터' 카테고리의 다른 글

조립 후 테스트  (0) 2016.02.08
하드웨어 조립  (0) 2016.02.08
부품 테스트 - 배터리  (0) 2016.02.08
부품 테스트 - 센서  (0) 2016.02.08
부품 주문  (0) 2016.02.08
:
Posted by youjin.A
2016. 2. 8. 01:20

부품 테스트 - 센서 작품/쿼드콥터2016. 2. 8. 01:20


센서는 다음 모델을 썼습니다. 

EBIMU-9DOFV2


간단하게 출력 테스트를 해봤는데요. EBIMU-9DOFV2는 roll, pitch, yaw 데이터를 문자열로 줍니다.

센서를 아두이노와 연결하여 데이터가 나오는지 확인해 보았습니다.


    


위 영상의 코드는 아래와 같습니다.

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
#include "SoftwareSerial.h"
 
#define SIZEOFSIGN 4
#define DATANUMBER 22
#define ROLL 0
#define PITCH 1
#define YAW 2
#define STARTBITNUM 2
 
SoftwareSerial mySerial(2,3);//Rx Tx
 
int s = 0, d = 0, data_ok = 0;
int start_bits[STARTBITNUM], data_bits[DATANUMBER*2];
char data;
int i = 0;
 
void setup() {
  Serial.begin(115200);
  mySerial.begin(57600);
}
 
void loop() {
  if(mySerial.available()){
    data= mySerial.read();
    Serial.print(data);
  }
 
}
cs

 



다음으로 제대로된 값이 나오는 지 확인하기 위해서 

센서의 출력을 "SerialChart"라는 프로그램을 이용하여 그래프로 나타내어 보았습니다.

그러기 위해서는 문자열로 된 데이터를 roll, pitch, yaw 별로 숫자로 변환해 주어야 했습니다.

    


위 코드의 영상은 아래와 같습니다.


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
#include "SoftwareSerial.h"
 
SoftwareSerial mySerial(2,4);//Rx Tx
 
char data[40];
int i = 0;
double  roll, pitch, yaw;
 
void printAll(char* ch)
{
  int n;
  
  for(n=0; n<i; n++){
    Serial.print(ch[n]);
  }
    Serial.println("");
}
 
void trans_ascii_to_num(char * SBuf, double * DegRoll, double * DegPitch, double * DegYaw)
{  
  int value, value2;
  
  value=FindComma(SBuf);
  //Serial.print(value);
  SBuf[value]='\0';
  *DegRoll=atof(SBuf);
        
  value++;
  value2=FindComma(&SBuf[value]);
  SBuf[value+value2]='\0';
  *DegPitch=atof(&SBuf[value]);
    
  value=value+value2+1;
  value2=FindComma(&SBuf[value]);
  SBuf[value+value2]='\0';
  *DegYaw=atof(&SBuf[value]);
 
 Serial.print(*DegRoll); Serial.print(", ");Serial.print(*DegPitch); Serial.print(", ");Serial.println(*DegYaw); 
}
 
int FindComma(char * buf)
{
   int n;
   for(n=0;n<40;n++)
    {
     if(buf[n]==','break;
    }
 
   return n;
}
 
void setup() {
  Serial.begin(115200);
  mySerial.begin(57600);
}
 
void loop() {
  
  if(mySerial.available()){
    data[i]= mySerial.read();
    i++;
   
    if(data[i-1== 0x0A)
      data[i-1= ',';
    
    if(data[i-1== '*'){
     // printAll(data);
      trans_ascii_to_num(data, &roll, &pitch, &yaw);
      i=0;
    }
  }
 
}
cs

'작품 > 쿼드콥터' 카테고리의 다른 글

조립 후 테스트  (0) 2016.02.08
하드웨어 조립  (0) 2016.02.08
부품 테스트 - 배터리  (0) 2016.02.08
부품테스트 ESC 및 BEC  (0) 2016.02.08
부품 주문  (0) 2016.02.08
:
Posted by youjin.A
2016. 2. 8. 01:13

부품 주문 작품/쿼드콥터2016. 2. 8. 01:13


'작품 > 쿼드콥터' 카테고리의 다른 글

조립 후 테스트  (0) 2016.02.08
하드웨어 조립  (0) 2016.02.08
부품 테스트 - 배터리  (0) 2016.02.08
부품테스트 ESC 및 BEC  (0) 2016.02.08
부품 테스트 - 센서  (0) 2016.02.08
:
Posted by youjin.A
2016. 2. 8. 00:51

링크 작품/A.I2016. 2. 8. 00:51

STT

https://wolfpaulus.com/journal/embedded/raspberrypi2-sr/

https://groups.google.com/forum/#!topic/jasper-support-forum/k9Xh6WkFEYM

https://wit.ai/docs/raspberry-pi/examples

http://www.sitepoint.com/five-simple-ways-to-build-artificial-intelligence-in-2016/

jesper

http://jasperproject.github.io/documentation/installation/

https://groups.google.com/forum/#!topic/jasper-support-forum/k9Xh6WkFEYM



리눅스 자동 대답 프로그램

http://cookingwithlinux.com/node/18

http://www.alicebot.org/aiml.html

https://code.google.com/archive/p/pycleverbot/downloads


한글TTS

http://rsmang.com/63


reading program

http://www.makeuseof.com/tag/4-of-the-best-ebook-readers-for-linux-users/

http://xmodulo.com/good-epub-reader-linux.html

(한국어) http://linux.softpedia.com/blog/calibre-2-39-ebook-reader-and-converter-supports-the-latest-kobo-firmware-492724.shtml


http://www.icbanq.com/pbloger/board_View.aspx?number=514&boardNum=&search=content&search_text=tts&page=1



http://blog.daum.net/_blog/BlogTypeView.do?blogid=0K6Pu&articleno=6271130&_bloghome_menu=recenttext


http://www.icbanq.com/pbloger/board_View.aspx?number=667&boardNum=&search=content&search_text=tts&page=1

'작품 > A.I' 카테고리의 다른 글

녹음  (0) 2016.07.01
A.I 소스  (0) 2016.02.12
마이크 녹음 하기  (0) 2016.02.12
test to speech  (0) 2016.02.12
google speech to text  (0) 2016.02.10
:
Posted by youjin.A

1. 과제명: 인터넷 Checksum 함수의 구현

2. 제출기한: 2015년 11월 18일(수)

3. 제출방법: on-line 제출

4. 내용:

 

인터넷 Checksum 계산과 검사를 위한 함수를 C로 구현하라. 구현하는 함수는 아래 내용을 참고하고, 함수의 이름이나 넘겨받는 메시지의 유형은 필요에 따라 다르게 정의하여도 된다.

 

(1) Checksum 계산과 검사를 위한 루틴에 대한 flow chart를 작성하라.

(구현은 교재 p.280의 Figure 10.17 인터넷 Checksum 알고리즘을 참고할 것.)

-Checksum계산

 

-Checksum 검사

 

  

(2) 아래의 함수를 완성하라.

 

int calculation_Checksum(message)

int *message;

{

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int calculaton_Checksum(int* message)
{
    /* 임의의 길이를 갖는 메시지를 넘겨받아 Checksum을 계산하여 return한다.*/
    int Checksum;
    int sum = 0, pre_sum = 0;
 
    for (int n = 0; n < data_num; n++)
    {
        sum += message[n];
        if (pre_sum > sum)
            sum++;
        pre_sum = sum;
    }
 
    Checksum = ~sum;
 
    message[data_num] = Checksum;
    data_num++;
 
    return Checksum;
}
cs

}

 

int check_Checksum(message)

int *message;

{

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int check_Checksum(int* message)
{
    /* Checksum이 부착된 임의의 메시지를 넘겨받아, 에러가 검출되면 0, 아니면 1을 return한다. */
    int result = 0;
    int sum = 0, pre_sum = 0;
 
    for (int n = 0; n < data_num; n++)
    {
        sum += message[n];
        if ((unsigned int)pre_sum >(unsigned int)sum)
            sum++;
        (int)pre_sum = (int)sum;
    }
 
    result = ~sum;
 
    if (result == 0)
        return 1;
    else
        return 0;
}
 
cs

}

 

(3) 완성된 함수 calculation_Checksum()와 check_Checksum()를 동작을 검증할 수 있는 테스트 프로그램을 작성하고 시험하라.

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
#include <stdio.h>
#define MAXNUM 100
 
int data_num;
 
void sending_message(int* message)
{
    printf("데이터의 갯수를 입력하시오.");
    scanf_s("%d"&data_num);
    if (data_num >= MAXNUM)
    {
        printf(" 최대 가능한 데이터 갯수를 초과하였습니다.\n 프로그램 종료.\n");
        exit(-1);
    }
 
 
    printf("데이터를 입력하시오.\n");
    for (int i = 0; i < data_num; i++)
    {
        scanf_s("%d"&message[i]);
    }
    printf("데이터 입력이 끝났습니다.\n\n");
 
}
 
int calculaton_Checksum(int* message)
{
    /* 임의의 길이를 갖는 메시지를 넘겨받아 Checksum을 계산하여 return한다.*/
    int Checksum;
    int sum = 0, pre_sum = 0;
 
    for (int n = 0; n < data_num; n++)
    {
        sum += message[n];
        if (pre_sum > sum)
            sum++;
        pre_sum = sum;
    }
 
    Checksum = ~sum;
 
    message[data_num] = Checksum;
    data_num++;
 
    return Checksum;
}
 
int check_Checksum(int* message)
{
    /* Checksum이 부착된 임의의 메시지를 넘겨받아, 에러가 검출되면 0, 아니면 1을 return한다. */
    int result = 0;
    int sum = 0, pre_sum = 0;
 
    for (int n = 0; n < data_num; n++)
    {
        sum += message[n];
        if ((unsigned int)pre_sum >(unsigned int)sum)
            sum++;
        (int)pre_sum = (int)sum;
    }
 
    result = ~sum;
 
    if (result == 0)
        return 1;
    else
        return 0;
}
 
void print(int* message)
{
    printf("message: ");
 
    for (int i = 0; i < data_num; i++)
        printf("%d ", message[i]);
    printf("\n");
}
 
int main(void)
{
    int mes[MAXNUM];
    int Cks;
 
    sending_message(mes);
    printf("sender: \n");
    print(mes);
 
    Cks = calculaton_Checksum(mes);
    printf("checksum: %d\n\n", Cks);
 
    if (!check_Checksum(mes))
        printf("Checksum error!!");
    else{
        printf("Receiver: \n");
        print(mes);
    }
    return 0;
}
 
cs



Term Project #2 2013104430 안유진.hwp


 

'프로그래밍 > 자료구조설계' 카테고리의 다른 글

다운  (0) 2016.02.07
void*  (0) 2015.10.23
열거형 enum  (1) 2015.10.23
윈도우에서 리눅스처럼 컴파일하기  (1) 2015.09.19
:
Posted by youjin.A