2020年1月28日 星期二

[RF] nRF24L01 2.4GHz 無線通訊(二) -- 加入兩個雙軸按鍵搖桿

本文旨在說明於 nRF24L01 的發射端加入兩個雙軸按鍵搖桿。我想使用左搖桿來控制水彈槍的 2 個伺服馬達和 1 個發射按鈕,使用右搖桿來控制小車的 4 個麥克納姆輪。



如果您還不熟悉 nRF24L01 模組基本的收發運作,請詳

[RF] nRF24L01 2.4GHz 無線通訊(一) -- 基本發射與接收



電路接線

發射端電路接線:

Arduino     nRF24L01    左搖桿     右搖桿
5V                                   5V            5V
3.3V           VCC
GND          GND            GND        GND
A0(註1)                          VRY     
A1(註1)                          VRX
A2(註1)                                           VRY
A3(註1)                                           VRX
D0                                   SW
D1                                                    SW
D7              CE
D8              CSN
D11            MOSI
D12            MISO
D13            SCK
(不接)        IRQ

註1:由於雙軸按鍵搖桿擺放的方式不同,會影響X軸與Y軸的配置,因此此處的腳位您需要配合自己的需求來調整。



接收端電路接線:

Arduino     nRF24L01
3.3V           VCC
GND          GND
D7              CE
D8              CSN
D11            MOSI
D12            MISO
D13            SCK
(不接)        IRQ



程式

發射端程式:

//RF_Transmitter01.ino
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Wire.h>

// Define the digital inputs
#define jB1 0  // Joystick button 1
#define jB2 1  // Joystick button 2

unsigned long currentTime, previousTime;
unsigned long elapsedTime = 100;

RF24 radio(7, 8);   // nRF24L01 (CE, CSN)
const byte address[6] = "00001"; // Address

// 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;
};

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

void setup() {
  Serial.begin(9600);

  // Define the radio communication
  radio.begin();
  radio.openWritingPipe(address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);

  // Activate the Arduino internal pull-up resistors
  pinMode(jB1, INPUT_PULLUP);
  pinMode(jB2, INPUT_PULLUP);
 
  // Set initial default values
  data.j1PotX = 127; // Values from 0 to 255. When Joystick is in resting position, the value is in the middle, or 127. We actually map the pot value from 0 to 1023 to 0 to 255 because that's one BYTE value
  data.j1PotY = 127;
  data.j2PotX = 127;
  data.j2PotY = 127;
  data.j1Button = 1;
  data.j2Button = 1;

  previousTime = currentTime;
}

void loop() {
  // Read all analog inputs and map them to one Byte value
  data.j1PotX = map(analogRead(A1), 0, 1023, 0, 255); // Convert the analog read value from 0 to 1023 into a BYTE value from 0 to 255
  data.j1PotY = map(analogRead(A0), 0, 1023, 0, 255);
  data.j2PotX = map(analogRead(A3), 0, 1023, 0, 255);
  data.j2PotY = map(analogRead(A2), 0, 1023, 0, 255);

  // Read all digital inputs
  data.j1Button = digitalRead(jB1);
  data.j2Button = digitalRead(jB2);

  // Send the whole data from the structure to the receiver
  currentTime = millis();
  if (currentTime - previousTime > elapsedTime) {
    radio.write(&data, sizeof(Data_Package));
    previousTime = currentTime;
  }
}


接收端程式:

//RF_Receiver01.ino
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8);   // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long previousTime = 0;
unsigned long currentTime = 0;
unsigned long elapsedTime = 100;

// Max size of this struct is 32 bytes
struct Data_Package {
  byte j1PotX;
  byte j1PotY;
  byte j1Button;
  byte j2PotX;
  byte j2PotY;
  byte j2Button;
};

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

int  PotX1, PotY1, PotX2, PotY2;
byte But1, But2;

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();
}

void loop() {
   // Check whether there is data to be received
  if (radio.available()) {
    radio.read(&data, sizeof(Data_Package));

    PotX1 = data.j1PotX;
    PotY1 = data.j1PotY;
    But1 = data.j1Button;
    PotX2 = data.j2PotX;
    PotY2 = data.j2PotY; 
    But2 = data.j2Button; 
 
    Serial.print(PotX1); Serial.print(" ");
    Serial.print(PotY1); Serial.print(" ");
    Serial.print(But1);  Serial.print(" ");
    Serial.print(PotX2); Serial.print(" ");
    Serial.print(PotY2); Serial.print(" ");
    Serial.println(But2); 
  }
}

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; 
}

在上傳發射端和接收端的程式之後,您可以打開接收端的 Serial Monitor(註2),您就可以看到如下圖所示。

註2:在打開 Serial Monitor 之前,或許您需要讓接收端成為目前的 COM Port。


理想中雙軸按鍵搖桿在置中時(不搖動它)所呈現的數值應該是 127,但由上圖我們可以觀察到它並非是這個值。雖然如此,它對於我們在控制伺服馬達和麥克納姆輪上面的影響似乎不大。

您可以搖動搖桿或按下搖桿上的按鍵,觀察 Serial Monitor 上的數值是否符合您的期望,如果不是,您可能要稍微調整一下電路接線(註1)。


相關網頁

https://lastminuteengineers.com/nrf24l01-arduino-wireless-communication/
https://howtomechatronics.com/projects/diy-arduino-rc-transmitter/


採購資訊

1100M nRF24L01+PA+LNA無線模組 https://goods.ruten.com.tw/item/show?21934545524992

雙軸按鍵搖桿 https://goods.ruten.com.tw/item/show?21628077440247

多功能雙軸按鍵搖桿固定板 https://goods.ruten.com.tw/item/show?21805664364959


沒有留言:

張貼留言