در دنیای امبدد الکترونیک، ساخت پروژهها و سیستمهایی که بتوانند به صورت وایرلس به شبکه متصل شوند، از اهمیت ویژهای برخوردار است. چرا که در این گونه سیستمها، معمولا به دلیل تمایل به قابل حمل و جمعوجور بودن، سیمهای چندانی در اختیار نداریم که بتوانیم سیستم را با شیوههای مرسوم به شبکه متصل کنیم.
از طرفی، تکنولوژیهایی که امکانات اتصال و برقراری ارتباط وایرلس را فراهم میکنند نیز متنوع هستند. از جمله ماژولهای بلوتوث، ماژولهای برقراری ارتباط از طریق فرکانس رادیویی (یا همان RFها؛ مانند 433Mhz RF) و … . هر کدام از این موارد مزایا و معایب مخصوص به خود را دارند. به عنوان مثال فاکتورهایی مانند قیمت، برد پوششدهی، سرعت، بروندهی و … . در این آموزش میخواهیم از ماژول RF استفاده کرده و با اتصال آن به میکروکنترلر STM32، به صورت وایرلس تبادل داده انجام دهیم.
اگر دربارهی این میکروکنترلر چیزی نمیدانید و یا اینکه تا به حال با آن کار نکردهاید، پیشنهاد میکنیم قبل از مطالعهی این آموزش، به مطالب مربوط به آموزش استفاده از میکروکنترلر STM32 در پروژهی سادهی LED چشمکزن و نیز مطالب دیگر مربوط به نحوهی پروگرم کردن این میکروکنترلر مراجعه کنید و پس از آن دوباره به اینجا بازگردید.
ضمن آنکه آموزش نحوهی اتصال ماژول RF 433Mhz Wireless به میکروکنترلرهای دیگر هم موجود میباشد که میتوانید آنها را نیز مطالعه کنید.
اما آموزش این جلسه را در قالب یک پروژهی دو قسمتی پیش میبریم. طبیعتا دادههایی که قرار است مبادله شوند، باید یک فرستنده و یک گیرنده داشته باشند. (دو ماژول RF جداگانه) ما میخواهیم فرستنده (transmitter) را به میکروکنترلر STM32 و گیرنده (receiver) را به یک بورد Arduino UNO متصل کنیم. برای هر کدام از این دو قسمت مدارها و توضیحات جداگانهای خواهیم داشت.
نحوهی عملکردی که برای سیستم در نظر میگیریم به این صورت است که ماژول RF در سمت فرستنده، دو مقدار را به ماژول RF که در سمت گیرنده قرار دارد ارسال میکند. این دو مقدار یکی فاصلهای است که توسط یک سنسور اولتراسونیک اندازهگیری شده است و دیگری مقدار ADC value که در حالت معمول عددی در بازهی ۰ تا ۴۰۹۵ است و ما میخواهیم آن را به عددی در بازهی ۰ تا ۱۰۰ نظیر کنیم. ماژول RF گیرنده پس از دریافت این دو مقدار، باید آنها را بر روی یک 2×16 LCD نمایش دهد.
تجهیزات مورد نیاز برای اجرای پروژه
- میکروکنترلر STM32
- بورد Arduino UNO
- ماژولهای فرستنده و گیرندهی 433MHz RF
- سنسور اولتراسونیک سنجش فاصله (HC-SR04)
- 2×16 LCD
- پتانسیومتر 10K
- برد بورد
- سیم رابط
شکل ظاهری ماژولهای فرستنده و گیرندهی RF
پایههای بخش فرستنده
پایههای بخش گیرنده
ویژگیهای ماژول 433Mhz RF
- ولتاژ کاری در هر دو ماژولهای فرستنده و گیرنده ۳ تا ۵ ولت میباشد.
- فرکانس کاری 433MHz است.
- برد پوششدهی تا ۳ متر (بدون استفاده از آنتن) و حداکثر تا ۱۰۰ متر میباشد.
- تکنیک مدولاسیون مورد استفاده ASK است.
- سرعت تبادل داده 10kbps است.
نقشه مدار در بخش فرستنده (اتصال ماژول فرستنده RF به میکروکنترلر STM32)
اتصال بین ماژول RF و میکرو
اتصال بین سنسور اولتراسونیک و میکرو
یک پتانسیومتر 10K را هم به یکی از پینهای ADC میکروکنترلر (PA0) وصل میکنیم تا ورودی آنالوگ با قابلیت تغییر دامنه (از صفر تا ۳.۳ ولت) برای آن فراهم کنیم.
نقشه مدار در بخش گیرنده (اتصال ماژول گیرنده RF به بورد Arduino UNO)
اتصال بین ماژول RF و بورد آردوینو
اتصال بین LCD و بورد آردوینو
بدیهی است کدی که مینویسیم هم باید در دو بخش باشد، یک بخش برای راهاندازی سمت فرستنده و دیگری برای سمت گیرنده. در ادامه کدهای پروژه را به صورت مختصر (بخشهای مهم) توضیح میدهیم و البته کدهای هر دو بخش را هم به صورت کامل در انتهای همین مطلب قرار دادهایم.
پروگرم کردن میکروکنترلر STM32 برای برقراری ارتباط وایرلس از طریق ماژول RF
میکروکنترلر STM32 را هم میتوانیم با استفاده از Arduino IDE پروگرم کنیم. بنابراین به پروگرمر FTDI یا SD-Link نیازی نداریم و فقط کافیست که میکرو را از طریق پورت USB آن به کامپیوتر وصل کرده و برای پروگرم کردن آن از طریق Arduino IDE اقدام کنیم. (آموزش این روش را در جلسات قبلی توضیح داده بودیم)
اما کاری که در این بخش باید انجام دهیم این است که فاصلهی بورد تا شی مورد نظر (مثلا به نام cm) را با استفاده از سنسور سنجش فاصله اندازهگیری کنیم و مقدار این فاصله را به همراه عددی که متعلق به مجموعهی ۰ تا ۱۰۰ است و از نظیر شدن مقدار ADC value (تولید شده توسط پتانسیومتر) به دست آمده است، به سمت بخش گیرنده ارسال کنیم.
ابتدا کتابخانهی Radiohead را اضافه میکنیم. ( لینک دانلود کتابخانه) از آنجا که این کتابخانه برای مدولاسیون از تکنیک ASK استفاده میکند، کار ما بسیار راحت خواهد بود.
پس از دانلود شدن، از مسیر Sketch -> include library -> Add .zip library کتابخانه را اضافه کنید.
#include <RH_ASK.h>
از آنجا که قرار است از یک سنسور اولتراسونیک هم استفاده کنیم، پینهای echo و trigger را تعریف میکنیم.
#define trigPin PB1 #define echoPin PB0
سپس یک object برای کتابخانهی RH_ASK تعریف میکنیم و نام آن را rf_drive میگذاریم. پارامترهای آن را هم به این ترتیب تعیین میکنیم، سرعت (۲۰۰۰)، پین PA9) RX) و پین PA10) TX).
RH_ASK rf_driver(2000, PA9, PA10);
سپس متغیرهای string که نیاز داریم را تعریف میکنیم.
String transmit_number; String transmit_distance; String transmit;
در مرحلهی بعد، در بخش تابع ()rf_driver ،setup را که به عنوان یک object تعریف کرده بودیم initialize میکنیم.
rf_driver.init();
پین trigger را به عنوان خروجی و PA0 (متصل به پتانسیومتر) و پین echo را هم به عنوان ورودی تعیین میکنیم. بادریت ارتباط سریال را هم روی ۹۶۰۰ تنظیم میکنیم.
Serial.begin(9600); pinMode(PA0,INPUT); pinMode(echoPin,INPUT); pinMode(trigPin,OUTPUT);
سپس در بخش تابع حلقه، مقدار پتانسیومتر را که ورودی آنالوگی برای پین ADC است دریافت کرده و به یک ADC value تبدیل میکنیم. از آنجا که ADC در میکروکنترلر STM32 دارای رزولوشن ۱۲ بیتی است، پس مقدار ADC value در بازهی ۰ تا ۴۰۹۵ خواهد بود که ما باید آن را به بازهی ۰ تا ۱۰۰ نظیر کنیم.
int analoginput = analogRead(PA0); int pwmvalue = map(analoginput,0,4095,0,100);
برای اندازهگیری فاصله توسط سنسور، باید پین Trigger را با فواصل ۲ میکروثانیهای یک کنیم.
digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW);
سیگنال ارسال شده توسط trigger به سمت شی مورد نظر، مجددا برگشت خورده و توسط پین echo دریافت میشود. اختلاف زمانی بین ارسال و دریافت سیگنال توسط این دو پین، با استفاده از فرمول مخصوص، فاصلهی سنسور تا شی را برای ما محاسبه خواهد کرد.
long duration = pulseIn(echoPin, HIGH); float distance= duration*0.034/2;
حالا هر دو دادهی مد نظر ما به مقادیر string تبدیل شده و در متغیرهای نظیر ذخیره میشوند.
transmit_number= String(pwmvalue); transmit_distance = String(distance)
هر دوی این دو stringها را در یک string یک خطی پشت سر هم قرار میدهیم و بین آنها را با یک «,» فاصله میدهیم. نام این رشتهی بزرگ را transmit میگذاریم.
transmit = transmit_pwm + "," + transmit_distance;
حالا این متغیر رشتهای را به آرایهای از کاراکترها تبدیل میکنیم.
const char *msg = transmit.c_str();
داده را ارسال کرده چند لحظه صبر میکنیم تا کامل مخابره شود.
rf_driver.send((uint8_t *)msg, strlen(msg)); rf_driver.waitPacketSent();
دادهای که ارسال میکنیم در مانیتور سریال هم نمایش داده میشود.
Serial.println(msg);
پروگرم کردن Arduino UNO برای برقراری ارتباط وایرلس از طریق ماژول RF
بورد Arduino UNO را همان طور که انتظار میرود باید با Arduino IDE پروگرم کنیم. اتفاقی که در این بخش باید بیفتد این است که ابتدا دادههای ارسال شده توسط ماژول فرستندهی RF در سمت میکروکنترلر، باید توسط ماژول گیرندهی RF در سمت بورد آردوینو دریافت شوند. این دادهها در قالب یک دیتای رشتهای هستند که باید در مرحلهی اول از هم تفکیک شوند و تبدیل به دو دادهی مجزای فاصله و ADC value شوند. سپس این دو داده باید بر روی نمایشگر LCD نشان داده شوند.
کدهایی که در این بخش باید استفاده کنیم را به طور مختصر با هم مرور کنیم.
در اینجا هم مانند بخش فرستنده، ابتدا باید کتابخانهی RadiohHead را اضافه کنیم تا بتوانیم با استفاده از آن مدولاسیون ASK را به راحتی و به صورت خودکار انجام دهیم.
#include <RH_ASK.h>
چون میخواهیم از LCD استفاده کنیم، کتابخانهی liquidcrystal را هم اضافه میکنیم.
#include <LiquidCrystal.h>
پین های اتصال آردوینو و LCD را تعریف میکنیم.
LiquidCrystal lcd(2,3,4,5,6,7);
سپس دو متغیر از نوع string تعریف میکنیم تا بتوانیم دادههای دریافتی را در آنها ذخیره کنیم.
String str_receive; String str_number; String str_distance;
برای کتابخانهی Radiohead یک object تعریف میکنیم.
RH_ASK rf;
در بخش تابع ()setup، مود LCD را روی ۲*۱۶ قرار میدهیم و پیغام اولیهی آن را برای لحظاتی نمایش داده و پاک میکنیم تا شروع به کار آن را اعلام کنیم.
lcd.begin(16,2); lcd.print("CIRCUIT DIGEST"); lcd.setCursor(0,1); lcd.print("RF with STM32"); delay(5000); lcd.clear();
پس از آن، rf object را initialize میکنیم.
rf.init();
وارد تابع حلقه میشویم. یک آرایه به نام []buf و با سایز ۷ تعریف میکنیم. ( چرا ۷؟ اگر «,» بین دو داده را هم در رشتهی ارسالی توسط فرستنده در نظر بگیریم، سایز آرایه باید ۷ باشد. بنابراین این عدد را همواره با در نظر گرفتن دادهی ارسالی باید تنظیم کنیم)
uint8_t buf[7]; uint8_t buflen = sizeof(buf);
در همین حلقه، مدام چک میکنیم که اگر داده توسط گیرندهی RF دریافت شده باشد، عبارت if سایز آن را چک کرده و شروع به ادامهی روند اجرای برنامه کند. برای دریافت داده از تابع ()rf.recv استفاده میکنیم.
if (rf.recv(buf, &buflen))
داده به محض دریافت وارد آرایهی buf میشود و سپس آن را در یک متغیر رشتهای به نام str_receive ذخیره میکنیم.
str_receive = String((char*)buf);
سپس دو دادهی موجود در رشته را با توجه به علامت «,» در میان آنها از هم جدا میکنیم.
for (int i = 0; i < str_receive.length(); i++) { if (str_receive.substring(i, i+1) == ",") { str_number = str_receive.substring(0, i); str_distance = str_receive.substring(i+1); break; }
دو آرایه از نوع کاراکتر تعریف میکنیم و هر کدام از دو بخش این رشته را که در مرحلهی قبل از هم تفکیک کردیم در یکی از این آرایهها ذخیره میکنیم.
char numberstring[4]; char distancestring[3]; str_distance.toCharArray(distancestring,3); str_number.toCharArray(numberstring,3);
سپس با استفاده از دستور ()atoi، آرایههای کاراکتری را به integer برمیگردانیم.
int distance = atoi(distancestring); int number = atoi(numberstring);
حالا میتوانیم این integerها را بر روی LCD نمایش دهیم.
lcd.setCursor(0,0); lcd.print("Number:"); lcd.print(number); lcd.setCursor(0,1); lcd.print("Distance :"); lcd.print(distance); lcd.print(" cm");
پس از تکمیل کدهای هر دو بخش و آپلود کردن آنها متناظرا بر روی میکروکنترلر و بورد آردوینو؛ نوبت به تست پروژه میرسد. باید ببینیم که آیا دادههایی مانند اعداد و فاصلهی اشیا که توسط فرستندهی RF ارسال شده و توسط گیرندهی RF دریافت میشوند، به درستی اندازهگیری، مبادله و نمایش داده میشوند یا خیر.
تست پروژهی تبادل وایرلس اطلاعات از طریق فرستنده و گیرندهی RF
- در این حالت ADC value به عدد ۰ نظیر شده و فاصله تا شی مورد نظر نیز ۶ سانتیمتر اندازهگیری شده است.
- در حالت بعدی ADC value به عدد ۴۷ نظیر شده و فاصله تا شی مورد نظر ۳ سانتیمتر اندازهگیری شده است.
کد
Transmitter code (STM32F103C8): //433MHZ RF Trasmitter with STM32F103C8 //Transmitter Code //Circuit Digest #include <RH_ASK.h> //RadioHead library #define trigPin PB1 //Sets the Trigpin of Ultrasonic sensor as PB1 #define echoPin PB0 //Sets the echoPin of Ultrasonic sensor as PB0 RH_ASK rf_driver(2000, PA9, PA10); //Sets Pin PA9 as receiver and PA10 as transmitterand 2000 as Speed String transmit_pwm; //Strings to store string value String transmit_distance; String transmit; void setup() { // Initialize ASK Object rf_driver.init(); Serial.begin(9600); pinMode(PA0,INPUT); pinMode(echoPin,INPUT); pinMode(trigPin,OUTPUT); } void loop() { int analoginput = analogRead(PA0); // ADC value from pin PA0 connected to Potentiometer int pwmvalue = map(analoginput,0,4096,0,100); // Converts 0 to 4096 into 0 to 100 digitalWrite(trigPin, LOW); //Makes TrigPin of Ultrasonic LOW delayMicroseconds(2); digitalWrite(trigPin, HIGH); //Makes TrigPin of Ultrasonic HIGH delayMicroseconds(10); digitalWrite(trigPin, LOW); //Makes TrigPin of Ultrasonic LOW long duration = pulseIn(echoPin, HIGH); //Receives the Echo signal reflected float distance= duration*0.034/2; //Calculates distance in CM of object transmit_pwm = String(pwmvalue); //Convert value into string transmit_distance = String(distance); //Convert value into string transmit = transmit_pwm + "," + transmit_distance; //Adds two String in one line const char *msg = transmit.c_str(); // rf_driver.send((uint8_t *)msg, strlen(msg)); //Sends the String rf_driver.waitPacketSent(); Serial.println(msg); //Serial Print value for debug delay(1000); } Receiver Code (Arduino UNO): //Receiver Arduino Code //433MHZ RF with STM32F103C8 as Transmitter //Circuit Digest #include <RH_ASK.h> //Includes RadioHead Library #include <LiquidCrystal.h> //Includes the LCD display Library LiquidCrystal lcd(2,3,4,5,6,7); //Initialize lcd with Pins connected to Arduino String str_receive; //Strings to Store Value String str_number; String str_distance; RH_ASK rf; //rf as object for RG_ASK void setup() { lcd.begin(16,2); //Lcd set as 16x2 Mode lcd.print("CIRCUIT DIGEST"); //Display Welcome message lcd.setCursor(0,1); lcd.print("RF with STM32"); delay(5000); lcd.clear(); rf.init(); //Initialize rf Object } void loop() { uint8_t buf[7]; uint8_t buflen = sizeof(buf); if (rf.recv(buf, &buflen)) { str_receive = String((char*)buf); // Receive String from the Transmitter for (int i = 0; i < str_receive.length(); i++) // Split string into two string { if (str_receive.substring(i, i+1) == ",") { str_number = str_receive.substring(0, i); str_distance = str_receive.substring(i+1); break; } } char numberstring[4]; char distancestring[3]; str_distance.toCharArray(distancestring,3); //Convert String into Char Array str_number.toCharArray(numberstring,3); int distance = atoi(distancestring); //Convery Array into integer value int number = atoi(numberstring); lcd.setCursor(0,0); lcd.print("Number:"); lcd.print(number); //Display number value at LCD display lcd.setCursor(0,1); lcd.print("Distance :"); lcd.print(distance); //Display distance value at LCD display lcd.print(" cm"); delay(1500); lcd.clear(); } }
ویدئو
- منبع: ترجمه از سایت circuitdigest.com
امیدواریم آموزش «اتصال ماژول 433Mhz RF به STM32» برایتان مفید واقع شده باشد. در ادامه پیشنهاد میکنیم دیگر آموزشهای STM32 را نیز مطالعه کنید.
اگر این نوشته برایتان مفید بود لطفا کامنت بنویسید.