تقديم
![]() |
المحرك سيرفو ليس مثل المحرك الخطوي. وبالتالي فهو يقوم بدوران في مجال محدد فقط. من أجل هذا يجب أن تحدد طول الذبذبة الرقمية ليتمكن المحرك من الدوران على راحته. |
![]() |
ما نريد فعله
نريد تحويل محرك عادي إلى محرك يعمل عمل المحرك سيرفو. |
|
الأجزاء الرئيسية
العربية الإنجليزية الفرنسية |
الكمية |
القيمة أو الصيغة |
يمكنك إيضا صناعته بنفسك |
ميكروكنترولور Microcontroller Microcontrôleur |
1 |
بطاقة أردوينو |
|
كنترولور المحرك Motor Controller Contrôleur de moteur |
1 |
أيا كان، مثلا: L298 Compact |
|
محرك عادي DC motor Moteur DC |
1 |
أيا كان |
|
مقاومة متغيرة Potentiometer |
1 |
أيا كانت |
|
صندوق أتراس Gear box |
1 |
أيا كان بشرط أن يكون متلائما مع المحرك |
|
الدارة الكهربائية
بالنسبة للدارة الكهربائية لهذا المشروع فهي سهلة جدا وهي كالآتي: |
|
في حقيقة الأمر، تظهر هذه الدارة طريقة مبسطة للتحكم بأي محرك عادي بتحريكه بسرعة محددة وتدويره نحو زاوية معينة. بالإستعانة بالمقاومة المتغيرة وبالميكروكنترولور أمكننا حينها بجعل المحرك يتحرك خلال 1024موضع في دورة واحدة حيث أن أقل زاوية للدوران هي 0.35درجة. |
البرمجة
للمقاومة المتغيرة 3مرابط اثنين للطاقة والباقي هو مربط الإشارة. باستعمال الدالة analogReadومربط الإشارة يمكننا تحركي المحرك لـ 1024موضعا مختلفا خلال دورة واحدة فقط. يمكن استعمال الشيفرة التالية مع أي محرك DCعادي وتحويله إلى محرك سيرفو.
يمكنك تشغيل البرنامج Arduinoوتحويل الشيفرة التالية إلى بطاقة أردوينو لتبدأ العمل بمحركك كما هو موصوف. يمكنك تحميل الشيفرة التالية من خلال الضغط على الرابط: source.pde |
1 /* 2 3 DIYServo 1.0 4 5 Controller Motor Speed and Movement with Absolute Positioning 6 7 A sketch for turning a standard DC gear motor into a servo 8 using a potentiometer. Can also be used to add finer-grained 9 control over existing servos. 10 11 Control over motor : 12 Speed (PWM) 13 Direction 14 Number of degrees to move (up to 1024) per move 15 How to long to wait between moves 16 17 To get finer control (1024 degrees, instead of 360) of an existing 18 servo, remove the controller and any stop-pins, disconnect the 19 potentiometer wires. Connect power lines from servo motor to a 20 DC motor controller, potentiometer wiper to an input pin on the arduino, 21 and the ouside potentiometer pins to 5v/GND. 22 23 Serial monitor: 24 25 use 'l' to tell the servo to move left 26 use 'r' to tell the servo to move right 27 use 's' to stop the servo 28 use 'g' to go (run the servo) 29 30 31 (c) 2008 C. A. Church - www.dronecolony.com 32 33 7/24/08 - initial version 34 35 */ 36 37 38 39 // USING_CONTROLLER says whether we have to bring an 40 // enable pin high (such as for the Compact L298 controller) 41 // before sending PWM down the LT/RT pins 42 // set this to 0 if you don't need an enable pin 43 44 45 #define USING_CONTROLLER 1 46 47 // enable pin 48 #define MOTOR_EN_PIN 8 49 // right direction pin 50 #define MOTOR_RT_PIN 6 51 // left direction pin 52 #define MOTOR_LT_PIN 9 53 54 55 // READ_AVG is how many readings to average 56 // set it to one less than the actual # 57 // e.g.: 10 readings = set to 9 58 // 59 // the more you average, the more accurate your reading is likely to 60 // be -- too many though, and you'll start missing changes if the motor 61 // is moving quickly 62 63 #define READ_AVG 9 64 65 66 67 // motor speed is from 0-255, test with low values 68 // as not all will move consistently for you 69 70 int motor_speed = 75; 71 72 // how many ms to pause between allowed movements 73 74 int motor_pause_tm = 1000; 75 76 // how many 'degrees' (absolute differences between 77 // potentiometer readings) to move before pausing 78 79 int motor_move_deg = 5; 80 81 // a counter for how many degrees we have moved 82 83 int move_deg_cnt = 0; 84 85 // setting to a default value 86 87 int motor_cur_pin = MOTOR_RT_PIN; 88 89 // control indicators 90 bool motor_started = false; 91 bool motor_paused = false; 92 bool first_run = true; 93 bool motor_run = false; 94 95 long paused_tm; 96 97 98 // our current and previous potentiometer readings 99 100 int cur_reading = 0; 101 int pre_reading = 0; 102 103 int steps = 0; 104 105 // our current readings array, and our previous average readings array 106 107 int vals[READ_AVG + 1]; 108 int prev_posts[2] = { 0, 0 }; 109 110 111 112 void setup() { 113 114 Serial.begin(19200); 115 Serial.println("Ready"); 116 117 memset( (char *)vals, 0, sizeof(int) * (READ_AVG + 1) ); 118 119 // set motor control pins 120 121 if( USING_CONTROLLER ) 122 digitalWrite(MOTOR_EN_PIN, HIGH); 123 124 digitalWrite(MOTOR_LT_PIN, LOW); 125 digitalWrite(MOTOR_RT_PIN, LOW); 126 127 } 128 129 void loop() { 130 131 // see if any input has come in the serial port 132 133 check_input(); 134 135 // figure out how many degrees we've moved (if at all) 136 137 move_deg_cnt = move_deg_cnt + read_pot(); 138 139 if( motor_run == true ) { 140 // if the motor is supposed to be running 141 142 // the following check is to prevent attempting to rotate all the 143 // way around on a potentiometer that has a stop. If yours doesn't 144 // have a stop in it, ou can remove this check 145 146 if( (motor_cur_pin == MOTOR_RT_PIN && prev_posts[1] >= 1020 ) || 147 ( motor_cur_pin == MOTOR_LT_PIN && prev_posts[1] <= 3 ) ) { 148 149 // we've reached our maximum point (don't want to harm our 150 // potentiometer 151 152 motor_run = false; 153 motor_started = false; 154 motor_paused = false; 155 156 // bring pin low 157 158 digitalWrite(motor_cur_pin, LOW); 159 160 // print status 161 162 Serial.println("Have Reached Edge of Movement"); 163 } 164 else if( motor_started == false ) { 165 // the motor is supposed to be running, but we haven't started 166 // it yet 167 168 // PWM output 169 170 analogWrite(motor_cur_pin, motor_speed); 171 172 // set status values 173 174 motor_started = true; 175 motor_paused = false; 176 first_run = true; 177 } 178 else if( move_deg_cnt >= motor_move_deg && motor_paused == false && first_run == false) { 179 180 // we've gone our specific # of degrees, pause by stopping the 181 // motor 182 183 Serial.println("Pausing"); 184 185 digitalWrite(motor_cur_pin, LOW); 186 motor_paused = true; 187 188 // record when we started our pause (so we know when to stop) 189 190 paused_tm = millis(); 191 } 192 else if( motor_paused == true && (millis() - paused_tm) > motor_pause_tm ) { 193 194 // if enough time has passed to stop pausing 195 196 Serial.println("Unpausing"); 197 motor_paused = false; 198 paused_tm = millis(); 199 200 // set move_deg_cnt to zero when re-starting to avoid any 201 // jitter while paused 202 203 move_deg_cnt = 0; 204 205 // generate PWM 206 analogWrite(motor_cur_pin, motor_speed); 207 208 } 209 } 210 211 } 212 213 int read_pot() { 214 215 //read the voltage on the potentiometer: 216 cur_reading = analogRead(0); 217 int diff = 0; 218 219 220 // we're going to average the last READ_AVG reads 221 // put in a value for our current step 222 223 vals[steps] = cur_reading; 224 225 // if we've saved enough values to go ahead and perform an average... 226 227 if( steps == READ_AVG ) { 228 229 // reset our read counter 230 231 steps = -1; 232 233 // determine the average value read 234 // -- this is mostly to deal with big jitter 235 236 int tot = 0; 237 int avg = 0; 238 239 // sum up totals 240 241 for (int i = 0; i <= READ_AVG; i++) 242 tot += vals[i]; 243 244 245 avg = tot / READ_AVG + 1; 246 247 // ignore current reading if it was either of our last two readings 248 // avoid bouncing back and forth between two readings (slight voltage 249 // variation in the same range) 250 251 if( avg == prev_posts[0] || avg == prev_posts[1] ) { 252 return(0); 253 } 254 255 // determine the absolute difference between the current average 256 // and the previous average 257 258 diff = avg > prev_posts[1] ? avg - prev_posts[1] : prev_posts[1] - avg; 259 260 261 // if there's a difference between the averages 262 263 if( diff > 0 ) { 264 265 // print our new reading 266 267 Serial.println(avg, DEC); 268 269 // move our last reading back, and put our current reading in 270 // our array to track the last two positions 271 272 prev_posts[0] = prev_posts[1]; 273 prev_posts[1] = avg; 274 275 // update this so the pause check knows that we have changed a position 276 // (otherwise, starting in a position oher than 0 will mess up our 277 // pause check) 278 279 first_run = false; 280 } 281 282 283 } 284 285 // increment our saved value # for the next loop 286 287 steps++; 288 289 // return the difference recorded 290 return(diff); 291 292 293 } 294 295 296 void check_input() { 297 if ( Serial.available()) { 298 char ch = Serial.read(); 299 300 switch(ch) { 301 case 'g': 302 Serial.println("Go - Running Motor"); 303 motor_run = true; 304 digitalWrite(13, HIGH); 305 break; 306 case 's': 307 Serial.println("Stopping Motor"); 308 motor_run = false; 309 motor_started = false; 310 analogWrite(motor_cur_pin, 0); 311 digitalWrite(13, LOW); 312 break; 313 case 'l': 314 motor_cur_pin = MOTOR_LT_PIN; 315 Serial.println("Direction = LEFT"); 316 break; 317 case 'r': 318 motor_cur_pin = MOTOR_RT_PIN; 319 Serial.println("Direction = RIGHT"); 320 break; 321 } 322 } 323 } |
تأليف
المؤلف: Chris Church
الصفحة الشخصية: http://dronecolony.com/about-2/
ترجمة بتصرف: محمد السهلي
{jumi [*3]}
المراجع
http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/