آموزش ساخت سیستم موقعیت یاب توسط ماژول SIM800 و آردوینو

الکترونیک و رباتیک -> ماژول ها و سنسور ها 6416 8 کاربر آکادمی پارتینه

در ساخت خودروهای بدون سرنشین، کامیون‌های دارای محموله ارزشمند، سیستم‌‌های مدیریت ناوگان و... استفاده از یک سیستم ردیاب جهت کنترل موقعیت ضروری است.  به طور کلی از ماژول‌های GPS در سیستم‌های ردیابی موقعیت استفاده می‌شود. در این آموزش نیز از ماژول GSM SIM800 و آردوینو به منظور راه‌اندازی یک سیستم موقعیت یاب استفاده خواهیم کرد. عملکرد این سیستم به این صورت است که با برقراری یک تماس تلفنی با سیم کارت ، ماژولGSM موقعیت را شناسایی کرده و پس از دریافت موقعیت ، لینک مکان را درGoogle Maps برای مخاطب ارسال می‌کند.

مواد اولیه :
# عنوان تعداد لینک
0 خرید برد آردوینو 1 لینک خرید
1 ماژول GSM SIM800 1 لینک خرید

مرحله 1 : اتصالات و دیاگرام مداری

در این سیستم ردیاب از GPRS ماژول SIM800 GSM استفاده می‌کند که به یک میکروکنترلر متصل می‌شود. این ماژول را می‌توان با آداپتور 12 ولت یا باتری 12 ولت تغذیه کرد. این میزان ولتاژ ورودی توسط یک مبدل به 4 ولت برای تغذیه ماژول GSM و 3.3 ولت برای تغذیه میکروکنترلر تبدیل می شود. دیاگرام مداری کامل این ماژول در تصویر نشان داده شده است.

در ادامه بخش های مختلف این مدار به صورت جداگانه بررسی می شوند.

مرحله 2 : ماژول مبدل کاهنده 3 آمپر LM2596

از مبدل LM2596 برای ایجاد 4 ولت به منظور تغذیه ماژول SIM800 استفاده شده است. جریان راه‌اندازی ماژول SIM800 به حداکثر 2 آمپر است، بنابراین باید این میزان جریان تامین شود تا ماژول وارد حالت Sleep نشود. از این رو مبدل LM2596 که تا 3 آمپر جریان را به راحتی تامین می‌کند، انتخاب مناسبی است. دیاگرام مداری بخش تغذیه ماژول در تصویر نشان داده شده است.  

ولتاژ 12 ولت به پین 1 اعمال شده و ولتاژ رگوله شده از پین 2 که یک فیلتر LC با مقادیر 100uH و 470uF  برای فیلتر نویز سوئیچینگ روی آن اعمال می‌شود، بدست می‌آید. از ولتاژ خروجی  توسط یک مدار مقسم ولتاژ ( مقاومت های 2.2K=R30 و 1K=R29)  فیدبک گرفته شده و به پین FB وارد می شود. فرمول‌های محاسبه ولتاژ خروجی برای LM2596 در زیر آورده شده است.

