Беспроводная доска объявлений, управляемая с помощью GSM, может найти множество применений в современном мире. С помощью данного устройства мы можем высвечивать на экране (например, ЖК дисплея) сообщение из любой точки мира. Все, что нужно будет сделать для этого, отправить SMS с вашего мобильного телефона с необходимыми служебными кодами (суффикс и префикс) перед и после текста SMS.
Описание работы устройства
В этом проекте плата Arduino Uno будет управлять всеми процессами, модуль GSM (SIM900A) будет принимать SMS-сообщения от мобильного телефона, а на экране ЖК дисплея будет отображаться принятое сообщение.
На проектируемую нами доску объявления мы можем передать любое сообщение, например, “#Circuit Digest*”, “#We Welcomes You*” при помощи SMS. В качестве префикса для передаваемого сообщения будем использовать ‘#’ – этот символ будет обозначать начало сообщения. А в качестве суффикса (концевика) сообщения будем использовать символ ‘*’.
Когда мы с помощью мобильного телефона осуществляем передачу SMS, GSM модуль принимает его и передает в Arduino. Плата Arduino извлекает смысловую часть сообщения из принятой строки и сохраняет ее в другой строке. А затем передает эту часть сообщения на ЖК дисплей. Структурная схема работы устройства показана на следующем рисунке.
Принципы работы GSM модуля
GSM модуль используется во многих устройствах, которые ориентированы на взаимодействие с технологией GSM. Обычно он используется для взаимодействия компьютера с GSM сетью. Однако в роли компьютера может выступать и плата Arduino.
GSM модуль понимает только AT команды и может на них отвечать. На большинство AT команд модуль отвечает сообщением “OK“ если он выполнил ее успешно, и сообщением “ERROR” если во время выполнения команды произошли какие либо проблемы. Существуют различные AT команды, например, ATA – ответить на звонок, ATD – сделать звонок, AT+CMGR - прочесть сообщение, AT+CMGS – передать SMS сообщение и т.д. AT команды должны заканчиваться символом возврата каретки, то есть \r (0D в шестнадцатеричном формате), например, “AT+CMGS\r”. К примеру, в нашем проекте мы можем использовать следующие AT команды:
ATE0 For echo off
AT+CNMI=2,2,0,0,0 <ENTER> режим автоматического открытия принимаемых сообщений
ATD<Mobile Number>; <ENTER> осуществить вызов (например, ATD+919610126059;\r\n)
AT+CMGF=1 <ENTER> выбор текстового режима
AT+CMGS=”Mobile Number” <ENTER> назначение мобильного номера получателя
>>после этого мы можем написать наше сообщение
>>после написания сообщения
Ctrl+Z команда передачи сообщения (26 в десятичном коде).
ENTER=0x0d в шестнадцатеричном формате
SIM900 представляет собой четырех диапазонный GSM/GPRS модуль, способный функционировать в диапазонах 850/900/1800/1900 МГц в режимах передачи/приема голоса, SMS и данных. Отличается низким энергопотреблением. Внешний вид данного модуля показан на следующем рисунке.
Работа схемы
Схема устройства представлена на следующем рисунке.
ЖК дисплей служит для отображения сообщений, принимаемых в SMS. Его контакты данных RS, EN, D4, D5, D6, D7 подсоединены к цифровым контактам Arduino 7, 6, 5, 4, 3, 2. Контакты Rx и Tx GSM модуля непосредственно подсоединены к контактам Tx и Rx платы Arduino. GSM модуль может быть запитан с помощью 12-вольтового адаптера.
Исходный код программы
В программе мы первым делом должны подключить библиотеку для работы с ЖК дисплеем, указать к каким контактам Arduino подключены контакты ЖК дисплея, инициализировать ряд переменных.
1 2 3 4 5 6 7 |
#include <LiquidCrystal.h> LiquidCrystal lcd(7,6,5,4,3,2); int led=13; int temp=0,i=0,x=0,k=0; char str[100],msg[32]; |
После этого необходимо инициализировать последовательный порт для работы со скоростью 9600 бод/с, задать направление работы для используемых контактов и инициализировать GSM модуль.
1 2 3 4 5 6 7 8 9 10 |
void setup() { lcd.begin(16,2); Serial.begin(9600); pinMode(led, OUTPUT); digitalWrite(led, HIGH); lcd.print("GSM Initilizing..."); gsm_init(); lcd.setCursor(0,0); lcd.print("Wireless Notice"); |
Для приема данных по последовательному порту мы будем использовать две функции: Serial.available – которая будет проверять поступили ли какие-нибудь данные по последовательному порту, и Serial.read - которая будет считывать данные, поступившие по последовательному порту.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void serialEvent() { while(Serial.available()) { char ch=(char)Serial.read(); str[i++]=ch; if(ch == '*') { temp=1; lcd.clear(); lcd.print("Message Received"); delay(1000); } } } |
После приема данных по последовательному порту мы сохраняем их в строке, эту строку проверяем на наличие символов ‘#’ и ‘*’ чтобы найти начало и конец сообщения. Затем очищенное от служебных символов сообщение показывается на ЖК дисплее с использованием команды lcd.print.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void loop() { for(unsigned int t=0;t<60000;t++) { serialEvent(); if(temp==1) { x=0,k=0,temp=0; while(x<i) { while(str[x]=='#') { x++; while(str[x]!='*') { msg[k++]=str[x++]; |
В функции ‘gsm_init()’ первым делом проверяется подсоединен ли GSM модуль при помощи передачи ему команды ‘AT’. Если модуль ответил на эту команду ‘OK’ - значит с ним все в порядке. Система будет проверять GSM модуль до тех пор, пока не получит в ответ команду ‘OK’. Затем в GSM модуле происходит отключение режима ECHO (эхо) с помощью команды ATE0 (после выполнения AT-команд будет выводиться только ответ (результат их выполнения).). Затем происходит проверка доступности сети при помощи команды ‘AT+CPIN?’. Если вставленная в модуль карта является SIM-картой и у нее присутствует PIN-код, то модуль формирует ответ +CPIN: READY. Эта проверка будет осуществляться до тех пор пока сеть не будет найдена. Более наглядно все эти процессы можно посмотреть в видео в конце статьи.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void gsm_init() { lcd.clear(); lcd.print("Finding Module.."); boolean at_flag=1; while(at_flag) { Serial.println("AT"); while(Serial.available()>0) { if(Serial.find("OK")) at_flag=0; } delay(1000); } |
Далее приведен полный текст программы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
#include <LiquidCrystal.h> LiquidCrystal lcd(7,6,5,4,3,2); int led=13; int temp=0,i=0,x=0,k=0; char str[100],msg[32]; void setup() { lcd.begin(16,2); Serial.begin(9600); pinMode(led, OUTPUT); digitalWrite(led, HIGH); lcd.print("GSM Initilizing..."); gsm_init(); lcd.setCursor(0,0); lcd.print("Wireless Notice"); lcd.setCursor(0,1); lcd.print(" Board "); delay(2000); lcd.clear(); lcd.print("Circuit Digest"); delay(1000); lcd.setCursor(0,1); lcd.print("System Ready"); Serial.println("AT+CNMI=2,2,0,0,0"); delay(500); Serial.println("AT+CMGF=1"); delay(1000); digitalWrite(led, LOW); } void loop() { for(unsigned int t=0;t<60000;t++) { serialEvent(); if(temp==1) { x=0,k=0,temp=0; while(x<i) { while(str[x]=='#') { x++; while(str[x]!='*') { msg[k++]=str[x++]; } } x++; } msg[k]='\0'; lcd.clear(); lcd.print(msg); delay(1000); temp=0; i=0; x=0; k=0; } } lcd.scrollDisplayLeft(); } void serialEvent() { while(Serial.available()) { char ch=(char)Serial.read(); str[i++]=ch; if(ch == '*') { temp=1; lcd.clear(); lcd.print("Message Received"); delay(1000); } } } void gsm_init() { lcd.clear(); lcd.print("Finding Module.."); boolean at_flag=1; while(at_flag) { Serial.println("AT"); while(Serial.available()>0) { if(Serial.find("OK")) at_flag=0; } delay(1000); } lcd.clear(); lcd.print("Module Connected.."); delay(1000); lcd.clear(); lcd.print("Disabling ECHO"); boolean echo_flag=1; while(echo_flag) { Serial.println("ATE0"); while(Serial.available()>0) { if(Serial.find("OK")) echo_flag=0; } delay(1000); } lcd.clear(); lcd.print("Echo OFF"); delay(1000); lcd.clear(); lcd.print("Finding Network.."); boolean net_flag=1; while(net_flag) { Serial.println("AT+CPIN?"); while(Serial.available()>0) { if(Serial.find("+CPIN: READY")) net_flag=0; } delay(1000); } lcd.clear(); lcd.print("Network Found.."); delay(1000); lcd.clear(); } |