ورکشاپ آموزشی - آیسی مدار
رفتن به محتوا

کنترل بی‌سیم لوازم خانگی با موبایل از طریق آردوینو و ماژول LoRa

رباتیک و هوشمندسازی
۰ نظر
۳۷ نفر
کد ۳۲۳۲

خیلی وقت‌ها پیش میاد که می‌خوایم وسایل برقی خونه، باغ یا کارگاه رو از راه دور کنترل کنیم، اما برد شبکه‌های وای‌فای یا بلوتوث به اندازه کافی زیاد نیست. تکنولوژی لورا (LoRa) دقیقا برای همین مواقع ساخته شده تا بتونیم داده‌ها رو تو مسافت‌های طولانی و با مصرف انرژی خیلی کم ارسال کنیم.

تو این پروژه از آیسی‌مدار قراره یه سیستم کنترل از راه دور هوشمند بسازیم. با این سیستم می‌تونی فقط با موبایلت و از طریق بلوتوث، به یک دستگاه مرکزی (کنترلر) وصل بشی و فرمان‌ها رو صادر کنی. این دستگاه، فرمان تو رو با ماژول LoRa تا مسافت‌های چند کیلومتری ارسال می‌کنه تا دستگاه گیرنده (هدف) اون رو دریافت کنه و وسایل برقی مثل لامپ 220 ولت یا فن 12 ولت رو روشن و خاموش کنه.

این پروژه هم بخش نرم‌افزاری جذابی داره و هم یه تمرین عالی برای کار با رله‌ها و ماژول‌های رادیوییه. پس قطعاتت رو روی میز بچین تا قدم‌به‌قدم این سیستم خفن رو با هم مونتاژ کنیم.

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

  • برد آردوینو نانو (2 عدد)
  • ماژول ترکیبی RYLR999 (LoRa + BLE) (2 عدد)
  • مبدل سطح ولتاژ دوطرفه 3.3 به 5 ولت
  • نمایشگر LCD کاراکتری 16×2 با رابط I2C
  • ماژول رله دو کاناله
  • فن 12 ولت DC
  • لامپ 220 ولت AC
  • سیم جامپر
  • منبع تغذیه 12 ولت
  • نرم‌افزار Arduino IDE
  • کتابخانه LiquidCrystal_I2C
  • اپلیکیشن موبایل LightBlue (برای اتصال BLE)
مرحله ۱

بررسی نحوه عملکرد سیستم کنترل از راه دور

این پروژه از دو بخش کاملا مجزا تشکیل شده که با هم ارتباط برقرار می‌کنن.

واحد کنترلر (سمت کاربر)

این بخش در واقع همون فرستنده‌ست که رابط بین گوشی موبایل تو و شبکه LoRa محسوب می‌شه. تو با موبایلت از طریق بلوتوث کم‌مصرف (BLE) به ماژول RYLR999 وصل می‌شی. وقتی فرمانی رو تو اپلیکیشن موبایل تایپ می‌کنی، آردوینو اون رو می‌خونه و بلافاصله میده به فرستنده LoRa. سپس ماژول LoRa این دستور رو به صورت بی‌سیم و تا مسافت‌های خیلی دور ارسال می‌کنه.

واحد گیرنده (سمت وسایل برقی)

بخش گیرنده منتظر دریافت سیگنال‌های LoRa می‌مونه. اینجا هم یه ماژول RYLR999 داریم که پیام رادیویی رو می‌گیره و می‌ده به آردوینو نانوی دوم. آردوینو دستور رو پردازش می‌کنه و به ماژول رله فرمان می‌ده تا مدار وسیله برقی رو قطع یا وصل کنه. برای تست و راه‌اندازی تو این پروژه، ما دو تا وسیله رو کنترل می‌کنیم:

  1. یک لامپ 220 ولت AC
  2. یک فن 12 ولت DC

در نهایت، بعد از اینکه رله فعال شد، گیرنده یه پیام تأیید هم برای فرستنده برمی‌گردونه تا روی نمایشگر LCD ببینی که دستورت با موفقیت اجرا شده.

