PDA

Просмотр полной версии : Arduino + GSM


Xellow
12.02.2017, 23:58
Добрый вечер всем. Появилась навязчивая мысль, сделать некое устройство на базе Arduino (https://duino.ru/arduino.html) + GSM модуля SIM 800L (https://duino.ru/SIM800L-GSM-modem-s-vneshnei-antennoi.html), которое будет в состоянии по звонку или СМС запросу, выполнять команды(запуск авто, пуск ПК), а так же сообщать в ответных СМС различную информацию, типа - напряжение АКБ, температура авто, удачный/неудачный пуск двигателя и т.д. И плюс использовать возможности перехода в режим энергосбережения Arduino и SIM 800L.
Сейчас уже использую связку Arduino + GSM устройство на базе GSM розетки Мегафона, для автозапуска, но не нравится энергопотребление этого "бутерброда" и не возможность добавлять свои команды и свои СМС в этом варианте.
Никто не делал что то подобное? Или может в интернете натыкался?

YAM1966
13.02.2017, 12:10
Ну тогда почитайте это (http://pryf.livejournal.com/9452072.html) для начала.... или аналогичное (http://mykor.ru/stati/za-pokupku-gps-trekera-ili-radionjani-mo.html).

awtoap
13.02.2017, 12:46
Ну тогда почитайте это для начала.... или аналогичное.

И каким боком это к вопросу автора? GPS и GSM не одно и тоже )

Xellow
13.02.2017, 12:53
Ну тогда почитайте это (http://pryf.livejournal.com/9452072.html) для начала.... или аналогичное (http://mykor.ru/stati/za-pokupku-gps-trekera-ili-radionjani-mo.html).

То же, не очень понял к чему это))

lti1
13.02.2017, 14:58
Есть более бюджетный вариант чем SIM 800, M590 (http://radiolaba.ru/microcotrollers/gsm-modul-neoway-m590-opisanie-i-komandyi-upravleniya.html), спящем режиме потребляемый ток составляет 2,5-3 мА.

Xellow
13.02.2017, 15:18
Железки уже заказал -отступать некуда))

