工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

RCモデルおよびArduinoプロジェクト用のDIYArduinoRCレシーバー

このチュートリアルでは、ArduinoベースのRC受信機を作成する方法を学びます。以前のビデオの1つでDIYArduinoRC送信機を作成して以来、専用の受信機を作成するようにという要望がたくさんありました。

次のビデオを見るか、以下のチュートリアルを読むことができます。

これで、これら2つのデバイスは簡単に通信でき、ワイヤレスで多くのものを制御するために使用できます。いくつかの例を通して、すべてがどのように機能するかを説明します。最初の例では、このArduino RCレシーバーを使用して、2つのDCモーターで構成される単純な車を制御します。 2番目の例では、多くの商用RC飛行機、ボート、自動車などに見られる一般的なコンポーネントであるブラシレスモーターとサーボを制御する方法を示します。それらを制御する方法を知っていれば、独自のカスタムビルドArduino送信機を使用して多くのRCモデルを簡単に変更および制御できます。

3番目の例として、このArduinoベースのRCシステムを変更して商用RCカーを制御する方法を紹介します。

ArduinoRCレシーバー回路図

まず、このシステムの回路図を見てみましょう。無線通信は、NRF24L01トランシーバモジュールに基づいています。

送信機は常にコントローラー、ジョイスティック、ボタン、ポテンショメーター、トグルスイッチからデータを送信し、受信機でこのデータを受信します。このArduino送信機の動作の詳細については、他の詳細なチュートリアルを確認してください。

また、このRC受信機は、私が作成したこの特定の送信機だけで動作するとは限らないことにも注意してください。 ArduinoボードとNRF24L01モジュールで構成される他の同様のセットアップで動作します。

それにもかかわらず、このRCレシーバーの頭脳はArduinoProMiniボードです。電源には、5Vを接続できるVCCピン、または6〜12Vを接続できるRAWピンのいずれかを使用できます。 Arduino Pro Miniには2つのバージョンがあります。たとえば、ここで使用している5Vで動作するバージョンと、3.3Vで動作するバージョンがあります。一方、NRF24L01モジュールは3.3Vで動作するため、電圧レギュレータが必要です。今回は、5Vから12Vの範囲の入力から3.3Vを出力するAMS1117電圧レギュレータを使用しています。

このArduinoRCレシーバーに必要なコンポーネントは以下のリンクから入手できます:

  • NRF24L01トランシーバモジュール……。………
  • NRF24L01 + PA+LNA…………………..……。
  • AMS11173.3V電圧レギュレータ………..
  • ピンヘッダーオス+メス………………..アマゾン /バングッド /AliExpress
  • ArduinoProMini………………..……..………..
  • 私が使用したようなArduinoProMini……

Arduinoとの通信には、NRF24L01モジュールはSPIプロトコルと2つの追加のデジタルピンを使用します。つまり、出力チャネルとして使用できる9つのデジタルピンが残っており、そのうちの2つはRXピンとTXピンです。スケッチをArduinoボードにアップロードするときは、これらのピンを何からも切断する必要があることに注意してください。そのため、別々のピンヘッダーを介して接続または切断できるようにしました。実際、アナログ入力をデジタル出力として使用することもできるので、このArduinoボードは非常に小さいですが、十分な出力またはチャネルを利用できます。

PCBデザイン

それでも、この回路をコンパクトに保つ​​ために、EasyEDAの無料オンライン回路設計ソフトウェアを使用してカスタムPCBを作成しました。ここでは、5Vとグラウンドレールのすぐ隣に8チャンネルを配置したので、サーボとECSを直接接続できます。チャネル番号9は、ArduinoのVCCピンの近くの別の位置にあるため、たとえば、5Vを提供するバッテリーエリミネーター回路機能を備えたArduinoに電力を供給するためにESCを使用できます。もちろん、VCCピンはそれらの5Vレールにも接続されているので、その目的のために他のチャネルを使用することもできます。

チャネル番号7と8については、これらのピンヘッダーでどのように中断されているかをここで確認できます。それらを使用する場合は、2つのピンを接続するだけです。プログラミングヘッダーは右上隅にあり、100uFコンデンサは電圧レギュレータとNRF24L01モジュールの両方に使用されます。 PCBの左下隅に、アナログピンを配置しました。

