شبکه بیسیم آردوینو با چندین ماژول NRF24L01
در این برنامه آموزشی ما چگونگی راه اندازی چندین ماژول NRF24l01 با آردوینو را یاد میگیریم.
مرور کلی بر راه اندازی چندین ماژول NRF24l01 با آردوینو
به عنوان مثال من شبکهای از ۵ گره ایجاد کردم و هر کدام از آنها میتوانند با هر گره در شبکه ارتباط برقرار کنند و در عین حال میتوانند هم به عنوان فرستنده و هم گیرنده کار کنند. این مثال در واقع روشی تنظیم شدهاست که توضیح میدهد چگونه یک شبکه بسیار بزرگتر بسازیم، یا دقیق باشیم، در کل میتوانیم ارتباط ۳۱۲۵ ماژول را در یک کانال RF واحد با یکدیگر برقرار کنیم. پس بیایید نگاهی به نحوه کار آن بیندازیم.
در آموزشهای قبلی یاد گرفتهایم که چگونه یک ارتباط بی سیم بین دو صفحه آردینو با استفاده از ماژول های NRF24L01 و کتابخانه RF24 ایجاد کنیم. اکنون علاوه بر این کتابخانه، ما از کتابخانه شبکه RF24 استفاده خواهیم کرد، که امکان ایجاد یک شبکه بیسیم آردوینو با صفحات ارتباطی بسیار به یکدیگر را فراهم میکند. در اینجا نحوه کار توپولوژی شبکه آورده شده است.
یک ماژول NRF24L01 واحد میتواند به طور فعال به ۶ ماژول دیگر در همان زمان گوش دهد.
این توانایی توسط کتابخانه شبکه RF24 برای تولید یک شبکه منظم شده در یک توپولوژی درختی استفاده میشود، که در آن یک گره پایه است، و تمام گرههای دیگر زیرگره آن گره یا گره دیگر هستند. هر گره میتواند تا ۵ زیرگره داشته باشد، و این میتواند تا ۵ سطح عمیق باشد، که به این معنی است که ما میتوانیم شبکهای از ۳۱۲۵ گره را ایجاد کنیم. هر گره باید با یک آدرس ۱۵ بیتی تعریف شود، که دقیقا موقعیت گره درون درخت را توصیف میکند.
ما در واقع میتوانیم آدرسهای گرهها را در قالب هشت ضلعی تعریف کنیم. بنابراین، آدرس پایه ۰۰ است، آدرس زیرگره پایه ۰۱ تا ۰۵ است، آدرس زیرگره گره ۰۱ از ۰۱۱ تا ۰۵۱ و غیره است.
توجه داشته باشید که اگر گره ۰۱۱ میخواهد با گره ۰۲ ارتباط برقرار کند، ارتباط باید از طریق گره ۰۱ و گره پایه ۰۰ حرکت کند، بنابراین این دو گره باید در تمام مدت فعال باشند تا ارتباط موفق باشد.
کنترل موتور سروو بیسیم آردوینو با استفاده از کتابخانه شبکه RF24
قبل از این که مثال اصلی این آموزش را توضیح دهیم، برای درک بهتر نحوه کار کتابخانه اجازه دهید مثالی سادهتر از دو صفحه آردوینو که با یکدیگر ارتباط برقرار میکنند، ارائه دهیم. این نمودار مدار برای این مثال است.
بنابراین با استفاده از پتانسیومتری در آردوینوی اول ما سروو موتور را در آردوینو دوم کنترل خواهیم کرد. این آموزش میتواند در بخش های مختلف آموزش رباتیک به کار ما بیاید.
بیایید حالا نگاهی به کدهای منبع بیندازیم.
این کد در سمت پتانسیومتر است:
/* Arduino Wireless Network - Multiple NRF24L01 Tutorial == Example 01 - Servo Control / Node 00 - Potentiometer == by Dejan, www.HowToMechatronics.com Libraries: nRF24/RF24, https://github.com/nRF24/RF24 nRF24/RF24Network, https://github.com/nRF24/RF24Network */ #include <RF24.h> #include <RF24Network.h> #include <SPI.h> RF24 radio(10, 9); // nRF24L01 (CE,CSN) RF24Network network(radio); // Include the radio in the network const uint16_t this_node = 00; // Address of this node in Octal format ( 04,031, etc) const uint16_t node01 = 01; void setup() { SPI.begin(); radio.begin(); network.begin(90, this_node); //(channel, node address) } void loop() { network.update(); unsigned long potValue = analogRead(A0); // Read the potentiometer value unsigned long angleValue = map(potValue, 0, 1023, 0, 180); // Convert the value to 0-180 RF24NetworkHeader header(node01); // (Address where the data is going) bool ok = network.write(header, &angleValue, sizeof(angleValue)); // Send the data }
ابتدا باید هر دو کتابخانه RF24 و شبکه RF24 و همچنین کتابخانه SPI را در نظر بگیریم. سپس ما باید شی RF24 را ایجاد کنیم، و آن را در شی شبکه RF24 قرار دهیم. در اینجا نیاز به تعریف آدرسهای گرهها در قالب هشت ضلعی، یا00 برای این گره، و 01 برای گره دیگر در سمت سروو داریم.
در بخش راهاندازی، ما باید شبکه را با تنظیم کانال و آدرس این گره آغاز کنیم.
در بخش حلقه ما به طور مداوم نیاز به فراخوانی تابع ()update داریم که از طریق آن تمام اقدامات در شبکه رخ میدهد. سپس ما یک سرآیند شبکه ایجاد میکنیم که در آن آدرس گره را که در آن دادهها در حال رفتن هستند، اختصاص میدهیم. در پایان با استفاده از تابع ()write، داده را به گره دیگر ارسال میکنیم. بنابراین در اینجا پارامتر اول شامل اطلاعات آدرسها، نقاط پارامتر دوم که دادهها ارسال خواهند شد و پارامتر سوم اندازه دادهها است.
این کد در سمت سروو است:
/* Arduino Wireless Network - Multiple NRF24L01 Tutorial == Example 01 - Servo Control / Node 01 - Servo motor == */ #include <RF24.h> #include <RF24Network.h> #include <SPI.h> #include <Servo.h> RF24 radio(10, 9); // nRF24L01 (CE,CSN) RF24Network network(radio); // Include the radio in the network const uint16_t this_node = 01; // Address of our node in Octal format ( 04,031, etc) Servo myservo; // create servo object to control a servo void setup() { SPI.begin(); radio.begin(); network.begin(90, this_node); //(channel, node address) myservo.attach(3); // (servo pin) } void loop() { network.update(); while ( network.available() ) { // Is there any incoming data? RF24NetworkHeader header; unsigned long incomingData; network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data myservo.write(incomingData); // tell servo to go to a particular angle } }
از طرف دیگر، در سروو موتور، ما باید کتابخانهها و اشیا را به همان روشی که قبلا توضیح داده شد تعریف کنیم. در اینجا آدرس این گره در فرمت هشت ضلعی ۰۱ است. پس از تعریف سروو موتور، در بخش حلقه، با استفاده از ()while حلقه و تابع ()available ما به طور مداوم بررسی میکنیم که آیا هیچ داده ورودی وجود دارد. اگر درست باشد، ما یک سرآیند شبکه ایجاد میکنیم که از طریق آن دادهها پذیرفته خواهند شد و همچنین متغیری که دادهها در آن ذخیره خواهند شد. سپس با استفاده از تابع ()read دادهها را خواندیم و آنها را در متغیر ورودی دادهها ذخیره کردیم. در پایان از این دادهها برای حرکت سروو موتور با توجه به پتانسیومتر از گره دیگر استفاده میکنیم.
شبکه بی سیم آردوینو با چندین ماژول NRF24L01
پس از درک این مثال، میتوانیم با مثال اصلی این برنامه آموزشی حرکت کرده و یک شبکه بیسیم از ۵ آردوینو که با یکدیگر ارتباط برقرار میکنند، بسازیم. این یک نمودار بلوکی از مثال است.
بنابراین از پایه، با استفاده از یک پتانسیومتر، سروو موتور را در گره ۰۱ کنترل خواهیم کرد، با دومین پتانسیومتر، LED را در گره ۰۲۲ کنترل خواهیم کرد، با استفاده از دکمه، LED را در گره ۰۱۲ کنترل خواهیم کرد، و LED در اینجا در پایه با استفاده از پتانسیومتر در گره ۰۲ کنترل خواهد شد. اگرچه ما میتوانیم متوجه شویم که این مثال نحوه انتقال و دریافت دادهها را به طور همزمان توضیح میدهد، و همچنین نحوه ارتباط با گرهها از شاخههای مختلف را توضیح میدهد. حالا بذار یک نگاهی به کدهای آردوینو بندازیم.
کد منبع پایه 00
/* Arduino Wireless Network - Multiple NRF24L01 Tutorial == Base/ Master Node 00== by Dejan, www.HowToMechatronics.com Libraries: nRF24/RF24, https://github.com/nRF24/RF24 nRF24/RF24Network, https://github.com/nRF24/RF24Network */ #include <RF24Network.h> #include <RF24.h> #include <SPI.h> #define button 2 #define led 3 RF24 radio(10, 9); // nRF24L01 (CE,CSN) RF24Network network(radio); // Include the radio in the network const uint16_t this_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 node012 = 012; const uint16_t node022 = 022; void setup() { SPI.begin(); radio.begin(); network.begin(90, this_node); //(channel, node address) radio.setDataRate(RF24_2MBPS); pinMode(button, INPUT_PULLUP); pinMode(led, OUTPUT); } void loop() { network.update(); //===== Receiving =====// while ( network.available() ) { // Is there any incoming data? RF24NetworkHeader header; unsigned long incomingData; network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data analogWrite(led, incomingData); // PWM output to LED 01 (dimming) } //===== Sending =====// // Servo control at Node 01 unsigned long potValue = analogRead(A0); unsigned long angleValue = map(potValue, 0, 1023, 0, 180); // Suitable for servo control RF24NetworkHeader header2(node01); // (Address where the data is going) bool ok = network.write(header2, &angleValue, sizeof(angleValue)); // Send the data // LED Control at Node 012 unsigned long buttonState = digitalRead(button); RF24NetworkHeader header4(node012); // (Address where the data is going) bool ok3 = network.write(header4, &buttonState, sizeof(buttonState)); // Send the data // LEDs control at Node 022 unsigned long pot2Value = analogRead(A1); RF24NetworkHeader header3(node022); // (Address where the data is going) bool ok2 = network.write(header3, &pot2Value, sizeof(pot2Value)); // Send the data }
بنابراین در پایه یا گره اصلی، ما باید کتابخانهها و اشیا را همانطور که قبلا توضیح داده شد تعریف کنیم، و همچنین تمام گرههای دیگری که اصل دادهها را به آنها ارسال خواهد کرد را تعریف کنیم. در بخش حلقه ما به طور مداوم بررسی میکنیم که آیا هیچ داده ورودی وجود دارد یا نه. اگر چنین است، ما دادهها را میخوانیم، آن را در متغیر دادههای ورودی ذخیره میکنیم و از آن برای کنترل روشنایی LED استفاده میکنیم. این دادهها در واقع از پتانسیومتر گره ۰۲ میآیند. اگر نگاهی به کد آن بیاندازیم، میتوانیم متوجه شویم که تنظیمات تقریباٌ یکسان است. نکته مهم این است که آدرس صحیح را به جایی که میخواهیم دادهها را ارسال کنیم، اختصاص دهیم. در این صورت، این کار 00 پایه است. بنابراین پس از خواندن مقدار پتانسیومتر و تبدیل آن به مقدار PWM مناسب از ۰ تا ۲۵۵، این دادهها را به پایه اصلی ارسال میکنیم. در اینجا میتوانیم متوجه شویم که من از تابع ()millis استفاده کردم و دادهها را در فواصل ۱۰ میلیثانیه ارسال کردم.
کد منبع گره ۰۲
/* Arduino Wireless Network - Multiple NRF24L01 Tutorial == Node 02 (Child of Master node 00) == */ #include <RF24Network.h> #include <RF24.h> #include <SPI.h> RF24 radio(10, 9); // nRF24L01 (CE,CSN) RF24Network network(radio); // Include the radio in the network const uint16_t this_node = 02; // Address of our node in Octal format ( 04,031, etc) const uint16_t master00 = 00; // Address of the other node in Octal format const unsigned long interval = 10; //ms // How often to send data to the other unit unsigned long last_sent; // When did we last send? void setup() { SPI.begin(); radio.begin(); network.begin(90, this_node); //(channel, node address) radio.setDataRate(RF24_2MBPS); } void loop() { network.update(); //===== Sending =====// unsigned long now = millis(); if (now - last_sent >= interval) { // If it's time to send a data, send it! last_sent = now; unsigned long potValue = analogRead(A0); unsigned long ledBrightness = map(potValue, 0, 1023, 0, 255); RF24NetworkHeader header(master00); // (Address where the data is going) bool ok = network.write(header, &ledBrightness, sizeof(ledBrightness)); // Send the data } }
سپس، از پایه، دادههای پتانسیومتر را برای کنترل سروو موتور به گره ۰۱ ارسال میکنیم.
کد منبع گره 01
/* Arduino Wireless Network - Multiple NRF24L01 Tutorial == Node 02 (Child of Master node 00) == */ #include <RF24Network.h> #include <RF24.h> #include <SPI.h> #include <Servo.h> #define led 2 RF24 radio(10, 9); // nRF24L01 (CE,CSN) RF24Network network(radio); // Include the radio in the network const uint16_t this_node = 01; // Address of our node in Octal format ( 04,031, etc) const uint16_t master00 = 00; // Address of the other node in Octal format Servo myservo; // create servo object to control a servo void setup() { SPI.begin(); radio.begin(); network.begin(90, this_node); //(channel, node address) radio.setDataRate(RF24_2MBPS); myservo.attach(3); // (servo pin) pinMode(led, OUTPUT); } void loop() { network.update(); //===== Receiving =====// while ( network.available() ) { // Is there any incoming data? RF24NetworkHeader header; unsigned long incomingData; network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data if (header.from_node == 0) { // If data comes from Node 02 myservo.write(incomingData); // tell servo to go to a particular angle } if (header.from_node == 10) { // If data comes from Node 012 digitalWrite(led, !incomingData); // Turn on or off the LED 02 } } }
گره ۰۱ در واقع دادهها را از دو گره مختلف دریافت میکند، یکی برای کنترل سروو و دیگری برای کنترل LED که از سنسور مادون قرمز از گره ۰۱۲ میآید.
کد منبع گره 012
/* Arduino Wireless Network - Multiple NRF24L01 Tutorial == Node 012 (child of Node 02)== */ #include <RF24Network.h> #include <RF24.h> #include <SPI.h> #define led 2 #define IR 3 RF24 radio(10, 9); // nRF24L01 (CE,CSN) RF24Network network(radio); // Include the radio in the network const uint16_t this_node = 012; // Address of our node in Octal format ( 04,031, etc) const uint16_t node01 = 01; // Address of the other node in Octal format void setup() { SPI.begin(); radio.begin(); network.begin(90, this_node); //(channel, node address) radio.setDataRate(RF24_2MBPS); pinMode(led, OUTPUT); pinMode(IR, INPUT); } void loop() { network.update(); //===== Receiving =====// while ( network.available() ) { // Is there any incoming data? RF24NetworkHeader header; unsigned long buttonState; network.read(header, &buttonState, sizeof(buttonState)); // Read the incoming data digitalWrite(led, !buttonState); // Turn on or off the LED } //===== Sending =====// unsigned long irV = digitalRead(IR); // Read IR sensor RF24NetworkHeader header8(node01); bool ok = network.write(header8, &irV, sizeof(irV)); // Send the data }
به عنوان مثال، ما از سرصفحه استفاده می کنیم. از ویژگی گره به منظور بدست آوردن اطلاعاتی از اینکه داده از کدام گره بدست می آید. در صورتی که دادههای ورودی از پایه باشند، از آن برای کنترل سروو استفاده میکنیم، و در صورتی که دادههای ورودی از گره ۰۱۲ باشد، از آن برای کنترل LED استفاده میکنیم.
در گره ۰۱۲ هم ارسال و هم دریافت داریم. سنسور مادون قرمز LED ذکر شده در گره ۰۱ را کنترل میکند و LED در اینجا از دکمه پایه کنترل میشود.
کد منبع گره 022
/* Arduino Wireless Network - Multiple NRF24L01 Tutorial == Node 022 (child of Node 02)== */ #include <RF24Network.h> #include <RF24.h> #include <SPI.h> #define led1 2 #define led2 3 #define led3 4 #define led4 5 RF24 radio(10, 9); // nRF24L01 (CE,CSN) RF24Network network(radio); // Include the radio in the network const uint16_t this_node = 022; // Address of our node in Octal format ( 04,031, etc) const uint16_t master00 = 00; // Address of the other node in Octal format void setup() { SPI.begin(); radio.begin(); network.begin(90, this_node); //(channel, node address) radio.setDataRate(RF24_2MBPS); pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); pinMode(led4, OUTPUT); } void loop() { network.update(); //===== Receiving =====// while ( network.available() ) { // Is there any incoming data? RF24NetworkHeader header; unsigned long potValue; network.read(header, &potValue, sizeof(potValue)); // Read the incoming data // Turn on the LEDs as depending on the incoming value from the potentiometer if (potValue > 240) { digitalWrite(led1, HIGH); } else { digitalWrite(led1, LOW); } if (potValue > 480) { digitalWrite(led2, HIGH); } else { digitalWrite(led2, LOW); } if (potValue > 720) { digitalWrite(led3, HIGH); } else { digitalWrite(led3, LOW); } if (potValue > 960) { digitalWrite(led4, HIGH); } else { digitalWrite(led4, LOW); } } }
در نهایت، LED ها در گره ۰۲۲ با استفاده از دادههای حاصل از پتانسیومتر دیگری در پایه کنترل میشوند.
بنابراین، برای جمعبندی، اگر همه چیز به درستی به هم متصل باشد، و همه گرهها در تمام مدت فعال باشند، کار ما تنها در پرداختن دقیق به گرهها خلاصه میشود و تمام کارهای سنگین پشت صحنه توسط کتابخانه باور نکردنی شبکه RF24 انجام میشود.
بنابراین، امیدوارم که شما از این پروژه آردوینو لذت برده باشید و چیز جدیدی یاد بگیرید.