Header Ads

  • Breaking News

    Cách chế tạo rô bốt - Kiểm tra phần cứng

    Phần ba của loạt bài viết về cách chế tạo một robot có thể đi theo đường thẳng hoặc tường và tránh chướng ngại vật!
    Phần ba của loạt bài viết về cách chế tạo một robot có thể đi theo đường thẳng hoặc tường và tránh chướng ngại vật!

    Những bài viết liên quan

    Cách chế tạo Robot:
    Phần 1: Thiết kế và Sơ đồ
    Phần 2: Thiết kế PCB
    Phần 4: Người theo dòng
    Phần 5: Tránh chướng ngại vật
    Phần 6: Robot theo dõi tường

    Tổng quat

    Đây là phần 3 của loạt bài viết về kinh nghiệm chế tạo một robot có thể làm nhiều việc của tôi. Tôi nghĩ sẽ thật gọn gàng nếu tạo ra một con robot dễ dàng lắp ráp lại với nhau bằng một chiếc mỏ hàn duy nhất và giá cả cũng phải chăng. Tôi đã đưa ra các yêu cầu sau cho rô bốt của mình:
    • Nhiều bộ dụng cụ đắt tiền, vì vậy nó phải tương đối rẻ.
    • Nó phải dễ dàng ghép lại với nhau mà không cần thiết bị đặc biệt.
    • Nó phải được lập trình dễ dàng mà không cần IDE hoặc lập trình viên phức tạp.
    • Nó phải đủ mạnh để có thể mở rộng.
    • Nó sẽ chạy khỏi một nguồn điện đơn giản.
    • Nó phải có thể đi theo một đường hoặc một bức tường và tránh chướng ngại vật.
    Trong bài viết này, tôi sẽ nói về cách lắp ráp rô bốt và viết thư viện rô bốt để kiểm tra các mạch điện khác nhau.

    Thu thập các thành phần

    Tôi đã đặt hàng tất cả các thành phần, tất cả đều đến trong một khoảng thời gian khá nhanh. Tại đây chúng được đặt sẵn sàng để lắp ráp.

    Lắp ráp các thành phần cơ khí

    Ball Caster

    Bánh xe đẩy bóng đến như một bộ đồ nghề phải được lắp ráp. Nó cung cấp nhiều tùy chọn kích thước. Không quá khó nên tôi không chụp bất kỳ hình ảnh nào về quá trình lắp ráp.

    Động cơ

    Động cơ cũng đi kèm như một bộ và phức tạp hơn nhiều. Bộ động cơ cung cấp 4 tỷ số truyền khác nhau. Cuối cùng, tôi chọn 38: 1 cho tỷ lệ tuyệt vời vì tôi không muốn robot quá chậm nhưng vẫn xử lý được việc kéo trọng lượng xung quanh. Tỷ số truyền cao hơn sẽ là một lượng mô-men xoắn không cần thiết. Trọng lượng thực duy nhất của robot là pin. Tỷ số truyền luôn có thể được điều chỉnh sau khi lắp ráp, nhưng sẽ hơi phiền phức. Tốc độ động cơ có thể được điều chỉnh bằng cách thay đổi chu kỳ làm việc PWM thành bộ điều khiển động cơ, vì vậy nếu tỷ số truyền được tạo ra quá cao của tốc độ, nó có thể được hạ xuống bằng phần mềm.
    Đây là tất cả các phần khác nhau từ bộ. Tôi đã sử dụng một cái thớt để lắp ráp vì những con ốc nhỏ có thói quen lăn ra khỏi bàn.
    Động cơ và bánh răng robot được lắp ráp hoàn chỉnh. Bộ dụng cụ đi kèm với mọi thứ cần thiết, bao gồm cả dầu mỡ. Công cụ duy nhất tôi cần là một cái tua vít. 
    Được gắn vào PCB, nó thực sự xếp hàng với màn hình lụa một cách độc đáo!

    Hàn các thành phần

    Tôi đã sử dụng tiêu đề nữ trong trường hợp tôi muốn hoán đổi các thành phần sau này. Việc hàn tất cả các tiêu đề đực vào bảng đột phá DIP hơi tẻ nhạt, nhưng dễ dàng hơn nhiều so với việc hàn tất cả các thành phần gắn kết bề mặt! Tôi đã phải sử dụng một loạt các tiêu đề kết nối với nhau để có được cảm biến dòng đủ gần với mặt đất để có thể cảm nhận được. Nếu tôi bắt đầu lại từ đầu, tôi thích cách lắp cảm biến dòng sạch hơn.

    Kiểm tra động cơ

    Lúc đầu, tôi chỉ kết nối động cơ trực tiếp với pin 2AA để xem các bánh răng đã được bôi trơn đúng cách chưa. Tôi cũng đo dòng điện để đảm bảo rằng nó nằm trong thông số kỹ thuật. Sau khi chứng minh động cơ có thể quay tới và quay ngược, tôi đã kết nối chúng với trình điều khiển động cơ. Tôi đã viết một số phần mềm thử nghiệm để chạy động cơ tiến và lùi trong năm giây. Điều này đã chứng minh các kết nối giữa Teensy, bộ điều khiển động cơ và động cơ cùng một lúc. Đó là một kết quả hài lòng khi bạn không phải khắc phục sự cố kết nối trên PCB bản sửa đổi đầu tiên! Đoạn mã sau điều khiển rô-bốt tiến về phía trước trong 5 giây với khoảng một nửa công suất và sau đó lùi lại trong 5 giây. Tôi đã viết một trình điều khiển có tên "robot.ino" đảm nhiệm các lượt và đọc cảm biến. Xem phần cuối của bài viết cho trình điều khiển. Để lập trình Teensy, hãy tải xuốngTiện ích bổ sung Teensyduino cho nền tảng Arduino. Sau đó, lập trình hoàn toàn giống như sử dụng Arduino.
    Tôi đã sử dụng jumper làm công tắc bật / tắt trong quá trình thử nghiệm.
    Nó còn sống!
    #include "robot.h"
    
    void setup()
    {
      Serial.begin(38400);
      Serial.println("Boot");
      rbt_init();  
      rbt_move(FWD,100);
      delay(5000);
      rbt_move(REV,100);
      delay(5000);
      rbt_move(BRAKE,0);
    }
    
    void loop()
    {
    }
    
    
    Testing_Hardware_1.zip

    Kiểm tra cảm biến

    Để kiểm tra các cảm biến, tôi đã viết một chương trình in giá trị thô từ các cảm biến. Tôi phát hiện ra rằng tôi không thể sử dụng các cảm biến trên tường cùng một lúc hoặc tất cả chúng sẽ kích hoạt 100% thời gian. Lý do cho điều này là các bộ thu IR có góc rộng và chúng thu tín hiệu từ các bộ phát liền kề. Tôi đã viết thư viện để nó luân phiên đọc từng cảm biến bằng cách tận dụng chân bật trên cảm biến. Các cảm biến trên tường cũng phải được nâng lên một chút, hoặc chúng nhấc mặt đất như một vật thể.
    Chức năng đọc cảm biến thực thi trong 1ms, cung cấp tốc độ 1kHz để xử lý các thuật toán điều khiển khá phức tạp nếu cần. Mã thử nghiệm cũng chứng minh rằng cảm biến vạch phải rất gần mặt đất để xác định hiệu quả sự khác biệt giữa các màu sắc. Nếu robot cách mặt đất một vài inch, cảm biến dòng đạt cực đại ở mức 1000. Điều này thực sự có thể hữu ích để làm cho robot ngừng di chuyển khi được mang đi xung quanh.
    Cảm biến dòng rất gần với mặt đất, nhưng không chạm vào!
    #include "robot.h"
    
    void setup()
    {
      Serial.begin(38400);
      Serial.println("Boot");
      rbt_init();  
    }
    
    uint16_t lleft,lmid,lright;
    boolean wleft,wmid,wright;
    void loop()                     
    {
      rbt_sns(&lleft,&lmid,&lright,&wleft,&wmid,&wright);
      Serial.print("Line left: ");
      Serial.print(lleft);
      Serial.print("Line mid: ");
      Serial.print(lmid);
      Serial.print("Line right: ");
      Serial.print(lright);
      Serial.print("Wall left: ");
      Serial.print(wleft);
      Serial.print("Wall mid: ");
      Serial.print(wmid);
      Serial.print("Wall right: ");
      Serial.println(wright);
    }
    
    
    Robot_Assembly_1.zip

    Phần kết luận

    Trong bài viết này, tôi đã trình bày quy trình lắp ráp một robot và thử nghiệm các thành phần riêng lẻ. Điều quan trọng là phải làm điều này khi bạn lần đầu tiên mua bo mạch, bởi vì bạn không bao giờ biết những sai lầm nào có thể đã xảy ra trong thiết kế hoặc sản xuất PCB. Nếu bạn nhảy ngay vào thiết kế ứng dụng, bạn có thể bỏ lỡ điều gì đó gây ra sự cố. Trong bài viết tiếp theo, tôi sẽ nói về cách biến rô bốt thành người theo dõi dòng bằng cách căn giữa một thuật toán đơn giản để giữ tâm trên một đường màu đen.

    Thư viện Robot

    robot.h
    #ifndef _ROBOT_H
    #define _ROBOT_H
    
    #include "Arduino.h"
    
    /*DRV8835*/
    const int BPHASE = 5;
    const int APHASE = 3;
    const int AEN = 4;
    const int BEN = 6;
    const int DRV_MODE = 2;
    #define MOTOR_REV  LOW
    #define MOTOR_FWD  HIGH
    
    /*reflection sensor interface*/
    const int OUT1 = 33;
    const int OUT2 = 32;
    const int OUT3 = 31;
    
    /*wall sensor interface*/
    const int WALL_LEFT_EN = 15;
    const int WALL_LEFT = 14;
    const int WALL_RIGHT_EN = 19;
    const int WALL_RIGHT = 18;
    const int WALL_MID_EN = 17;
    const int WALL_MID = 16;
    
    /*robot interface*/
    typedef enum{
      LEFT,
      RIGHT,
      FWD,
      REV,
      BRAKE,
    }direction_t;
    
    void rbt_move(direction_t new_dir, uint8_t speed);
    void rbt_sns( uint16_t *line_left,
                  uint16_t *line_mid,
                  uint16_t *line_right,
                  boolean  *wall_left,
                  boolean  *wall_mid,
                  boolean  *wall_right);
    void rbt_init();
    
    #endif /*_ROBOT_H*/
    
    
    Robot_Assembly.zip
    robot.ino
    #include "robot.h"
    
    void rbt_init()
    {
      pinMode(BPHASE, OUTPUT);
      pinMode(APHASE, OUTPUT);
      pinMode(AEN, OUTPUT);
      pinMode(BEN, OUTPUT);
      pinMode(DRV_MODE, OUTPUT);
      pinMode(WALL_LEFT_EN, OUTPUT);
      pinMode(WALL_MID_EN, OUTPUT); 
      pinMode(WALL_RIGHT_EN, OUTPUT);
      pinMode(WALL_LEFT, INPUT);
      pinMode(WALL_MID, INPUT); 
      pinMode(WALL_RIGHT, INPUT);
      digitalWrite(WALL_LEFT_EN,LOW);
      digitalWrite(WALL_MID_EN,LOW);
      digitalWrite(WALL_RIGHT_EN,LOW);
        /*simplified drive mode*/
      digitalWrite(DRV_MODE, HIGH);
    }
    
    void rbt_move(direction_t new_dir, uint8_t speed)
    {
      if(speed)
      {
        switch(new_dir){
          case LEFT:
            digitalWrite(BPHASE,MOTOR_FWD);
            digitalWrite(APHASE,MOTOR_FWD);
            analogWrite(AEN,speed);
            analogWrite(BEN,speed-speed/2);
            break;
          case RIGHT:
            digitalWrite(BPHASE,MOTOR_FWD);
            digitalWrite(APHASE,MOTOR_FWD);
            analogWrite(AEN,speed-speed/2);
            analogWrite(BEN,speed);
            break;
          case FWD:
            digitalWrite(BPHASE,MOTOR_FWD);
            digitalWrite(APHASE,MOTOR_FWD);
            analogWrite(AEN,speed);
            analogWrite(BEN,speed);
            break;
          case REV:
            digitalWrite(BPHASE,MOTOR_REV);
            digitalWrite(APHASE,MOTOR_REV);
            analogWrite(AEN,speed);
            analogWrite(BEN,speed);
            break;
          default:
              analogWrite(AEN,0);
              analogWrite(BEN,0);
              break;
        }
      }
      else
      {
        analogWrite(AEN,0);
        analogWrite(BEN,0);
      }
    }
    
    /*function takes 1ms to run*/
    #define LOOP_ITER_CNT 2
    void rbt_sns( uint16_t *line_left,
                  uint16_t *line_mid,
                  uint16_t *line_right,
                  boolean  *wall_left,
                  boolean  *wall_mid,
                  boolean  *wall_right)
    {
      *line_left=0;
      *line_mid=0;
      *line_right=0;
      uint16_t usec_timer=0;
      /*line sensor*/
      /*charge lines*/
      pinMode(OUT1, OUTPUT);
      pinMode(OUT2, OUTPUT);
      pinMode(OUT3, OUTPUT);
      digitalWrite(OUT1,HIGH);
      digitalWrite(OUT2,HIGH);
      digitalWrite(OUT3,HIGH);
      delayMicroseconds(3);
      /*set to Hi-Z to let cap discharge*/
      pinMode(OUT1, INPUT);
      pinMode(OUT2, INPUT);
      pinMode(OUT3, INPUT);
      /*enable first wall sensor*/
      digitalWrite(WALL_LEFT_EN,HIGH);
      while(1){
        /*each loop is about 2us at 48MHz*/
        usec_timer+=LOOP_ITER_CNT;
        /*increment counts for line sensors every us to track the decay of the capacitor*/
        if(digitalRead(OUT1) == 1)
        {
          (*line_left)+=LOOP_ITER_CNT;
        }
        if(digitalRead(OUT2) == 1)
        {
          (*line_mid)+=LOOP_ITER_CNT;
        }
        if(digitalRead(OUT3) == 1)
        {
          (*line_right)+=LOOP_ITER_CNT;
        }
        /*take turns reading wall sensors because they interfere with each other*/
        if(usec_timer == 300)
        {
          *wall_left = (digitalRead(WALL_LEFT) ? false:true);
          digitalWrite(WALL_LEFT_EN,LOW);
        }
        if(usec_timer == 400)
        {
          digitalWrite(WALL_MID_EN,HIGH);
        }
        if(usec_timer == 700)
        {
          *wall_mid = (digitalRead(WALL_MID) ? false:true);
          digitalWrite(WALL_MID_EN,LOW);
        }
        if(usec_timer == 700)
        {
          digitalWrite(WALL_RIGHT_EN,HIGH);
        }
        if(usec_timer>=1000)
        {
          *wall_right = (digitalRead(WALL_RIGHT) ? false:true);
          digitalWrite(WALL_MID_EN,LOW);
          return;
        }
      }
    }
    

    Không có nhận xét nào

    Post Top Ad

    ad728

    Post Bottom Ad

    ad728