ここでもう1つ注意することができます。それは、一部のArduino Pro Miniボードのピン配置が異なる可能性があるため、ArduinoProMiniボードに一致するものを選択できるようにPCBのバージョンをもう1つ含めました。

>

このPCBのプロジェクトファイルへのリンクは次のとおりです。そのため、設計が完了したら、PCBの製造に必要なガーバーファイルを生成しました。

ガーバーファイル:

次に、このビデオのスポンサーでもあるJLCPCBにPCBを注文しました。

ここでは、ガーバーファイルをドラッグアンドドロップするだけで、アップロードしたら、ガーバービューアでPCBを確認できます。すべて問題がなければ、先に進んでPCBに必要なプロパティを選択できます。これで、PCBをリーズナブルな価格で簡単に注文できるようになりました。 JLCPCBからの最初の注文の場合、わずか2ドルで最大5つのPCBを入手できることに注意してください。

PCBアセンブリ

数日後、PCBが到着しました。 PCBの品質は素晴らしく、すべてが設計とまったく同じです。

これで、PCBを組み立てることができます。まず、Arduinoボードのピンヘッダーをはんだ付けする必要があります。そのための便利な方法は、ブレッドボードを使用してピンヘッダーを貼り付けることです。これにより、はんだ付け中にボードがしっかりと固定されます。先ほど申し上げましたように、ボードによってはピンが少し異なる場合がありますので、はんだ付けの際はご注意ください。

また、その下のPCBでいくつかのトレースが実行されているため、空けておく必要のあるグラウンドピンがいくつかあります。 Arduinoボードをはんだ付けしたら、ピンから余分な長さを切り取りました。

次に、他のすべてのピンヘッダーを配置しました。男性と女性の両方のピンヘッダーが必要です。または、実際に使用するピンヘッダーはユーザー次第です。ただし、サーボモーターとESC接続はメスであるため、デジタルチャネルにはオスのピンヘッダーを使用することをお勧めします。これにより、簡単に接続できます。

電圧レギュレーターは表面実装部品であるため、はんだ付け中にBlue-Tack接着剤を使用して所定の位置に保持しました。最後に、2つのコンデンサを所定の位置にはんだ付けしたら、NRF24L01モジュールを適切なピンヘッダーに取り付けることができます。

用途や必要な範囲に応じて、アンテナを搭載した通常のモジュール、またはより大きなアンテナを取り付けてオープンスペースで最大700メートルの無線通信を実現できるモジュールのいずれかを使用できます。 。これで、Arduino RCレシーバーの準備が整い、好きなように使用できるようになりました。

レシーバーのプログラミング、またはArduino Pro Miniのコンピューターへの接続には、プログラミングヘッダーに接続できるUSB-シリアルUARTインターフェイスを使用できます。

Arduino IDEツールメニューで、ArduinoProまたはProMiniボードを選択し、適切なバージョンのプロセッサを選択し、ポートを選択して、「USBasp」へのプログラミング方法を選択する必要があります。

これで、Arduinoにコードをアップロードできるようになりました。

例1-ArduinoRCカー

では、次に進んで最初の例を見てみましょう。

これは2つの12VDCモーターで構成されるシンプルな車であり、以前のビデオのいくつかで、それがどのように機能し、どのように構築するかをすでに示しました。

参照:L298Nモータードライバー– Arduinoインターフェース、仕組み、コード、回路図

今回は、新しいArduinoRCレシーバーを使用して制御します。 DCモーターの駆動には、L298Nモータードライバーを使用し、電力供給には、約12Vを供給する3つのリチウムイオンバッテリーを使用しています。

この例に必要なコンポーネントは、以下のリンクから入手できます。

  • L298Nドライバー………………………………..
  • 12V高トルクDCモーター…………..
  • プラスチックタイヤホイール付きDCモーター……。
  • ブレッドボードとジャンパー線…………

