پروژه های ARM, پروژه‌ها

برقراری ارتباط بین ماژول 433 مگاهرتزی RF با برد STM32F103C8

ساختن پروژه‌های بی‌سیم در لوازم الکترونیکی تعبیه شده بسیار مهم و مفید است زیرا هیچ سیم پیچ‌خورده‌ای وجود ندارد و به همین دلیل باعث می‌شود تا دستگاه به راحتی حمل شود. فناوری‌های بی‌سیم زیادی وجود دارد که از جمله آنها می‌توان به بلوتوث، وای‌فای و 433MHz  RF ( فرکانس رادیویی) اشاره کرد. هرکدام از این فناوری‌ها مزایا و معایب خاص خود را دارند مانند هزینه، انتقال فاصله یا دامنه، سرعت یا توان عملیاتی و … .

امروز می‌خواهیم از ماژول RF همراه با برد STM32 برای ارسال و دریافت داده‌ها به صورت بی‌سیم استفاده کنیم.

همانطور که گفتیم قصد داریم یک ماژول بی‌سیم 433 MHz RF را به یک میکروکنترلر STM32F103C8 متصل ‌کنیم. این پروژه به دو بخش تقسیم شده است، فرستنده به برد STM32 و گیرنده به برد آردوینو Uno متصل می‌شود. برای قسمت‌های انتقال و دریافت مدارهای مختلفی وجود دارد.

در این آموزش، فرستنده RF دو مقدار را به سمت گیرنده می‌فرستد: فاصله با استفاده از سنسور اولتراسونیک و مقدار ADC پتانسیومتر ( 0 تا 4096 ) که به صورت عدد (0 تا 100) نگاشت می‌شود اندازه‌گیری می‌شوند. گیرنده‌ی RF برد آردوینو هردو مقدار را دریافت می‌کند و مقادیر فاصله و تعداد را در صفحه نمایش 16×2 LCD  به صورت بی‌سیم چاپ می‌کند.

 

قطعات موردنیاز :

ماژول فرستنده و گیرنده 433Mhz RF

Pinout فرستنده RF:

Pinout گیرنده‌ی RF:

مشخصات ماژول 433 مگاهرتز:

  • ولتاژ عملیاتی گیرنده: 3 تا 5 ولت
  • ولتاژ عملیاتی فرستنده: 3 تا 5 ولت
  • فرکانس عملیاتی: 433 مگاهرتز
  • فاصله انتقال: 3 تا 100 متر (بدون آنتن)
  • تکنیک ماژول‌سازی: ASK (Amplitude Shift Keying)
  • سرعت انتقال داده: 10Kbps

نمودار مدار فرستنده‌ی RF با برد STM32F103C8

اتصالات مدار بین فرستنده‌ی RF و برد STM32F103C8:

اتصالات مدار بین سنسور اولتراسونیک و برد STM32F103C8:

برای ایجاد مقدار آنالوگ ورودی (0 تا 3.3 ولت) به PA0 پین ADC برد STM32، یک پتانسیومتر 10k به یک برد STM32F103C8 متصل شده است.

نمودار مدار گیرنده‌ی RF با برد آردوینو Uno

اتصالات مدار بین گیرنده‌ی RF و برد آردوینو Uno:

اتصالات مدار بین LCD 16×2 و برد آردوینو Uno:

در ادامه‌ی این آموزش کدنویسی را به طور خلاصه شرح می‌دهیم. این طرح 2 قسمت دارد که قسمت اول فرستنده و قسمت دوم گیرنده است.

 

برنامه‌نویسی STM32F103C8 برای فرستنده‌ی RF بی‌سیم

با استفاده از IDE می‌توان برروی برد STM32F103C8 برنامه‌نویسی کرد. برای آپلود کردن کد نیازی به پروگرمر FTDI یا ST-Link نیست. به راحتی برد STM32 را با استفاده از یک پورت USB به PC متصل کنید.

