دمج الوحدات · الدرس 3.8
التحكم بالمحرك الخطوي (Stepper Motor) عبر المشفّر الدوّار (Rotary Encoder)
العودة إلى الدروسالتعرف على المشفّر
سنستخدم المشفّر الدوّار (Rotary Encoder) مع محرك خطوي (28BYJ-48 Stepper Motor) ووحدة قيادة المحرك الخطوي (ULN2003 Stepper Motor Driver Module). المحرك ليس سريعًا أو عالي العزم لكنه مناسب لتجارب المبتدئين. نجعل المحرك يتحرك في اتجاه تدوير المشفّر، ونتتبع الخطوات لإعادته إلى البداية عند ضغط زر المشفّر.
المكونات المطلوبة
- لوحة أردوينو (ELEGOO UNO R3) ولوحة تجارب (Breadboard) 830 نقطة.
- وحدة مشفّر دوار (Rotary Encoder Module) ووحدة قيادة المحرك الخطوي (ULN2003 Stepper Motor Driver Module) ومحرك خطوي (Stepper Motor).
- وحدة تغذية (Power Supply Module) ومحول طاقة (9V1A Adapter).
- تسعة أسلاك أنثى إلى ذكر (Female to Male DuPont Wires) وسلك ذكر إلى ذكر (Male to Male Jumper Wires).
المشفّر الدوّار (Rotary Encoder)
جهاز كهروميكانيكي يحول الموضع الزاوي أو حركة المحور إلى رمز تناظري أو رقمي. نوعاه الرئيسيان مطلق وتزايدي أو نسبي. يعطي المطلق الموضع الحالي، والتزايدي معلومات الحركة التي يمكن معالجتها لاستخراج السرعة والمسافة والموضع.
يستخدم في التحكم الصناعي والروبوتات وعدسات تصوير متخصصة وأجهزة دخل الحاسوب مثل الفأرة البصرية الميكانيكية و Trackball، وأجهزة قياس ريولوجي للإجهاد، ومنصات الرادار الدوارة، وغيرها مما يحتاج دورانًا مستمرًا ودقة للمحور.

التوصيل


المنافذ 8–11 للمحرك، و 2–4 لمعلومات المشفّر. وصّل 5V وأرضي UNO بالمشفّر. استخدم وحدة تغذية (Power Supply Module) للمحرك لأن استهلاكه قد يتجاوز قدرة UNO، ووصل أرضي UNO بأرضي لوحة التجارب (Breadboard) مرجعًا مشتركًا.
البرنامج وتتبع الموضع
قبل رفع البرنامج، تأكد من توفر مكتبة Stepper في بيئة Arduino IDE. إذا لم تكن مثبتة أو ظهرت رسالة تشير إلى مكتبة مفقودة، فاتبع خطوات التثبيت في قسم «ما هي المكتبات؟» وطرق تثبيتها في الدرس 1.5 «وميض LED وإضافة المكتبات».
افتح ملف البرنامج With_Encoder.ino من ملفات الدرس في بيئة Arduino IDE. بعد إتمام التوصيلات، وصّل لوحة أردوينو (UNO R3 Board) بالحاسوب بكابل توصيل (USB Cable)، ثم اضغط زر Upload (رفع) لنقل البرنامج إلى اللوحة وتشغيله عليها.
إذا تعذر نقل البرنامج إلى اللوحة، فراجع قسم «رفع البرنامج ومعالجة خطأ الاتصال» في الدرس 1.5 «وميض LED وإضافة المكتبات» للتحقق من اتصال USB واختيار نوع اللوحة والمنفذ التسلسلي في بيئة Arduino IDE.
يحفظ البرنامج الموضع الحالي في متغيرات ليعيد المحرك إلى البداية. ويضم فحصًا للأخطاء لتقليل احتمال فقد خطوات من المشفّر، لأن ذلك يجعل موضع المحرك غير دقيق.
الكود
With_Encoder/With_Encoder.ino
//www.elegoo.com
//2016.12.12
#include "Stepper.h"
#define STEPS 32 // Number of steps for one revolution of Internal shaft
// 2048 steps for one revolution of External shaft
volatile boolean TurnDetected; // need volatile for Interrupts
volatile boolean rotationdirection; // CW or CCW rotation
const int PinCLK=2; // Generating interrupts using CLK signal
const int PinDT=3; // Reading DT signal
const int PinSW=4; // Reading Push Button switch
int RotaryPosition=0; // To store Stepper Motor Position
int PrevPosition; // Previous Rotary position Value to check accuracy
int StepsToTake; // How much to move Stepper
// Setup of proper sequencing for Motor Driver Pins
// In1, In2, In3, In4 in the sequence 1-3-2-4
Stepper small_stepper(STEPS, 8, 10, 9, 11);
// Interrupt routine runs if CLK goes from HIGH to LOW
void isr () {
delay(4); // delay for Debouncing
if (digitalRead(PinCLK))
rotationdirection= digitalRead(PinDT);
else
rotationdirection= !digitalRead(PinDT);
TurnDetected = true;
}
void setup () {
pinMode(PinCLK,INPUT);
pinMode(PinDT,INPUT);
pinMode(PinSW,INPUT);
digitalWrite(PinSW, HIGH); // Pull-Up resistor for switch
attachInterrupt (0,isr,FALLING); // interrupt 0 always connected to pin 2 on Arduino UNO
}
void loop () {
small_stepper.setSpeed(700); //Max seems to be 700
if (!(digitalRead(PinSW))) { // check if button is pressed
if (RotaryPosition == 0) { // check if button was already pressed
} else {
small_stepper.step(-(RotaryPosition*50));
RotaryPosition=0; // Reset position to ZERO
}
}
// Runs if rotation was detected
if (TurnDetected) {
PrevPosition = RotaryPosition; // Save previous position in variable
if (rotationdirection) {
RotaryPosition=RotaryPosition-1;} // decrase Position by 1
else {
RotaryPosition=RotaryPosition+1;} // increase Position by 1
TurnDetected = false; // do NOT repeat IF loop until new rotation detected
// Which direction to move Stepper motor
if ((PrevPosition + 1) == RotaryPosition) { // Move motor CW
StepsToTake=50;
small_stepper.step(StepsToTake);
}
if ((RotaryPosition + 1) == PrevPosition) { // Move motor CCW
StepsToTake=-50;
small_stepper.step(StepsToTake);
}
}
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
}