산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

RC 모델 및 Arduino 프로젝트를 위한 DIY Arduino RC 수신기

<메인 클래스="사이트-메인" id="메인">

이 튜토리얼에서는 Arduino 기반 RC 수신기를 만드는 방법을 배웁니다. 이전 비디오 중 하나에서 DIY Arduino RC 송신기를 만든 이후로 전용 수신기를 만들어 달라는 요청이 많이 있어 여기에 있습니다.

다음 비디오를 보거나 아래에 작성된 튜토리얼을 읽을 수 있습니다.

이제 이 두 장치는 쉽게 통신할 수 있으며 무선으로 많은 것을 제어하는 ​​데 사용할 수 있습니다. 몇 가지 예를 통해 모든 것이 어떻게 작동하는지 설명하겠습니다. 첫 번째 예에서는 이 Arduino RC 수신기를 사용하여 두 개의 DC 모터로 구성된 간단한 자동차를 제어합니다. 두 번째 예에서는 많은 상업용 RC 비행기, 보트, 자동차 등에서 흔히 볼 수 있는 브러시리스 모터와 서보를 제어하는 ​​방법을 보여 드리겠습니다. 그것들을 제어하는 ​​방법을 알면 자체 제작한 Arduino 송신기로 많은 RC 모델을 쉽게 수정하고 제어할 수 있습니다.

세 번째 예로 이 Arduino 기반 RC 시스템을 수정하여 상업용 RC 자동차를 제어하는 ​​방법을 보여 드리겠습니다.

Arduino RC 수신기 회로도

먼저 이 시스템의 회로도를 살펴보겠습니다. 무선 통신은 NRF24L01 트랜시버 모듈을 기반으로 합니다.

송신기는 컨트롤러, 조이스틱, 버튼, 전위차계 및 토글 스위치에서 지속적으로 데이터를 보내고 우리는 이 데이터를 수신기로 받습니다. 이 Arduino 송신기의 작동 방식에 대한 자세한 내용은 제 다른 자세한 자습서를 참조하십시오.

우리는 또한 이 RC 수신기가 내가 만든 이 특정 송신기에서만 작동하는 것은 아니라는 점에 유의할 수 있습니다. Arduino 보드 및 NRF24L01 모듈로 구성된 다른 유사한 설정과 함께 작동할 수 있습니다.

그럼에도 불구하고 이 RC 수신기의 두뇌는 Arduino Pro Mini 보드입니다. 전원을 공급하기 위해 5V를 연결할 수 있는 VCC 핀을 사용하거나 6에서 12V까지 연결할 수 있는 RAW 핀을 사용할 수 있습니다. Arduino Pro Mini에는 5V에서 작동하는 버전과 3.3V에서 작동하는 다른 버전과 같이 두 가지 버전이 있습니다. 반면에 NRF24L01 모듈은 3.3V에서 동작하므로 전압 레귤레이터가 필요합니다. 이번에는 5V ~ 12V 범위의 입력에서 3.3V를 출력하는 AMS1117 전압 조정기를 사용하고 있습니다.

아래 링크에서 이 Arduino RC 수신기에 필요한 구성 요소를 얻을 수 있습니다.

Arduino와의 통신을 위해 NRF24L01 모듈은 SPI 프로토콜과 2개의 추가 디지털 핀을 사용합니다. 즉, 출력 채널로 사용할 수 있는 9개의 디지털 핀이 남아 있으며 그 중 2개는 RX 및 TX 핀입니다. 아두이노 보드에 스케치를 업로드하는 동안 이 핀을 무엇과도 연결 해제해야 하므로 별도의 핀 헤더를 통해 연결하거나 분리할 수 있도록 했습니다. 실제로 아날로그 입력을 디지털 출력으로 사용할 수도 있기 때문에 이 Arduino 보드는 매우 작지만 사용할 수 있는 출력 또는 채널이 많이 있습니다.

PCB 디자인