در بخش فرستنده، فاصله شی با استفاده از سنسور اولتراسونیک محاسبه می‌شود و تعداد (0 تا 100) با استفاده از پتانسیومتر تعیین می‌شود که از طریق فرستنده‌ی RF به برد STM32 متصل شده است.

در قدم اول، کتابخانه‌ی Radiohead فراخوانی می‌شود. این کتابخانه برای انتقال و دریافت دیتا از ASK  (تکنیک تغییر کلید دامنه) استفاده می‌کند که باعث می‌شود تا برنامه‌نویسی بسیار آسان شود.

در ادامه‌ی این آموزش کدنویسی را به طور خلاصه شرح می‌دهیم. این طرح 2 قسمت دارد که قسمت اول فرستنده و قسمت دوم گیرنده است

				
					#include <RH_ASK.h>  
				
			

در این آموزش در سمت فرستنده برای اندازه‌گیری فاصله از سنسور اولتراسونیک استفاده شده بنابراین پین‌های trigger و echo مشخص می‌شوند.

				
					  #define trigPin PB1                            
 #define echoPin PB0      
				
			

سپس اسم اشیا برای کتابخانه‌ی RH_ASK به عنوان rf_driver با پارامترهایی مانند سرعت (2000)، پین RX (PA9) و پین TX (PA10) تعریف می‌شود.

				
					RH_ASK rf_driver(2000, PA9, PA10);    
				
			

بعد متغیر رشته‌های مورد نیاز در این برنامه تعریف می‌شوند.

				
					String transmit_number;                            
  String transmit_distance;
  String transmit;
				
			

سپس در ()void setup، شی مربوط به RH_ASK rf_driver مقداردهی اولیه شده است.

				
					rf_driver.init();
				
			

سپس پین trigger به عنوان پین OUTPUT و پین PA0  (متصل به پتانسیومتر) و echo به عنوان پین INPUT تنظیم می‌شوند. ارتباطات سریال با نرخ   9600‌buad شروع می‌شود.

				
					  Serial.begin(9600);
    pinMode(PA0,INPUT);
    pinMode(echoPin,INPUT);
    pinMode(trigPin,OUTPUT);
				
			

سپس در ()void loop، ابتدا مقدار پتانسیومتر که ولتاژ آنالوگ ورودی است به مقدار دیجیتال تبدیل می‌شود (مقدار ADC یافت می‌شود). از آنجایی که ADC برد STM32 رزولوشن 12 بیتی دارد، بنابراین، مقدار دیجیتال از (0 تا 4096) متفاوت است که در بازه (0 تا 100) نگاشت شده است.

				
					   int analoginput = analogRead(PA0);                  
    int pwmvalue = map(analoginput,0,4095,0,100);     
				
			

بعد فاصله را با استفاده از سنسور اولتراسونیک با تنظیم high و low پین trigger را با تاخیر 2 میکروثانیه اندازه‌گیری می‌کنیم.

				
					   digitalWrite(trigPin, LOW);                          
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);                          
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);    
				
			

پین echo موج منعکس شده را دریافت می‌کند، یعنی مدت زمانی که موج trigger منعکس می‌شود فاصله‌ی شیء با استفاده از فرمول محاسبه می‌شود.

				
					   long duration = pulseIn(echoPin, HIGH);              
    float distance= duration*0.034/2;   
				
			

اکنون تعداد دیتا و فاصله‌ی اندازه‌گیری شده به دیتای رشته‌ای تبدیل شده و در متغیرهای رشته‌ی مربوطه ذخیره می‌شوند.

				
					    transmit_number= String(pwmvalue);                     
    transmit_distance = String(distance);   
				
			

هر دو رشته به عنوان یک خط اضافه می‌شود و در رشته‌ای به نام انتقال ذخیره می‌شود و برای جداسازی بین دو رشته از کاما “,” استفاده می‌شود.

				
					  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);  
				
			