مرحله ۲

چرا باید از ماژول رله استفاده کنیم؟

بردهای آردوینو با ولتاژ پایین (5 ولت) کار می‌کنن و پایه‌های دیجیتالشون فقط می‌تونن جریان خیلی ضعیفی رو تأمین کنن. از اون طرف، وسایل برقی مثل لامپ‌های 220 ولت یا موتورهای 12 ولت به جریان و ولتاژ بسیار بالاتری نیاز دارن. اگر این وسایل رو مستقیم به آردوینو وصل کنی، همون لحظه برد می‌سوزه و حتی ممکنه خطرات جانی داشته باشه.

اینجاست که ماژول رله وارد عمل می‌شه و نقش یک کلید قطع و وصل الکترومغناطیسی رو بازی می‌کنه. آردوینو یه سیگنال خیلی ضعیف و ایمن به رله می‌ده، و رله با اون سیگنال مدار وسیله برقی رو قطع یا وصل می‌کنه. با این ترفند ساده، میکروکنترلر کاملا از مدارهای قدرت بالا و خطرناک ایزوله می‌شه و می‌تونه با خیال راحت لوازم خانگی رو کنترل کنه.

مرحله ۳

سیم‌کشی و اتصالات بخش کنترلر (فرستنده)

بخش فرستنده از قطعات زیر تشکیل شده:

  1. آردوینو نانو
  2. ماژول RYLR999 (LoRa + BLE)
  3. مبدل سطح ولتاژ
  4. نمایشگر LCD با ماژول I2C

ارتباط ماژول RYLR999 با آردوینو از طریق پورت سریال (UART) انجام می‌شه. اما چون سطح منطقی ماژول LoRa روی 3.3 ولته و آردوینو 5 ولته، حتما باید بینشون از یک مبدل سطح ولتاژ دوطرفه استفاده کنی تا ماژول آسیب نبینه. تغذیه خود ماژول رو هم از پین 5 ولت آردوینو می‌گیریم.

پایه‌های فرستنده و گیرنده ماژول (TX و RX) بعد از عبور از مبدل ولتاژ به پورت سریال آردوینو وصل می‌شن تا بتونن دستورات رو از طریق امواج رادیویی مخابره کنن.

برای ارتباط بلوتوثی با موبایل، از قابلیت SoftwareSerial تو کدهای آردوینو استفاده کردیم تا فرمان‌ها به صورت مستقل دریافت بشن. نمایشگر LCD هم که با رابط I2C کار می‌کنه، خیلی راحت با اتصال پین‌های A4 (به عنوان SDA) و A5 (به عنوان SCL) راه‌اندازی می‌شه. این نمایشگر تو طول کار اطلاعات زیر رو بهت نشون می‌ده:

  1. وضعیت اولیه و راه‌اندازی ماژول
  2. دستورات دریافت شده از موبایل
  3. وضعیت ارسال دیتا
  4. پیام‌های تأییدی که از واحد گیرنده برمی‌گرده

داشتن این نمایشگر، خطایابی و مانیتورینگ کارکرد سیستم رو برات خیلی راحت‌تر می‌کنه.

مرحله ۴

سیم‌کشی بخش گیرنده و اتصال رله‌ها

واحد گیرنده شامل این قطعاته:

  1. آردوینو نانو
  2. ماژول رادیویی RYLR999
  3. مبدل سطح ولتاژ
  4. ماژول رله
  5. نمایشگر LCD

سیم‌کشی ماژول LoRa به آردوینو تو این بخش دقیقا مثل بخش کنترلره، با این تفاوت که اینجا دیگه از ارتباط بلوتوثی (BLE) استفاده نمی‌کنیم. به جاش، ماژول فقط منتظر دریافت پیام‌های رادیویی می‌مونه. به محض اینکه پیامی برسه، آردوینو اون رو تفسیر می‌کنه و پایه‌های متصل به رله رو فعال یا غیرفعال می‌کنه. تو این پروژه ما از دو تا کانال رله استفاده کردیم:

  1. رله کانال 1 (متصل به پین D11) – برای کنترل لامپ AC
  2. رله کانال 2 (متصل به پین D12) – برای کنترل فن DC

