[Arduino cơ bản] Giao tiếp động cơ bước

Thảo luận trong 'Arduino' bắt đầu bởi VuPhat.MCA, 19/8/19.

  1. VuPhat.MCA

    VuPhat.MCA New Member

    Bài này mình sẽ hướng dẫn các bạn cách điều khiển động cơ bước.

    Chuẩn bị:

    a) Arduino UNO R3
    b) Động cơ bước 28BYJ-48
    c) Module điều khiển động cơ bước ULN2003

    Sơ đồ kết nối:
    [​IMG]

    Động cơ bước:
    Động cơ bước thường được sử dụng trong các máy dịch chuyển cơ học như ổ đĩa, máy in, robot, chúng được dùng để điều khiển vị trí. Động cơ bước thường có cấu tạo gồm stato là 4 cuộn dây và stato là nam châm vĩnh cửu (Xem hình vẽ).
    [​IMG]

    Các động cơ bước thông thường có trục chạy tự do, còn trong động cơ bước trục di chuyển theo số bước tăng dần và lặp lại, nó cho phép di chuyển đến một vị trí chính xác. Chuyển động này dựa theo nguyên lý từ tính cơ bản nơi các cực cùng dấu thì đẩy nhau, các cực khác dấu thì hút nhau. Hướng quay của động cơ bước phụ thuộc vào các cực của roto. Các cực tính này được xác định bởi chiều dòng điện chạy qua cuộn dây. Trong bài này mình sẽ hướng dẫn cho các bạn cách sử dụng động cơ bước 4 cuộn dây trong đó 2 cực COM đã được mắc chung là 28BYJ-48 (Xem hình dưới).
    [​IMG]
    Bước góc:

    Nguyên lý điều khiển:

    Chương trình:
    Mã:
    const int aPin = 4; // Chân Arduino nối với chân A của động cơ bước
    const int bPin = 5; // Chân Arduino nối với chân B của động cơ bước
    const int cPin = 6; // Chân Arduino nối với chân C của động cơ bước
    const int dPin = 7; // Chân Arduino nối với chân D của động cơ bước
    
    // Độ phân giải của động cơ bước
    #define STEP_RESOLUTION 4096
    
    // Biến lưu giá trị trước đó của micros
    unsigned long prevMicros = 0;
    
    void setup() {
      // Khởi tạo Serial để debug
      Serial.begin(9600);
      // Cấu hình các chân Arduino là đầu ra
      pinMode(aPin, OUTPUT);
      pinMode(bPin, OUTPUT);
      pinMode(cPin, OUTPUT);
      pinMode(dPin, OUTPUT);
    }
    
    void loop() {
      // Biến góc quay ngẫu nhiên từ -360 đến 360
      int randAngle = -360 + random(721);
      // In giá trị góc quay
      Serial.print("Goc quay: ");
      Serial.println(randAngle);
      // Thực thi động cơ bước với góc quay ngẫu nhiên ở trên và tốc độ 16rpm
      stepper_runAngle(randAngle, 16);
      // Trễ 500ms
      delay(500);
    }
    
    // Hàm thực thi động cơ bước với góc quay và tốc độ
    void stepper_runAngle(int angleVal, float rpmSpeed) {
      // Tính toán giá trị bước ứng với góc quay
      // 360 độ <-> STEP_RESOLUTION
      // angleVal <-> stepVal
      int stepVal = round(abs(angleVal) * (float)STEP_RESOLUTION / 360);
      // Nếu góc dương thì quay theo chiều kim đồng hồ
      // ngược lại quay ngược chiều kim đồng hồ
      (angleVal > 0) ? (stepper_runStep(stepVal, rpmSpeed)) : (stepper_runStep(-stepVal, rpmSpeed));
    }
    
    // Hàm thực thi động cơ bước với số bước và tốc độ
    void stepper_runStep(int stepVal, float rpmSpeed) {
      // Biến kiểm tra hướng quay
      char dir = 0;
      // Nếu giá trị Bước dương thì quay theo chiều kim đồng hồ
      if (stepVal > 0) dir = 1;
      // Nếu giá trị Bước âm thì quay ngược chiều kim đồng hồ
      if (stepVal < 0) dir = 0;
      // Biến Bước tạm thời = Giá trị bước truyền vào
      int tempStep = abs(stepVal);
      // Tốc độ bước/giây = Tốc động vòng/phút * độ phân giải động cơ / 60
      int sps = round(rpmSpeed * (float)STEP_RESOLUTION / 60);
    
      // Trong khi bước tạm thời lớn hơn 0
      while (tempStep > 0) {
        // Thời gian trễ của mỗi bước = 1/sps (giây)
        // Định thời 1/sps * 1000000 micro giây
        if (micros() - prevMicros >= ((1.0 / sps) * 1000000)) {
          // Đặt lại thời điểm micro giây cũ
          prevMicros = micros();
          // Đặt giá trị bước cần thực thi và hướng
          stepper_setStep(tempStep % 8, dir);
          // Giảm bước tạm thời xuống 1
          tempStep--;
        }
      }
    }
    
    // Hàm đặt giá trị các bước (Half-Step) và hướng quay
    // Quay theo chiều kim đồng hồ: 0 -> 7
    // Quay ngược chiều kim đồng hồ: 7 -> 0
    // Bước | A | B | C | D
    // --------------------
    // 0    | 1 | 0 | 0 | 1
    // 1    | 1 | 0 | 0 | 0
    // 2    | 1 | 1 | 0 | 0
    // 3    | 0 | 1 | 0 | 0
    // 4    | 0 | 1 | 1 | 0
    // 5    | 0 | 0 | 1 | 0
    // 6    | 0 | 0 | 1 | 1
    // 7    | 0 | 0 | 0 | 1
    // --------------------
    void stepper_setStep(int stepVal, char dir) {
      // Kiểm tra giá trị bước theo thứ tự
      switch (stepVal) {
        case 0:
          // Nếu hướng dir == 0 thì thực hiện bước 7, ngược lại thực hiện bước 0
          (dir == 0) ? (stepper_setState(0, 0, 0, 1)) : (stepper_setState(1, 0, 0, 1));
          break;
        case 1:
          // Nếu hướng dir == 0 thì thực hiện bước 6, ngược lại thực hiện bước 1
          (dir == 0) ? (stepper_setState(0, 0, 1, 1)) : (stepper_setState(1, 0, 0, 0));
          break;
        case 2:
          // Nếu hướng dir == 0 thì thực hiện bước 5, ngược lại thực hiện bước 2
          (dir == 0) ? (stepper_setState(0, 0, 1, 0)) : (stepper_setState(1, 1, 0, 0));
          break;
        case 3:
          // Nếu hướng dir == 0 thì thực hiện bước 4, ngược lại thực hiện bước 3
          (dir == 0) ? (stepper_setState(0, 1, 1, 0)) : (stepper_setState(0, 1, 0, 0));
          break;
        case 4:
          // Nếu hướng dir == 0 thì thực hiện bước 3, ngược lại thực hiện bước 4
          (dir == 0) ? (stepper_setState(0, 1, 0, 0)) : (stepper_setState(0, 1, 1, 0));
          break;
        case 5:
          // Nếu hướng dir == 0 thì thực hiện bước 2, ngược lại thực hiện bước 5
          (dir == 0) ? (stepper_setState(1, 1, 0, 0)) : (stepper_setState(0, 0, 1, 0));
          break;
        case 6:
          // Nếu hướng dir == 0 thì thực hiện bước 1, ngược lại thực hiện bước 6
          (dir == 0) ? (stepper_setState(1, 0, 0, 0)) : (stepper_setState(0, 0, 1, 1));
          break;
        case 7:
          // Nếu hướng dir == 0 thì thực hiện bước 0, ngược lại thực hiện bước 7
          (dir == 0) ? (stepper_setState(1, 0, 0, 1)) : (stepper_setState(0, 0, 0, 1));
          break;
      }
    }
    
    // Hàm đặt trạng thái các chân
    void stepper_setState(int aVal, int bVal, int cVal, int dVal) {
      // Xuất chân a mức giá trị aVal được truyền vào
      digitalWrite(aPin, aVal);
      // Tương tự với các chân khác
      digitalWrite(bPin, bVal);
      digitalWrite(cPin, cVal);
      digitalWrite(dPin, dVal);
    }
    
    Kết quả:
    Quan sát động cơ bước, chúng ta thấy động cơ quay theo chiều kim đồng hồ hoặc ngược chiều kim đồng hồ với 1 góc ngẫu nhiên.

     
    Last edited: 19/8/19

trang này