그럼에도 불구하고 이 회로를 컴팩트하게 유지하기 위해 EasyEDA 무료 온라인 회로 설계 소프트웨어를 사용하여 맞춤형 PCB를 만들었습니다. 여기서는 5V와 그라운드 레일 바로 옆에 8개의 채널을 배치하여 서보와 ECS를 직접 연결할 수 있도록 했습니다. 채널 번호 9는 Arduino의 VCC 핀 근처의 별도 위치에 있으므로 예를 들어 5V를 제공하는 배터리 제거 회로 기능으로 Arduino에 전원을 공급하기 위해 ESC를 사용할 수 있습니다. 물론 VCC 핀이 해당 5V 레일에도 연결되어 있으므로 이를 위해 다른 채널을 사용할 수도 있습니다.

채널 번호 7과 8의 경우 여기에서 이러한 핀 헤더가 어떻게 중단되는지 확인할 수 있습니다. 그것들을 사용하려면 두 개의 핀을 함께 연결하기만 하면 됩니다. 프로그래밍 헤더는 오른쪽 상단 모서리에 있으며 100uF 커패시터는 전압 조정기와 NRF24L01 모듈 모두에 사용됩니다. PCB의 왼쪽 하단 모서리에 아날로그 핀을 배치했습니다.

여기서 한 가지 더 언급할 수 있습니다. 일부 Arduino Pro Mini 보드에는 다른 핀 배열이 있을 수 있으므로 Arduino Pro Mini 보드와 일치하는 것을 선택할 수 있도록 PCB 버전을 하나 더 포함시켰습니다.

다음은 이 PCB의 프로젝트 파일에 대한 링크입니다. 그래서 디자인이 끝나면 PCB 제작에 필요한 Gerber 파일을 생성했습니다.

거버 파일:

그리고 이 영상의 스폰서이기도 한 JLCPCB에서 PCB를 주문했습니다.

여기에서 Gerber 파일을 간단히 끌어다 놓을 수 있으며 업로드되면 Gerber 뷰어에서 PCB를 검토할 수 있습니다. 모든 것이 정상이면 계속해서 PCB에 대해 원하는 속성을 선택할 수 있습니다. 이제 우리는 합리적인 가격에 PCB를 주문할 수 있습니다. JLCPCB에서 처음 주문하는 경우 단돈 $2에 최대 5개의 PCB를 얻을 수 있습니다.

PCB 어셈블리

며칠 후 PCB가 도착했습니다. PCB의 품질이 우수하고 모든 것이 디자인과 동일합니다.

이제 계속해서 PCB를 조립할 수 있습니다. 먼저 Arduino 보드의 핀 헤더를 납땜해야 합니다. 이를 수행하는 편리한 방법은 브레드보드를 ​​사용하여 핀 헤더를 고정하여 납땜하는 동안 보드가 제자리에 단단히 고정되도록 하는 것입니다. 앞서 말씀드린 것처럼 보드에 따라 핀이 조금씩 다를 수 있으니 솔더링 시 참고하시기 바랍니다.

또한 그 아래 PCB에서 실행되는 일부 트레이스가 있으므로 비워 두어야 하는 접지 핀이 있습니다. 아두이노 보드를 납땜한 후 핀에서 여분의 길이를 잘라냈습니다.

다음으로 다른 모든 핀 헤더를 제자리에 배치했습니다. 우리는 암수 핀 헤더가 모두 필요하거나 실제로 사용할 핀 헤더를 선택하는 것은 귀하에게 달려 있습니다. 그러나 서보 모터와 ESC 연결이 암이므로 디지털 채널에 수 핀 헤더를 사용하는 것이 좋습니다. 그래서 쉽게 연결할 수 있습니다.

전압 조정기는 표면 실장 구성 요소이므로 납땜하는 동안 제자리에 고정하기 위해 일부 Blue-Tack 접착제를 사용했습니다. 마지막으로 두 개의 커패시터를 제자리에 납땜하면 NRF24L01 모듈을 적절한 핀 헤더에 연결할 수 있습니다.