YAM1966
13.02.2017, 15:28
SIM800L (https://duino.ru/SIM800L-GSM-modem-s-vneshnei-antennoi.html) в плане управления получше, так как ко всему прочему позволяет управляться с помощью DTMF (https://duino.ru/product_info.php/info/p2321_MT8870---Dekoder-DTMF-signalov.html) команд с телефона. Да и меньше по габаритам.

lti1
13.02.2017, 23:38
YAM1966, согласен. И цена не сильно то и отличается от M590.
Xellow, SIM800L (https://duino.ru/SIM800L-GSM-modem-s-vneshnei-antennoi.html) и Arduino работа в режиме энергосбережения.
NWYFjK6M6Fw

skanch
14.02.2017, 18:55
Никто не делал что то подобное? Или может в интернете натыкался?
Модуль SIM800L (https://duino.ru/SIM800L-GSM-modem-s-vneshnei-antennoi.html) очень надежный, простой и не требует сложных манипуляций. Единственное требование- это к питанию - от 3.7В до 4.2В. Пользуюсь такими-очень доволен.Ниже несколько скетчей - может пригодятся.

Один с запросом баланса на СИМ и триггером включения канала по звонку.

#include <SoftwareSerial.h>
#include <Bounce.h>
String currStr = "";
SoftwareSerial gprsSerial(2, 3);
String nomber_Phone = "";//Строка содержит номер телефона
Bounce bouncer = Bounce(5, 40); //создаем экземпляр класса Bounce для 5 вывода
//String currStr1 = "";//Строка содержит текущую строку, полученую от сим модуля.
char data;//Содержит символ полученый от сим модуля.
String str_1 = "", number = ""; // str_1 - сообщение, number - телефонный номер звонившего


void setup()
{
pinMode(9, OUTPUT); //пин к которому подключен светодиод
pinMode(5, INPUT_PULLUP); //переключаем 5 вывод в режим входа (от SIM модуля)
Serial.begin(9600);
gprsSerial.begin(9600);
// Настраиваем приём сообщений
// Между командами даём время на их обработку

gprsSerial.println("AT");
delay(500);
Serial.println("AT+CMGD=4");//Удаляем всё SMS которые могут содержаться на сим карте.
gprsSerial.println("ATE0"); // выключаем эхо

delay(100);

gprsSerial.println("AT+CLIP=1"); // Включаем АОН

delay(100);

gprsSerial.println("AT+CSCS=\"GSM\""); // Режим кодировки текста = GSM (только англ.)

delay(100);

gprsSerial.println("AT+CNMI=2,2"); // Текст смс выводится в com-порт

delay(100);
gprsSerial.println("AT+CSQ");// Проверяем уровень сигнала
delay(800);

gprsSerial.println("AT+CMGF=1"); //устанавливает текстовый режим смс-сообщения
delay(300);

gprsSerial.println("AT+IFC=1,1"); //устанавливает программный контроль потоком передачи данных
delay(300);

gprsSerial.print("AT+CPBS=");//открывает доступ к данным телефонной книги
gprsSerial.print((char)34);
gprsSerial.print("SM"); // SIM-карты
gprsSerial.print((char)34);
gprsSerial.println("");
// gprsSerial.print((char)13);
delay(300);

gprsSerial.println("AT+CNMI=1,2,2,1,0");//включает оповещение о новых сообщениях,
//новые сообщения приходят в следующем формате:
// +CMT: "<номер телефона>", "", "<дата, время>",
//а на следующей строчке с первого символа идёт содержимое сообщения
delay(300);
balance();

}


void loop()
{
{
if (Serial.available())
gprsSerial.write(Serial.read());
// если поступил звонок
if (bouncer.update())
{
if (bouncer.read()==0)
{
digitalWrite(9, HIGH); //включить светодиод
gprsSerial.println("ATD +7981*******;"); //показать номер номер телефона
delay(15000);
gprsSerial.println("ATH0");
digitalWrite(9, LOW); //выключить светодиод
}
}
if (gprsSerial.available()) // если пришло что то от GSM модуля, то вызываем обработчик
{
response_on_dial();
}
}



//++++Запрос баланса+++//
{
if (gprsSerial.available()){
char currSymb = gprsSerial.read();
if ('\r' == currSymb) { //если символ перевод каретки
if (currStr.startsWith("+CUSD: 0,")) {
int zzz = currStr.indexOf("UAH");
String balance=currStr.substring(10,zzz-3); //баланс на сим карте
Serial.print(balance);
smsSendAlarm( currStr);
}
currStr = "";
}
else if ('\n' != currSymb) { //если символ НЕ новая строка
currStr += String(currSymb);
}
}
}
}
//процедура отправки СМС
void smsSendAlarm(String text)
{
String NBoss = "7981*******"; // вместо звездочек вписать номер телефона
gprsSerial.println("AT+CMGS=\"" + NBoss + "\""); //Отправляем на GSM комманду отправка смс-номер
NBoss = ""; //Очищаем перемунную
delay(300); //Делаем задержку на передачу комманды
gprsSerial.print(text); //Отправляем на GSM комманду отправка смс-текст
text = ""; //Очищаем перемунную
delay(500); //Делаем задержку на передачу комманды
gprsSerial.print((char)26); //Отправляем на GSM комманду отправка смс!
delay(5000); //Делаем задержку отправку смс

}
void balance () {

gprsSerial.print("AT+CUSD=1,");
gprsSerial.print('"');
gprsSerial.print("#100#");
gprsSerial.println('"');

}

// Обработчик входящего вызова
void response_on_dial()
{
delay(500);
while (gprsSerial.available())
{
char c = gprsSerial.read();
Serial.write(c);
str_1 += c; // загоняем в str_1 сообщение от модуля
}
// Находим в строке "+7981" и выдёргиваем из строки номер телефона
if (str_1.startsWith("RING", 2))
{
int index_number = str_1.lastIndexOf("+7981");
if (index_number != -1)
{
number = str_1.substring(index_number, (index_number + 13));
// Пришел вызов в номера "number", далее пишем, что делаем
String str_2 = "Ring!!!" + number;
Serial.println(str_2);
delay(3000);
gprsSerial.println("ATH0"); // сбрасываем вызов АТ-командой "АТН"

if(digitalRead(9) == LOW)
{Serial.println("Led ON");
digitalWrite(9,HIGH); // инвертируем выход led

}
else
{
digitalWrite(9,LOW);
Serial.println("Led OFF");
}
}
}
str_1 = "";
}

Второй просто триггер.

#include <SoftwareSerial.h>
//#include <EEPROM.h>
#include <Bounce.h>
String nomber_Phone = "";//Строка содержит номер телефона. далее Разрешенный номер.
SoftwareSerial mySerial(2, 3); // RX, TX +,0,3,2,- (3-3, 2-2)
Bounce bouncer = Bounce(5, 40); //создаем экземпляр класса Bounce для 5 вывода
String currStr = "";//Строка содержит текущую строку, полученую от сим модуля.
char data;//Содержит символ полученый от сим модуля.
String str_1 = "", number = ""; // str_1 - сообщение, number - телефонный номер звонившего


void setup()
{
pinMode(9, OUTPUT);
pinMode(5, INPUT_PULLUP); //переключаем 5 вывод в режим входа
//digitalWrite(5, HIGH); //включаем на нем подтягивающий резистор
pinMode(13, OUTPUT);
Serial.begin(19200); //Скорость порта для связи Arduino с компьютером
//Serial.println("Goodnight moon!");
mySerial.begin(19200); //Скорость порта для связи Arduino с GSM модулем
mySerial.println("AT");
delay(500);
Serial.println("AT+CMGD=4");//Удаляем всё SMS которые могут содержаться на сим карте.
mySerial.println("ATE0"); // выключаем эхо

delay(100);

mySerial.println("AT+CLIP=1"); // Включаем АОН

delay(100);

mySerial.println("AT+CMGF=1"); // Формат СМС = ASCII текст

delay(100);

mySerial.println("AT+CSCS=\"GSM\""); // Режим кодировки текста = GSM (только англ.)

delay(100);

mySerial.println("AT+CNMI=2,2"); // Текст смс выводится в com-порт

delay(100);
mySerial.println("AT+CSQ");// Проверяем уровень сигнала
delay(800);





void loop()
{
if (Serial.available())
mySerial.write(Serial.read());
if (bouncer.update())
{
if (bouncer.read()==0)
{
digitalWrite(9, HIGH);
mySerial.println("ATD +7981*******;"); //т
delay(15000);
mySerial.println("ATH0");
digitalWrite(9, LOW);
}
}
if (mySerial.available()) // если пришло что то от GSM модуля, то вызываем обработчик
{
response_on_dial();
}
}
// Обработчик входящего вызова
void response_on_dial()
{
delay(500);
while (mySerial.available())
{
char c = mySerial.read();
Serial.write(c);
str_1 += c; // загоняем в str_1 сообщение от модуля
}
// Находим в строке "+7981" и выдёргиваем из строки номер телефона
if (str_1.startsWith("RING", 2))
{
int index_number = str_1.lastIndexOf("+7981");
if (index_number != -1)
{
number = str_1.substring(index_number, (index_number + 13));
// Пришел вызов в номера "number", далее пишем, что делаем
String str_2 = "Ring!!!" + number;
Serial.println(str_2);
delay(3000);
mySerial.println("ATH0"); // сбрасываем вызов АТ-командой "АТН"

if(digitalRead(9) == LOW)
{Serial.println("Led ON");
digitalWrite(9,HIGH); // инвертируем выход led
}
else
{
digitalWrite(9,LOW);
Serial.println("Led OFF");
}
}
}
str_1 = "";
}


Программки давнишние - уже не помню, что у самого залито... Но точно рабочие. Вот несколько ссылок на соответствующие темы. Здесь (http://sdivcom.ru/?p=2231), здесь (https://github.com/stephaneAG/SIM800L/blob/master/README.md), здесь (http://neru5.ru/index.php?route=news/article&news_id=15), еще (http://we.easyelectronics.ru/blog/part/369.html).

skanch
14.02.2017, 20:02
Наткнулся в интернете (http://mysku.ru/blog/ebay/43282.html) - можно "прикрутить" под свои нужды.

Xellow
14.02.2017, 23:48
Спасибо за наводки - буду курить). Кое что из этого уже видел. Sim800 заказал 2-й версии с питанием 5В. С нетерпением жду подарков от братьев-китайцев)), чтоб начать экскрименты..

defed
25.02.2017, 18:46
Xellow. Привет.Как успехи? Пришел модуль? Заказал тоже 5 вольтовый sim800l хочу запускать webasto по звонку с нужного номера. Очень интересует вопрос перехода в спящий режим с минимальным энергопотреблением.

skanch
25.02.2017, 19:08
Очень интересует вопрос перехода в спящий режим с минимальным энергопотреблением.
Вот (http://www.pccar.ru/showpost.php?p=382268&postcount=8) же выше lti1 выкладывал ссылку... Готовое решение, только подставить свои параметры.
/* arduino SIM800L
D2 RING
D4 TX
D5 RX
D6 DTR */

#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
#include "call.h"
#include <avr/sleep.h>
#include <avr/power.h>

int pin = 2; // подключается к ring пину gsm модуля
int relay = 9; // реле
byte stat=0;

SMSGSM sms;
CallGSM call;

void setup(){
set_sleep_mode(SLEEP_MODE_STANDBY); //Определяем режим сна
pinMode(pin, INPUT);
digitalWrite(pin,HIGH);

pinMode(6, OUTPUT); // к DTR пину GSM модуля
digitalWrite(6,LOW); // пробуждаем GSM модуль

pinMode(relay, OUTPUT);
digitalWrite(relay,HIGH);

Serial.begin(115200);
Serial.println("GSM test.");

if (gsm.begin(2400)) {
Serial.println("\nstatus=READY");

} else Serial.println("\nstatus=IDLE");

delay(300);

gsm.SimpleWrite(F("AT+CSCLK=1"));
gsm.SimpleWriteln("");

}

void loop(){

stat=call.CallStatus();

if(stat==CALL_INCOM_VOICE) {
// Serial.println("CALL!!!");
// sms.SendSMS("+79371662772", "Vipolneno!");
digitalWrite(relay,LOW);
delay(2000);
digitalWrite(relay,HIGH);
call.HangUp(); // Кладем трубку
}

digitalWrite(6,HIGH); // вырубаем GSM модуль
EnterSleep(); //Пора спать

}

void wakeUp()
{
Serial.println("WakeUp"); //Проснулись
detachInterrupt(0); //Отключаем прерывания
digitalWrite(6,LOW); // пробуждаем GSM модуль
delay(500);
}

void EnterSleep()
{
attachInterrupt(0, wakeUp, LOW); //Если на 0-вом прерываниии - ноль, то просыпаемся.
delay(100);

sleep_enable(); //Разрешаем спящий режим
sleep_mode(); //Спим (Прерывания продолжают работать.) Программа останавливается.
sleep_disable(); //Запрещаем спящий режим
}

Xellow
26.02.2017, 18:58
Нет пока не приехал SIM800(( жду. Приведённый выше скетч, рассматриваю как базовый, для последующего допиливания.

Xellow
26.02.2017, 22:04
Со спящим режимом SIM 800 v2 пролёт - 5ти вольтовая версия его похоже не поддерживает - нет пина DTR(((

defed
27.02.2017, 06:16
Вот это пролет... Может напрямую к модулю можно подключиться. Даташит нужно изучить.

skanch
27.02.2017, 15:25
Во второй версии (http://www.microchip.ua/simcom/SIM800x/SIM800H/SIM800H&SIM800L_Hardware_Design_V2.02.pdf) спящий режим реализован немного по другому (это одно из отличий от предыдущей версии и можно обойтись без DTR).
Ниже выдержка-перевод из даташита.

"4.3.4.
Спящий режим 2 (Sleep Mode 2) (команда "AT+CSCLK=2") (это новый режим и его нет в V1.0)
В этом режиме, SIM800H&SIM800L будет постоянно отслеживать последовательный порт данных сигнала. При отсутствии передачи данных в течение 5 секунд на (пине)RXD или нет сигнала и нет в эфире аппаратных прерываний (например, GPIO interrupt), SIM800H&SIM800L переходит в режим сна 2 автоматически. В этом режиме SIM800H/L по-прежнему может получать оповещения или SMS из сети .


4.3.5.
Пробуждение SIM800H&SIM800L из спящего режима 2.

Когда SIM800H&SIM800L находится в спящем режиме 2 (Sleep Mode 2) (команда "AT+CSCLK=2"), следующие методы могут разбудить модуль:

: Отправить данные на SIM800H&SIM800L через основной последовательный порт .
: Входящий звонок или передача данных из сети.
: Входящее SMS из сети."

Сам не проверял - нужно пробовать.

defed
27.02.2017, 19:18
skanch,спасибо будем побывать по приезду. отпишемся по результату))

Xellow
02.03.2017, 19:39
skanch, Присоединяюсь, спасибо огромное - появилась надежда)))

Xellow
11.03.2017, 12:37
Добрый день. Не могу найти как сформулировать условие выполнения команды по СМС только от одного заданного номера, код из примера - как хотелось бы видеть...

void getsms()
{
sms.GetSMS(pos,n,20,smsbuffer,160);
//Serial.println(n); //номер входящей СМС
//Serial.println(smsbuffer); //текст сМС
input_string =String(smsbuffer);
if ((n) != (n1)) - //Если номер входящей СМС не соответствует заданному (char n1[] = "+79XXXXXXXXX";)
{
sms.DeleteSMS(pos); - //Удаляем эту СМС
delay(1000);
}


Собственно вопрос - как правильно сформулировать выделенное цветом условие?

lti1
11.03.2017, 15:38
Добрый день. Не могу найти как сформулировать условие выполнения команды по СМС только от одного заданного номера, код из примера - как хотелось бы видеть...

void getsms()
{
sms.GetSMS(pos,n,20,smsbuffer,160);
//Serial.println(n); //номер входящей СМС
//Serial.println(smsbuffer); //текст сМС
input_string =String(smsbuffer);
if ((n) != (n1)) - //Если номер входящей СМС не соответствует заданному (char n1[] = "+79XXXXXXXXX";)
{
sms.DeleteSMS(pos); - //Удаляем эту СМС
delay(1000);
}


Собственно вопрос - как правильно сформулировать выделенное цветом условие?
Так попробуйте:if(strstr(n, n1) != NULL) {
если номер совпадает
}
else {
если номер не совпадает
}

skanch
11.03.2017, 15:52
...условие выполнения команды по СМС только от одного заданного номера...

Объявить в "шапке"
char adminNumber[] = "+7**********"; //Ваш номер телефона

и далее

if(strcmp(number, adminNumber) == 0) //принимать СМС только с определенного номера

Как вариант...

Xellow
11.03.2017, 16:50
Респект! Работает!
Код пишется, в принципе основные хотелки реализованы, но пока без энергосбережения... Что получится - выложу, если будут желающие его улучшить- только "за"). Писатель я не очень..

Xellow
12.03.2017, 17:00
Ну вот примерно что получилось... Что работает: Старт - стоп по СМС, возврат данных о напряжении сети и температуре по СМС запросу, старт по температуре и останов от аварийного сигнала(опущен ручник, включена передача). Все события подтверждаются соответствующими СМС. Теперь чего нет: Энергосбережение(((, ардуину не усыпить, т.к. нужно мерить температуру и напряжение, а SIM800, при включении режима энергосбережения - ведёт себя неадекватно(может руки кривые). В общем то сам скетч - это выдержки из разных творений на просторах интернета, собранные в один, так что прошу сильно не пинать если что))). Сам код автозапуска уже полтора года трудится у меня в машине, без особых нареканий. Энергопотребление получилось около 20мА, позже перемерю более точным прибором. Если будет желание, что либо поправить - буду только ЗА. Есть одна замеченная проблема!!! Если в результате каких либо манипуляций СИМ забивается необработанными СМС, то конструкция перестаёт функционировать, до очистки СИМ через АТ команды. Как это прописать в коде я не разобрался((.

skanch
12.03.2017, 17:58
Удаление всех СМС АТ- команда "AT+CMGD=4". Все команды можно посмотреть здесь (http://www.2150692.ru/faq/47-at-komandy-sim900).

Xellow
12.03.2017, 18:36
Я эти команды знаю.. но не могу их в скетч корректно встроить.. По чему то все варианты отправки АТ команд, которые я пробовал встроить в скетч - делали его не работоспособным((( Пробовал так:
gsm.SimpleWrite(F("AT+CMGDA=DEL ALL"));
gprsSerial.print("AT+CMGDA=DEL ALL");
GsmSerial.println("AT+CMGDA=DEL ALL");

Xellow
12.03.2017, 20:13
Поэкспериментировал ещё... Прописал Serial.print("AT+CMGDA=DEL ALL");
Скетч работает, в сериале команда проходит, но СМС не удаляет(( в порт прописывает следующее:
ATT: "REC READ"
RIC:
+CMGR: "REC READ","+79ххххххххх","","17/03/12,19:10:53+12"
6

OK

AT+CMGDA=DEL ALLATT: OK
RIC: NO STRING RCVDATT: OK
RIC: NO STRING RCVDATT: OK
RIC: NO STRING RCVDATT: OK
RIC:

ATT: OK
RIC:
OK

skanch
12.03.2017, 21:04
А такой вариант на прошел?
Serial.println("AT+CMGD=4");//Удаляем всё SMS которые могут содержаться на сим карте.

Xellow
12.03.2017, 22:09
Странно, но AT+CMGD=4, не удаляет СМС, даже в режиме подачи АТ команд напрямую из консоли.

skanch
12.03.2017, 23:41
Здесь (https://geektimes.ru/post/254982/) подсмотрел вариант

{
gsm.begin(2400);
delay(10000);
for(i = 1; i <= 21; i++)
{
sms.DeleteSMS(i);
}

Xellow
12.03.2017, 23:57
Да я видел... У меня подозрение, что это работает, только если связка SIM800 - Ардуино нормально фунциклирует..т.е. SIM800 получил СМС - Ардуина это поняла и присвоила этой СМС номер(i) и потом, согласно номера (i) - удалила. А вот если по какой либо причине эта связка рассогласована, например нет питания на ардуине, то полученные СИМ800 СМС не получают номера и не удаляются... ИМХО.

skanch
13.03.2017, 00:12
Возможно, что и так...К сожалению проверить не на чем...

Xellow
13.03.2017, 00:20
Я был не прав - чистит прекрасно, можно пользоваться. Спасибо за помощь!!

skanch
13.03.2017, 00:26
Рад, что был полезен...

Xellow
13.01.2018, 21:55
Всем добрый день. Устройство установлено в авто и функционирует как положено...но есть маааленькие косячки..)
- иногда sim800 либо зависает, либо теряет сеть. Т.е отправленное смс не приводит ни к какому результату в течении длительного времени, и спустя 10-20 минут вдруг просыпается и начинается "action"! К этому времени необходимости запуска уже нет. Происходит лишнее клацанье реле.
Как мне видится решением проблемы может стать reset sim800, при потере сети, только не очень понимаю как это реализовать...
Слать периодически АТ команды - например "AT+CPAS"?
Если кто подскажет как это реализовать в коде - буду признателен)

- И вторая проблемка - отваливается датчик температуры ds18b20. На столе всё работает. В машине, с увеличением длины кабеля работает не стабильно. Кабель использовал "витая пара". Но насколько я понял - это проблема распространённая и методы борьбы у всех разные.. Если есть соображения по этому поводу, с удовольствием "выслушаю".