CAFE

영상처리및제어

[제어] 아두이노 Uno에서 드론(R1-F450) 제작 (수정중)

작성자한창호|작성시간19.01.22|조회수3,733 목록 댓글 0

두번째 드론을 조립해 보자. 기존 제품 중 많이 사용하는 R1-F450 프레임을 이용하여 제작해보자. 소스는 바로 전 소형 드론 소스와 동일하며, 모터부분을 수정했다.


--- 부품 리스트 ---

아두이노 Uno (16MHz)

드론 프레임 (R1-450) - 최강 아두이노 드론 키트 R1-F450 - 올퍼스트에듀   165,000원

MPU-6050 자이로센서

HM-10 블루투스 모듈

모터 - A2212/13T, 1000KV BLDC 모터

배터리 - LiPo (11.1V 2700mAh)

충전기 - iMax B6 LiPro Balance Charger

프로펠러 보호대 및 프로펠러 추가


--- 전체 소스코드 ---

첨부파일 drone_simple_v1.04.zip   - BLDC 모터로 수정, 시리얼통신 checksum 버그 수정 (def.h에서 모델 선택)




1. 드론 조립


1) 바닥판에 ESC (Electronic Speed Controller) 연결


- 납을 듬뿍 묻혀 굵은 검은색/빨간색 전선이 푹 파뭍이도록 납땜을 한다.



2) 모터와 프레임을 조립


- 상판을 조립한다.

- 프로펠러를 연결한다.  (프로펠러는 확실하게 조이지 않으면 이탈하여 프로펠러 혼자 하늘 높이 날아간다.)

- ESC는 꼭 단단하게 끈으로 고정해야 한다. 그럻지 않으면 모터 속도 오류가 발생하기도 한다.


완성된 모습, 하지만 실험 중 프로펠러가 박살난 그림밖에 없어서...




3) 상판위에 쿠션을 깔기


- 쿠션 장치가 없으면 자이로센서 노이즈가 엄청나다. 꼭 필요함.

- 쿠션은 상판에 양면 테이프로 고정하였음. 고무줄은 아두이노 보드 고정하기 위한 장치 (좀 불안함)




4) 아두이노 보드와 회로보드 설치


- 양면 테이프로 붙였다. 그리고 고무줄로 다시 고정 함.



- 회로보드는 ESC 제어보드, MPU-6050 보드, HM-10 블루투스 보드, 아두이노 파워 (5v) 등을 연결한다.

- 다음 그림에서 빨간 부분은 주의해야 한다. 아두이노 보드가 USB 전원을 사용할 경우 노란색선(내부전원사용)은 단락시킨다.




- 회로 배선 구성은 다음과 같다.

- 모터 배선은 3가닥이 나와 있는데 CW는 차례로 연결하고, CCW는 엇갈리게 연결해야 한다.


  모터 CW    빨간색  -  첫번째  ESC              모터 CCW  노란색  -  첫번째 ESC

                검은색  -  두번째                                   검은색  -  두번째 

                노란색  -  세번째                                   빨간색  -  세번째


- 회로 보드 배선도

- 다음 배선도에서 주의할 것은 아두이노 내부전원을 공급하기 위한 전원을 어느것을 사용할 것인가? 이다.


  아두이노 전원 (1) - 컨넥터 (ESC와 5V)를 합선하면 모터의 ESC로부터 전원을 Vin으로 공급하여 아두이노를 구동시킨다.

  아두이노 전원 (2) - 어댑터 연결한다.  이때는 컨넥터 (ESC와 5V) 를 끊는다. (합선 방지)


- 아두이노용 어댑터와 배터리에 연결된 모터(ESC) 전원을 합선시키면 충돌이 난다. 