وقتی آردوینو رله رو فعال می‌کنه، پلاتین‌های داخلی رله به هم می‌چسبن و جریان برق به وسیله برقی می‌رسه. با این روش می‌تونی هر وسیله AC یا DC رو کنترل کنی. ⚠️ نکته ایمنی: موقع وصل کردن سیم‌های لامپ به رله، حتما دوشاخه رو از برق شهر بکش و به هیچ وجه به قسمت‌های فلزی زیر ماژول رله دست نزن.

مرحله ۵

بررسی فرمت دستورات ارسالی

برای کنترل دستگاه‌ها، باید دستورات متنی خاصی رو از طریق اپلیکیشن بلوتوثی گوشیت به سمت کنترلر بفرستی. فرمت این دستورات خیلی ساده‌ست و مثل نمونه‌های زیر نوشته می‌شه:

TXT
*L1# Turn bulb ON
*L0# Turn bulb OFF
*F1# Turn fan ON
*F0# Turn fan OFF

وقتی کنترلر این پیام رو می‌گیره، متن اصلی رو استخراج می‌کنه و از طریق شبکه LoRa می‌فرسته. گیرنده با دیدن این متن، رله مربوطه رو روشن می‌کنه. بلافاصله بعد از اجرای کار، گیرنده یه پیام تأیید هم به فرستنده برمی‌گردونه.

نمونه پیام تأییدی که دریافت می‌کنی:

TXT
DONE
مرحله ۶

تست و راه‌اندازی نهایی سیستم کنترل بی‌سیم

حالا که همه‌چیز رو مونتاژ کردی، وقتشه پروژه رو تست کنی:

  1. تغذیه هر دو برد آردوینو رو وصل کن تا روشن بشن.
  2. اپلیکیشن LightBlue رو تو گوشیت باز کن.
  3. از لیست بلوتوث‌ها به ماژول RYLR999 متصل شو.
  4. دستورات متنی رو به صورت دستی تایپ کن و بفرست.
  5. به نمایشگرهای LCD روی هر دو واحد دقت کن.

فرآیندی که باید ببینی به این صورته:

  1. دستور توسط کنترلر دریافت می‌شه.
  2. دستور از طریق LoRa ارسال می‌شه.
  3. همون دستور تو واحد گیرنده دریافت می‌شه.
  4. رله فعال شده و وسیله برقی روشن می‌شه.
  5. پیام تأیید انجام کار، روی نمایشگر گیرنده نشون داده می‌شه.

اگر آنتن ماژول‌های LoRa رو در جای مناسبی قرار بدی و مانع فیزیکی زیادی سر راهشون نباشه، این سیستم می‌تونه به راحتی وسایل رو از فاصله‌های چند کیلومتری روشن و خاموش کنه!

مرحله ۷

کدهای آردوینو برای بخش فرستنده (کنترلر)