したがって、接続は非常に簡単で、バッテリーからの12Vはレシーバーの12Vピンに接続され、ドライバーの6つの制御ピンは6つのチャネルに接続されます。ここで、モーターの速度を制御できるようにするには、ドライバーのイネーブルAピンとイネーブルBピンにPWM信号を供給する必要があることに注意する必要があります。私たちの受信機では、チャネル番号2、3、6、および9がPWM信号を出力できるため、この場合、ドライバーのイネーブルピンをチャネル番号2および6に接続しました。

ここでArduinoコードを見てみましょう。

/*
   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チュートリアルを確認できます。

ループセクションでは、データを受信して​​いるかどうかを常にチェックし、受信している場合は、その受信データを読み取ります。送信機のコードをざっと見てみると、受信機にどのようなデータが送信されているかがわかります。すべてのコントローラー、ジョイスティック、ポテンショメーター、ボタンからデータを読み取り、そのデータを単一のパッケージとして受信機に送信します。

したがって、そのデータを読み取ると、それを使ってやりたいことが何でもできます。この場合、スロットルを制御するためにジョイスティック1のY軸の値を使用し、ステアリングを制御するためにX軸の値を使用します。このデータを別々のスロットル変数とステアリング変数に入れました。ジョイスティックから取得する値は0〜255です。したがって、ジョイスティックを下に動かすと、車が後方に移動するようにドライバーコントロールピンを適切に設定し、スロットル値を使用して移動速度を制御します。同じ原理が、前進、左、右への運転にも当てはまります。繰り返しになりますが、私はすでにこの車がどのように機能するかについての詳細なチュートリアルを持っているので、よりよく理解するためにそれをチェックすることができます。コードの下部に、resetData()カスタム関数があります。この関数は、すべての値を初期のデフォルト値にリセットするため、無線通信が失われた場合に、車が移動していることがわかります。

例2–ArduinoRCレシーバーサーボとブラシレスモーター制御

これで、このArduinoRCレシーバーを使用してサーボとブラシレスモーターを制御する2番目の例に進むことができます。

ブラシレスモーターを制御するには、ESCまたは電子速度コントローラーが必要です。 Arduinoは1本のピンでESCと通信します。 ESCを制御するために、Arduinoは特定のPWM信号をESCに送信し、それを使用してESCがモーター速度を制御します。同じ接続のESCは、バッテリーエリミネーター回路機能を介して5Vを提供するため、レシーバーにも電力を供給できます。

参照:Arduinoブラシレスモーター制御チュートリアル| ESC | BLDC

サーボモーターに関しては、ESCと同じタイプの接続があり、使用可能な任意のチャネルに簡単に接続できます。

この例に必要なコンポーネントは、以下のリンクから入手できます。

  • ブラシレスモーター………………………..
  • ESC30A………………………………………
  • Li-Poバッテリー……………………..……
  • MG996Rサーボモーター………………

ESCを使用してサーボとブラシレスモーターの両方を制御するための入力信号はほぼ同じです。 Arduinoサーボライブラリを使用して簡単に生成できる特定の50HzPWM信号を使用します。

注: この設定でMG996Rサーボを使用すると、回路に問題が発生し、ArduinoProMiniが焼損する可能性があります。はより高い電流を引き込む可能性があり、5Vレールで電圧スパイクを引き起こす可能性があります。 Arduino Pro Miniは5Vピンで最大5.5vを処理する必要がありますが、これらのスパイクが発生すると、Arduinoが焼ける可能性があります。回路をテストするときにこの問題が発生し、コメントセクションの誰かも同じことを報告しました。これに対する解決策は、サーボに大きなデカップリングコンデンサを配置することかもしれませんが、よくわかりません。テストしていません。したがって、この問題に注意してください。

一方、この例では、Arduinoを燃焼させなかった他の2つのMG996Rサーボを使用しました。これは、これらがそれほど高いスパイクを引き起こしていないためだと思います。また、この例を4つの小さいS90サーボで使用しましたが、問題はありませんでした。

参照:サーボモーターの仕組み&#038; 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に送信し、ブラシレスモーターの速度を最小から最大に制御できるようにします。

参照:ArduinoRC飛行機| 100%DIY

つまり、RC飛行機、車、ボートなどは通常このタイプのモーター、サーボ、ブラシレスモーターを使用しているため、これを制御する方法です。

例3–RCカーモデルの制御

RCカーには、前輪を左右に動かしたり、前後に動かしたりできる独自のコントローラーが付属しています。

ただし、安価なRCカーであるため、コントロールはデジタル、またはオンまたはオフのいずれかで、左右の最大位置と最大速度になります。それにもかかわらず、私は車を分解して、中身と、それを制御するためのArduinoRCレシーバーを実装する方法を確認しました。

電子部品を見つけたら、2つのモーターが実際には5Vで動作する単純なDCモーターであることに気づきました。ステアリングの制限された動きを制御するフロントモーターでさえ、単純な連続回転DCモーターです。

したがって、明らかに、DCモーターの制御方法はすでにわかっているので、この回路基板をDIYArduinoレシーバーに置き換えるのは非常に簡単です。レシーバーに加えて、2つのモーターを同時に駆動できるモータードライバーが必要です。最初の例で使用したL298Nドライバーでさえ、その目的のためのオプションはたくさんあります。

ただし、これはこのアプリケーションには大きすぎるため、MX1508モータードライバーを選択しました。これは、HブリッジとPWM制御を備えたシンプルなデュアルDCモータードライバーです。 4つの制御入力ピン、モーター用の4つのピン、および電源用の2つのピンがあります。

RCカーの回路基板からモーター接続をはんだ除去し、ドライバーにはんだ付けしました。裏側で電源ピンをはんだ付けしました。残っているのは、このドライバーをレシーバーに接続することです。このRCカーの電力は、車の下部にある4.8VNi-Cdバッテリーから供給されます。

そこで、ジャンプワイヤーを使用して、これらのピンをArduinoのVCCピンに接続し、ドライバーの4つの制御入力ピンも4つのデジタルチャネルに接続しました。前述したように、このドライバーはPWM制御をサポートしているため、モーターBまたはリアモーターには、PWMチャネル番号2および3を使用しました。

この例に必要なコンポーネントは、以下のリンクから入手できます。

  • MGRCRCカー…………………………………
  • MX1508DCモータードライバー………………
  • ブレッドボードとジャンパー線…………

この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()関数を使用して、input4ピンをLOWに保持しながら、PWM信号をInput3ピンでドライバーに送信します。前進するために、私たちはそれを反対の方法で行います。ジョイスティックが真ん中にある場合は、ドライバーにブレーキをかけるかモーターを停止するように命令します。ステアリングモーターにも同じ原理が使用されますが、このモーターの速度を制御する必要がないため、ここではanalogWrite()関数を使用する必要はありません。

このスケッチをArduinoにアップロードした後、RCカーを組み立て直さなければなりませんでした。小さなドライバーをハウジングの内側に置き、残りの部品をネジで固定しました。レシーバーをドライバーに再接続し、レシーバーに収まる十分な場所がある車のアウターハウジングの下に置きました。

そこで、このRCカーをDIY RC送信機で制御できるように変更しただけでなく、PWM制御を追加して車の速度も制御できるように改良しました。変更するRCモデルにDCモーターの代わりにサーボとブラシレスモーターがある場合は、2番目の例で説明した方法に従うことができます。

このチュートリアルを楽しんで、何か新しいことを学んだことを願っています。以下のコメントセクションでお気軽に質問してください。Arduinoプロジェクトのコレクションを確認することを忘れないでください。


製造プロセス

  1. DIY:HomeBrewの温度監視と規制
  2. 実験室および科学プロジェクトの温度測定
  3. DIYクラフトプロジェクトのためのCNCルーターとCNCレーザーカッターのどちらかを選択します。
  4. LCDアニメーションとゲーム
  5. Arduinoとスマートフォンを使用したDIY電圧計
  6. ArduinoとNokia5110ディスプレイを備えたDIY電圧計
  7. Python3とArduinoコミュニケーション
  8. ArduinoとRDA8057Mを使用したFMラジオ
  9. 金属加工プロジェクトにおけるCADモデルの重要性
  10. 研磨とバリ取りのための強化された旋盤
  11. Mkr1000 のピン配置:IoT プロジェクトに最適な選択肢