아두이노를 넣은 초록색 보드까지 프레임에 장착한 후 모든 모터가 제대로 작동하는 지 테스트 해 보았습니다.
블루투스를 이용하여 각각의 모터를 선택하고 또한 모터의 출력을 높이거나 낮출 수 있도록 하였습니다.
위 동영상의 코드 아래에...
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] = {5, 9, 10, 3}; 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] = {5, 9, 10, 3}; 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
'작품 > 쿼드콥터' 카테고리의 다른 글
롤 제어 (0) | 2016.02.08 |
---|---|
호버링 제어 (0) | 2016.02.08 |
하드웨어 조립 (0) | 2016.02.08 |
부품 테스트 - 배터리 (0) | 2016.02.08 |
부품테스트 ESC 및 BEC (0) | 2016.02.08 |