Arduino
/*
Code to receive commands from Mobile device using bluetooth functionality of RLY999 module and send these commands from one Arduino to another Arduino using LORA functionality of RYL999 Module and display complete communication on I2C LCD
by playwithcircuit.com
*/
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
// below MACROS are for LORA communication
#define REPLY_TIMEOUT_IN_MS 300
#define REPLY_END_CHAR '\n'
#define SELF_ADDRESS 0
#define TARGET_ADDRESS 1
#define MIN_CHAR_TO_RCV 1
#define WAIT_FOR_TARGET_REPLY 3000
// below MACROS and strings are for Bluetooth communication
#define START_CHAR_BT_COMM '*'
#define END_CHAR_BT_COMM '#'
#define START_CHAR_TIME_OUT_BT_COMM (3000U) // time in ms
#define END_CHAR_TIME_OUT_BT_COMM (300U) // time in ms
// these four strings can be received from bluetooth Rx pin which are transmitted by the mobile application
String sCMDLampON = "L1";
String sCMDLampOFF = "L0";
String sCMDFanON = "F1";
String sCMDFanOFF = "F0";
// save received command in this global string object
String receivedCommand;
// initialize softserial port at pin 3(Rx) and 2(Tx)
SoftwareSerial btSerial(3, 2);
// Init LCD at 0x27, 16x2
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
boolean boRetVal = false;
// begin serial communication at baud 115200,n,8,1
// to communicate with the LORA functionality of module
Serial.begin(115200);
// begin soft serial communication at baud 115200,n,8,1
// to communicate with the Bluetooth functionality of module
btSerial.begin(115200);
btSerial.setTimeout(END_CHAR_TIME_OUT_BT_COMM); // set time out for readStringUntil() function
// Initialize the LCD
lcd.init();
// Turn ON the Backlight
lcd.backlight();
// Clear the display buffer
lcd.clear();
receivedCommand.reserve(50); // prevents fragmentation, as multiple times data shall be received in this string
// clear receive buffer of LORA
flushBuffer(); // clear rx data
// Reset settings to factory defaults for LORA functionality
boRetVal = boRestoreFactoryDefaults();
// setting the address of LORA
if (boRetVal == true) {
flushBuffer(); // clear rx data
boRetVal = boSetAddress();
}
if (boRetVal == true) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Module Init");
lcd.setCursor(0, 1);
lcd.print("Successful");
delay(1000);
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Module Init");
lcd.setCursor(0, 1);
lcd.print("Failed");
while (1)
;
}
}
void loop() {
String expected_reply = "DONE";
bool boRetVal = false;
flushBuffer(); // clear rx data
// get commands using BT functionality using Mobile Application
boRetVal = rcvCommand(START_CHAR_TIME_OUT_BT_COMM);
if (boRetVal == false) {
// Displaying Failed Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("No BT Command");
lcd.setCursor(0, 1);
lcd.print("Received");
} else {
// check if valid command is received
if ((receivedCommand == sCMDLampON) || (receivedCommand == sCMDLampOFF) || (receivedCommand == sCMDFanON) || (receivedCommand == sCMDFanOFF)) {
// transmits receivedCommand
boRetVal = boSendData(receivedCommand);
if (boRetVal == true) {
// Displaying Sent Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Cmd Rcvd & Sent");
lcd.setCursor(0, 1);
lcd.print(receivedCommand);
delay(1000);
boRetVal = chkReply(expected_reply, REPLY_END_CHAR, WAIT_FOR_TARGET_REPLY);
if (boRetVal == true) {
// Displaying received Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Reply Received:");
lcd.setCursor(0, 1);
lcd.print(expected_reply);
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("No Reply");
lcd.setCursor(0, 1);
lcd.print("Received");
}
} else {
// Displaying Failed Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Command");
lcd.setCursor(0, 1);
lcd.print("Sending Failed");
}
} else {
// Displaying Invalid Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Invalid:");
lcd.print(receivedCommand);
lcd.setCursor(0, 1);
lcd.print("Command Received");
}
}
}
/******************************************** Function Definition Related to LORA Functionality ***********************/
void sendCrLf(void) {
Serial.write(0x0D); // Carriage Return
Serial.write(0x0A); // Line Feed
}
// clear receive buffer of LORA
void flushBuffer(void) {
while (Serial.available() > 0) {
Serial.read();
}
}
// check data on rx pin of LORA functionality
bool chkReply(String chkString, char receiveUntil, unsigned int timeout) {
String receivedString; // save received data in this string object
bool boReturnValue = false; // function's return value
// wait for reply
do {
timeout--;
delay(1); // delay of 1 ms
} while ((Serial.available() < MIN_CHAR_TO_RCV) && (timeout > 0));
if (timeout) {
// if timeout is left then a reply is received check for the string in the reply
receivedString = Serial.readStringUntil(receiveUntil);
if (receivedString.indexOf(chkString) != -1) {
boReturnValue = true;
} else {
boReturnValue = false;
}
} else {
boReturnValue = false;
}
// return result
return boReturnValue;
}
// Reset settings to factory defaults for LORA functionality
bool boRestoreFactoryDefaults(void) {
const char factoryDefaultCmd[] = "AT+FACTORY"; // command to be sent
bool boReturnValue = false; // function's return value
char downCounter = 100; // Down counter to wait for reply
String receivedString; // save received data in this string object
String chkRcvString1 = "+FACTORY";
String chkRcvString2 = "+READY";
// send command
Serial.print(factoryDefaultCmd);
sendCrLf();
// check first string in reply
boReturnValue = chkReply(chkRcvString1, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
if (boReturnValue == true) {
// check second string in reply
boReturnValue = chkReply(chkRcvString2, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
}
// return result
return boReturnValue;
}
// setting the address of LORA
bool boSetAddress(void) {
const char setAddressCmd[] = "AT+ADDRESS="; // command to be sent
bool boReturnValue = false; // function's return value
String chkRcvString = "+OK";
// send command
Serial.print(setAddressCmd);
Serial.print(SELF_ADDRESS);
sendCrLf();
// check reply
boReturnValue = chkReply(chkRcvString, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
// return result
return boReturnValue;
}
// Send data to LORA in command form
bool boSendData(String data) {
const char sendDataCmd[] = "AT+SEND="; // command to be sent
bool boReturnValue = false; // function's return value
String chkRcvString = "+OK";
// send command
Serial.print(sendDataCmd);
Serial.print(TARGET_ADDRESS);
Serial.print(',');
Serial.print(data.length());
Serial.print(',');
Serial.print(data);
sendCrLf();
// check reply
boReturnValue = chkReply(chkRcvString, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
// return result
return boReturnValue;
}
/******************************************** Function Definition Related to BT Functionality *************************/
// Receive Command from Rx pin of Bluetooth functionality
bool rcvCommand(unsigned int timeout) {
bool boReturnValue = false; // function's return value
unsigned long startTime;
// wait for reply
do {
timeout--;
delay(1); // delay of 1 ms
if (((btSerial.available() >= MIN_CHAR_TO_RCV) && (btSerial.read() == START_CHAR_BT_COMM)) || (timeout == 0)) {
break;
}
} while (1);
// if start character is received within time then timeout will be greater than or equal to 1
if (timeout) {
startTime = millis();
receivedCommand = btSerial.readStringUntil(END_CHAR_BT_COMM);
if ((millis() - startTime) <= END_CHAR_TIME_OUT_BT_COMM) {
boReturnValue = true; // it means in readStringUntil() function '#' is received
} else {
boReturnValue = false; // it means in readStringUntil() function timeout has occurred
}
} else {
boReturnValue = false; // it means get character timeout has occured
}
// return result
return boReturnValue;
}
مرحله ۸

کدهای آردوینو برای بخش گیرنده

Arduino
/*
Code to receive commands to control the appliances from another Arduino using RLYR999 Module and send "DONE" in reply after implementing the required task and display the communication and tasks over I2C LCD.
by playwithcircuit.com
*/
#include <LiquidCrystal_I2C.h>
// below MACROS are for LORA communication
#define REPLY_TIMEOUT_IN_MS 300
#define REPLY_END_CHAR '\n'
#define CMD_END_CHAR '\n'
#define MODULE_ADDRESS 1
#define CONTROLLER_ADDRESS 0
#define MIN_CHAR_TO_RCV 1
#define WAIT_FOR_REQUEST 3000
// these four commands can be received from controller module
String sCMDLampON = "L1";
String sCMDLampOFF = "L0";
String sCMDFanON = "F1";
String sCMDFanOFF = "F0";
// save received command in this global string object
String receivedCommand;
// Init LCD at 0x27, 16x2
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Appliance Control MACROS
#define LAMP_CTRL_PIN 11
#define FAN_CTRL_PIN 12
#define LAMP_ON() digitalWrite(LAMP_CTRL_PIN, 0)
#define LAMP_OFF() digitalWrite(LAMP_CTRL_PIN, 1)
#define FAN_ON() digitalWrite(FAN_CTRL_PIN, 0)
#define FAN_OFF() digitalWrite(FAN_CTRL_PIN, 1)
void setup() {
boolean boRetVal = false;
// begin serial communication at baud 115200,n,8,1
// to communicate with the RF module
Serial.begin(115200);
// Initialize the LCD
lcd.init();
// Turn ON the Backlight
lcd.backlight();
// Clear the display buffer
lcd.clear();
// initialize appliances pins and turn off
pinMode(LAMP_CTRL_PIN, OUTPUT);
pinMode(FAN_CTRL_PIN, OUTPUT);
LAMP_OFF();
FAN_OFF();
receivedCommand.reserve(50); // prevents fragmentation, as multiple times data shall be received in this string
delay(1000);
flushBuffer(); // clear rx data
// Reset settings to factory defaults
boRetVal = boRestoreFactoryDefaults();
// setting the address if reset successfully
if (boRetVal == true) {
flushBuffer(); // clear rx data
boRetVal = boSetAddress();
}
if (boRetVal == true) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Module Init");
lcd.setCursor(0, 1);
lcd.print("Successful");
delay(1000);
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Module Init");
lcd.setCursor(0, 1);
lcd.print("Failed");
while (1)
;
}
}
void loop() {
String expected_reply = "DONE";
bool boRetVal = false;
// check string sent by controller
boRetVal = rcvCommand(CMD_END_CHAR, WAIT_FOR_REQUEST);
if (boRetVal == false) {
// Displaying Failed Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("No Command");
lcd.setCursor(0, 1);
lcd.print("Received");
} else {
// check if valid command is received
if ((receivedCommand == sCMDLampON) || (receivedCommand == sCMDLampOFF) || (receivedCommand == sCMDFanON) || (receivedCommand == sCMDFanOFF)) {
// Implement receivedCommand
vImplementTask(receivedCommand);
// Displaying Sent Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Command Received");
lcd.setCursor(0, 1);
lcd.print("Task Done");
delay(1000);
// transmits receivedCommand
boRetVal = boSendData(expected_reply);
if (boRetVal == true) {
// Displaying Sent Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Reply Sent");
} else {
// Displaying Failed Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Reply");
lcd.setCursor(0, 1);
lcd.print("Sending Failed");
}
delay(1000);
} else {
// Displaying Invalid Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Invalid:");
lcd.print(receivedCommand);
lcd.setCursor(0, 1);
lcd.print("Command Received");
}
}
}
void sendCrLf(void) {
Serial.write(0x0D); // Carriage Return
Serial.write(0x0A); // Line Feed
}
void flushBuffer(void) {
while (Serial.available() > 0) {
Serial.read();
}
}
bool rcvCommand(char receiveUntil, unsigned int timeout) {
bool boReturnValue = false; // function's return value
unsigned long startTime;
int firstComma;
int secondComma;
int thirdComma;
String data;
// wait for reply
do {
timeout--;
delay(1); // delay of 1 ms
} while ((Serial.available() < MIN_CHAR_TO_RCV) && (timeout > 0));
if (timeout) {
startTime = millis();
// if timeout is left then a reply is received check for the string in the reply
data = Serial.readStringUntil(receiveUntil);
if ((millis() - startTime) <= timeout) {
boReturnValue = true; // it means in readStringUntil() function receiveUntil character is received
// as the data will be in form of "+RCV=0,2,F1,-88,11" we need to extract command between second and third comma
firstComma = data.indexOf(',');
secondComma = data.indexOf(',', firstComma + 1);
thirdComma = data.indexOf(',', secondComma + 1);
// extract value between 2nd and 3rd comma
receivedCommand = data.substring(secondComma + 1, thirdComma);
} else {
boReturnValue = false; // it means in readStringUntil() function timeout has occurred
}
} else {
boReturnValue = false; // it means get character timeout has occured
}
// return result
return boReturnValue;
}
bool chkReply(String chkString, char receiveUntil, unsigned int timeout) {
String receivedString; // save received data in this string object
bool boReturnValue = false; // function's return value
// wait for reply
do {
timeout--;
delay(1); // delay of 1 ms
} while ((Serial.available() < MIN_CHAR_TO_RCV) && (timeout > 0));
if (timeout) {
// if timeout is left then a reply is received check for the string in the reply
receivedString = Serial.readStringUntil(receiveUntil);
if (receivedString.indexOf(chkString) != -1) {
boReturnValue = true;
} else {
boReturnValue = false;
}
} else {
boReturnValue = false;
}
// return result
return boReturnValue;
}
bool boRestoreFactoryDefaults(void) {
const char factoryDefaultCmd[] = "AT+FACTORY"; // command to be sent
bool boReturnValue = false; // function's return value
char downCounter = 100; // Down counter to wait for reply
String receivedString; // save received data in this string object
String chkRcvString1 = "+FACTORY";
String chkRcvString2 = "+READY";
// send command
Serial.print(factoryDefaultCmd);
sendCrLf();
// check first string in reply
boReturnValue = chkReply(chkRcvString1, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
if (boReturnValue == true) {
// check second string in reply
boReturnValue = chkReply(chkRcvString2, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
}
// return result
return boReturnValue;
}
bool boSetAddress(void) {
const char setAddressCmd[] = "AT+ADDRESS="; // command to be sent
bool boReturnValue = false; // function's return value
String chkRcvString = "+OK";
// send command
Serial.print(setAddressCmd);
Serial.print(MODULE_ADDRESS);
sendCrLf();
// check reply
boReturnValue = chkReply(chkRcvString, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
// return result
return boReturnValue;
}
bool boSendData(String data) {
const char sendDataCmd[] = "AT+SEND="; // command to be sent
bool boReturnValue = false; // function's return value
String chkRcvString = "+OK";
// send command
Serial.print(sendDataCmd);
Serial.print(CONTROLLER_ADDRESS);
Serial.print(',');
Serial.print(data.length());
Serial.print(',');
Serial.print(data);
sendCrLf();
// check reply
boReturnValue = chkReply(chkRcvString, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
// return result
return boReturnValue;
}
// this function is used to control the relay which controls the appliances using digital pins
void vImplementTask(String data) {
if (receivedCommand == sCMDLampON) {
LAMP_ON();
} else if (receivedCommand == sCMDLampOFF) {
LAMP_OFF();
} else if (receivedCommand == sCMDFanON) {
FAN_ON();
} else if (receivedCommand == sCMDFanOFF) {
FAN_OFF();
}
}
مرحله ۹

جمع‌بندی نهایی

خب، این هم از ساخت یک سیستم حرفه‌ای و دوربرد برای کنترل وسایل برقی! با این پروژه‌ای که تو آیسی‌مدار ساختیم، دیگه محدودیت‌های بلوتوث و وای‌فای مانع کارت نمی‌شه و می‌تونی هر وسیله‌ای رو از کیلومترها دورتر روشن و خاموش کنی. کدهای کامل هر دو بخش تو مراحل قبلی قرار داده شده تا به راحتی روی بردهات آپلود کنی.

حتما این سیستم کاربردی رو بساز و نظرت رو برامون تو بخش کامنت‌ها بنویس؛ اگر هم سوالی یا ایده‌ای برای ارتقاش داشتی، مشتاقانه منتظر خوندنش هستیم!

تو میتونی اولین سازنده باشی!

اگه پروژه رو ساختی به اشتراک بزار و اعتبار هدیه بگیر

این آموزش با استانداردهای اختصاصی آیسی‌مدار بازنویسی و بهینه‌سازی شده و تمامی حقوق انتشار آن متعلق به این مجموعه است و در صورت کپی یا بازنشر پیگرد قانونی خواهد داشت.

آموزش‌های مشابه

گفتگو‌های کاربران

هنوز نظری ثبت نشده؛ تو شروع کن!