2. PID 제어 실험 


 (참고 동영상: https://www.youtube.com/watch?v=YNzqTGEl2xQ&feature=youtu.be)

 (PID 동영상: https://www.youtube.com/watch?v=BZzMQTMsXEM)


- PID 제어를 실험하기 위해 그림과 같이 양쪽 방향을 끈으로 묶고 모터는 2개만 동작 시킨다.

- PID 값이 제대로 맞으면 pitch 또는 roll 제어도 정확하게 동작한다.

- PID 값이 잘못될 경우, 회전을 하기도 하고, 마치 줄을 탈출하려고 시도하는 것처럼 보이는데, 상당히 위험하다.

- 기체가 단단하게 조여있지 않으면, 이때 망가지는 많은 경험을 하게 된다.

- MPU-6050도 단단하게 고정한다.

- ESC 제어보드도 단단하게 고정한다.

- 프로펠러도 단단하게 고정한다.



현재까지 조정된 PID 값이며, Trim 값도 5를 주었다. 이륙시 한쪽으로 자꾸 기울어서 조정을 했다.


 static struct {
  float   Kp[3], Ki[3], Kd[3];  // PID 값
  int16_t angleTrim[3];         // Hovering시 영점 조정 (미세조정)
  uint8_t checksum;             // MUST BE ON LAST POSITION OF CONF STRUCTURE!
} conf;


void initParameters()
{

  //       Kp[Pit,Roll,Yaw]       Ki[Pit,Roll,Yaw]          Kd[Pit,Roll,Yaw]    angleTrim[Pit,Roll,Yaw]
  conf = { { 0.41, 0.41, 0.14 }, { 0.0007, 0.0007, 0.0055 }, { 0.06, 0.06, 0 },    { 5,5,0 } };
}



* 이중 PID 사용하기


- 하나의 PID 값만으로 제어하기가 매우 어렵다. 이때는 이중 PID를 이용하면 훨씬 조정하기 쉬워진다. 다음과 같은 방법으로 설정해보자.


LPF 구하기 - LPF를 사용하면 overshooting을 많이 줄일 수 있다. 반응 속도가 느린것 같으면 앞 계수(0.7)를 더 낮춘다.

AccLPF = AccLPF * 0.7  +  Acc 값 * 0.3;

GyroLPF = GyroLPF * 0.98 + Gyro 값 * 0.02;


이중 PID 개요

Perr1 = 조종기 각도 - AccLPF

1차 P값 구하기

Perr2 = 1차 P값 - GyroLPF

2차 P값 구하기


2차 PID로 자이로만 적용한다. 

 1차 PID, 2차 PID 모두 적용

 Trim

Kp1 = 0, Ki1 = 0, Kd1 = 0;   // 1차 PID

Kp2 = 3, Ki2 = 0, Kd2 = 0;   // 2차 PID


이때 드론의 양쪽 날개가 균형을 이루며, 한쪽으로 힘을 주면 반대(원래 위치)로 돌아오려고 한다.

다만, 서서히 각도가 틀어진다.

Kp1 = 2, Ki1 = 0, Kd1 = 0;   // 1차 PID

Kp2 = 3, Ki2 = 0, Kd2 = 0;   // 2차 PID


이때는 양쪽 날개가 평형을 유지하며 위로 날아 오른다. 단, 옆으로 이동 할 수 있다.


 호버링시 한쪽으로 이동하며 위로 올라가는 경우 Trim 값을 조정하여 해결할 수 있다.



3. 소스분석


- 위 소스는 전의 소형 드론 소스와 거의 동일하며, 다만, 모터 제어부분이 다르다.

- 모터 (A2212/ 13T,  1000Kv)

- 모터 캘리브레이션은 사용하지 않아도 제어가 가능하다. 다만, 사용하는 방법은 다음과 같다.


  /*
  * 캘리브레이션 하기
  * (1) 이 소스를 업로드 한다. -> 최대값 180으로 출력함
  * (2) 모터 배터리를 연결한다. -> 삐삐삐 (도레미),  삐 소리 발생
  * (3) 최소값 0을 입력한다. -> 삐삐 -> 삐~~~ (높은음) 소리 발생
  * (4) 캘리브레이션이 완료
  *
  * 모터 속도, value는 PWM high일때의 duty   ___^^^___^^^___
  * write(int value) : value의 범위는 0 ~180
  * writeMicroseconds(int value) : value의 범위는 1000 ~ 2000
  */


void initMotor()
{  
  for(uint8_t i=0; i< NUMBER_MOTOR; i++) esc_motor[i].attach(PWM_PIN[i], 1000, 2000);


  // ESC calibration
  //for(uint8_t i=0; i< NUMBER_MOTOR; i++) esc_motor[i].writeMicroseconds(2000);
  //delay(8000); 


  for(uint8_t i=0; i< NUMBER_MOTOR; i++) esc_motor[i].writeMicroseconds(0); // init
  delay(300); 
}



void writeMotors() // [1000;2000] => [125;250]
{
  int16_t maxMotor,i;

  // -----------------------------------------------------------------------
  // apply to motors
  motor[0] = rcCommand[THROTTLE] - axisPID[PITCH] - axisPID[ROLL] + axisPID[YAW];     //REAR_R
  motor[1] = rcCommand[THROTTLE] + axisPID[PITCH] - axisPID[ROLL] - axisPID[YAW];     //FRONT_R
  motor[2] = rcCommand[THROTTLE] - axisPID[PITCH] + axisPID[ROLL] - axisPID[YAW];     //REAR_L
  motor[3] = rcCommand[THROTTLE] + axisPID[PITCH] + axisPID[ROLL] + axisPID[YAW];     //FRONT_L

  // -----------------------------------------------------------------------
  // normalize the Motors values
  for(i=0; i< NUMBER_MOTOR; i++) if (motor[i]>maxMotor) maxMotor=motor[i];
  for(i=0; i< NUMBER_MOTOR; i++) {
    // 하나의 모터가 최대치를 초과할때, 전체 모터를 초과 크기만큼 전부 내린다.
    if (maxMotor > MAX_THROTTLE) motor[i] -= maxMotor - MAX_THROTTLE;
    motor[i] = constrain(motor[i], MIN_THROTTLE, MAX_THROTTLE);
    // 착륙시 또는 dis-armed 이면 모터를 정지한다.
    if (rcData[THROTTLE] < MIN_RC_CHECK || !fARMED) motor[i] = MINCOMMAND;
  }

  for(i=0; i< NUMBER_MOTOR; i++) esc_motor[i].writeMicroseconds(motor[i]);

}




4. 배터리 충전


- LiPro Balance Charger,  2.7A,  11.1V (3s) 로 설정한 후 Enter키를 1초간 꾹 눌러서 충전 실행한다.

- 충전이 끝나면 (12.6V) 삐삐 소리가 난다고 함.

- Lipo 배터리  2.7A,  11.1V (3s)  - 3개의 셀로 구성 3s x 3.7V = 11.1V
- 과충전(4.2V이상), 과방전(2.7V 이하) 화재발생 가능함. 하나의 셀의 중간 전압이 3.7V 임.

- 4일이상 사용안할 경우 저장모드로 충/방전 해야함




5. 드론 실험


- 이륙시 옆으로 이동하는 경우가 있으니 넓은 장소에서 동작할 필요가 있다.

- 착륙시 조정 미흡으로 다리가 부러졌다. 그래서 아예 떼어 버렸다.

- 날개에 무릅이 맞았더니 피가나서 딱정이가 생겼다. ㅠㅠ, 그래서 날개 보호대(흰색)를 구입하여 달았다.


- LPF를 넣고 이중 PID 방법을 사용하였을 경우 훨씬 쉽게 PID를 구할 수 있었고, 안정적으로 동작하는 것을 확인하였다.

- 따라서 현재 위 소스를 수정하여 이중 PID를 적용해보자.



다음검색
현재 게시글 추가 기능 열기

댓글

댓글 리스트
맨위로

카페 검색

카페 검색어 입력폼