برنامه‌نویسی برروی برد آردوینو Uno با استفاده از IDE آردوینو انجام می‌شود. در بخش گیرنده، دیتاهایی که از قسمت فرستنده منتقل می‌شوند و توسط ماژول گیرنده RF دریافت می‌شوند و داده‌های رشته‌ای دریافت شده به داده‌های مربوطه (فاصله و تعداد) تقسیم می‌شوند و در صفحه نمایش 2×16 LCD  نمایش داده می‌شوند.

در ادامه کدهای گیرنده را به طور خلاصه توضیح می‌دهیم:

همانند بخش فرستنده ابتدا باید کتابخانه‌ی RadiohHead را فراخوانی کنیم. به این دلیل که این کتابخانه از ASK برای انتقال و دریافت دیتا استفاده می‌کند، باعث می‌شود برنامه‌نویسی آن بسیار آسان باشد.

				
					#include <RH_ASK.h>     
				
			

از آنجاییکه در این پروژه از نمایشگر LCD استفاده شده است، بنابراین کتابخانه‌ی liquidcrystal نیز فراخوانی می‌شود.

				
					#include <LiquidCrystal.h>   
				
			

و پین‌های نمایشگر 2×16 LCD که به برد آردوینو Uno متصل شده مشخص شده و از lcd به عنوان شیء استفاده می‌کند.

				
					LiquidCrystal lcd(2,3,4,5,6,7);    
				
			

سپس متغیرهای String data را برای ذخیره‌سازی دیتاهای رشته‌ای تعریف می‌کنیم.

				
					String str_receive;                
String str_number;
String str_distance;
				
			

شیء برای کتابخانه‌ی Radiohead تعریف می‌شود.

				
					      RH_ASK rf;   
				
			

حال در ()void setup، نمایشگر LCD برروی حالت 2×16 تنظیم می‌شود و یک پیام خوش آمد گویی نمایش داده شده و پاک می‌شود.

				
					 lcd.begin(16,2);              
    lcd.print("CIRCUIT DIGEST");  
    lcd.setCursor(0,1);
    lcd.print("RF with STM32");
    delay(5000);
    lcd.clear();
				
			

سپس، شی RF مقداردهی اولیه می‌شود.

				
					rf.init();    
				
			

حال در ()void loop، آرایه‌ی []buf با سایز 7 تعریف می‌شود. 

				
					   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);   
				
			

از حلقه‌ی loop برای تقسیم رشته‌ی دریافتی به دو قسمت استفاده می‌شود. در صورتی که “,” بین دو رشته تشخیص داده شود رشته دریافتی به دو قسمت تقسیم می‌شود.

				
					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 با 2 مقدار تعریف می‌شوند و رشته‌ای که به دو رشته تقسیم شده است باتبدیل رشته به آرایه‌ی کاراکتری در این آرایه‌ها ذخیره می‌شود.

				
					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، فاصله و تعداد مقادیر در نمایشگر    2×16 LCD  نمایش داده می‌شود.

				
					   lcd.setCursor(0,0);
      lcd.print("Number:");
      lcd.print(number);                 
      lcd.setCursor(0,1);
      lcd.print("Distance :");
      lcd.print(distance);                   
      lcd.print(" cm");
				
			

پس از آپلود کد فرستنده در برد STM32 و گیرنده در برد آردوینو Uno، داده‌هایی مانند تعداد و فاصله شی با اندازه گیری STM32 از طریق فرستنده RF به گیرنده RF منتقل می‌شوند و مقادیر دریافت شده در صفحه LCD به صورت بی‌سیم نمایش داده می‌شوند

آزمایش برد STM32 براساس فرستنده و گیرنده‌ی RF

  1. وقتی تعداد 0 و فاصله جسم در 6 سانتی‌متری باشد.
  1. وقتی تعداد 47 و شیء در فاصله‌ی 3سانتی‌متری قرار گرفته باشد.
				
					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();

}

}
				
			

نظرتان را درباره این مقاله بگویید 2 نظر

برقراری ارتباط بین ماژول 433 مگاهرتزی RF با برد STM32F103C8

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *