커뮤니티

  • 제 목 [로봇 팔 제어 프로젝트] STM32 MCU를 활용한 원격 로봇 팔 제어
  • 작성자 Dongdon 조회 : 28,075 좋아요 : 6 댓글 : 1
  • 작성일 2019-12-10 오후 3:50:08
  • 첨부파일 stm32_Robot_Arm.zip
  • 이번 실습은 STM32 MCU를 활용한 로봇 팔 제어입니다. 기존과 동일하게 아두이노 Nano, 조이스틱, 서보모터를 활용해서

    블루투스 통신을 통해 원격으로 로봇 팔을 동작시킵니다.


     

     

     

     

    1. 동작 원리

     

    조이스틱 3개를 통해 블루투스 통신으로 6개의 서보모터를 제어하여 로봇 팔을 움직이게 합니다.

    조이스틱은 아두이노 Nano와 연결되어 있으며, 서보모터는 STM32F7 MCU와 연결되어 동작합니다.

    조이스틱과 블루투스 모듈은 5V를 공급, 서보모터는 6.5V를 공급해야 안정적으로 동작합니다.

     

     

     

     

    2. 준비물

     

      제품명 수량
    1 STM32F746NG 1
    2 아두이노 Nano 1
    3 블루투스 모듈 HC-06 2
    4 조이스틱 3
    5 서보모터 6

     

     

     

     

    3. 가이드

     

    3-1. STM32F746 개발 환경 설정

           STM 보드는 아두이노 개발 환경을 지원합니다. 라이브러리를 추가하는 방식으로 Aduino IDE에서도

           기존에 사용하던 코드들을 활용할 수 있습니다.

     

     

    (1) 메뉴 탭 '파일' -> '환경설정'

     

     

     

     

    (2) 추가적인 보드매니저 버튼 클릭

     

     

     

     

    (3) '비공식 보드 지원 URL 목록을 보려면 클릭하세요' 선택

     

     

     

     

     

    (4) 링크가 열리면 Ctrl+F로 'STM32'를 검색합니다. 이후 아래의 주소를 복사합니다.

         개발 환경을 지원하는 보드를 아래에서 확인할 수 있습니다.

     

     

     

     

    (5) Arduino IDE로 돌아와서 복사한 링크를 붙여넣기 합니다

     

     

     

     

    (6) 메뉴 탭의 '툴' -> '보드' -> '보드 매니저'를 선택합니다.

     

     

     

     

    (7) 맨 아랫부분에 있는 STM32 보드 패키지를 설치합니다. 커서를 올리면 '설치' 버튼이 생깁니다.

     

     

     

     

    (8) 보드 설정 메뉴에서 다양한 STM32 MCU가 생긴 것을 확인할 수 있습니다. 아래와 같이 설정해 줍니다.

     

     

     

     

    (9) STM32 MCU를 컴파일하기 위해선 프로그램이 필요합니다. 아래의 링크에서 소프트웨어 툴을 설치합니다.

        * STM32 Cube Prog

          https://www.st.com/en/development-tools/stm32cubeprog.html

     

     

     

    (10) Arduino IDE에서 STM32 MCU의 핀을 사용하기 위해선 기존의 아두이노 Uno와는 다릅니다.

          STM32 보드에 대한 코드를 작성할 떄에는 아래 붉은 색 박스에 있는 핀 번호를 사용하도록 합니다.

          각각 아날로그, 디지털 핀의 이름 입니다.

     

     

     

     

     

    (11) STM32 MCU 사용시 주의점 입니다.

          제 경우, 각 포트는 아래와 같았습니다.

          COM10 : 아두이노 Nano

          COM16 : STM32 시리얼 모니터 포트

          COM3 : STM32 코드 업로드용 포트

          STM32 MCU는 두 개의 포트를 사용합니다. 하나는 시리얼 모니터용, 하나는 코드 업로드용 입니다.

          따라서 혼용하지 않아야 합니다. 시리얼 모니터로 데이터 전송 상태를 볼 때엔, COM16으로 전환한 뒤에 가능합니다.

          업로드는 COM3 포트만을 사용해야하며 COM16을 사용하면 에러가 발생합니다.

     

     

     

     

    (12) 다음과 같이 조이스틱, 서보모터, 보드를 연결합니다.

          * 아래 사진에선 STM32 Nucleo를 사용했지만, 핀 구조는 동일하므로 STM32F7 보드를 사용해도 무방합니다.

     

     

     

     

     

    3-2. 코드 작성

     

    <Master> - 아두이노 Nano

    조이스틱과 연결 될 Nano 보드에 업로드할 코드들 입니다.

    코드는 기존의 것과 동일합니다.

    #include<SoftwareSerial.h>
    //블루투스 통신을 위한 헤더파일
    
    int motor1 = A0; //1번 조이스틱 X축 사용 (아날로그 핀)
    int motor2 = A2; //1번 조이스틱 Y축 사용 (아날로그 핀)
    int motor3 = A3; //2번 조이스틱 X축 사용 (아날로그 핀)
    int motor4 = A4; //2번 조이스틱 Y축 사용 (아날로그 핀)
    int motor5 = A5; //3번 조이스틱 X축 사용 (아날로그 핀)
    int motor6 = A6; //3번 조이스틱 Y축 사용 (아날로그 핀)
    
    int BLE_RX = 2;   //Rx (받는핀 설정) - 디지털 핀 2번
    int BLE_TX = 3;   //Tx (보내는핀 설정) - 디지털 핀 3번
    SoftwareSerial bleSerial(BLE_RX, BLE_TX);  //블루투스 통신 설정
    
    void setup()
    {
      bleSerial.begin(9600); //bleSerial 블루투스 통신
      Serial.begin(9600); //시리얼 모니터 사용
    }
    
    void loop ()
    {
      if (( (analogRead(motor1) >= 0)&& (analogRead(motor1) <= 300))
            || ((analogRead(motor1) >= 700) && (analogRead(motor1) <=1023)) )
       //사용자가 원치 않는 조이스틱의 입력을 막기 위해 범위 지정
      {
        int vrx = analogRead(motor1);    // 조이스틱의 입력 값을 받아 vrx로 선언
        vrx = map(vrx, 0, 1023, 0, 179);
        // 블루투스가 보낼 수 있는 값은 0~255까지므로 조이스틱 값을 적절한 값으로 맵핑
        bleSerial.write(vrx); // 블루투스로 조이스틱 값 전송
        bleSerial.write(1);   // 블루투스로 모터 판별용 상수 전송
        Serial.print("조이스틱 입력값");
        Serial.println(vrx);  // 시리얼 모니터에 조이스틱 값 출력
        Serial.println("1번 모터");    // 시리얼 모니터에 모터 판별용 상수 출력
        delay(50);
      }
    
      else if (( (analogRead(motor2) >= 0)&& (analogRead(motor2) <= 300))
            || ((analogRead(motor2) >= 700) && (analogRead(motor2) <=1023)) )
       //사용자가 원치 않는 조이스틱의 입력을 막기 위해 범위 지정
      {
        int vrx = analogRead(motor2);    // 조이스틱의 입력 값을 받아 vrx로 선언
        vrx = map(vrx, 0, 1023, 0, 179); 
        // 블루투스가 보낼 수 있는 값은 0~255까지므로 조이스틱 값을 적절한 값으로 맵핑
        bleSerial.write(vrx); // 블루투스로 조이스틱 값 전송
        bleSerial.write(2);   // 블루투스로 모터 판별용 상수 전송
        Serial.print("조이스틱 입력값");
        Serial.println(vrx);  // 시리얼 모니터에 조이스틱 값 출력
        Serial.println("2번 모터");    // 시리얼 모니터에 모터 판별용 상수 출력
        delay(50);
      }
    
      else if (( (analogRead(motor3) >= 0)&& (analogRead(motor3) <= 300))
            || ((analogRead(motor3) >= 700) && (analogRead(motor3) <=1023)) )
       //사용자가 원치 않는 조이스틱의 입력을 막기 위해 범위 지정
      {
        int vrx = analogRead(motor3);    // 조이스틱의 입력 값을 받아 vrx로 선언
        vrx = map(vrx, 0, 1023, 0, 179);
        // 블루투스가 보낼 수 있는 값은 0~255까지므로 조이스틱 값을 적절한 값으로 맵핑
        bleSerial.write(vrx); // 블루투스로 조이스틱 값 전송
        bleSerial.write(3);   // 블루투스로 모터 판별용 상수 전송
        Serial.print("조이스틱 입력값");
        Serial.println(vrx);  // 시리얼 모니터에 조이스틱 값 출력
        Serial.println("3번 모터");    // 시리얼 모니터에 모터 판별용 상수 출력
        delay(50);
      }
    
      
      else if (( (analogRead(motor4) >= 0)&& (analogRead(motor4) <= 300))
            || ((analogRead(motor4) >= 700) && (analogRead(motor4) <=1023)) )
       //사용자가 원치 않는 조이스틱의 입력을 막기 위해 범위 지정
      {
        int vrx = analogRead(motor4);    // 조이스틱의 입력 값을 받아 vrx로 선언
        vrx = map(vrx, 0, 1023, 0, 179);
        // 블루투스가 보낼 수 있는 값은 0~255까지므로 조이스틱 값을 적절한 값으로 맵핑
        bleSerial.write(vrx); // 블루투스로 조이스틱 값 전송
        bleSerial.write(4);   // 블루투스로 모터 판별용 상수 전송
        Serial.print("조이스틱 입력값");
        Serial.println(vrx);  // 시리얼 모니터에 조이스틱 값 출력
        Serial.println("4번 모터");    // 시리얼 모니터에 모터 판별용 상수 출력
        delay(50);
      }
    
    
      else if (( (analogRead(motor5) >= 0)&& (analogRead(motor5) <= 300))
            || ((analogRead(motor5) >= 700) && (analogRead(motor5) <=1023)) )
       //사용자가 원치 않는 조이스틱의 입력을 막기 위해 범위 지정
      {
        int vrx = analogRead(motor5);    // 조이스틱의 입력 값을 받아 vrx로 선언
        vrx = map(vrx, 0, 1023, 0, 179);
        // 블루투스가 보낼 수 있는 값은 0~255까지므로 조이스틱 값을 적절한 값으로 맵핑
        bleSerial.write(vrx); // 블루투스로 조이스틱 값 전송
        bleSerial.write(5);   // 블루투스로 모터 판별용 상수 전송
        Serial.print("조이스틱 입력값");
        Serial.println(vrx);  // 시리얼 모니터에 조이스틱 값 출력
        Serial.println("5번 모터");    // 시리얼 모니터에 모터 판별용 상수 출력
        delay(50);
      }
    
    
      
      else if (( (analogRead(motor6) >= 0)&& (analogRead(motor6) <= 300))
            || ((analogRead(motor6) >= 700) && (analogRead(motor6) <=1023)) )
       //사용자가 원치 않는 조이스틱의 입력을 막기 위해 범위 지정
      {
        int vrx = analogRead(motor6);    // 조이스틱의 입력 값을 받아 vrx로 선언
        vrx = map(vrx, 0, 1023, 0, 179);
        // 블루투스가 보낼 수 있는 값은 0~255까지므로 조이스틱 값을 적절한 값으로 맵핑
        bleSerial.write(vrx); // 블루투스로 조이스틱 값 전송
        bleSerial.write(6);   // 블루투스로 모터 판별용 상수 전송
        Serial.print("조이스틱 입력값");
        Serial.println(vrx);  // 시리얼 모니터에 조이스틱 값 출력
        Serial.println("6번 모터");    // 시리얼 모니터에 모터 판별용 상수 출력
        delay(50);
      }
    
      
    }

     

     

     

     

    <Slave> - STM32F746NG

    서보모터와 연결 될 STM32 MCU에 업로드 해야하는 코드입니다.

    아두이노 Nano에서 보낸 조이스틱 값을 받아서, 모터 앵글 값 계산 및 원하는 서보모터 동작을 수행합니다.

    * 주의점 : STM32 MCU에서는 아두이노 보드들과 달리 SoftwareSerial.h을 통해 블루투스 통신을 시도하면

                 시리얼 모니터용 포트가 정지합니다. 따라서 디지털 핀 1번, 디지털 핀 2번으로 블루투스 통신을 하기 위해

                 HardwareSerial.h를 사용해야 합니다. 또한, 위에 언급했듯이 보드의 핀은 각각 STM32의 핀 네임을 사용해야 합니다

                 STM32 MCU개발 환경에선 컴파일 할 때 다소 시간이 걸립니다. 여유롭게 기다리시면 됩니다~

    #include <HardwareSerial.h>
    #include <Servo.h>
    
    // Servo.h는 서보모터를 사용하기 위한 헤더
    // HardwareSerial.h는 STM32F7에서 블루투스를 사용하기 위한 헤더 (아두이노는 SoftwareSerial.h로 해야함)
    
    Servo servo1, servo2, servo3, servo4, servo5, servo6; // 서보 모터용 변수 선언
    int angle1, angle2, angle3, angle4, angle5, angle6;   // 모터 앵글값 변수 선선
    int motor1, motor2; // motor1은 조이스틱 값을 받아오고, motor2는 모터 판별용 변수를 받아온다.
    
    #define BLE_RX (PC7) //Rx (받는핀 설정) - 디지털 핀 0번
    #define BLE_TX (PC6) //Tx (보내는핀 설정) -  디지털 핀 1번
    HardwareSerial bleSerial(BLE_RX, BLE_TX); // 블루투스 통신 설정
    
    void setup() {  
      bleSerial.begin(9600);  // 블루투스 통신 시작
      Serial.begin(9600);     // 시리얼 모니터 사용
      servo1.attach(PB15);    // 디지털 11번 핀을 서보모터로 지정
      servo1.write(90);       // 서보모터 초기 값 설정
      servo2.attach(PA8);     // 디지털 10번 핀을 서보모터로 지정
      servo2.write(90);       // 서보모터 초기 값 설정
      servo3.attach(PA15);    // 디지털 9번 핀을 서보모터로 지정
      servo3.write(90);       // 서보모터 초기 값 설정
      servo4.attach(PI2);     // 디지털 8번 핀을 서보모터로 지정
      servo4.write(90);       // 서보모터 초기 값 설정
      servo5.attach(PI3);     // 디지털 7번 핀을 서보모터로 지정
      servo5.write(90);       // 서보모터 초기 값 설정
      servo6.attach(PH6);     // 디지털 6번 핀을 서보모터로 지정
      servo6.write(90);       // 서보모터 초기 값 설정
      angle1 = 90;            // 앵글 초기 값 설정
      angle2 = 90;            // 앵글 초기 값 설정
      angle3 = 90;            // 앵글 초기 값 설정
      angle4 = 90;            // 앵글 초기 값 설정
      angle5 = 90;            // 앵글 초기 값 설정
      angle6 = 90;            // 앵글 초기 값 설정
      }
    
    
    void loop() {
       if (bleSerial.available()>=2){
          motor1 = bleSerial.read(); // motor1에 조이스틱의 값을 받아옴
          motor2 = bleSerial.read(); // motor2에 모터 판별용 상수를 받아옴
    
        switch(motor2) // 모터 판별용 상수에 따라 각 서보모터가 동작한다
        {
    
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▼서보모터 1 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---  
          case 1 :     // 모터 판별용 변수가 1인 경우 1번 서보모터 동작
                if ((motor1 <= 60) && (motor1 >= 0)) 
                // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle1 = angle1 - 2;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle1 <= 40) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle1 = 40;
                    }
        
                    if (angle1 >= 150) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle1 = 150;
                    }
                    
                    servo1.write(angle1);      // 모터에 앵글 값을 입력
                    Serial.println("1번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle1);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
              }
    
              else if ((motor1 <= 179) && (motor1 >= 118)) 
              // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle1 = angle1 + 2;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle1 <= 40) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle1 = 40;
                    }
        
                    if (angle1 >= 150) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle1 = 150;
                    }
                  
                    servo1.write(angle1);      // 모터에 앵글 값을 입력
                    Serial.println("1번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle1);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
                }
            break;
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▲서보모터 1 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--
    
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▼서보모터 2 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---  
          case 2 :    // 모터 판별용 변수가 2인 경우 2번 서보모터 동작
                if ((motor1 <= 60) && (motor1 >= 0)) 
                // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle2 = angle2 - 1;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle2 <= 20) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle2 = 20;
                    }
        
                    if (angle2 >= 100) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle2 = 100;
                    }
                    
                    servo2.write(angle2);      // 모터에 앵글 값을 입력
                    Serial.println("2번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle2);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
              }
    
              else if ((motor1 <= 179) && (motor1 >= 118))  
              // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle2 = angle2 + 1;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle2 <= 20) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle2 = 20;
                    }
        
                    if (angle2 >= 100) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle2 = 100;
                    }
                  
                    servo2.write(angle2);      // 모터에 앵글 값을 입력
                    Serial.println("2번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle2);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
                }
            break;
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▲서보모터 2 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--
    
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▼서보모터 3 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---  
          case 3 :    
                if ((motor1 <= 60) && (motor1 >= 0)) 
                // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle3 = angle3 - 1;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle3 <= 50) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle3 = 50;
                    }
        
                    if (angle3 >= 140) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle3 = 140;
                    }
                    
                    servo3.write(angle3);      // 모터에 앵글 값을 입력
                    Serial.println("3번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle3);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
              }
    
              else if ((motor1 <= 179) && (motor1 >= 118)) 
              // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle3 = angle3 + 1;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle3 <= 50) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle3 = 50;
                    }
        
                    if (angle3 >= 140) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle3 = 140;
                    }
                  
                    servo3.write(angle3);      // 모터에 앵글 값을 입력
                    Serial.println("3번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle3);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
                }
            break;
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▲서보모터 3 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--
    
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▼서보모터 4 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---  
          case 4 :    
                if ((motor1 <= 60) && (motor1 >= 0)) 
                // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle4 = angle4 - 1;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle4 <= 50) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle4 = 50;
                    }
        
                    if (angle4 >= 140) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle4 = 140;
                    }
    
                    servo4.write(angle4);      // 모터에 앵글 값을 입력
                    Serial.println("4번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle4);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
              }
    
              else if ((motor1 <= 179) && (motor1 >= 118)) 
              // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle4 = angle4 + 1;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle4 <= 50) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle4 = 50;
                    }
        
                    if (angle4 >= 140) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle4 = 140;
                    }
                  
                    servo4.write(angle4);      // 모터에 앵글 값을 입력
                    Serial.println("4번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle4);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
                }
            break;
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▲서보모터 4 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--
    
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▼서보모터 5 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---  
          case 5 :    
                if ((motor1 <= 60) && (motor1 >= 0)) 
                // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle5 = angle5 - 1;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle5 <= 20) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle5 = 20;
                    }
        
                    if (angle5 >= 150) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle5 = 150;
                    }
                    
                    servo5.write(angle5);      // 모터에 앵글 값을 입력
                    Serial.println("5번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle5);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
              }
    
              else if ((motor1 <= 179) && (motor1 >= 118))
              // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle5 = angle5 + 1;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle5 <= 20) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle5 = 20;
                    }
        
                    if (angle5 >= 150) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle5 = 150;
                    }
                  
                    servo5.write(angle5);      // 모터에 앵글 값을 입력
                    Serial.println("5번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle5);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
                }
            break;
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▲서보모터 5 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--
    
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▼서보모터 6 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---  
          case 6 :    
                if ((motor1 <= 60) && (motor1 >= 0)) 
                // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle6 = angle6 - 1;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle6 <= 50) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle6 = 50;
                    }
        
                    if (angle6 >= 127) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle6 = 127;
                    }
                    
                    servo6.write(angle6);      // 모터에 앵글 값을 입력
                    Serial.println("6번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle6);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
              }
    
              else if ((motor1 <= 179) && (motor1 >= 118)) 
              // 조이스틱이 움직였을 때만 작동하도록 적절한 범위 선정
                {
                   angle6 = angle6 + 1;
                    //로봇팔의 회전속도를 조절하기 위해 실험을 통해 나온 적절한 속도값을 계산하여 구함
    
                    if (angle6 <= 50) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle6 = 50;
                    }
        
                    if (angle6 >= 127) // 과도한 앵글로 인해 버벅이는 현상을 줄이기 위해 범위를 제한
                    {
                      angle6 = 127;
                    }
                  
                    servo6.write(angle6);      // 모터에 앵글 값을 입력
                    Serial.println("6번 모터"); // 시리얼 모니터에 현재 동작하는 모터를 출력
                    Serial.print("모터 각도 : ");
                    Serial.println(angle6);    // 시리얼 모니터에 앵글 값 출력
                    delay(50);                 // 모터 동작을 기다려주는 delay타임
                }
            break;
           
    //\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\---▲서보모터 6 제어\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--\--
    
          }
        }
    }

     

     

     

     

    4. 동작 영상

     

     

     

     

    `

    5. 알아두시면 좋을 정보

     

    기존의 프로젝트에서 문제점은 세 가지였습니다.

     

    첫 번째, 모터 회전시 떨림 현상

    두 번째, 동작시 다른 모터에 시그널 간섭 현상으로 인해 동작하지 않아야 하는 모터가 흔들리는 현상

    세 번째, 모터 6개를 모두 동작시키기 위해선 8~8.5V가 필요했으나, 모터의 정격전압은 7V 이하였기 때문에 

               장시간 사용시 과열 발생

     

    이번 프로젝트에서 Uno 보드 대신에 STM32F7 MCU를 사용하여 위의 문제점들을 어느정도 극복해낼 수 있었습니다.

    Uno에 비해서 이번에 사용한 STM32 보드가 좀 더 메모리에 여유가 있기 때문에 블루투스 통신이 원활했던 것으로 보입니다.

    다만, 아직 존재하는 로봇 팔 프레임이 흔들리는 현상은 기계 부품을 개선하거나 좀 더 최적화된 코드 작성으로 해결할 수 있을

    것으로 보입니다.

     

     

    아래는 이번 프로젝트 진행시에 참고했던 STM32F7의 매뉴얼들 입니다. 참고하시면 좀 더 수월한 진행이 가능합니다.

    (클릭하시면 해당 매뉴얼이 열립니다)

     

    STM32F7 User Manual

    STM32F7 Reference Manual

    STM32F7 Programming Manual

     

    궁금하신 점은 언제든 댓글로 문의주시기 바랍니다~

  • #STM32F7 #MCU #로봇 #아두이노
2020.12.14 08:38 답글 신고
안녕하세요 프로젝트 잘봤습니다. 저도 한 번 도전해보려고 하는데 STM32 F103RB_Nucleo 보드로 따라서 코딩할 때 문제없을까요?? 보드는 올려주신 사진과 동일하게 생긴 듯 합니다.