(Vout = 1.23 * ((R1+R2)/R1


 توجه داشته باشید که ولتاژ کاری SIM800 دارای حساست بالایی است و حتما باید بین ۳٫۴ تا ۴٫۴ ولت باشد.

مرحله 3 : تغذیه و برقراری ارتباط با آی سی SIM800

ولتاژ برای اتصال به پین VBAT از آی سی رگولاتور LM2596 بدست می‌آید. نام پین به این دلیل VBAT است که به صورت نرمال توسط باتری لیتیمی تغذیه می‌شود. بنابراین اگر به عنوان یک دستگاه پرتابل از این سیستم استفاده می‌کنید، می‌توانید از مدار LM2596 صرف نظر کرده و آن را به صورت مستقیم به باتری لیتیمی متصل کنید.

پین‌های شبکه به 6 پین نگهدارنده‌ی سیم کارت متصل شده و پینNETLIGHT به یک نشانگر LED متصل می‌شود. این نشانگر LED وضعیت شبکه را نشان می‌دهد. همچنین پین  BT_ANT هنگام اتصال آنتن به ماژول استفاده می‌شود. در نهایت پین‌های TxD و RxD جهت برقراری ارتباط سریال با بودریت 9600 به میکروکنترلر متصل می‌شوند.

سایر اتصالات نشان داده شده در مدار بالا اختیاری بوده و اهمیت چندانی ندارد.

مرحله 4 : واحد پردازنده موقعیت یاب GSM

از میکروکنترلر AVR مدل ATMEGA328P که در بوردهای آردوینو Nano و UNO به کار می‌رود، به عنوان پردازنده‌ی این ماژول استفاده شده است. میکروکنترلر امبدد شده به طور مستقیم با ماژول SIM800 ارتباط برقرار می‌کند. از آنجا که ماژول SIM800 در سطح ولتاژ 3.3 ولت کار می‌کند، چیپ ATMEGA328P در این میزان ولتاژ کاری نیز عمل می‌کند.                  

همانطور که در دیاگرام نشان داده شده است، از آی سی رگولاتور 3.3 ولت مدل AMS1117 برای رگوله کردن ولتاژ ورودی 12 ولت به منظور تغذیه چیپ Atmega328 استفاده شده است. هم چنین ماژول SIM800 در سطح ولتاژ منطقی 3.3 ولت کار می‌کند. هم چنین در این مدار تعدادی از پین‌ها به منظور پروگرام کردن میکروکنترلر از طرق پروگرامر خارجی FTDI در نظر گرفته شده‌اند.

مرحله 5 : ساخت PCB جهت ردیاب موقعیت GSM

حال که مداری شامل ماژول GSM و میکروکنترلر داریم بهتر است یک PCB تهیه شود. به منظور مدیریت و حفظ فضا، این PCB به صورت دو طرفه با اجزای SMD طراحی شده است. شکل نهایی طراحی PCB در تصاویر نشان داده شده است. PCB طراحی شده در فرمت GERBER از این لینک قابل دریافت است.

 

مرحله 6 : اتصال ماژول به آردوینو

اتصال ماژول به آردوینو مطابق جدول انجام شده است. از PWR_KY  که به پین D12 آردوینو متصل شده، برای فعال و غیرفعال کردن ماژول پس از روشن شدن استفاده می‌شود. این کار به صرفه جویی در مصرف انرژی هنگام استفاده از ماژول کمک می‌کند. پین‌های D11 و D12 که به عنوان پین‌های ارتباط سریال سرسیال نرم افزاری آردوینو تعریف شده‌اند، به ترتیب به پین‌های Tx و Rx ماژول متصل می‌شوند. 

مرحله 7 : کدنویسی و تنظیمات نرم‌افزاری

برنامه این پروژه به سه بخش اصلی تقسیم می‌شود که این سه بخش عبارتند از دریافت تماس از کاربر ، دریافت جهت‌های جغرافیایی GPS از SIM800  و ارسال داده‌های GPS به گیرنده تماس از طریق ارسال پیامک

بدست آوردن طول و عرض جغرافیایی از ماژول GSM SIM800
از AT command هایی که در جدول بالا مشخص شده است، به منظور دریافت اطلاعات موقعیت در فرمت DD از ماژول SIM800 استفاده می‌شود.

نکته: قبل از انجام مراحل فوق مطمئن شوید كه سیم کارت از شبکه 2G و GPRS پشتیبانی می‌كند. 

در صورت اجرای دستورات فوق چیزی مانند تصویری که در بالا مشاهده می‌کنید، در سریال مانیتور آردوینو دیده می‌شود.

در تصویر بالا و قعیت نهایی در کادر قرمز مشخص شده است. همانطور که می بینید پاسخ برای دستور "AT + CIPGSMLOC = 1،1" چیزی شبیه به این خواهد بود:

+CIPGSMLOC: 0,75.802460,26.848892,2019/04/23,08:32:35

عدد 0 نشان دهنده‌ی پین کد مکان، 26.8488832 عرض و 75.802460 طول جغرافیایی است. بنابراین از این مقادیر باید مکان مورد نظر را خارج کرده و آن را به یک لینک Google Map اضافه کنیم تا مکان و آدرس آن روی نقشه مشخص شود. لینک به صورت زیر خواهد بود:

https://www.google.com/maps/place/26.8488892,75.802460

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

آردوینو با ماژول SIM800 ارتباط سریال برقرار کرده و از طریق  AT Command ها فرمان می‌گیرد. با ارسال هر AT Command،  ماژول با ارسال کاراکتر پاسخ داده و اگر نتیجه موفقیت آمیز باشد با پیام OK خاتمه می‌یابد.

بنابراین قبل از شروع برنامه ، تابعی به نام SIM800_send را می نویسیم که Command AT را به صورت یک رشته دریافت کرده و با استفاده از SIM800 آن را به ماژول GSM منتقل کند. تابع  ()SIM800.read، نتیجه را از ماژول SIM800 دریافت کرده و آن را برمی‌گرداند. تابع به صورت زیر است:

String SIM800_send(String incoming) //Function to communicate with SIM800 module
{
    SIM800.println(incoming); delay(100); //Print what is being sent to GSM module
    String result = "";
    while (SIM800.available()) //Wait for result
    {
    char letter = SIM800.read();
    result = result + String(letter); //combine char to string to get result
    }
return result; //return the result
}

در داخل setup function میزان بودریت ماژول و کامپایلر را 9600 قرار می‌دهیم. همچنین پین 12(PWR_KY) برای 1 ثانیه low کرده تا ماژول GSM را فعال کنیم.  ابتدا حالت echo را با استفاده از دستور "ATE1" فعال کرده و سپس دستورات ذکر شده در بالا را دنبال می‌کنیم تا هماهنگی های لازم را از ماژول GSM بدست آوریم.  در حالت echo به ازای ارسال هر کاراکتر ماژول دقیقا همان کاراکتر را بر می‌گرداند.  پس از ارسال هر AT command ، به منظور اشکال زدایی پاسخ را در سریال مانیتور کامپایلر نشان می‌دهیم.

void setup() {
//PWRKY pin of GSM module has to be pulled low for 1sec to enable the module
  pinMode(12,OUTPUT);
  digitalWrite(12, LOW);   //Pull-down
  delay(1000);                     
  digitalWrite(12, HIGH); //Release
 
  Serial.begin(9600); //Serial COM for debugging
  SIM800.begin(9600); //Software serial called SIM800 to speak with SIM800 Module
 
  delay(1000); //wait for serial COM to get ready
 
  responce = SIM800_send("ATE1"); //Enable Echo if not enabled by default
  Serial.print ("Responce:"); Serial.println(responce);
  delay(1000);
 
  responce = SIM800_send("AT+CGATT=1"); //Set the SIM800 in GPRS mode
  Serial.print ("Responce:"); Serial.println(responce);
  delay(1000);
 
  responce = SIM800_send("AT+SAPBR=3,1,"CONTYPE","GPRS" "); //Activate Bearer profile
  Serial.print ("Responce:"); Serial.println(responce);
  delay(1000);
 
  responce = SIM800_send("AT+SAPBR=3,1,"APN","RCMNET" "); //Set VPN options => 'RCMNET' 'www'
  Serial.print ("Responce:"); Serial.println(responce);
  delay(2000);
 
  responce = SIM800_send("AT+SAPBR=1,1"); //Open bearer Profile
  Serial.print ("Responce:"); Serial.println(responce); //Open bearer Profile
  delay(2000);
 
  responce = SIM800_send("AT+SAPBR=2,1"); //Get the IP address of the bearer profile
  Serial.print ("Responce:"); Serial.println(responce);
  delay(1000);
}

توجه داشته باشید که از AT+CIPGSMLOC  که در واقع مختصات مکان را  می‌دهد استفاده نشده است. به این دلیل که قرار است از این دستور فقط هنگام تماس با ماژول GSM استفاده شود. در داخل حلقه اصلی، بررسی می‌شود که آیا ماژول درخواستی ارسال کرده است یا خیر. در صورت دریافت تماس از جانب ماژول پیغام "RING" نیز نمایش داده می‌شود.


/*if (SIM800.available()) { //Check if the SIM800 Module is telling anything */
   /* char a = SIM800.read(); */
  /*  Serial.write(a); //print what the module tells on serial monitor */
  /*  incoming = incoming + String(a); */
    /*if (a == 13) //check for new line*/
  /*  incoming =""; //clear the string if new line is detected */
 /*   incoming.trim(); //Remove /n or /r from the incomind data */

  /*  if (incoming=="RING") //If an incoming call is detected the SIM800 module will say "RING" check for it */

  /*  {  */

در صورت دریافت تماس باید داده‌های مربوط به تشخیص موقعیت واکشی شده و به یک لینک google map تبدیل شده و در نهایت به عنوان یک پیامک ارسال شوند. قبل از آن لازم است تماس ورودی قطع شود. برای این کار از دستور "ATH " استفاده می‌شود. سپس حالت echo را با استفاده از ATE0 غیرفعال کرده و دستور  "AT + CIPGSMLOC = 1،1" برای بدست آوردن طول و عرض جغرافیایی ارسال می‌شود.

  Serial.println ("Sending sms"); delay(1000);

     responce = SIM800_send("ATH"); //Hand up the incoming call using ATH

     delay (1000);

     responce = SIM800_send("ATE0"); //Disable Echo

     delay (1000);

     responce = ""; Latitude=""; Longitude=""; //initialise all string to null

     SIM800.println("AT+CIPGSMLOC=1,1"); delay(5000); //Request for location data

مجددا از همان تکینکی که در حلقه اصلی استفاده شد برای تبدیل کاراکترهای خروجی به رشته استفاده می‌شود. رشته پاسخ دستور AT + CIPGSMLOC = 1،1 خواهد بود که شامل طول و عرض جغرافیایی است. برای مرتب کردن و نمایش این مقادیر از تابع ()prepare_message استفاده می‌شود.

void prepare_message()

{

  //Sample Output for AT+CIPGSMLOC=1,1   ==> +CIPGSMLOC: 0,75.802460,26.848892,2019/04/23,08:32:35 //where 26.8488832 is Lattitude and 75.802460 is longitute

  int first_comma = responce.indexOf(','); //Find the position of 1st comma

  int second_comma = responce.indexOf(',', first_comma+1); //Find the position of 2nd comma

  int third_comma = responce.indexOf(',', second_comma+1); //Find the position of 3rd comma

  for(int i=first_comma+1; i<second_comma; i++) //Values form 1st comma to 2nd comma is Longitude

    Longitude = Longitude + responce.charAt(i);

  for(int i=second_comma+1; i<third_comma; i++) //Values form 2nd comma to 3rd comma is Latitude

    Latitude = Latitude + responce.charAt(i);

حال که مقدار طول و عرض جغرافیایی بدست آمده است، باید آن را با دستور زیر به فرمت یک لینک تبدیل کرد. در آخر لینک به صورت پیامک به شماره تلفن همراه مورد نظر ارسال می‌شود. شماره تلفن همراه توسط دستور"AT + CMGS = +98912xxxxxxx" ثبت می‌شود. در این دستور شماره تلفن مورد نظر خود جایگزین کنید.

SIM800.println("AT+CMGF=1"); //Set the module in SMS mode

     delay(1000);




     SIM800.println("AT+CMGS="+98912xxxxxxx ""); //Send SMS to this number

     delay(1000);




     SIM800.println(Link); // we have send the string in variable Link

     delay(1000);




     SIM800.println((char)26);// ASCII code of CTRL+Z - used to terminate the text message

     delay(1000);

مرحله 8 : تست دستگاه ردیاب موقعیت

بعد از اتصال ماژول به آردوینو مطابق با آنچه در قسمت قبل گفته شد، سیم کارت را وارد اسلات قرار گرفته بر روی ماژول کرده و مطمئن شوید که ارتباط با شبکه برقرار شده است. هنگام برقراری اتصال نشانگر LED روی ماژول باید هر 3 ثانیه یک بار چشمک بزند. در این حالت پیغام‌هایی مطابق با آنچه در تصویر مشاهده می‌کنید در سریال مانیتور نمایش داده می‌شوند.

این بدان معنی است که ماژول GSM برای استخراج جهت‌های جغرافیایی کالیبره شده و آماده تماس‌های دریافتی است. به سادگی امکان تماس از هر شماره به سیم کارت GSM وجود داشته و متوجه می‌شوید که تماس پس از شنیدن چند بوق متوقف شده و شماره‌ای که در برنامه وارد شده است، پیامی دریافت خواهد کرد. پیام متنی دریافتی حاوی لینک Google map خواهد بود.

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

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

کد:

/*Program to send Latitude and Logitute Information from SIM800 to Phone via SMS on call request
 * Code by: B.Aswinth Raj
 * For: www.circuitdigest.com
 * Dated:23-04-2019
 * Sample Output for AT+CIPGSMLOC=1,1   ==> +CIPGSMLOC: 0,75.802460,26.848892,2019/04/23,08:32:35 //where 26.8488832 is Lattitude and 75.802460 is longitute 
 * Link to send: https://www.google.com/maps/place/26.8488892,75.802460  //where 26.8488832 is Lattitude and 75.802460 is longitute 
 */

#include <SoftwareSerial.h> //Software Serial header to communicate with GSM module 

SoftwareSerial SIM800(10, 11); // RX, TX 

String Link = "The current Location is https://www.google.com/maps/place/"; //we will append the Lattitude and longitude value later int the program 
String responce = "";
String Longitude = "";
String Latitude = ""; 

String SIM800_send(String incoming) //Function to communicate with SIM800 module 
{
    SIM800.println(incoming); delay(100); //Print what is being sent to GSM module 
    String result = "";
    while (SIM800.available()) //Wait for result 
    {
    char letter = SIM800.read();
    result = result + String(letter); //combine char to string to get result 
    }
    
return result; //return the result 
}

void setup() {

//PWRKY pin of GSM module has to be pulled low for 1sec to enable the module 
  pinMode(12,OUTPUT);
  digitalWrite(12, LOW);   //Pull-down
  delay(1000);                      
  digitalWrite(12, HIGH); //Release 
 
  Serial.begin(9600); //Serial COM for debugging 
  SIM800.begin(9600); //Software serial called SIM800 to speak with SIM800 Module 

  delay(1000); //wait for serial COM to get ready 

  responce = SIM800_send("ATE1"); //Enable Echo if not enabled by default 
  Serial.print ("Responce:"); Serial.println(responce); 
  delay(1000);

  responce = SIM800_send("AT+CGATT=1"); //Set the SIM800 in GPRS mode 
  Serial.print ("Responce:"); Serial.println(responce); 
  delay(1000);

  responce = SIM800_send("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\" "); //Activate Bearer profile 
  Serial.print ("Responce:"); Serial.println(responce); 
  delay(1000);

  responce = SIM800_send("AT+SAPBR=3,1,\"APN\",\"RCMNET\" "); //Set VPN options => 'RCMNET' 'www'
  Serial.print ("Responce:"); Serial.println(responce); 
  delay(2000);
   
  responce = SIM800_send("AT+SAPBR=1,1"); //Open bearer Profile
  Serial.print ("Responce:"); Serial.println(responce); //Open bearer Profile 
  delay(2000);

  responce = SIM800_send("AT+SAPBR=2,1"); //Get the IP address of the bearer profile 
  Serial.print ("Responce:"); Serial.println(responce); 
  delay(1000);

}

void prepare_message()
{
  //Sample Output for AT+CIPGSMLOC=1,1   ==> +CIPGSMLOC: 0,75.802460,26.848892,2019/04/23,08:32:35 //where 26.8488832 is Lattitude and 75.802460 is longitute 
  int first_comma = responce.indexOf(','); //Find the position of 1st comma 
  int second_comma = responce.indexOf(',', first_comma+1); //Find the position of 2nd comma 
  int third_comma = responce.indexOf(',', second_comma+1); //Find the position of 3rd comma 

  for(int i=first_comma+1; i<second_comma; i++) //Values form 1st comma to 2nd comma is Longitude 
    Longitude = Longitude + responce.charAt(i); 

  for(int i=second_comma+1; i<third_comma; i++) //Values form 2nd comma to 3rd comma is Latitude 
    Latitude = Latitude + responce.charAt(i); 

  Serial.println(Latitude); Serial.println(Longitude); 
  Link = Link + Latitude + "," + Longitude; //Update the Link with latitude and Logitude values 
  Serial.println(Link);
}

String incoming = "";

void loop() {
  
  if (SIM800.available()) { //Check if the SIM800 Module is telling anything 
    char a = SIM800.read();
    Serial.write(a); //print what the module tells on serial monitor 
    incoming = incoming + String(a);
    if (a == 13) //check for new line 
    incoming =""; //clear the string if new line is detected 
    incoming.trim(); //Remove /n or /r from the incomind data 
    
    if (incoming=="RING") //If an incoming call is detected the SIM800 module will say "RING" check for it 
    {
     Serial.println ("Sending sms"); delay(1000);
     responce = SIM800_send("ATH"); //Hand up the incoming call using ATH
     delay (1000);
     responce = SIM800_send("ATE0"); //Disable Echo
     delay (1000);

     responce = ""; Latitude=""; Longitude=""; //initialise all string to null
     SIM800.println("AT+CIPGSMLOC=1,1"); delay(5000); //Request for location data 
      while (SIM800.available()) 
      {
       char letter = SIM800.read();
       responce = responce + String(letter); //Store the location information in string responce 
      }
      Serial.print("Result Obtained as:");   Serial.print(responce); Serial.println("*******");

     prepare_message(); delay(1000); //use prepare_message funtion to prepare the link with the obtained LAT and LONG co-ordinates 

     SIM800.println("AT+CMGF=1"); //Set the module in SMS mode
     delay(1000);
     
     SIM800.println("AT+CMGS=\"9612345678\""); //Send SMS to this number 
     delay(1000);

     SIM800.println(Link); // we have send the string in variable Link 
     delay(1000);

     SIM800.println((char)26);// ASCII code of CTRL+Z - used to terminate the text message 
     delay(1000);
    }
  }
  
  if (Serial.available()) { //For debugging 
    SIM800.write(Serial.read());
  }
  
}