آیا از ارتباط سیمی خسته شدهاید؟ سیمها، میز کارتان را اشغال کردهاند؟ ما برای حل این مشکل راهحل داریم!
در این آموزش قصد داریم شما را با ماژول nRF24L01 که یکی از پر طرفدارترین و پر مصرفترین ماژولهای ارتباط بی سیم است آشنا کنیم. چه مبتدی باشید چه باتجربه، میتوانید در این آموزش، روش جدیدی برای ارسال و دریافت داده یاد بگیرید و از آن در پروژههای مختلف استفاده کنید.
در این آموزش، عملکرد ماژول nRF24L01 را بررسی خواهیم کرد و نحوه ارتباط آن با آردوینو و بردهای مبتنی بر ESP32/8266 برای ایجاد سیستمهای ارتباطی بیسیم را آموزش خواهیم داد.
آنچه در این آموزش یاد میگیرید
- اصول اولیه ماژول فرستنده/گیرنده nRF24L01
- نحوه انتخاب ماژول nRF24L01 مناسب برای پروژه با مقایسه گزینههای مختلف
- آشنایی با برترین کتابخانههای nRF24L01 برای آردوینو
- ایجاد یک سیستم فرستنده/گیرنده دوطرفه با ماژول nRF24L01
- درک مفهوم شبکههای مش nRF24L01 و نحوه کار آنها
- ساخت یک مثال عملی از شبکه مش nRF24L01 با استفاده از سنسور دمای DHT22 و ESP32
معرفی ماژول فرستنده/گیرنده RF بیسیم nRF24L01
nRF24L01 یک ماژول فرستنده/گیرنده بیسیم محبوب است که توسط Nordic Semiconductor توسعه یافته است. این ماژول در باند ISM 2.4 گیگاهرتز کار میکند و به دلیل سادگی و قابلیت اطمینان در برقراری اتصالات بیسیم، بهطور گسترده برای ارتباطات کوتاهبرد در پروژههای مختلف الکترونیکی، از جمله سیستمهای کنترل از راه دور، شبکههای حسگر و پروژههای اینترنت اشیا استفاده میشود. همچنین، ابعاد این ماژول حدودا 15×28 میلیمتر است که آن را برای استفاده در فضای محدود مناسب میسازد.
مشخصات مهم این ماژول به صورت زیر است:
- آنتن 4 گيگاهرتز روي بورد
- برد 100 متر (بدون مانع و با دید مستقیم در محیط بدون نویز)
- نرخ تبادل اطلاعات قابل تنظيم از 250 كيلوبيت تا 2 مگابيت بر ثانيه
- Auto Acknowledge
- Re-Transmit Auto
- Multiceiver با 6 ديتا پايپ
- داراي 32 بايت FIFO بصورت مجزا براي TX و RX
- پايههاي ورودي با تحمل ولتاژ 5 ولت
- قابليت تنظيم كانال ارتباطي از 2400 مگاهرتز تا 2525 مگاهرتز (125 كانال قابل انتخاب)
- حداقل نياز به قطعات جانبي جهت راهاندازي
ماژولهای nRF24L01 چگونه کار میکنند؟
ماژولهای ارتباط رادیویی، تنظیمات و پیکربندیهای مختلفی دارند. در اینجا، به بعضی از مهمترین آنها اشاره میکنیم و با نحوه کار و پیکربندیهای مختلف این ماژول آشنا خواهیم شد.
فرکانس کانال ارتباطی nRF24L01
ماژولهای nRF24L01 دادهها را در فرکانس خاصی که به عنوان “کانال” شناخته میشود، ارسال و دریافت میکند. برای اینکه دو یا چند ماژول در یک محیط با یکدیگر ارتباط برقرار کنند و تداخلی بین دادهها ایجاد نشود، باید در کانالهای مجزا باشند. این کانال میتواند هر فرکانسی در باند ISM 2.4 گیگاهرتز، یا به طور دقیقتر، هر فرکانسی بین 2.400 تا 2.525 گیگاهرتز (2400 تا 2525 مگاهرتز) داشته باشد.
هر کانال، کمتر از 1 مگاهرتز از پهنای باند را اشغال میکند که به معنی وجود 125 کانال مجزا در محدوده ذکر شده است. بنابراین، شما میتوانید در یک محیط، 125 ارتباط مجزا بین ماژولهای nRF24L01 داشته باشید.
شبکه Multiceiver با nRF24L01
nRF24L01 یک ویژگی دارد معروف به Multiceiver که مخفف Multiple Transmitter Single Receiver میباشد.
در یک شبکه با چند گیرنده، هر کانال RF به صورت منطقی به شش کانال داده موازی به عنوان Pipe line تقسیم میشود. به عبارت دیگر، یک Pipe، یکی از شش کانال منطقی در یک کانال فیزیکی RF است. هر Pipe line، آدرس منحصر به فرد خود را دارد که به عنوان آدرس Data Pipe شناخته میشود. قابل ذکر است که در هر لحظه، فقط یک Data Pipe میتواند یک بسته را دریافت کند.
در تصویر زیر، یک شبکه چند گیرنده نمایش داده شده است.
مقایسه ماژولهای مختلف nRF24L01
قبل از تهیه ماژول nRF24L01، بهتر است که از تفاوتها بین ماژولهای nRF24L01 موجود در بازار درک کافی داشته باشید. در این بخش تفاوتهای عمده موجود بین انواع ماژولهای nRF24L01 را معرفی میکنیم تا بر اساس آن، ماژول مناسب را انتخاب کنید.
قابلیت (PA) Power Amplification و (LNA) Low Noise Amplification: برخی از ماژولها دارای ویژگیهای تقویت توان (PA) و تقویت کم نویز (LNA) هستند که میتواند دامنه ارتباطات را افزایش دهد. این ماژولها اغلب با عنوان “nRF24L01+PA+LNA” برچسبگذاری میشوند. یکی از این ماژولها را میتوانید دراین لینک مشاهده کنید.
امکان نصب آنتن خارجی: ماژولهای مختلف ممکن است پیکربندی آنتن متفاوتی داشته باشند. برخی از ماژولها دارای آنتن داخلی هستند، در حالی که برخی دیگر یک اتصال آنتن خارجی را برای افزایش برد دارند. یکی از این ماژولها را میتوانید در این لینک مشاهده کنید.
محدوده ولتاژ: محدوده ولتاژ کار میتواند در بین ماژولها متفاوت باشد. با وجود اینکه اکثر ماژولها در محدوده 3.3 ولت کار میکنند، لازم است در انتخاب ماژول، به این پارامتر دقت داشته باشید.
نرخ داده: حداکثر سرعت داده پشتیبانی شده توسط ماژول nRF24L01 میتواند متفاوت باشد. در حالی که نرخ استاندارد داده 250 کیلوبیت در ثانیه است، برخی از ماژولها ممکن است از نرخهای بالاتر مانند 1 مگابیت در ثانیه یا 2 مگابیت در ثانیه پشتیبانی کنند.
برد مفید: محدوده موثر ارتباط میتواند بر اساس عواملی مانند وجود PA/LNA، نوع آنتن و شرایط محیطی متفاوت باشد. برخی از ماژولها ممکن است در مقایسه با بقیه برد بیشتری داشته باشند.
هزینه: هزینه ماژولهای nRF24L01 بر اساس ویژگیها و مشخصات میتواند متفاوت باشد. ماژولهایی با قابلیتهای بیشتر، مانند آنتنهای خارجی یا PA/LNA، ممکن است گرانتر از ماژولهای دیگر باشند.
سازنده و برند: تولیدکنندگان مختلف، ماژولهای nRF24L01 را تولید میکنند. کیفیت قطعات استفاده شده در آنها متفاوت است و باعث تغییر در کیفیت ارسال و دریافت داده میشود.
در تصویر زیر، انواع ماژولهای موجود را مشاهده میکنید.
تفاوت ماژولهای nRF24L01 و nRF24L01+PA/LNA
nRF24L01 و nRF24L01+PA/LNA دو نسخه از ماژول فرستنده/گیرنده بیسیم محبوب هستند که توسط Nordic Semiconductor توسعه یافتهاند. با وجود شباهتهای زیاد، تفاوتهای کلیدی دارند.
PA مخفف Power Amplifier است. این سیستم، سیگنالی را که توسط تراشه PA/LNA+nRF24L01 ارسال میشود، تقویت میکند. LNA مخفف Low-Noise Amplifier است و وظیفه آن تقویت سیگنال بسیار ضعیف دریافتی از آنتن (معمولاً زیر میکروولت یا -100dBm) تا سطح ولتاژ قابل فهمتر (معمولاً حدود 0.5 تا 1 ولت) است.
Duplexer دو سیگنال را ایزوله میکند و از اعمال خروجی PA نسبتاً قدرتمند بر ورودی حساس LNA جلوگیری میکند.
اگر ماژول nRF24L01 و ماژول nRF24L01+PA/LNA را مقایسه کنیم، به نتایج زیر دست پیدا خواهیم کرد.
ماژول nRF24L01:
این ماژول، نسخه اصلی ماژول است که بدون تقویتکننده توان خارجی (PA) یا تقویتکننده کم نویز (LNA) میباشد. این محصول برد محدودی دارد که معمولاً برای ارتباطات کوتاهبرد در یک اتاق (چند متر) مناسب است.
همچنین، آنها معمولاً با یک آنتن PCB داخلی عرضه میشوند که جمع و جور است اما ممکن است محدودۀ ارتباط موثر را کاهش دهد. مصرف انرژی nRF24L01 در مقایسه با نوع PA و LNA کمتر است و معمولاً ارزانتر نیز میباشد.
ماژول nRF24L01+PA/LNA:
نسخه nRF24L01+PA/LNA شامل تقویتکننده توان خارجی (PA) و تقویتکننده کم نویز (LNA) است که به طور قابل توجهی محدوده ارتباطی را افزایش می دهد. این ماژول برای کاربردهایی طراحی شده است که نیاز به دسترسی بیشتر و قدرت سیگنال بهبودیافته دارند و آن را برای پروژههایی با مسافتهای طولانیتر مناسب می کند. ممکن است با یک آنتن خارجی یا یک کانکتور آنتن ارائه شود که انعطاف پذیری را برای استفاده از انواع مختلف آنتن برای سفارشیسازی بیشتر فراهم می کند. با اضافه شدن اجزای PA/LNA ممکن است مصرف انرژی در مقایسه با ماژول اصلی nRF24L01 کمی بیشتر شود.
چگونه برد ماژولهای nRF24L01 را افزایش دهیم؟
اگر میخواهید برد ماژول های NRF24L01 را افزایش دهید، نکات زیر را در نظر بگیرید:
- ارتقا آنتن: یکی از مؤثرترین راهها برای بهبود برد، ارتقای آنتنهای فرستنده و گیرنده است. میتوانید آنتن PCB داخلی را با یک آنتن خارجی جایگزین کنید.
برای عملکرد بهتر، از آنتنهایی با بهره dBi بالاتر استفاده کنید. آنتن 2.4 گیگاهرتز با بهره dBi 2 یا بالاتر یک انتخاب رایج است.
- نصب خازن: خازنها را در نزدیکی پایههای Vcc و GND ماژولهای NRF24L01 قرار دهید تا تغذیه تثبیت شود و نویز را فیلتر کند.
- کاهش نرخ داده: کاهش نرخ داده میتواند محدوده تحت پوشش را بهبود بخشد. میتوانید با نرخ دادههای پایینتر آزمایش کنید تا ببینید آیا نیازهای شما را برآورده میکند یا خیر.
- استفاده از از ماژول های PA/LNA: برخی از ماژولهای nRF24L01 دارای تقویتکننده توان داخلی (PA) و تقویت کننده کم نویز (LNA) هستند. این ماژولها میتوانند برد بهتری نسبت به ماژولهای استاندارد ارائه دهند.
- کاهش تداخل: تداخل سایر دستگاههای الکترونیکی که در محدوده 4 گیگاهرتز کار میکنند را به حداقل برسانید. روترهای Wi-Fi، اجاقهای مایکروویو و سایر دستگاههای بیسیم میتوانند با nRF24L01 تداخل داشته باشند.
- قدرت سیگنال و RSSI: برای سنجش کیفیت سیگنال، نشانگر قدرت سیگنال دریافتی (RSSI) را کنترل کنید. میتوانید از این اطلاعات برای بهینهسازی قرار دادن ماژولها برای ارتباط بهتر استفاده کنید.
- ایجاد خط دید مستقیم (LOS): در صورت امکان از یک خط دید واضح بین فرستنده و گیرنده اطمینان حاصل کنید. موانعی مانند دیوارها و سایر موانع فیزیکی میتوانند به میزان قابل توجهی برد موثر را کاهش دهند.
کاربردهای ماژول فرستنده/گیرنده RF بیسیم nRF24L01
در اینجا برخی از کاربردها و موارد استفاده رایج از nRF24L01 آورده شده است:
- شبکههای حسگر بیسیم: nRF24L01 به طور گسترده در ایجاد شبکههای حسگر بیسیم استفاده میشود که در آن چندین گره حسگر با یک کنترلکننده مرکزی یا با یکدیگر ارتباط برقرار میکنند. این شبکهها معمولاً در اتوماسیون خانگی، نظارت صنعتی و سنجش محیطی استفاده میشوند.
- سیستمهای کنترل از راه دور: این ماژول اغلب در برنامههای کنترل از راه دور، مانند کنترل پهپادها، سیستمهای رباتیک یا هر وسیلهای که نیاز به فرمان و کنترل بیسیم دارد، استفاده میشود.
- پروژههای اینترنت اشیا: nRF24L01 در پروژههای اینترنت اشیا، ارتباط بین دستگاههای مختلف اینترنت اشیا را تسهیل می کند و به آنها اجازه میدهد تا به صورت بیسیم دادهها را مبادله کنند. این برای برنامههایی مانند سیستمهای خانه هوشمند، دستگاههای پوشیدنی و موارد دیگر مفید است.
- ثبت دادهها و تلهمتری: nRF24L01 میتواند برای انتقال بیسیم دادهها از مکانهای دور به یک مرکز داده ثبت یا ایستگاه نظارت استفاده شود. این امر به ویژه در سناریوهایی که اجرای کابلهای فیزیکی غیرعملی است بسیار ارزشمند است.
- کاربردهای کم مصرف: مصرف انرژی کم nRF24L01 آن را برای دستگاههایی که با باتری کار می کنند مناسب میکند و عمر عملیاتی دستگاهها را در برنامههایی که بهرهوری انرژی بسیار مهم است افزایش میدهد.
پایههای ماژول nRF24L01
ماژول nRF24L01 دارای 8 پایه است که در تصویر زیر مشاهده میکنید. ماژولهای دارای PA و LNA نیز دارای آرایش پایههای مشابهی هستند.
عملکرد پایهها به صورت زیر است:
- VIN: تغذیه ماژول (1.9 الی 3.9 ولت)
- GND: زمین
- MOSI: خط ارسالی اطلاعات برای پروتکل SPI
- MISO: خط دریافتی اطلاعات برای پروتکل SPI
- SCK: همزمانسازی برای پروتکل SPI
- IRQ: وقفه برای پروتکل SPI
- CSN: انتخاب ماژول برای پروتکل SPI (معکوس)
- CE: فعالسازی پروتکل SPI
کتابخانههای محبوب nRF24L01 برای آردوینو
چندین کتابخانه آردوینو برای کار با ماژولهای فرستنده/گیرنده nRF24L01 موجود است. در زیر تعدادی از کتابخانههای محبوب برای ارتباط nRF24L01 با آردوینو آورده شده است. با کلیک بر روی عنوان هریک از کتابخانههای زیر، میتوانید آنها را دانلود کنید.
TMRh20 RF24 (RF24Network, RF24Mesh): این کتابخانه که توسط TMRh20 توسعه یافته، کتابخانه RF24 را با افزودن ویژگیهایی مانند عملکرد شبکه و مش گسترش میدهد. RF24Network ایجاد ساختارهای شبکه را ممکن میسازد و RF24Mesh قابلیتهای شبکه مش را فراهم می کند.
Mirf: کتابخانه Mirf استفاده از ماژولهای nRF24L01 را با ارائه یک رابط ساده آسان میکند. استفاده از این کتابخانه برای افراد مبتدی و کسانی که فقط قصد آشنایی با این ماژول را دارند، مناسب است.
Maniacbug NRF24L01: این کتابخانه مجموعهای قوی و مستند از عملکردها را برای کار با ماژولهای nRF24L01 ارائه میدهد. از پیکربندیهای مختلف پشتیبانی میکند و به عنوان یکی از کتابخانهها با قابلیت اطمینان بالا شناخته میشود.
لوازمی که به آن احتیاج دارید
قطعات مورد نیاز برای ساخت هر دست server یا client به شرح زیر است. با توجه به نیاز پروژه، تعداد آنها را تعیین کنید.
*: از هر برد آردوینو یا ESP32/8266 دیگر نیز میتوانید استفاده کنید.
لیست انواع ماژولهای NRF24L01 که برای ارتباط، حداقل به 2 عدد از آنها نیاز دارید و نیازی نیست که هر دو از یک مدل باشند.
راهاندازی ماژول فرستنده/گیرنده nRF24L01 با آردوینو
گام اول: سیمبندی مدار فرستنده و گیرنده
همانند تصویر زیر، پایههای SPI آردوینو را به پایههای SPI ماژول nRF24L01 متصل کنید. 2 عدد از مدار زیر را برای ایجاد فرستنده و گیرنده بسازید.
در صورتی که قصد استفاده از ماژول NodeMCU به جای آردوینو UNO را داشته باشید، پایههای SPI برد NodeMCU را همانند تصویر زیر به پایههای SPI ماژول nRF24L01 متصل کنید. از آنجا که مدار تغذیه این برد 3.3 ولت است، میتوانید از این پایه جهت تغذیه ماژول nRF24L01 استفاده کنید. هر یک از ماژولهای NodeMCU زیر، دارای آرایش چیدمان پایههای یکسانی هستند.
برد توسعه NodeMcu دارای هسته وایفای ESP8266 و مبدل CH340
برد توسعه NodeMcu دارای هسته وایفای ESP8266 و مبدل CP2102 رابط تایپ C
گام دوم: نصب کتابخانه
کتابخانه Maniacbug NRF24L01 را -که در بخشهای قبلی به شما معرفی کردیم- در نرمافزار آردوینو نصب کنید
گام سوم: کد آردوینوی سمت گیرنده nrf24l01
کد زیر را بر روی آردوینوی سمت گیرنده آپلود کنید. توضیحات کد در آن به صورت کامنت درج شده است. با مطالعه آن و متن آموزش، نحوه عملکرد کد را کاملاً متوجه خواهید شد.
/*
nRF24L01
modified on Sep 8, 2020
by Mohammed Damirchi @ ElectroPeak
https://electropeak.com/
*/
/* 1 ch NRF 24 TRANSMITTER example.
Module // Arduino UNO // ESP32
GND -> GND -> GND
Vcc -> 3.3V(External)-> 3.3v
CE -> D9 -> D4
CSN -> D10 -> D5
CLK -> D13 -> D18
MOSI -> D11 -> D23
MISO -> D12 -> D19
*/
/* First we include the libraries.
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <printf.h>
/*//////////////////////////////////////////////////////*/
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) ||defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
#define CSN 10
#define CE 9
#elif defined(ESP32)
#define CSN 5
#define CE 4
#else
#error "Make Config you're self"
#endif
#define Debug_mode false
/*Create a unique pipe out. The receiver has to
wear the same unique code*/
const uint64_t pipeIn = 0x662266; //IMPORTANT: The same as in the receiver!!!
/*//////////////////////////////////////////////////////*/
/*Create the data struct we will send
The sizeof this struct should not exceed 32 bytes
This gives us up to 32 8 bits channals */
RF24 radio(CE, CSN); // select CSN and CE pins
/*//////////////////////////////////////////////////////*/
//Create a struct to send over NRF24L01
struct MyData {
byte test;
};
MyData data;
/*//////////////////////////////////////////////////////*/
//This function will only set the value to 0 if the connection is lost...
void resetData()
{
data.test = 0;
}
/**************************************************/
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600); //Set the speed to 9600 bauds if you want.
//You should always have the same speed selected in the serial monitor
resetData();
radio.begin();
if (Debug_mode)
printf_begin();
radio.setDataRate(RF24_250KBPS); //speed RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
radio.openWritingPipe(pipeIn);//Open a pipe for writing
radio.openReadingPipe(1, pipeIn);//Open a pipe for reading
radio.openReadingPipe(2, pipeIn);//Open a pipe for reading
radio.openReadingPipe(3, pipeIn);//Open a pipe for reading
radio.openReadingPipe(4, pipeIn);//Open a pipe for reading
radio.openReadingPipe(5, pipeIn);//Open a pipe for reading
radio.setAutoAck(true); // Ensure autoACK is enabled
radio.setChannel(108);// Set RF communication channel.
radio.setPALevel(RF24_PA_MAX); //translate to: RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM, and RF24_PA_HIGH=0dBm.
radio.enableDynamicPayloads(); //This way you don't always have to send large packets just to send them once in a while. This enables dynamic payloads on ALL pipes.
//radio.disableDynamicPayloads();//This disables dynamic payloads on ALL pipes. Since Ack Payloads requires Dynamic Payloads, Ack Payloads are also disabled. If dynamic payloads are later re-enabled and ack payloads are desired then enableAckPayload() must be called again as well.
radio.setCRCLength(RF24_CRC_16); // Use 8-bit or 16bit CRC for performance. CRC cannot be disabled if auto-ack is enabled. Mode :RF24_CRC_DISABLED ,RF24_CRC_8 ,RF24_CRC_16
radio.setRetries(10, 15);//Set the number of retry attempts and delay between retry attempts when transmitting a payload. The radio is waiting for an acknowledgement (ACK) packet during the delay between retry attempts.Mode: 0-15,0-15
radio.startListening();//Start listening on the pipes opened for reading.
}
/******Reset the received data to 0 if connection is lost******/
unsigned long lastRecvTime = 0;
void recvData()
{
while ( radio.available() )//Check whether there are bytes available to be read
{
radio.read(&data, sizeof(MyData));//Read payload data from the RX FIFO buffer(s).
lastRecvTime = millis(); //here we receive the data
}
}
/**************************************************************/
void loop()
{
recvData(); //Resive Data
unsigned long now = millis();
//Here we check if we've lost signal, if we did we reset the values
if ( now - lastRecvTime > 1000 ) {
// Signal lost?
resetData();
}
Serial.print("Resive Value: "); Serial.println(data.test);
analogWrite(LED_BUILTIN, data.test);
delay(100);
if (Debug_mode)
radio.printDetails();//Show debug data
توضیحات کد
در این قسمت، عملکرد قسمتهای مهم کد فوق را به شما توضیح خواهیم داد:
- خط 49: ایجاد شی (Object) لازم برای ماژول با مشخص کردن پایههای CS و CSN
RF24 radio(CE, CSN); // select CSN and CE pins
- خط 78: تعیین سرعت انتقال داده
radio.setDataRate(RF24_250KBPS);
- خط 79: مشخص کردن گیرنده برای فرستنده
radio.openWritingPipe(pipeIn);
- خط 80 الی 84: مشخص کردن فرستنده برای گیرنده (ها)
radio.openReadingPipe(1, pipeIn);
- خط 85: فعالسازی قابلیت Auto Acknowledgment
radio.setAutoAck(true);
- تعیین کانال رادیویی
radio.setChannel(108);
- خط 87: مقدار توان مصرفی را برای ماژول مشخص میکند. این مقدار باید با توجه به فاصله فرستنده و گیرنده از یکدیگر تعیین گردد.
radio.setPALevel(RF24_PA_MAX);
- خط 90: تنظیم طول عبارت CRC
radio.setCRCLength(RF24_CRC_16);
- خط 92: فعال شدن حالت گیرنده
radio.startListening();
- خط 101: انتظار برای ورود داده
while ( radio.available() )
- خط 103: دریافت داده از RF
radio.read(&data, sizeof(MyData));
گام چهارم: کد آردوینو سمت فرستنده nrf24l01
کد زیر را بر روی آردوینوی سمت فرستنده آپلود کنید. توضیحات کد در آن به صورت کامنت درج شده است. با مطالعه آن و متن آموزش، نحوه عملکرد کد را کاملاً متوجه خواهید شد.
/*
nRF24L01
modified on Sep 8, 2020
by Mohammed Damirchi @ ElectroPeak
https://electropeak.com/
*/
/* 1 ch NRF 24 TRANSMITTER example.
Module // Arduino UNO // ESP32
GND -> GND -> GND
Vcc -> 3.3V(External)-> 3.3v
CE -> D9 -> D4
CSN -> D10 -> D5
CLK -> D13 -> D18
MOSI -> D11 -> D23
MISO -> D12 -> D19
*/
/* First we include the libraries. Download it from
my webpage if you donw have the NRF24L01 library */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <printf.h>
/*//////////////////////////////////////////////////////*/
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) ||defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
#define CSN 10
#define CE 9
#elif defined(ESP32)
#define CSN 5
#define CE 4
#else
#error "Make Config you're self"
#endif
#define Debug_mode false
/*Create a unique pipe out. The receiver has to
wear the same unique code*/
const uint64_t pipeOut = 0x662266; //IMPORTANT: The same as in the receiver!!!
/*//////////////////////////////////////////////////////*/
/*Create the data struct we will send
The sizeof this struct should not exceed 32 bytes
This gives us up to 32 8 bits channals */
RF24 radio(CE, CSN); // select CSN and CE pins
/*//////////////////////////////////////////////////////*/
//Create a struct to send over NRF24L01
struct MyData {
byte test;
};
MyData data;
byte count = 0;
/*//////////////////////////////////////////////////////*/
//This function will only set the value to 0 if the connection is lost...
void resetData()
{
data.test = 0;
}
void setup()
{
Serial.begin(9600);
if (Debug_mode)
printf_begin();
radio.begin();
radio.setDataRate(RF24_250KBPS); //speed RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
radio.openWritingPipe(pipeOut); //Open a pipe for writing
radio.openReadingPipe(0, pipeOut); //Open a pipe for reading
radio.setChannel(108);// Set RF communication channel.
radio.setPALevel(RF24_PA_MAX); //translate to: RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM, and RF24_PA_HIGH=0dBm.
radio.enableDynamicPayloads(); //This way you don't always have to send large packets just to send them once in a while. This enables dynamic payloads on ALL pipes.
//radio.disableDynamicPayloads();//This disables dynamic payloads on ALL pipes. Since Ack Payloads requires Dynamic Payloads, Ack Payloads are also disabled. If dynamic payloads are later re-enabled and ack payloads are desired then enableAckPayload() must be called again as well.
radio.setCRCLength(RF24_CRC_16); // Use 8-bit or 16bit CRC for performance. CRC cannot be disabled if auto-ack is enabled. Mode :RF24_CRC_DISABLED ,RF24_CRC_8 ,RF24_CRC_16
radio.setRetries(10, 15);//Set the number of retry attempts and delay between retry attempts when transmitting a payload. The radio is waiting for an acknowledgement (ACK) packet during the delay between retry attempts.Mode: 0-15,0-15
radio.setAutoAck(true); // Ensure autoACK is enabled
radio.stopListening();//Stop listening for incoming messages, and switch to transmit mode.
resetData();
}
/**************************************************/
void loop()
{
count++;
data.test = count;//fill data to MyData
Serial.print("Send");
Serial.println(count);
if (count == 254) {
count = 0;
}
NRF24L01_Transmit();//Transmit MyData
delay(200);
}
void NRF24L01_Transmit() {
radio.writeFast(&data, sizeof(MyData));//Transmit Data. use one of this two: write() or writeFast()
if (Debug_mode)
radio.printDetails();//Show debug data
bool OK = radio.txStandBy();//Returns 0 if failed. 1 if success.
delayMicroseconds(50);
radio.flush_tx();//Empty all 3 of the TX (transmit) FIFO buffers
}
توضیحات کد
برای فهم بهتر این کد، قسمت توضیحات کد سمت گیرنده را مطالعه کنید.
گام پنجم: اجرای کد
پس از آپلود کدهای فرستنده و گیرنده بر روی میکروکنترلرهای خود، پنجره Serial Monitor نرمافزار آردوینو را برای هر دوی آنها باز کنید. اطلاعات ارسالشده و دریافتشده در آن نمایش داده خواهد شد.
ایجاد شبکه با nRF24L01، تبادل داده بین آنها و نمایش آن روی وب سرور
در این قسمت، قصد داریم شما را با نحوه ایجاد یک شبکه مش بیسیم (تصویر زیر) با استفاده از nRF24L01 آشنا کنیم. استفاده از این روش برای تبادل داده، برای کارهایی که نیاز به ارتباط همزمان با چندین ایستگاه (ند) وجود داشته باشد، کارایی بهتری دارد.
ند مرکزی تصویر فوق، به عنوان گره بیس عمل میکند و دو وظیفه کلی را بر عهده دارد. ابتدا اطلاعات فرستادهشده از ندهای دیگر را جمعآوری کرده و سپس آنها را بر روی وب سرور آپلود میکند. اطلاعات ارسالی هر ند را میتواند با ایجاد تغییرات در کد، متناسب با نیاز خود تغییر دهید.
در ادامه، مراحل انجام این پروژه را به صورت گام به گام توضیح میدهیم.
گام اول: نصب کتابخانههای مورد نیاز
ابتدا کتابخانههای زیر را دانلود کرده و در نرمافزار آردوینو نصب کنید.
گام دوم: سیمبندی گرههای فرعی
همانند مداری که در بخش قبل نمایش دادیم، پایههای SPI آردوینو را به ماژول nRF24L01 وصل کنید.
سیمبندی همه ندهای فرستنده یکسان هستند. تنها با تغییر سنسور استفادهشده (که در اینجا پتانسیومتر است)، میتوانید اطلاعات خواندهشده از آن را در شبکه nRF24L01 ارسال کنید
گام سوم: کد گرههای فرعی (کلاینت)
توضیحات کد به صورت کامنت در آن درج شده است. با مطالعه آنها میتوانید جزئیات مراحل مختلف کد را بفهمید.
/*
nRF24L01 Network
modified on Jan 8, 2024
by Majid Merati @ ElectroPeak
https://electropeak.com/
*/
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) ||defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
#define CSN 10
#define CE 9
#elif defined(ESP32)
#define CSN 5
#define CE 4
#elif defined(ESP8266)
#define CSN D0
#define CE D4
#else
#error "Make Config you're self"
#endif
RF24 radio(CE, CSN); //RF24 (CE,CSN)
RF24Network network(radio); // Include the radio in the network
const uint16_t Base_node = 00; // Address of the base node in Octal ( 04,031, etc)
const uint16_t this_node = 01; // Address of this node node in Octal
const unsigned long interval = 1000; //How often to send data to the base unit (ms)
unsigned long last_sent; // last time we sent data
void setup() {
SPI.begin();
Serial.begin(9600);
radio.begin();
network.begin(90, this_node); //(channel, node address)
radio.setDataRate(RF24_250KBPS);
}
void loop() {
network.update();
unsigned long now = millis();
if (now - last_sent >= interval) { // If it's time to send a data, send it!
last_sent = now;
unsigned long temperature = analogRead(A0);
Serial.println(temperature);
RF24NetworkHeader header(Base_node); // (Address where the data is going)
bool ok = network.write(header, & temperature, sizeof(temperature)); // Send the data to base node
}
}
پس از آپلود کردن کد بر روی آردوینو، هر ثانیه یکبار مقدار آنالوگ پایه A0 خوانده میشود و از طریق nRF24L01 به ند بیس ارسال میشود.
همانطور که اشاره کردیم، هر سنسوری را میتوانید به آردوینو وصل کنید و مقدار آن را بخوانید و ارسال کنید. اغلب سنسورهای موجود در فروشگاه electropeak دارای آموزشهای راهاندازی هستند که میتوانید با مطالعه آنها مقادیر اندازهگیریشده هرکدام را به دست آورید.
گام چهارم: سیمبندی گره بیس (سرور)
در گره بیس، ما از برد NodeMCU استفاده کردیم تا اطلاعات را بر روی یک وب سرور نمایش دهیم. سیمبندی گره بیس را مطابق تصویری که در قسمت قبل، برای اتصال ماژول nRF24L01 به NodeMCU ارائه شد، انجام دهید.
گام پنجم: کد بیس (سرور)
توضیحات کد به صورت کامنت در آن درج شده است. با مطالعه آنها میتوانید جزئیات مراحل مختلف کد را بفهمید.
/*
nRF24L01 Network
modified on Jan 8, 2024
by Majid Merati @ ElectroPeak
https://electropeak.com/
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#ifndef STASSID
#define STASSID "************" //Please type your Wifi network SSID
#define STAPSK "************" //Please type your Wifi network Pass
#endif
const char *ssid = STASSID;
const char *password = STAPSK;
ESP8266WebServer server(80); //Server port No.
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) ||defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
#define CSN 10
#define CE 9
#elif defined(ESP32)
#define CSN 5
#define CE 4
#elif defined(ESP8266)
#define CSN D0
#define CE D4
int analog_read[10];
RF24 nRF (CE, CSN); // nRF24L01 (CE,CSN)
RF24Network network(nRF); // Include the radio in the network
const uint16_t Base_node = 00; // Address of this node in Octal format ( 04,031, etc)
const uint16_t node01 = 01; // Address of the other node in Octal format
const uint16_t node02 = 02;
const uint16_t node03 = 03;
void handleRoot() {
char temp[400];
int sec = millis() / 1000;
int min = sec / 60;
int hr = min / 60;
snprintf(temp, 400,
"<html>\
<head>\
<meta http-equiv='refresh' content='5'/>\
<title>ESP8266 Data Server</title>\
<style>\
body { background-color: #000000; font-family: Arial, Helvetica, Sans-Serif; Color: #ffff00; }\
</style>\
</head>\
<body>\
<h1>Analog data charts</h1>\
<p>Uptime: %02d:%02d:%02d</p>\
<img src=\"/test.svg\" />\
</body>\
</html>",
hr, min % 60, sec % 60
);
server.send(200, "text/html", temp);
}
void handleNotFound() {
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
}
void drawGraph() {
String out;
out.reserve(750);
char temp[70];
out += "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"400\" height=\"150\">\n";
out += "<rect width=\"400\" height=\"150\" fill=\"rgb(100, 100, 100)\" stroke-width=\"2\" stroke=\"rgb(210, 210, 0)\" />\n";
out += "<g stroke=\"yellow\">\n";
unsigned long Temperature;
network.update(); //Update the network state
while ( network.available() ) { // Is there any incoming data?
RF24NetworkHeader header;
network.read(header, &Temperature, sizeof(Temperature)); //Read incoming data and store it
if (header.from_node == 1) { // If data comes from Node 01
//Serial.println(Temperature);
for (int j = 0; j < 10; j++) //store read value on array to show on graph
{
analog_read[j] = analog_read[j + 1];
}
analog_read[9] = map(Temperature, 0, 1023, 0, 130);
for (int x = 0; x < 10; x++)
{
sprintf(temp, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke-width=\"1\" />\n", x * 44, 140 - analog_read[x], (x + 1) * 44, 140 - analog_read[x + 1]);
out += temp;
}
out += "</g>\n</svg>\n";
server.send(200, "image/svg+xml", out);
}
if (header.from_node == 2) { // If data comes from Node 02
digitalWrite(13, HIGH); // Turn on the LED
delay(100);
digitalWrite(13, LOW); //// Turn off the LED
}
}
}
void setup(void) {
SPI.begin();
nRF.begin();
network.begin(90, Base_node); //(channel, node address)
nRF.setDataRate(RF24_250KBPS);
pinMode(button, INPUT_PULLUP);
pinMode(led, OUTPUT);
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (MDNS.begin("esp8266")) {
Serial.println("MDNS responder started");
}
server.on("/", handleRoot);
server.on("/test.svg", drawGraph);
server.on("/inline", []() {
server.send(200, "text/plain", "this works as well");
});
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop(void) {
server.handleClient();
MDNS.update();
}
توضیحات کد
برای فهم بهتر این کد، ابتدا توضیحات کد قسمت nRF24L01 گیرنده را مطالعه کنید.
- خط 43 الی 45: تعریف گرههای موجود در شبکه
const uint16_t node01 = 01;
const uint16_t node02 = 02;
const uint16_t node03 = 03;
- خط 49 الی 75: کد html برای ایجاد صفحه وب سرور
- خط 93 الی 130: ایجاد نمودار در صفحه وب و نمایش دادههای دریافتی از گرههای Slave
قبل از آپلود کردن این کد بر روی ESP8266/32، ابتدا SSID و PASSWORD شبکه WiFi خود را در خط 12 و 13 کد ویرایش کنید.
اجرای کدها
پس از آپلود کدها بر روی میکروکنترلرهای خود، Serial Monitor سمت بیس را باز کنید. پس از چند ثانیه انتظار، متن زیر برای شما نمایش داده میشود.
با کپی کردن آدرس URL چاپشده در مرورگر خود، صفحه وب سرور ایجاد شده، باز خواهد شد.
یک گام جلوتر
در این پروژه، ابتدا با ماژول nRF24L01 و انواع کاربردهای آن آشنا شدید. سپس به شما آموزش دادیم که چگونه با استفاده از آن و بردهای آردوینو، یک ارتباط بیسیم برقرار کنید.
سپس نحوه ایجاد یک شبکه با nRF24L01 و آپلود داده جمعآوری شده بر روی وب سرور را معرفی کردیم.
برای توسعه این پروژه، میتوانید کارهای زیر را انجام دهید.
- چندین کلاینت بسازید و آنها را به سرور متصل کنید. با این کار میتوانید اماکن را هوشمندسازی کنید.
- به جای آردوینو، از بردهای ESP32 استفاده کنید که تا حدودی قابلیت اجرای کدهای php را دارند. با این کار میتوانید از طرف کلاینت به سرور داده ارسال (POST) کنید.
- ماژولهای مختلف از جمله رله، دماسنج، سنسور گاز، روشنایی وغیره را به پروژه خود بیافزایید.
Comments (23)
برای راه اندازی طبق آموزش خودتون پیش رفتم که خطای printf.h: No such file or directory میده
آموزش های دیگه هم بررسی کردم خطا نمیده اما برنامه عملکردی نداره
از آردوینو مگا 2560 و آردوینو یونو استفاده کردم ( ترتیب اتصال پینهای CE و CSN و MOSI و MISO و SCK رو با توجه به آردوینو های استفاده شده رعایت کردم ) VCC رو هم به 3.3 ولت متصل کردم
یا را اندازی متفاوتی داره ( چون اکثر اتفاق از این نوع ماژول استفاده نشده و فقط توضیحات ماژول داده شده ) و یا ماژول ها واقعا خرابه و کار نمیکنن
سلام،
کتابخونه printf.h جزو کتابخونههای پیشفرض آردوینو هست و در صورتی که موقع کامپایل کد، برد رو یکی از بردهای آردوینو انتخاب کرده باشید این خطارو نباید دریافت کنید. اگر برد رو به درستی انتخاب کردید و هنوز خطارو دریافت میکنید سعی کنید از نسخه آپدیت شده نرمافزار آردوینو استفاده کنید. در صورتی که مشکل بر طرف نشد میشه گزینههای دیگر رو بررسی کرد.
و همچنین در مورد ماژولهای توضیح داده شده در این آموزش، این ماژولها همگی راهاندازی یکسان دارند و با همین آموزش میشه از این ماژولها استفاده کرد. تنها برخی مشخصات فنیشون در عمل متفاوت هست.
سلام
از صحت این کد مطمئن هستید ؟ من دو جفت nrf مختلف گذاشتم ولی جوابی نگرفتم
سلام.
بله تمامی کدهایی که در آموزشها گذاشته میشن کامل چک میشن. کد مربوط به این آموزش هم اخیرا استفاده شده و مشکلی نداشته. اگر تو راهاندازی مشکلی خاصی برخورد کردید میتونید با بخش تلگرام پشتیبانی فنیمون هم مشورت کنید.
سلام رو فایل کتابخونه ای #include ارور printf.h: No such file or directory رو می ده می شه یه راهنمایی کنید که الان باید چیکار کنم
سلام.
همین مورد در یکی از کامنتهای قبلی هم بررسی شده که براتون همون پاسخ رو میذارم:
“کتابخونه printf.h جزو کتابخونههای پیشفرض آردوینو هست و در صورتی که موقع کامپایل کد، برد رو یکی از بردهای آردوینو انتخاب کرده باشید این خطارو نباید دریافت کنید. اگر برد رو به درستی انتخاب کردید و هنوز خطارو دریافت میکنید سعی کنید از نسخه آپدیت شده نرمافزار آردوینو استفاده کنید. در صورتی که مشکل بر طرف نشد میشه گزینههای دیگر رو بررسی کرد.”
احتمالا با آپدیت آردوینو و انتخاب درست برد مشکلتون حل میشه.
سلام
من میخوام از این ماژول ها یک فرستنده و گیرنده درست کنم
و راستش کانال های زیادی نمیخوام فقط دو تا کانال ثابت
و دارم با نانو اردینو راه اندازیش میکنم طبق راهنمایی سایت های دیگه با نانو اردینو و کمی هم از سایت شما
و میخوام این رو به کوادکوپتر وصل کنم وقتی دکمه ای فلانی چیزی توی قرستنده میزنی گیرنده عمل کنه و سروو رو تا درجه اخر بچرخونه که با این حساب دیگه سروو نیاز به سه تا سیم نداره و و چیزی که بهش وصله به کمک سروو جدا بشه و من مبتدی هستم خواهش میکنم کامل و دقیق راهنمایی کنید در رابطه با سیم کشی و کد های مورد ویرایش
سلام
این کدهای که برای فرستنده و گیرنده نوشته شده رو میتونید استفاده کنید، در قسمت گیرنده دیتایی رو که از طریق فرستنده میفرستید در این تابع میتونید دریافت کنید radio.read(&data, sizeof(MyData));//Read payload data from the RX FIFO buffer(s).
و کاری خواستید روی data انجام بدید ، همون سروو رو راه اندازی کنید یا هر تسک دیگه ایی، در کد فرستنده هم به همین شکل از تابع radio.writeFast(&data, sizeof(MyData)); جهت ارسال data استفاده میشود که میتونید دیتای مد نظرتون رو در ورودی همین تابع قرار بدید
برای دریافت توضیحات تکمیلی تر میتونید سوالتون رو در انجمن فنی کافه ربات بپرسید.
با تشکر
سلام من چند تا از این ماژول ها را دارم ولی مشکلی که هست بعضی از ماژول ها ارتباط برقرار نمی کنند و بعضی از ماژول ها را فقط می توان به عنوان فرستنده استفاده کرد و وقتی که به مدار گیرنده متصل می کنم ارتباط برقرار نمی کنند و بر عکس بعضی از ماژول ها را فقط می توان برای گیرنده استفاده کرد .
من از اردوینو مگا و unoو از ماژول رگلاتور استفاده می کنم.
با سلام
در کد های فرستنده و گیرنده خطی وجود دارد به صورت زیر
#define Debug_mode false
آن را به true تغییر بدهید تا مود دیباگ فعال بشود. ماژول ها را وصل کنید و بررسی کنید در آنجا دیتا هایی در مورد خود میکرو و رجیستر هایش به شما نمایش داده می شود.
امکان دارد خطایی برای ارتباط وجود داشته باشد که این اتفاق برای شما می افتد می توانید به این صورت بررسی کنید.
سلام
كامپايل كدهاي sketch من دچار مشكل شدن و كدهاي خيلي ساده هم كامپايلش نزديك ٥دقيقه طول ميكشه، البته اخطار ميده ولي اِرور نيست و بالاخره كامپايل و اپلود ميشن اما بسيار زمان طولاني لازمه. جالبه هميشه اين اخطارو نميده و گاهي فقط، يعني يكي درميان اخطار ميده.
لازم به ذكره آنتي ويروس رو هم غيرفعال كردم.
ورژن اردوينوم ١.٨.١٩ هستش.
اين هم اخطارش:
The directory name is invalid
Access is denied.
امکان دارد به دسترسی های نرم افزار آردوینو به سیستم شما باشد.
میتوانید نرم افزار را یک بار حذف و دوباره نصب کنید تا دسترسی ها درست بشود. در صورتی که درست نشد.
آدرس فایل هایی که نرم افزار به آن درسترسی دارد را دسترسی سطح ادمین بدهید.
برای تنظیم کردن این موضوع بر روی پوشه مورد نظر راست کلیک کرده و Properties را باز کرده و در تب Security گزینه Edit را بزنید از بخش بالا بر روی تک تک User ها کلیک کنید و در بخش پایین سطح دسترسی را بر روی Full Control قرار بدهید.(توجه داشته باشید که به چه چیز هایی سطح دسترسی میدهید)
امکان داشته باشد از این بخش باشد.
از esp32 هم میشه برای راه اندازی این ماژول استفاده کرد؟
بله
در بخش کد دقت کنید پین های مورد استفاده برای ESP32 نیز آمده اند.
سلام مشکلی که من دلشتم این بود که برای فرستنده توی سریال مانیتور اعداد به ترتیب زیاد میشن ولی توی گیرنده فقط صفر نشون میشه
و البته وقتی سیم های ce و csn گیرنده رو در میارم و دوباره جا میزنم همون لحظه اعداد تغییر میکنن ولی باز دوباره صفر میشن
با سلام
این مشکل اکثرا در سیم های ارتباطی به وجود می آید.
از سیم های دیگری استفاده بنمایید و کانکشن های خود را بررسی بنمایید.
سلام و خسته نباشید به تمامی دست اندر کاران کافه ربات
متن عالی هست فقط یک مشکل تایپی تو قسمت پایه های ماژول هست که حداکثر ولتاژ ماژول رو ۹ ولت ذکر کردید در صورتی که حداکثر ۳.۹ ولت هستش
با سلام
ممنون از نظر خوبتون، اصلاح شد
سلام من میخام nrf24l01+pa+lna داده ها را بفرستم به esp32 wroom 32-d ولی هیچجا درمورد این مطلبی نیست لطفا راهنمایی کنید
سلام میشه از برد esp32_wroom برای راه اندازی استفاده کرد ؟
با سلام
بله، شما میتوانید از هر میکروکنترلری برای راهاندازی این ماژول استفاده نمایید.
فقط پایه ها را بر اساس میکرو خود به درستی تنظیم بنمایید.
و اینکه با آردوینو nano ch340 تست کردم
حتما تغذیه را از رگوراتور جدا مشابه آموزش استفاده بکنید
تغذیه 3.3 ولت روی آردوینو جریان کافی برای تامین برق NRF را ندارد.