애플리케이션 또는 필요한 범위에 따라 온보드 안테나가 있는 일반 모듈을 사용하거나 더 큰 안테나를 부착할 수 있는 모듈을 사용할 수 있으며 개방된 공간에서 최대 700미터의 무선 통신을 달성할 수 있습니다. . 이제 Arduino RC 수신기가 준비되었으며 원하는 모든 것에 사용할 수 있습니다.

수신기를 프로그래밍하거나 Arduino Pro Mini를 컴퓨터에 연결하기 위해 USB를 사용하여 프로그래밍 헤더에 연결할 수 있는 직렬 UART 인터페이스를 사용할 수 있습니다.

Arduino IDE 도구 메뉴에서 Arduino Pro 또는 Pro Mini 보드를 선택하고 적절한 프로세서 버전을 선택하고 포트를 선택하고 프로그래밍 방법을 "USBasp"로 선택해야 합니다.

이제 Arduino에 코드를 업로드할 수 있습니다.

예제 1 – Arduino RC 자동차

자, 이제 첫 번째 예를 살펴보겠습니다.

2개의 12V DC 모터로 구성된 간단한 자동차이며 이전 비디오에서 작동 방식과 제작 방법을 이미 보여드린 적이 있습니다.

참조: L298N 모터 드라이버 – Arduino 인터페이스, 작동 방식, 코드, 회로도

이번에는 제어를 위해 새로운 Arduino RC 수신기를 사용할 것입니다. DC 모터 구동에는 L298N 모터 드라이버를 사용하고 전원에는 약 12V를 제공하는 3개의 리튬 이온 배터리를 사용합니다.

아래 링크에서 이 예제에 필요한 구성 요소를 얻을 수 있습니다.

따라서 연결은 정말 간단합니다. 배터리에서 나오는 12V는 수신기의 12V 핀으로, 드라이버의 6개 제어 핀은 6채널로 연결됩니다. 모터의 속도를 제어할 수 있으려면 드라이버의 Enable A 및 Enable B 핀에 PWM 신호를 제공해야 합니다. 수신기에서 채널 번호 2, 3, 6 및 9는 PWM 신호를 출력할 수 있으므로 여기에서 드라이버의 활성화 핀을 채널 번호 2 및 6에 연결했습니다.

이제 아두이노 코드를 살펴보자.

