دمج الوحدات · الدرس 3.8

التحكم بالمحرك الخطوي (Stepper Motor) عبر المشفّر الدوّار (Rotary Encoder)

العودة إلى الدروس

التعرف على المشفّر

سنستخدم المشفّر الدوّار (Rotary Encoder) مع محرك خطوي (28BYJ-48 Stepper Motor) ووحدة قيادة المحرك الخطوي (ULN2003 Stepper Motor Driver Module). المحرك ليس سريعًا أو عالي العزم لكنه مناسب لتجارب المبتدئين. نجعل المحرك يتحرك في اتجاه تدوير المشفّر، ونتتبع الخطوات لإعادته إلى البداية عند ضغط زر المشفّر.

المكونات المطلوبة

المشفّر الدوّار (Rotary Encoder)

جهاز كهروميكانيكي يحول الموضع الزاوي أو حركة المحور إلى رمز تناظري أو رقمي. نوعاه الرئيسيان مطلق وتزايدي أو نسبي. يعطي المطلق الموضع الحالي، والتزايدي معلومات الحركة التي يمكن معالجتها لاستخراج السرعة والمسافة والموضع.

يستخدم في التحكم الصناعي والروبوتات وعدسات تصوير متخصصة وأجهزة دخل الحاسوب مثل الفأرة البصرية الميكانيكية و Trackball، وأجهزة قياس ريولوجي للإجهاد، ومنصات الرادار الدوارة، وغيرها مما يحتاج دورانًا مستمرًا ودقة للمحور.

وحدة المشفّر الدوّار (Rotary Encoder Module)
وحدة المشفّر الدوّار (Rotary Encoder Module)

التوصيل

المخطط الكهربائي للمشفّر والمحرك
المخطط الكهربائي للمشفّر والمحرك
التوصيل العملي للمشفّر ولوحة القيادة
التوصيل العملي للمشفّر ولوحة القيادة

المنافذ 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);     
}

ملفات الدرس والمكتبات

المكتبات المرفقة

ملفات الدرس

100%

عرض الصورة

استخدم + و− للتكبير والتصغير، أو اضغط Esc للإغلاق.