GIỚI THIỆU MODULE NRF24L01 VÀ GIAO TIẾP VỚI ARDUINO Tổng quan Module thu phát song RF nRF24L01 được thiết kế để hoạt động trong vùng tần số 2 4GHz và sử dụng kỹ thuật điều chế GFSK cho việc truyền dữ[.]
Trang 1GIỚI THIỆU MODULE NRF24L01 VÀ GIAO TIẾP VỚI ARDUINO
Tổng quan
Module thu phát song RF nRF24L01 được thiết kế để hoạt động trong vùng tần số2.4GHz và sử dụng kỹ thuật điều chế GFSK cho việc truyền dữ liệu không dây Dữliệu truyền có thể đạt với các tốc độ 250kbps, 1Mbps và 2Mbps
Băng tần 2.4GHz ISM là gì? Đó là băng tần dùng cho các thiết bị công suất thấp mộttrong những băng tần dành cho công nghiệp, khoa học kỹ thuật và y tế Chẳng hạnnhư: Cordless phone, Bluetooth, mạng máy tính không dây (Wifi)…
Công suất tiêu thụ
Hoạt động với điện áp nguồn 1.9V đến 3.6V, các chân logic hoạt động 5V điều nàythuận lợi trong việc kết nối với vi điều khiển mà không cần bộ chuyển mức logic.Dòng tiêu thụ xấp xỉ 12mA
Giao tiếp SPI
Module thu phát nRF24L01 + giao tiếp qua chuẩn nối tiếp 4 chân (SPI) với tốc độ dữliệu tối đa 10Mb /giây Tất cả các tham số như tần số kênh(tổng cộng có thể 125kênh), công suất đầu ra (0 dBm, -6 dBm, -12 dBm hoặc -18 dBm) và tốc độ dữ liệu(250kbps, 1Mbps hoặc 2Mbps) qua truyền thông SPI
Chuẩn SPI sử dụng khái niệm Master và Slave trong hầu hết các ứng dụng Trong đó
vi điều khiển như: Arduino vai trò là Master và nRF24L01 + là Slave Không nhưchuẩn chuẩn I2C, số lượng Slave trên chuẩn SPI có giới hạn, với Arduino Uno chỉ có
Trang 2thể sử dụng tối đa hai Slave, nghĩa là chỉ có 2 module thu phát nRF24L01 + kết nốiđược với 1 module Arduino.
nRF24L01+ transceiver module Specification Bảng thông số kỹ thuật của nRF24L01
Module nRF24L01+ tích hợp ăng-ten onboardPhiên bản đầu tiên sử dụng ăng-ten on-board Đây là một phiên bản nhỏ gọn mangtính đột phá Tuy nhiên, ăng-ten nhỏ cũng có nghĩa là phạm vi truyền thấp hơn Vớiphiên bản này, vùng giao tiếp trong khoảng cách 100m Tuy nhiên, phạm vi trongnhà, đặc biệt là có nhiều bức tường, sẽ bị suy giảm bán kính truyền
Trang 3Module nRF24L01+ PA LNA với ăng-ten ngoài
Phiên bản thứ hai đi kèm với đầu nối SMA và ăng-ten ngoài Sự khác biệt với loạithứ nhất là được trạng bị chip RFX2401C đặc biệt, tích hợp bộ chuyển mạch PA(Power Amplifier), LNA (Low-Noise Amplifier) và chuyển mạch thu-phát Với chipnày cùng với ăng-ten ngoài làm tăng phạm vi truyền lớn hơn đáng kể khoảng 1000m.Ngoại trừ sự khác biệt này, cả hai mô-đun đều tương thích Có nghĩa là, nếu sử dụngnRF24L01 thì có thể thay thế bằng nRF24L01+ PA LNA mà không cần thực hiện bất
kỳ thay đổi nào đối với hệ thống
Trang 4Tuy nhiên, mỗi kênh chiếm băng thông dưới 1 MHz với tốc độ dữ liệu 250kbps và1Mbps Tuy nhiên, ở tốc độ dữ liệu 2Mbps, băng thông chiếm 2 MHz Vì vậy, đểđảm bảo các kênh không chồng chéo ở chế độ 2Mbps, cần thiết lập khoảng cách 2MHz giữa mỗi kênh.
Tần số kênh RF của kênh được chọn theo công thức sau:
Mạng nRF24L01+ Multiceiver
Sơ đồ trên, cho thấy bộ thu chính đóng vai trò là hub trung tâm lựa chọn thu thậpthông tin từ 6 nút truyền khác nhau cùng một lúc Bộ thu trung tâm có thể ngừngnhận dữ liệu bất cứ lúc nào và hoạt động như một máy phát Nhưng điều này chỉ cóthể được thực hiện một ống/nút tại một thời điểm
Cấu trúc đóng gói được chia thành 5 vùng khác nhau, được minh họa dưới đây
Trang 5nRF24L01+ Enhanced ShockBurst Packet Structure
Tự động giao tiếp bắt tay giữa các module nRF24L01+
Có 3 hình thức về cách hai mô-đun nRF24L01 + giao tiếp với nhau
- Trường hợp hoàn hảo Truyền thông với ACK và ngắt Khi máy phát bắt đầu truyềnthông bằng cách gửi gói dữ liệu đến máy thu Khi toàn bộ gói được truyền đi, nó sẽchờ (khoảng 130µs) để nhận gói tin xác nhận (gói ACK) Khi máy thu nhận được góidata, nó sẽ gửi gói ACK đến máy phát Khi nhận được gói ACK, máy phát xác nhậntín hiệu ngắt (IRQ) để cho biết dữ liệu mới sẽ bắt đầu
- Truyền thông trong trường hợp gói dữ liệu bị mất Đây là một trường hợp cầntruyền lại do mất gói được truyền Sau khi gói được truyền đi, phía phát chờ gói ACK
tù phía nhận Nếu máy phát không nhận được ACK trong thời gian tự động truyền lạiAuto-Retransmit-Delay (ARD), thì gói tin được truyền lại Khi máy thu nhận đượcgói truyền lại, sẽ phát gói ACK, từ đó tại máy phát tạo ra ngắt
Trường hợp truyền thông dịch với gói ACK bị mất Ở đây ngay cả khi phía thu nhậnđược gói trong lần thử đầu tiên, do mất gói ACK, phía phát cho rằng bên thu khôngnhận được gói nào cả Vì vậy, sau khi thời gian trì hoãn tự động truyền lại hết hiệulực, phía phát sẽ truyền lại gói Lúc này, phía thu nhận được 2 gói chứa IDgiốngnhau, nó sẽ loại bỏ 1 gói và gửi lại ACK
Qui trình xử lý toàn bộ các trường hợp trên được thực hiện tự động bởi chipnRF24L01 + mà không cần lập trình từ vi điều khiển
Trang 6Sơ đồ chân của module nRF24L01+
Sơ đồ chân của Module nRF24L01 được trình bày hình và Module nRF24L01PA/LNA như hình
GND Chân mass thường có hình chân vuông để làm chuẩn cho việc nhận dạng cácchân còn lại
VCC chân nguồn dương cung cấp cho module hoạt động ở mức điện áp từ 1.9V đến3.9V Có thể kết nối vào nguồn ra 3.3V từ board Arduino Chú ý kết nối nguồn 5V sẽlàm hư module nRF24L01
CE (Chip Enable) chân cho phép, hoạt động ở mức HIGH Khi được cho phépnRF24L01 sẽ truyền hoặc nhận, tùy thuộc vào chế độ hiện tại
CSN (Chip Select Not) chân này hoạt động mức LOW, bình thường giữ mức HIGH.Khi chuyển từ HIGH xuống LOW thì nRF24L01 sẽ “lắng nghe” trên port dữ liệu SPIcủa nó và đọc dữ liệu vào ngay lập tức
SCK (Serial Clock) chân nhận xung clock điều khiển đường truyền từ bus Master MOSI (Master Out Slave In) là chân ngõ vào nRF24L01
MISO (Master In Slave Out) là chân ngõ ra xuất data từ nRF24L01 đến Master
IRQ là chân ngắt có thể báo hiệu cho Master khi có data mới cần xử lý
Kết nối nRF24L01+ với Arduino UNO
Mỗi dòng Arduino có các chân SPI khác nhau cần được kết nối tương ứng, thể hiệnqua bảng sau:
Trang 7Chân SPI của các loại board
Wiring nRF24L01+ Wireless Transceiver Module to Arduino UNO
Wiring nRF24L01+ PA LNA Wireless Module to Arduino UNO
Trang 8Cần phải thực hiện hai mạch Một hoạt động như một bộ phát và một là bộ thu Hệthống kết nối cho cả hai là giống nhau.
Cần download các thư viện sẳn có của module nRF24L01 trước khi lập trình
Trang 9//address through which two modules communicate.
const byte address[6] = "00001";
Trang 10const char text[] = "Hello World";
radio.write(&text, sizeof(text));
delay(1000);
}
Giải thích:
Cần include thư viện SPI.h để điều khiển đường truyền SPI và nRF24L01.h, RF24.h
để điều khiển module RF
Tiếp theo, cần tạo một mảng kiểu byte tượng trưng cho địa chỉ đường ống thông qua
đó hai module nRF24L01+ sẽ giao tiếp với nhau
//address through which two modules communicate
const byte address[6] = "00001";
Có thể thay đổi giá trị của địa chỉ này thành bất kỳ chuỗi 5 ký tự bất kỳ tùy ý, chẳnghạn như nút “node1” Địa chỉ là cần thiết nếu có 1 mạng nhiều module Căn cứ địachỉ, có thể chọn một modle cụ thể cần giao tiếp Vì vậy trong trường hợp này, sẽ tạocùng một địa chỉ cho cả 2 phía phát và thu
Tiếp theo trong phần thiết lập: cần khởi tạo đối tượng RF bằng lệnhradio.begin() và sử dụng hàm radio.openWritingPipe(address) đểđặt địa chỉ của phía phát
//set the address
radio.openWritingPipe(address);
Trang 11Cuối cùng, sử dụng hàm radio.stopListening() có chức năng thiết lậpmodule với chức năng truyền dữ liệu.
//Set module as transmitter
radio.stopListening();
Trong phần vòng lặp: tạo một mảng ký tự để có thể gán thông điệp cần truyền là
“Hello World” Sử dụng hàm radio.write() để gửi tin nhắn đó đến phía thu.Đối số đầu tiên ở đây là thông điệp cần gửi, đối số thứ hai là số byte của thông điệpđó
const char text[] = "Hello World";
radio.write(&text, sizeof(text));
Thông qua phương thức này, có thể gửi tối đa mỗi lần 32 byte Vì đó là kích thước tối
đa của một gói tin mà nRF24L01 có thể xử lý Nếu cần một xác nhận rằng phía thu
đã nhận được dữ liệu, phương thức radio.write() trả về giá trị bool. Nếu ACKtrả về TRUE, dữ liệu đã đến được phía thu Nếu ACK trả về FALSE, nghĩa là dữ liệu
//address through which two modules communicate
const byte address[6] = "00001";
void setup()
{
Trang 12radio.openReadingPipe(0, address);
Đối số đầu tiên là số lượng luồng dữ liệu Có thể tạo tối đa 6 luồng dữ liệu tương ứngvới các địa chỉ khác nhau Ở đây chỉ tạo 1 địa chỉ cho số luồng 0 Đối số thứ hai làđịa chỉ cần thu thập dữ liệu vào luồng 0
Trang 13Bước tiếp theo là thiết lập module là máy thu và bắt đầu nhận dữ liệu Để làm điều
đó, sử dụng hàm radio.startListening(). Từ lúc đó, module sẽ chờ dữ liệu được gửi đến địa chỉ được chỉ định
//Set module as receiver
radio.startListening();
Trong vòng lặp, chương trình sẽ kiểm tra dữ liệu có được nhận từ địa chỉ sử dụng haychưa bằng radio.available(). Hàm này sẽ trả về TRUE khi có dữ liệu nhậnđược trong bộ đệm tạm thời
Cuối cùng, cần in thông điệp nhận được trên màn hình nối tiếp Nếu mọi thứ ổn vàkhông có lỗi trong kết nối, sẽ thấy thông tin hiển thị như hình… trên màn hìnhArduino IDE
nRF24L01+ Transceiver Output on Serial Monitor
Trang 14Bài thực hành 2- Truyền thông hai chiều với Arduino
Để giải thích về truyền thông không dây, ví dụ đầu tiên gửi một tin nhắn đơn giảnHello World từ Arduino này sang Arduino khác, và trong ví dụ thứ hai, sẽ minh họagiao tiếp hai chiều giữa các bo mạch Arduino
Trong đó sử dụng Joystick làm “cần” điều khiển ở Arduino thứ nhất và sẽ điều khiểnmotor servo ở Arduino thứ hai Ngược lại, sử dụng nút ấn ở Arduino thứ hai, để điềukhiển LED ở Arduino thứ nhất
Trang 15radio.openWritingPipe(addresses[1]); // 00002radio.openReadingPipe(1, addresses[0]); // 00001radio.setPALevel(RF24_PA_MIN)
Trang 16}
delay(5)
radio.stopListening();
Trang 17const byte addresses[][6] = {"00001", "00002"};
In the setup section we need to define both pipes, and note that the writing address at the first Arduino needs to be the reading address at the second Arduino, and vice versa, the reading address at the first Arduino needs to be the writing address at the second Arduino
Trong phần setup, chúng ta cần xác định cả hai đường ống và lưu ý rằng địa chỉ ghi ở Arduino đầu tiên cần phải là địa chỉ đọc ở Arduino thứ hai và ngược lại, địa chỉ đọc ở Arduino đầu tiên cần là địa chỉ ghi ở Arduino thứ hai.
radio.stopListening();
int potValue = analogRead(A0);
Trang 18int angleValue = map(potValue, 0, 1023, 0, 180);
radio.write(&angleValue, sizeof(angleValue));
On the other side, using the radio.startListening() function we set the second Arduino as receiver and we check whether there is available data While there is data available we will read it, save it to the “angleV” variable and thenuse that value to rotate the servo motor
Next, at the transmitter, we set the first Arduino as receiver and with an empty
“while” loop we wait for the second Arduino the send data, and that’s the datafor the state of the push button whether is pressed or not If the button is pressed the LED will light up So these process constantly repeats and both Arduino boards are constantly sending and receiving data
Trang 19HOW TO BUILD AN ARDUINO WIRELESS NETWORK WITH MULTIPLE NRF24L01 MODULES
Overview
As an example I made a network of 5 nodes and each of them can
communicate with any node in the network and at the same time they can work as both transmitters and receivers This example is actually set up in a way that explains how to make a much larger network, or to be precise, we can have a total of 3125 modules communicating to each other on a single
RF channel So let’s take a look how it works
In my previous tutorials we have already learned how to make a wireless communication between two Arduino boards using the NRF24L01 modules and the RF24 library Now in addition to this library, we will use
the RF24Network library, which enables in an easy way to build a wireless network with many Arduino boards communicating to each other Here’s how the network topology works
A single NRF24L01 module can actively listen up to 6 other modules at the same time
Trang 20This ability is utilized by the RF24Network library to generate a network
arranged in a tree topology, where one node is the base, and all other nodes are children of either that node or of another Each node can have up to 5 children, and this can go 5 levels deep, which means we can create a
network of total 3125 nodes Each node must be defined with a 15-bit
address, which precisely describes the position of the node within the tree.Note that if node 011 wants to talk to the node 02, the communication will have to go through the node 01 and the base node 00, so these two nodes must be active all the time in order the communication to be successful
Arduino Wireless Servo Motor Control using the RF24Network Library
Trang 21Before we explain the main example of this tutorial, for better understanding how the library works let’s make a simpler example of two Arduinos
communicating to each other Here’s the circuit diagram for this example
We can actually define the addresses of the nodes in octal format So, the address of the master or the base is 00, the base children addresses are 01
to 05, the 01 node children addresses are 011 to 051 and so on
Trang 22So using the potentiometer at the first Arduino we will control the servo motor
at the second Arduino Let’s take a look at the source codes now
Here’s the code at the potentiometer side:
/*
Arduino Wireless Network - Multiple NRF24L01 Tutorial
== Example 01 - Servo Control / Node 00 - Potentiometer ==
RF24Network network(radio); // Include the radio in the network
Trang 23void loop() {
network.update();
potentiometer value
Convert the value to 0-180
RF24NetworkHeader header(node01); // (Address where the data is going)
bool ok = network.write(header, &angleValue,
}
First we need to include both libraries RF24 and RF24Network, as well as theSPI library Then we need to create the RF24 object, and include it into the RF24Network object Here we need define the addresses of the nodes in octal format, or 00 for this node, and 01 for the other node at the servo side
In the setup section we need to initialize the network, by setting the channel and the address of this node
In the loop section we constantly need to call the update() function through which all action in the network happens Then we read the value of the
potentiometer and convert it into a value from 0 to 180 which is suitable for the servo control Then we create a network header where we assign the address of the node where the data is going At the end, using the write() function we send the data to the other node So here the first parameter contains the addresses information, the second parameter points which data will be send, and the third parameter is the size of the data
Here’s the code at the servo side:
/*
Arduino Wireless Network - Multiple NRF24L01 Tutorial
== Example 01 - Servo Control / Node 01 - Servo motor ==
*/
Trang 24RF24Network network(radio); // Include the radio in the network
network.begin(90, this_node); //(channel, node address)
myservo.attach(3); // (servo pin)
network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data
myservo.write(incomingData); // tell servo to go to a particular angle
}
}
Trang 25On the other side, at the servo motor, we need to define the libraries and the objects in the same way as explained earlier Here the address of this node inoctal format is 01 After defining the servo motor, in the loop section, using the while() loop and the available() function we constantly check whether there is any incoming data If true, we create a network header through whichthe data will be accepted and also a variable where the data will be stored Then using the read() function we read the data, and store it into the
incomingData variable At the end we use this data to move the servo motor according to the potentiometer from the other node
Arduino Wireless Network with Multiple NRF24L01 Modules
After understanding this example we can move on with the main example of this tutorial and build a wireless network of 5 Arduinos communicating to eachother Here’s a block diagram of the example
So from the base, using a potentiometer we will control the servo motor at thenode 01, with the second potentiometer we will control the LEDs at the node
022, using the button we will control the LED at node 012, and the LED here
at the base will be control using the potentiometer at node 02 Also using the infrared sensor at the node 012 we will control the LED at node 01 So we can notice that this example explains how to both transmit and receive data atthe same time, as well as how to communicate with nodes from different branches Let’s take a look at the Arduino codes now
Base 00 source code
/*