/*
   Arduino RC Receiver - Car Example 
   by Dejan, www.HowToMechatronics.com
   Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define enA 9  // Arduino pin D9 - CH6 on PCB board - PWM output
#define in1 8  // D8 - CH5 
#define in2 7  // D7 - CH4
#define in3 6  // D6 - CH3 
#define in4 4  // D4 - CH1 
#define enB 5  // D5 - CH2 - PWM output

RF24 radio(3, 2);   // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;

// Max size of this struct is 32 bytes
struct Data_Package {
  byte j1PotX;
  byte j1PotY;
  byte j1Button;
  byte j2PotX;
  byte j2PotY;
  byte j2Button;
  byte pot1;
  byte pot2;
  byte tSwitch1;
  byte tSwitch2;
  byte button1;
  byte button2;
  byte button3;
  byte button4;
};

Data_Package data; //Create a variable with the above structure

int  steering, throttle;
int motorSpeedA = 0;
int motorSpeedB = 0;

void setup() {
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  //Serial.begin(9600);  
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening(); //  Set the module as receiver
  resetData();
}
void loop() {
  // Check whether we keep receving data, or we have a connection between the two modules
  currentTime = millis();
  if ( currentTime - lastReceiveTime > 1000 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection
    resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone jas a throttle up, if we lose connection it can keep flying away if we dont reset the function
  }
  // Check whether there is data to be received
  if (radio.available()) {
    radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
    lastReceiveTime = millis(); // At this moment we have received the data
  }
  
  // Parse the data from the Joystic 1 to the throttle and steering variables
  throttle = data.j1PotY;
  steering = data.j1PotX;  
  
  // Throttle used for forward and backward control
  // Joystick values: 0 to 255; down = 0; middle = 127; up = 255
  if (throttle < 110) {
    // Set Motor A backward
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    // Set Motor B backward
    digitalWrite(in3, HIGH);
    digitalWrite(in4, LOW);
    // Convert the declining throttle readings for going backward from 110 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed
    motorSpeedA = map(throttle, 110, 0, 0, 255);
    motorSpeedB = map(throttle, 110, 0, 0, 255);
  }
  else if (throttle > 140) {
    // Set Motor A forward
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
    // Set Motor B forward
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);
    // Convert the increasing throttle readings for going forward from 140 to 255 into 0 to 255 value for the PWM signal for increasing the motor speed
    motorSpeedA = map(throttle, 140, 255, 0, 255);
    motorSpeedB = map(throttle, 140, 255, 0, 255);
  }
  // If joystick stays in middle the motors are not moving
  else {
    motorSpeedA = 0;
    motorSpeedB = 0;
  }
  // Steering used for left and right control
  if (steering < 110) {
    // Convert the declining steering readings from 140 to 255 into increasing 0 to 255 value
    int xMapped = map(steering, 110, 0, 0, 255);
    // Move to left - decrease left motor speed, increase right motor speed
    motorSpeedA = motorSpeedA - xMapped;
    motorSpeedB = motorSpeedB + xMapped;
    // Confine the range from 0 to 255
    if (motorSpeedA < 0) {
      motorSpeedA = 0;
    }
    if (motorSpeedB > 255) {
      motorSpeedB = 255;
    }
  }
  if (steering > 140) {
    // Convert the increasing steering readings from 110 to 0 into 0 to 255 value
    int xMapped = map(steering, 140, 255, 0, 255);
    // Move right - decrease right motor speed, increase left motor speed
    motorSpeedA = motorSpeedA + xMapped;
    motorSpeedB = motorSpeedB - xMapped;
    // Confine the range from 0 to 255
    if (motorSpeedA > 255) {
      motorSpeedA = 255;
    }
    if (motorSpeedB < 0) {
      motorSpeedB = 0;
    }
  }
  // Prevent buzzing at low speeds (Adjust according to your motors. My motors couldn't start moving if PWM value was below value of 70)
  if (motorSpeedA < 70) {
    motorSpeedA = 0;
  }
  if (motorSpeedB < 70) {
    motorSpeedB = 0;
  }
  analogWrite(enA, motorSpeedA); // Send PWM signal to motor A
  analogWrite(enB, motorSpeedB); // Send PWM signal to motor B
}
void resetData() {
  // Reset the values when there is no radio connection - Set initial default values
  data.j1PotX = 127;
  data.j1PotY = 127;
  data.j2PotX = 127;
  data.j2PotY = 127;
  data.j1Button = 1;
  data.j2Button = 1;
  data.pot1 = 1;
  data.pot2 = 1;
  data.tSwitch1 = 1;
  data.tSwitch2 = 1;
  data.button1 = 1;
  data.button2 = 1;
  data.button3 = 1;
  data.button4 = 1;
}Code language: Arduino (arduino)

설명: 따라서 먼저 SPI와 RF24 라이브러리를 포함하고 일부 핀, 무선 개체 및 송신기에서 들어오는 데이터를 저장할 데이터 구조를 정의해야 합니다. 설정 섹션에서 핀 출력을 정의하고 무선 통신을 시작해야 합니다. 이것이 어떻게 작동하고 각각의 라인이 하는 일에 대한 자세한 내용은 내 상세한 NRF24L01 튜토리얼을 확인할 수 있습니다.

루프 섹션에서 데이터를 수신하는지 여부를 지속적으로 확인하고 수신하는 경우 수신 데이터를 읽습니다. 송신기 코드를 간단히 살펴보면 수신기에 어떤 종류의 데이터를 보내는지 알 수 있습니다. 모든 컨트롤러, 조이스틱, 전위차계 및 버튼에서 데이터를 읽고 해당 데이터를 단일 패키지로 수신기에 보냅니다.

따라서 해당 데이터를 읽은 후에는 데이터로 원하는 모든 작업을 수행할 수 있습니다. 이 경우 스로틀을 제어하는 ​​데 Joystick 1 Y축 값을 사용하고 스티어링을 제어하는 ​​데 X축 값을 사용합니다. 이 데이터를 별도의 스로틀 및 스티어링 변수에 넣었습니다. 조이스틱에서 얻는 값은 0에서 255 사이입니다. 따라서 조이스틱을 아래로 움직이면 차가 뒤로 움직이도록 운전자 제어 핀을 적절하게 설정하고 스로틀 값을 사용하여 이동 속도를 제어합니다. 전진, 좌회전, 우회전에도 동일한 원칙이 적용됩니다. 다시 말하지만, 이 차가 어떻게 작동하는지에 대한 자세한 자습서가 이미 있으므로 더 나은 이해를 위해 확인할 수 있습니다. 코드 하단에서 모든 값을 초기 기본값으로 재설정하는 resetData() 사용자 정의 함수를 볼 수 있으므로 무선 통신이 두절된 경우 자동차가 움직이는 것을 감지합니다.

예제 2 – Arduino RC 수신기 서보 및 브러시리스 모터 제어

자, 이제 이 Arduino RC 수신기를 사용하여 서보와 브러시리스 모터를 제어하는 ​​두 번째 예제로 넘어갈 수 있습니다.

브러시리스 모터를 제어하려면 ESC 또는 전자식 속도 컨트롤러가 필요합니다. Arduino는 단일 핀으로 ESC와 통신합니다. ESC를 제어하기 위해 Arduino는 ESC에 특정 PWM 신호를 보내고 ESC는 모터 속도를 제어합니다. 동일한 연결을 사용하는 ESC는 배터리 제거기 회로 기능을 통해 5V를 제공하므로 이를 통해 수신기에도 전원을 공급할 수 있습니다.

참조: Arduino 브러시리스 모터 제어 튜토리얼 | ESC | BLDC

서보 모터의 경우 ESC와 동일한 유형의 연결이 있으며 사용 가능한 모든 채널에 간단히 연결할 수 있습니다.

아래 링크에서 이 예제에 필요한 구성 요소를 얻을 수 있습니다.

ESC를 사용하여 서보와 브러시리스 모터를 제어하기 위한 입력 신호는 거의 동일합니다. Arduino Servo 라이브러리를 사용하여 쉽게 생성할 수 있는 특정 50Hz PWM 신호를 사용합니다.

참고:  이 설정으로 MG996R 서보를 사용하면 회로에 문제가 발생하여 Arduino Pro Mini를 태울 수 있습니다. 더 높은 전류를 끌어 5V 레일에서 전압 스파이크를 유발할 수 있습니다. Arduino Pro Mini는 5V 핀에서 최대 5.5v를 처리해야 하지만 이러한 스파이크가 발생하면 Arduino를 태울 수 있습니다. 회로를 테스트할 때 이 문제가 발생했으며 의견 섹션의 누군가도 같은 내용을 보고했습니다. 이에 대한 솔루션은 서보에 더 큰 디커플링 커패시터를 배치할 수 있지만 확실하지 않고 테스트하지 않았습니다. 따라서 이 문제를 인지하시기 바랍니다.

반면에 예에서 Arduino를 태우지 않은 두 개의 다른 MG996R 서보를 사용했는데, 아마도 그렇게 높은 스파이크를 일으키지 않았기 때문인 것 같습니다. 또한 이 예를 4개의 더 작은 S90 서보와 함께 사용했는데 문제가 없었습니다.

참조:서보 모터 작동 방식 & Arduino를 사용하여 서보를 제어하는 ​​방법

/*
  DIY RC Receiver - Servos and Brushless motors control
  by Dejan, www.HowToMechatronics.com
  Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>

RF24 radio(3, 2);   // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;
Servo esc;  // create servo object to control the ESC
Servo servo1;
Servo servo2;
int escValue, servo1Value, servo2Value;
// Max size of this struct is 32 bytes - NRF24L01 buffer limit
struct Data_Package {
  byte j1PotX;
  byte j1PotY;
  byte j1Button;
  byte j2PotX;
  byte j2PotY;
  byte j2Button;
  byte pot1;
  byte pot2;
  byte tSwitch1;
  byte tSwitch2;
  byte button1;
  byte button2;
  byte button3;
  byte button4;
};
Data_Package data; //Create a variable with the above structure
void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening(); //  Set the module as receiver
  resetData();
  esc.attach(10);   // Arduino digital pin D10 - CH9 on PCB board
  servo1.attach(4); // D4 - CH1
  servo2.attach(5); // D5 - CH2
}
void loop() {

  // Check whether we keep receving data, or we have a connection between the two modules
  currentTime = millis();
  if ( currentTime - lastReceiveTime > 1000 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection
    resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone jas a throttle up, if we lose connection it can keep flying away if we dont reset the function
  }

  // Check whether there is data to be received
  if (radio.available()) {
    radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
    lastReceiveTime = millis(); // At this moment we have received the data
  }

  // Controlling servos
  servo1Value = map(data.j2PotX, 0, 255, 0, 180); // Map the receiving value form 0 to 255 to 0 to 180(degrees), values used for controlling servos
  servo2Value = map(data.j2PotY, 0, 255, 0, 180);
  servo1.write(servo1Value);
  servo2.write(servo2Value);

  // Controlling brushless motor with ESC
  escValue = map(data.j1PotY, 127, 255, 1000, 2000); // Map the receiving value form 127 to 255 to  1000 to 2000, values used for controlling ESCs
  esc.writeMicroseconds(escValue); // Send the PWM control singal to the ESC
  
}
void resetData() {
  // Reset the values when there is no radio connection - Set initial default values
  data.j1PotX = 127;
  data.j1PotY = 127;
  data.j2PotX = 127;
  data.j2PotY = 127;
  data.j1Button = 1;
  data.j2Button = 1;
  data.pot1 = 1;
  data.pot2 = 1;
  data.tSwitch1 = 1;
  data.tSwitch2 = 1;
  data.button1 = 1;
  data.button2 = 1;
  data.button3 = 1;
  data.button4 = 1;
}Code language: Arduino (arduino)

그래서 송신기로부터 데이터를 받은 후 write() 함수를 사용하여 서보를 제어하기 위해 0에서 255까지의 값을 0에서 180까지의 값으로 변환합니다. 비슷한 방법으로 ESC를 제어하기 위한 데이터를 1000에서 2000 사이의 값으로 변환합니다. 이 예에서는 이 ESC를 조이스틱 번호 1의 중간 지점에서 위쪽 위치로 제어하므로 중간에서 값을 변환합니다. , 127 ~ 255를 1000 ~ 2000 사이의 값으로 변환합니다. 서보 라이브러리 writeMicroseconds() 함수를 사용하여 PWM 신호를 ESC로 전송하므로 브러시리스 모터의 속도를 최소에서 최대로 제어할 수 있습니다.

참조: Arduino RC 비행기 | 100% DIY

일반적으로 이러한 유형의 모터, 서보 및 브러시리스 모터를 사용하는 RC 비행기, 자동차, 보트 등을 ​​제어하는 ​​방법은 다음과 같습니다.

예시 3 – RC 자동차 모델 제어

RC 자동차에는 앞바퀴를 제어하여 좌우로 움직일 수 있는 자체 컨트롤러가 포함되어 있으며 자동차를 앞뒤로 움직일 수 있습니다.

그러나 값싼 RC카인 만큼 컨트롤은 디지털로 되어 있거나 켜짐 또는 꺼짐으로 되어 있어 좌우 최대 위치, 최대 속도까지 가능합니다. 그럼에도 불구하고 내부에 무엇이 있는지, 그리고 이를 제어하기 위해 Arduino RC 수신기를 구현하는 방법을 알아보기 위해 차를 분해했습니다.

전자 부품을 발견한 후 두 모터가 실제로는 5V에서 작동하는 단순한 DC 모터라는 것을 알았습니다. 조향을 위해 제한된 움직임을 제어하는 ​​프론트 모터도 단순한 연속 회전 DC 모터입니다.

따라서 분명히 DC 모터를 제어하는 ​​방법을 이미 알고 있으므로 이 회로 기판을 DIY Arduino 수신기로 교체하는 것은 매우 쉬울 것입니다. 수신기 외에 동시에 두 개의 모터를 구동할 수 있는 모터 드라이버만 있으면 됩니다. 첫 번째 예에서 사용한 L298N 드라이버를 포함하여 이를 위한 옵션이 많이 있습니다.

그러나 이 애플리케이션에는 너무 커서 MX1508 모터 드라이버를 선택했습니다. 이것은 H-브리지 및 PWM 제어를 특징으로 하는 간단한 이중 DC 모터 드라이버입니다. 제어 입력 핀 4개, 모터용 핀 4개, 전원 공급용 핀 2개가 있습니다.

나는 RC 자동차 회로 기판에서 모터 연결을 제거하고 드라이버에 납땜했습니다. 뒷면에 나는 전원 핀을 납땜했고 이제 남은 것은 이 드라이버를 수신기에 연결하는 것입니다. 이 RC 자동차의 전원은 자동차 바닥에 있는 4.8V Ni-Cd 배터리에서 나옵니다.

그래서 점프 와이어를 사용하여 이 핀을 Arduino의 VCC 핀에 연결하고 드라이버의 4개 제어 입력 핀도 4개의 디지털 채널에 연결했습니다. 앞서 말했듯이 이 드라이버는 PWM 제어를 지원하므로 모터 B 또는 후면 모터의 경우 PWM 채널 번호 2와 3을 사용했습니다.

아래 링크에서 이 예제에 필요한 구성 요소를 얻을 수 있습니다.

이 RC 자동차의 코드는 첫 번째 예와 매우 유사합니다.

/*
   Arduino RC Receiver - RC Model control
   by Dejan , www.HowToMechatronics.com
   Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define in3 5  // D5 - CH2 - PWM output
#define in4 6  // D6 - CH3 - PWM output
#define in1 7  // D7 - CH4
#define in2 8  // D8 - CH5


RF24 radio(3, 2);   // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;

// Max size of this struct is 32 bytes
struct Data_Package {
  byte j1PotX;
  byte j1PotY;
  byte j1Button;
  byte j2PotX;
  byte j2PotY;
  byte j2Button;
  byte pot1;
  byte pot2;
  byte tSwitch1;
  byte tSwitch2;
  byte button1;
  byte button2;
  byte button3;
  byte button4;
};

Data_Package data; //Create a variable with the above structure

int  steering, throttle;
int motorSpeedA = 0;
int motorSpeedB = 0;

void setup() {
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening(); //  Set the module as receiver
  resetData();
}
void loop() {
  // Check whether we keep receving data, or we have a connection between the two modules
  currentTime = millis();
  if ( currentTime - lastReceiveTime > 1000 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection
    resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone jas a throttle up, if we lose connection it can keep flying away if we dont reset the function
  }
  // Check whether there is data to be received
  if (radio.available()) {
    radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
    lastReceiveTime = millis(); // At this moment we have received the data
  }
  // Parse the data from the Joystic 1 to the steering and throttle variables
  steering = data.j2PotX;
  throttle = data.j1PotY;


// Throttle used for forward and backward control
  if (throttle < 110) {
    // Convert the declining throttle readings for going backward from 110 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed
    motorSpeedB = map(throttle, 110, 0, 0, 255);
    // Set Motor B backward
    analogWrite(in3, motorSpeedB);
    digitalWrite(in4, LOW);
  }
  else if (throttle > 140) {
    // Convert the increasing throttle readings for going forward from 140 to 255 into 0 to 255 value for the PWM signal for increasing the motor speed
    motorSpeedB = map(throttle, 140, 255, 0, 255);
    // Set Motor B forward
    digitalWrite(in3, LOW);
    analogWrite(in4, motorSpeedB);
  }
  // If joystick stays in middle the motors are not moving
  else {
    digitalWrite(in3, HIGH);
    digitalWrite(in4, HIGH);
  }
  
// steering used for left and right control
  if (steering < 110) {
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
  }
  if (steering > 140) {
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
  }
  // If joystick stays in middle the motors are not moving
  else {
    digitalWrite(in1, HIGH);
    digitalWrite(in2, HIGH);
  }
}
void resetData() {
  // Reset the values when there is no radio connection - Set initial default values
  data.j1PotX = 127;
  data.j1PotY = 127;
  data.j2PotX = 127;
  data.j2PotY = 127;
  data.j1Button = 1;
  data.j2Button = 1;
  data.pot1 = 1;
  data.pot2 = 1;
  data.tSwitch1 = 1;
  data.tSwitch2 = 1;
  data.button1 = 1;
  data.button2 = 1;
  data.button3 = 1;
  data.button4 = 1;
}Code language: Arduino (arduino)

우리는 조이스틱에서 오는 데이터를 사용하여 RC 자동차의 스로틀과 스티어링을 제어합니다. 뒤로 이동하기 위해 analogWrite() 함수를 사용하여 PWM 신호를 Input3 핀에서 드라이버로 보내고 input4 핀을 LOW로 유지합니다. 앞으로 나아가기 위해 반대 방향으로 진행합니다. 조이스틱이 중간에 있으면 운전자에게 모터를 제동하거나 정지하라는 명령을 내립니다. 스티어링 모터에도 동일한 원리가 사용되지만 여기서는 이 모터의 속도를 제어할 필요가 없으므로 analogWrite() 함수를 사용할 필요가 없습니다.

이 스케치를 Arduino에 업로드한 후 RC 자동차를 다시 조립해야 했습니다. 나는 작은 드라이버를 내부 하우징에 넣고 나사로 나머지 부품을 고정했습니다. 리시버와 드라이버를 다시 연결하고 리시버가 들어갈 수 있는 충분한 공간이 있는 차량 외부 하우징 아래에 놓았습니다.

그래서 우리는 이 RC 자동차를 DIY RC 송신기로 제어하도록 수정했을 뿐만 아니라 PWM 제어를 추가하여 개선하여 이제 자동차의 속도도 제어할 수 있습니다. 수정하려는 RC 모델에 DC 모터가 아닌 서보와 브러시리스 모터가 있는 경우 두 번째 예에서 설명한 방법을 따를 수 있습니다.

이 튜토리얼을 즐기고 새로운 것을 배웠기를 바랍니다. 아래 댓글 섹션에서 언제든지 질문을 하고 내 Arduino 프로젝트 컬렉션을 확인하는 것을 잊지 마세요.


제조공정

  1. DIY:HomeBrew의 온도 모니터링 및 규정
  2. 실험실 및 과학 프로젝트를 위한 온도 측정
  3. 당신의 DIY 공예 프로젝트를 위해 CNC 라우터와 CNC 레이저 커터 중에서 선택하십시오.
  4. LCD 애니메이션 및 게임
  5. Arduino와 스마트폰을 사용한 DIY 전압계
  6. Arduino 및 Nokia 5110 디스플레이가 있는 DIY 전압계
  7. Python3 및 Arduino 통신
  8. 금속 제작 프로젝트를 위한 CAD 모델의 중요성
  9. 연마 및 디버링을 위한 향상된 선반
  10. Mkr1000 핀아웃:IoT 프로젝트에 선호되는 선택