اتصال nRF24L01 به آردوینو کاملا آسان بوده و نیاز به المان خاصی نیست. ارتباط nRF24l01 توسط پروتکل SPI و نمایشگر کاراکتری 1602 توسط پروتکل I2C صورت میگیرد.
طراحان سیستمهای الکترونیکی از پروتکلهای ارتباطی بیسیم مختلفی مانند بلوتوث، زیگبی (Zigbee)، ESP8266 ، ماژول Wi-Fi ، ماژولهایRF ، LoRa و غیره استفاده میکنند که انتخاب پروتکل ارتباطی بستگی به نوع کاربرد مورد نظر از جانب کاربر دارد. در میان تمامی این سیستمهای ارتباطی، یک شبکه ارتباطی بیسیم محبوب ، شبکه محلی nRF24L01 است. این ماژولها در پهنای باند 2.4 گیگاهرتز باند ISM با سرعت انتقالداده از 250Kbps تا 2Mbps که مقداری استاندارد در بسیاری از کشورها بوده و قابل استفاده در کاربردهای صنعتی و پزشکی است، عمل میکنند. همچنین ادعا میشود که در صورت استفاده از آنتن مناسب، این ماژول ها قابلیت ارتباط تا فاصلهی حداکثر 100 متر را دارند.
در آموزش قبلی نحوهی کنترل سروو موتور از طریق ماژول nRF24L01 مورد بررسی قرار گرفت. در این آموزش از این ماژول برای برقراری ارتباط بی سیم بین رزبری پای و آردوینو استفاده خواهد شد. به این صورت که رزبری پای به عنوان فرستنده و آردوینو به عنوان گیرنده عمل کرده و پیام ارسال شده توسط رزبری بر روی نمایشگر کاراکتری 1602 نشان داده میشود. آموزش به دو بخش تقسیم میشود. در بخش اول ارتباط nRF24L01 با Arduino به عنوان گیرنده بررسی شده و در بخش دوم ارتباط رزبری پای با nRF24L01 عنوان فرستنده مورد بررسی قرار خواهد گرفت.
معرفی ماژول فرستنده گیرنده رادیویی NRF24L01
ماژولهای NRF24L01 ماژولهای فرستنده گیرنده (Transceiver) هستند که می توانند دادهها را بطور همزمان ارسال یا دریافت کنند. پروتکل ارتباطی این ماژول با میکروکنترلر SPI است.
ولتاژ کاری این ماژول از 1.9 ولت تا 3.6 ولت است (به طور معمول 3.3 ولت). سایر پایههای ارتباطی ماژول قابلیت تحمل 5 ولت را داشته و مستقیما به میکرو کنترلرهای 5 ولتی متصل میشوند. جریان مصرفی این ماژول در حالت آماده کار نزدیک به صفر بوده و در حالت دریافت سیگنال با بیشترین سرعت انتقال داده (Mbps2) حدود 13 میلیآمپر جریان میکشد. این میزان جریان مصرفی بسیار کم، امکان استفاده از این ماژول در پروژههای قابلحمل که انرژی را از طریق باتری تامین میکنند، فراهم میکند. مزیت دیگر استفاده از این ماژول ها این است که هر ماژول NRF میتواند به 6 ماژول دیگر متصل شده و یک شبکه با توپولوژی ستاره یا مش تشکیل دهد.
اتصال nRF24L01 به آردوینو کاملا آسان بوده و نیاز به المان خاصی نیست. ارتباط nRF24l01 توسط پروتکل SPI و نمایشگر کاراکتری 1602 توسط پروتکل I2C صورت میگیرد.
اتصال nRF24L01 به رزبری پای نیز بسیار ساده بوده و از طریق پروتکل SPI انجام میشود.
در این پروژه برنامهنویسی رزبری پای با استفاده از Python3 انجام میشود. در حالحاضر یک کتابخانه برای ماژول nRF24l01 در پایتون موجود است که میتوانید از صفحه github دانلود کنید. توجه داشته باشید کتابخانه و اسکرپت پایتون باید در یک پوشه یکسان قرار داشته باشند تا پایتون قادر به یافتن کتابخانه باشد. پس از نصب كتابخانه میتوانید کد نویسی را آغاز کنید. در مرحله اول برای دسترسی به پورتهای GPIO رزبری پای و دسترسی به توابع مربوط به زمان کتابخانههای زیر فراخوانی میشوند.
import RPi.GPIO as GPIO
import time
import spidev
from lib_nrf24 import NRF24
ذر این مرحله حالتهای GPIO توسط کانال "Broadcom SOC" یعنی با شماره BCM مشخص میشود.
GPIO.setmode(GPIO.BCM)
در گام بعدی آدرسی را به منظور برقراری ارتباط با گیرنده آردوینو تعریف کرده که این آدرس به صورت هگزا دسیمال تعریف میشود.
pipes = [[0xE0, 0xE0, 0xF1, 0xF1, 0xE0], [0xF1, 0xF1, 0xF0, 0xF0, 0xE0]]
برای ماژول رادیویی از GPIO08 به عنوان CE و GPIO25 به عنوان پین CSN استفاده میشود.
radio.begin(0, 25)
دیتا به صورت 32 بیتی ، آدرس ماژول 76 ، سرعت انتقال داده 1 مگابیت در ثانیه و میزان توان ماژول حداقل تعریف میشود.
radio.setPayloadSize(32)
radio.setChannel(0x76)
radio.setDataRate(NRF24.BR_1MBPS)
radio.setPALevel(NRF24.PA_MIN)
Pip را باز کرده تا خواندن و نوشتن دیتا بر روی ماژول انجام شود.
radio.openWritingPipe(pipes[0])
radio.printDetails()
پیام زیر به صورت string برای نمایش به آردوینو ارسال میشود.
sendMessage = list("Hi..Arduino UNO")
while len(sendMessage) < 32:
sendMessage.append(0)
اطلاعات دریافت شده همراه با زمان دریافت اطلاعات را در ماژول ثبت شده و پیام Sent the message نمایش داده میشود.
while True:
start = time.time()
radio.write(sendMessage)
print("Sent the message: {}".format(sendMessage))
send
radio.startListening()
بعد از اتمام ارسال پیام در صورتیکه ماژول در دسترس نباشد یا پیام به صورت کامل دریافت نشود ، پیغام زیر روی نمایشگر نشان داده میشود.
## while not radio.available(0):
time.sleep(1/100)
if time.time() - start > 2:
print("Timed out.") # print error message if radio disconnected or not functioning anymore
## break
در چنین حالتی ارتباط با ماژول را به مدت 3 ثانیه متوقف شده و بعد از آن مجددا ارتباط برقرار میشود..
radio.stopListening() # close radio
time.sleep(3) # give delay of 3 seconds
در این مرحله دریافت پیام از ماژول متوقف شده و ارتباط قطع میشود. بعد از 3 ثانیه ارتباط مجدداً برقرار شده تا پیام بعدی ارسال شود.
گام اول: برنامه پایتون و کتابخانهها را در یک پوشه قرار دهید.
گام دوم: برای مثال نام فایل برنامه قرستنده nrfsend.py است.
گام سوم: وارد Command Terminal رزبری پای شده و محل ذخیره فایل برنامه را با فرمان “cd” مشخص کنید.
گام چهارم: سپس فایل برنامه را باز کرده و دستور “sudo python3 your_program.py” اجرا کنید. با این کار قادر خواهید بود جزئیات و مشخصات ماژول nRf24 را ببینید. هر 3 ثانیه یکبار ارسال پیام آغاز شده و بعد از ارسال کاراکترها پیام دریافت نشان داده میشود.
روند پروگرام کردن آردوینو UNO نیز شبیه رزبری پای است. کتابخانه nRF24l01 برای آردوینو را از صفحه github دانلود کرده تا از توابع این کتابخانه برای کار با این ماژول استفاده شود. ارتباط با نمایشگر 1602 از طریق رابط I2C صورت میگیرد. بنابراین کتابخانهی Wire.h را نیز فراخوانی میکنیم. همچنین ماژول nRF24l01 از طریق پروتکل SPI نیز ارتباط برقرار میکند. برای دسترسی به توابع RF24 و نمایشگر از دو کتابخانه RF24 و LiquidCrystal_I2C استفاده کنید.
#include<SPI.h>
#include <Wire.h>
#include<RF24.h>
#include <LiquidCrystal_I2C.h>
آدرس نمایشگر 27 بوده و ابعاد آن 2x16 است. تابع زیر با توجه به این موارد تکمیل میشود.
LiquidCrystal_I2C lcd(0x27, 16, 2);
در این قسمت پینهای اتصال پایههای ماژول (CE وCS) مشخص میشوند. مطابق با اتصالات به پایههای 9 و 10 متصل شدهاند.
RF24 myRadio (9,10);
در این حرحله ارتباط آغاز شده و سطح توان ماژول مشخص میشود. همچنین آدرسpipe مطابق با آدرس رزبری پای تنظیم شده و pipe برای خواندن اطلاعات باز میشود.
radio.begin();
radio.setPALevel(RF24_PA_MAX) ;
radio.setChannel(0x76) ;
const uint64_t pipe = 0xE0E0F1F1E0LL ;
radio.openReadingPipe(1, pipe) ;
در این مرحله ارتباط I2C را برقرار شده و نمایشگر راهاندازی اولیه میشود.
Wire.begin();
lcd.begin();
lcd.home();
lcd.print("Ready to Receive");
حال ماژول منتظر دریافت پیام مانده ، در صورت دریافت ذخیره و نمایش داده میشود. سپس دریافت پیام به مدت 10 میکرو ثانیه متوقف شده و مجددا آغاز میشود.
کد کامل برنامه:
NRF Transmitter Side Code (Raspberry Pi):
import RPi.GPIO as GPIO # import gpio
import time #import time library
import spidev
from lib_nrf24 import NRF24 #import NRF24 library
GPIO.setmode(GPIO.BCM) # set the gpio mode
# set the pipe address. this address shoeld be entered on the receiver alo
pipes = [[0xE0, 0xE0, 0xF1, 0xF1, 0xE0], [0xF1, 0xF1, 0xF0, 0xF0, 0xE0]]
radio = NRF24(GPIO, spidev.SpiDev()) # use the gpio pins
radio.begin(0, 25) # start the radio and set the ce,csn pin ce= GPIO08, csn= GPIO25
radio.setPayloadSize(32) #set the payload size as 32 bytes
radio.setChannel(0x76) # set the channel as 76 hex
radio.setDataRate(NRF24.BR_1MBPS) # set radio data rate
radio.setPALevel(NRF24.PA_MIN) # set PA level
radio.setAutoAck(True) # set acknowledgement as true
radio.enableDynamicPayloads()
radio.enableAckPayload()
radio.openWritingPipe(pipes[0]) # open the defined pipe for writing
radio.printDetails() # print basic detals of radio
sendMessage = list("Hi..Arduino UNO") #the message to be sent
while len(sendMessage) < 32:
sendMessage.append(0)
while True:
start = time.time() #start the time for checking delivery time
radio.write(sendMessage) # just write the message to radio
print("Sent the message: {}".format(sendMessage)) # print a message after succesfull send
radio.startListening() # Start listening the radio
while not radio.available(0):
time.sleep(1/100)
if time.time() - start > 2:
print("Timed out.") # print errror message if radio disconnected or not functioning anymore
break
radio.stopListening() # close radio
time.sleep(3) # give delay of 3 seconds
# >
NRF Receiver Side Code (Arduino):
#include<SPI.h> // spi library for connecting nrf
#include <Wire.h> // i2c libary fro 16x2 lcd display
#include<RF24.h> // nrf library
#include <LiquidCrystal_I2C.h> // 16x2 lcd display library
LiquidCrystal_I2C lcd(0x27, 16, 2); // i2c address is 0x27
RF24 radio(9, 10) ; // ce, csn pins
void setup(void) {
while (!Serial) ;
Serial.begin(9600) ; // start serial monitor baud rate
Serial.println("Starting.. Setting Up.. Radio on..") ; // debug message
radio.begin(); // start radio at ce csn pin 9 and 10
radio.setPALevel(RF24_PA_MAX) ; // set power level
radio.setChannel(0x76) ; // set chanel at 76
const uint64_t pipe = 0xE0E0F1F1E0LL ; // pipe address same as sender i.e. raspberry pi
radio.openReadingPipe(1, pipe) ; // start reading pipe
radio.enableDynamicPayloads() ;
radio.powerUp() ;
Wire.begin(); //start i2c address
lcd.begin(); // start lcd
lcd.home();
lcd.print("Ready to Receive"); // print starting message on lcd
delay(2000);
lcd.clear();
}
void loop(void) {
radio.startListening() ; // start listening forever
char receivedMessage[32] = {0} ; // set incmng message for 32 bytes
if (radio.available()) { // check if message is coming
radio.read(receivedMessage, sizeof(receivedMessage)); // read the message and save
Serial.println(receivedMessage) ; // print message on serial monitor
Serial.println("Turning off the radio.") ; // print message on serial monitor
radio.stopListening() ; // stop listening radio
String stringMessage(receivedMessage) ; // change char to string
lcd.clear(); // clear screen for new message
delay(1000); // delay of 1 second
lcd.print(stringMessage); // print received mesage
}
delay(10);
}