GSM сигнализация не работает без ПК
- Войдите на сайт для отправки комментариев
Вс, 27/01/2019 - 10:00
Доброго времени суток уважаемые форумчане!
На просторах интернета нашел простенькую GSM сигнализацию на основе модуля SIM800l и управлением с помощью СМС. Заказал, собрал, запустил. Все работало отлично, но стоило мне отключить сигналку от ПК, как она перестала работать. Стоит мне снова подключить сигналку к ПК, так она снова начинает работать как часы. Реагирует на СМС команды, высылает ответы на команды, срабатывает на открытие двери (датчик Холла стоит), световая индикация срабатывает. Но при отключении от ПК, снова превращается в "кирпич". Подскажите в чем проблема? Скетч прилагаю.
#include <SoftwareSerial.h> // Библиотека програмной реализации обмена по UART-протоколу SoftwareSerial SIM800(8, 9); // RX, TX int flag1=0; //Переменная 1 для выполнения программы сработки int flag2=0; //Переменная 2 для выполнения программы взятия и снятия int flag3=0; //Переменная 3 для выполнения программы контроля входящего напряжени int flag4=0; //Переменная 4 для выполнения программы РЕЛЕ int flag5=0; //Переменная 5 для выполнения программы Розетка String n1 = "+71111111111"; String n2 = "+71111111112"; String sms0 = "Pod Ohranoi"; String sms1 = "Srabotka"; //String sms2 = "+12Volt Warning"; //String sms3 = "+12Volt Ready"; String sms4 = "Snyto"; String sms5 = "Realy ON"; String sms6 = "Realy OFF"; String sms7 = "Realy2 ON"; String sms8 = "Realy2 OFF"; String sms9 = "The system works normally.OK"; String msgphone = ""; uint8_t hours = 0; String _response = ""; // Переменная для хранения ответа модуля long lastUpdate = millis(); // Время последнего обновления long updatePeriod = 15000; // Проверять каждые 15 секунд String phones = "+71111111111, +71111111112, +71111113"; // Белый список телефонов void setup() { pinMode(5, OUTPUT); // Сюда подключаем выход на реле управления розеткой pinMode(6, OUTPUT); // Сюда подключаем выход на реле управления обогрева АВТО pinMode(2, OUTPUT); // Сюда подключаем красный Диод черз резистор минус к выходу 4 через резистор 560 Ом pinMode(3, OUTPUT); // Сюда подключаем зеленый Диод черз резистор минус к выходу 5 через резистор 560 Ом pinMode(4, INPUT); // геркон или объемник pinMode(7, INPUT); // +5 вольт с делителя напряжения питания (следит за питанием 12 вольт БП) Serial.begin(9600); // Скорость обмена данными с компьютером (это для отладки) SIM800.begin(9600); // Скорость обмена данными с модемом Serial.println("Start!"); sendATCommand("AT", true); // Отправили AT для настройки скорости обмена данными delay(5000); // Ждем 5 секунд sendATCommand("AT+CMGDA=\"DEL ALL\"", true); // Удаляем все SMS, чтобы не забивать память // Команды настройки модема при каждом запуске _response = sendATCommand("AT+CLIP=1", true); // Включаем АОН _response = sendATCommand("AT+DDET=1", true); // Включаем DTMF _response = sendATCommand("AT+CMGF=1;&W", true); // Включаем текстовый режима SMS (Text mode) и сразу сохраняем значение (AT&W)! lastUpdate = millis(); // Обнуляем таймер } String sendATCommand(String cmd, bool waiting) { String _resp = ""; // Переменная для хранения результата Serial.println(cmd); // Дублируем команду в монитор порта SIM800.println(cmd); // Отправляем команду модулю if (waiting) { // Если необходимо дождаться ответа... _resp = waitResponse(); // ... ждем, когда будет передан ответ // Если Echo Mode выключен (ATE0), то эти 3 строки можно закомментировать if (_resp.startsWith(cmd)) { // Убираем из ответа дублирующуюся команду _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2); } Serial.println(_resp); // Дублируем ответ в монитор порта (для отладки) } return _resp; // Возвращаем результат. Пусто, если проблема } String waitResponse() { // Функция ожидания ответа и возврата полученного результата String _resp = ""; // Переменная для хранения результата long _timeout = millis() + 10000; // Переменная для отслеживания таймаута (10 секунд) while (!SIM800.available() && millis() < _timeout) {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то... if (SIM800.available()) { // Если есть, что считывать... _resp = SIM800.readString(); // ... считываем и запоминаем } else { // Если пришел таймаут, то... Serial.println("Timeout..."); // ... оповещаем об этом и... } return _resp; // ... возвращаем результат. Пусто, если проблема } bool hasmsg = false; // Флаг наличия сообщений к удалению void loop() { if (lastUpdate + updatePeriod < millis() ) { // Пора проверить наличие новых сообщений do { _response = sendATCommand("AT+CMGL=\"REC UNREAD\",1", true);// Отправляем запрос чтения непрочитанных сообщений if (_response.indexOf("+CMGL: ") > -1) { // Если есть хоть одно, получаем его индекс int msgIndex = _response.substring(_response.indexOf("+CMGL: ") + 7, _response.indexOf("\"REC UNREAD\"", _response.indexOf("+CMGL: ")) - 1).toInt(); char i = 0; // Объявляем счетчик попыток do { i++; // Увеличиваем счетчик _response = sendATCommand("AT+CMGR=" + (String)msgIndex + ",1", true); // Пробуем получить текст SMS по индексу _response.trim(); // Убираем пробелы в начале/конце if (_response.endsWith("OK")) { // Если ответ заканчивается на "ОК" if (!hasmsg) hasmsg = true; // Ставим флаг наличия сообщений для удаления sendATCommand("AT+CMGR=" + (String)msgIndex, true); // Делаем сообщение прочитанным sendATCommand("\n", true); // Перестраховка - вывод новой строки parseSMS(_response); // Отправляем текст сообщения на обработку break; // Выход из do{} } else { // Если сообщение не заканчивается на OK Serial.println ("Error answer"); // Какая-то ошибка sendATCommand("\n", true); // Отправляем новую строку и повторяем попытку } } while (i < 10); break; } else { lastUpdate = millis(); // Обнуляем таймер if (hasmsg) { delay(4000); // Ждем 4 секунд sendATCommand("AT+CMGDA=\"DEL ALL\"", true); // Удаляем все сообщения hasmsg = false; } break; } } while (1); } if (SIM800.available()) { // Если модем, что-то отправил... _response = waitResponse(); // Получаем ответ от модема для анализа _response.trim(); // Убираем лишние пробелы в начале и конце Serial.println(_response); // Если нужно выводим в монитор порта if (_response.indexOf("+CMTI:")>-1) { // Пришло сообщение об отправке SMS lastUpdate = millis() - updatePeriod; // Теперь нет необходимости обрабатываеть SMS здесь, достаточно просто // сбросить счетчик автопроверки и в следующем цикле все будет обработано } } if (Serial.available()) { // Ожидаем команды по Serial... (возможность через серийный порт общаться с модемом для отладки) SIM800.write(Serial.read()); // ...и отправляем полученную команду модему }; //Сработка if (digitalRead(4)==HIGH && flag2==1 && flag1==0) { flag1++; digitalWrite(2, HIGH); // Выключаем зеленый светодиод digitalWrite(3, LOW); // Включаем красный светодиод SIM800.println("AT+CMGS=\"" + n1 + "\""); // ...и отправляем полученную команду модему delay(500); // Ждем 0,5 секунд SIM800.println(sms1+ "\r\n" + ((char)26)); // текст смс и После текста отправляем перенос строки и Ctrl+Z delay(5000); // Ждем 5 секунд } /*Контроль питания отсутствие if (digitalRead(7)==LOW && flag3==0) { flag3++; SIM800.println("AT+CMGS=\"" + n1 + "\""); // ...и отправляем полученную команду модему delay(500); // Ждем 0,5 секунд SIM800.println(sms2+ "\r\n" + ((char)26)); // текст смс и После текста отправляем перенос строки и Ctrl+Z delay(5000); // Ждем 5 секунд } //Контроль питания востановлено if (digitalRead(7)==HIGH && flag3==1) { flag3=0; SIM800.println("AT+CMGS=\"" + n1 + "\""); // ...и отправляем полученную команду модему delay(500); // Ждем 0,5 секунд SIM800.println(sms3+ "\r\n" + ((char)26)); // текст смс и После текста отправляем перенос строки и Ctrl+Z delay(5000); // Ждем 5 секунд } */ } void parseSMS(String msg) { // Парсим SMS String msgheader = ""; String msgbody = ""; msg = msg.substring(msg.indexOf("+CMGR: ")); msgheader = msg.substring(0, msg.indexOf("\r")); // Выдергиваем телефон msgbody = msg.substring(msgheader.length() + 2); msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK")); // Выдергиваем текст SMS msgbody.trim(); int firstIndex = msgheader.indexOf("\",\"") + 3; int secondIndex = msgheader.indexOf("\",\"", firstIndex); msgphone = msgheader.substring(firstIndex, secondIndex); Serial.println("Phone: " + msgphone); // Выводим номер телефона на компьютер в монитор порта Serial.println("Message: " + msgbody); // Выводим текст SMS на компьютер в монитор порта if (msgphone.length() > 6 && phones.indexOf(msgphone) > -1) { // Если телефон в белом списке, то... setLedState(msgbody, msgphone); // ...выполняем команду } else { Serial.println("Unknown phonenumber"); SIM800.println("AT+CMGS=\"" + n1 + "\""); // ...и отправляем полученную команду модему, отправляет 1 номеру Unknown phonenumber, можно добавить, чтоб номер еще отправлял левый delay(1000); // Ждем 1 секунд SIM800.println(msgphone + " Unknown phonenumber" + "\r\n" + ((char)26)); // текст смс и После текста отправляем перенос строки и Ctrl+Z } } void setLedState (String result, String phone) { bool correct = false; // Для оптимизации кода, переменная корректности команды String msgToSend = ""; String my_ohr = ""; // Переменная для хранения ответа охраны String my_power = ""; // Переменная для хранения ответа питания String my_realy = ""; // Переменная для хранения ответа Реле String my_realy2 = ""; // Переменная для хранения ответа Розетки String my_status = ""; // Переменная для хранения ответа статуса //Постановка на охрану if (result == "On" && digitalRead(10)==LOW && flag1==0 && flag2==0) { digitalWrite(3, HIGH); // Исполняем команду flag2++; delay(2000); // Ждем 1 секунд msgToSend = sms0; // Статус исполнения correct = true; // Флаг корректности команды } //Снятие с охраны if (result == "Off" && flag2==1) { flag1=0; flag2=0; digitalWrite(2, LOW); // выключаем светодиод digitalWrite(3, LOW); // выключаем светодиод delay(1000); // Ждем 1 секунд msgToSend = sms4; // Статус исполнения correct = true; // Флаг корректности команды } //Включение РЕЛЕ if (result == "Realy ON" && flag4==0) { flag4=1; digitalWrite(3, HIGH); // включаем РЕЛЕ delay(1000); // Ждем 1 секунд msgToSend = sms5; // Статус исполнения correct = true; // Флаг корректности команды } //Выключение РЕЛЕ if (result == "Realy OFF" && flag4==1) { flag4=0; digitalWrite(3, LOW); // вsключаем РЕЛЕ delay(1000); // Ждем 1 секунд msgToSend = sms6; // Статус исполнения correct = true; // Флаг корректности команды } //Включение Розетки if (result == "Realy2 ON" && flag5==0) { flag5=1; digitalWrite(6, HIGH); // включаем РЕЛЕ delay(1000); // Ждем 1 секунд msgToSend = sms7; // Статус исполнения correct = true; // Флаг корректности команды } //Выключение Розетки if (result == "Realy2 OFF" && flag5==1) { flag5=0; digitalWrite(6, LOW); // вsключаем РЕЛЕ delay(1000); // Ждем 1 секунд msgToSend = sms8; // Статус исполнения correct = true; // Флаг корректности команды } if(millis() - lastUpdate >= 3600000) {lastUpdate = millis(); hours++;} if(hours >= 1) {// Меняем время контроля системы на свое, 1 часа.кол-во часов . msgToSend = sms9; delay(10000); hours = 0; lastUpdate = millis(); } //Статус if (result == "Status") { if (flag2==1 && digitalRead(2)==HIGH){ my_ohr = "Pod Ohranoi"; //Статус на охране } if (flag2==0 && flag1==0 && digitalRead(2)==LOW && digitalRead(3)==LOW) { my_ohr = "Snyto"; //Статус снят с охраны } if (flag2==1 && flag1==1 && digitalRead(2)==LOW && digitalRead(3)==HIGH) { my_ohr = "Srabotka"; // Статус сработки } if (flag3==0) { my_power = "+12Volt Ready"; // Статус наличия питания 12 вольт } if (flag3==1) { my_power = "+12Volt Warning"; // Статус отсутствия питания 12 вольт } if (flag4==1 && digitalRead(6)==HIGH) { my_realy = "Realy ON"; // Статус включеного РЕЛЕ } if (flag4==0 && digitalRead(6)==LOW) { my_realy = "Realy OFF"; // Статус отключеного РЕЛЕ } if (flag5==1 && digitalRead(7)==HIGH) { my_realy2 = "Realy2 ON"; // Статус включеного РЕЛЕ } if (flag5==0 && digitalRead(7)==LOW) { my_realy2 = "Realy2 OFF"; // Статус отключеного РЕЛЕ } msgToSend = (my_ohr + "\r\n" + my_power + "\r\n" + my_realy + "\r\n" + my_realy2); // Статус исполнения correct = true; // Флаг корректности команды } if (!correct) { msgToSend = "Incorrect command: " + result; // Статус исполнения } //Тут идет проверка номера, если команды отправляет 1 номер, то все в норме, если 2 или 3 и так далее из белого списка, то ответ дублируется 1 номеру + номер того, кто производит запросы if (msgphone == "+77051314021"){ SIM800.println("AT+CMGS=\"" + msgphone + "\""); // ...и отправляем полученную команду модему delay(500); // Ждем 0,5 секунд SIM800.println(msgToSend + "\r\n" + ((char)26)); // текст смс и После текста отправляем перенос строки и Ctrl+Z Serial.println("1 uslovie" + msgphone + msgToSend + "\r\n" + ((char)26)); } else { SIM800.println("AT+CMGS=\"" + msgphone + "\""); // ...и отправляем полученную команду модему delay(500); // Ждем 0,5 секунд SIM800.println(msgToSend+ "\r\n" + ((char)26)); // текст смс и После текста отправляем перенос строки и Ctrl+Z delay(5000); // Ждем 5 секунд SIM800.println("AT+CMGS=\"" + n1 + "\""); // ...и отправляем полученную команду модему delay(500); // Ждем 0,5 секунд SIM800.println(msgphone + " " + msgToSend + "\r\n" + ((char)26)); // текст смс и После текста отправляем перенос строки и Ctrl+Z delay(1000); // Ждем 1 секунд Serial.println("2 uslovie" + msgphone + msgToSend + "\r\n" + ((char)26)); } }
Схема подключения?
Все работало отлично, но стоило мне отключить сигналку от ПК, как она перестала работать.
Извините, набросал как смог.
Все работало отлично, но стоило мне отключить сигналку от ПК, как она перестала работать.
Так с питанием как раз все в порядке. Схема питается от контроллера заряда TP4056 и плюс там еще предусмотрено резервное питание от 18650.
На приведенной схеме ардуина не запитана от контроллера заряда и при отключениии от ПК работать не сможет.
На приведенной схеме ардуина не запитана от контроллера заряда и при отключениии от ПК работать не сможет.
Я прошу прощение, я просто забыл прорисовать. Уже исправил. На самом деле и ардуино и модуль запитаны от контроллера заряда. Ардуино запитана через пин VIN.
Я может не совсем правильно выразился. Дело в том, что когда я отключаю ардуинку от ПК, то и модуль SIM800l , и ардуинка продолжают работать, и моргать светодиодами. Если позвонить на модуль, то звонок проходит. Но модуль не реагирует на смс команды. т.е. смс доходят до модуля, но модуль их игнорирует. А стоит только подключить ардуинку к ПК, так она тут же начинает отвечать на смс команды.
Я даже пробовал запитывать ардуинку от power bank через юсб шнур, думал, может где то питания не хватает ардуинке. Но все равно это никак не помогает.
На самом деле и ардуино и модуль запитаны от контроллера заряда. Ардуино запитана через пин VIN.
Это неправильно. Пин VIN подключён к линейному регулятору напряжения на плате ардуино и предназначен для подачи нестабилизированного питания с напряжением от 6В до 12В. А контроллер зарада выдает около 4.2В, а аккумулятор и того меньше.
Если напряжение питания 5В и меньше, то подавать его нужно на пин +5V, который подключен напрямую к ножке VCC микроконтроллера.
Уважаемый ТС, слона надо есть по частям. Сначала вместо аккумуляторов и всей остальной обвязки по питанию подключите блок питания ампера в 2, чтобы наверняка. Если все заработает, то проблема в Вашем питании. Туда и надо будет копать.
Это неправильно. Пин VIN подключён к линейному регулятору напряжения на плате ардуино и предназначен для подачи нестабилизированного питания с напряжением от 6В до 12В. А контроллер зарада выдает около 4.2В, а аккумулятор и того меньше.
Если напряжение питания 5В и меньше, то подавать его нужно на пин +5V, который подключен напрямую к ножке VCC микроконтроллера.
Спасибо. Перепаял и все заработало. Еще раз спасибо. Но вот в процессе эксплуатации обнаружился глюк. После срабатывания сигналки нужно ее снять с охраны и потом снова поставить, чтобы она вновь была активированна. А как можно это исправить? Чтобы не приходилось снимать, а чтобы можно было просто повторно перепоставить командой "On"?
а чтобы можно было просто повторно перепоставить командой "On"?
Можно, для этого flag1 надо сделать нулем.
Добрый день форумчане!
Прошу еще вашего совета. В исходном скетче не отрабатывает функция отвечающая за отправку еженедельных сообщений, о состоянии системы строки 85-94. Подскажите в чем я накосячил?
кстати, для нормальной работы на SIM8OOL нужно подать 4 вольта 1 ампер.
ваша схема по питаню в корне не правильная.
кстати, для нормальной работы на SIM8OOL нужно подать 4 вольта 1 ампер.
ваша схема по питаню в корне не правильная.
Согласно даташиту на SIM800l он питается от 3,4-4,4 В. По моей схеме питание подается около 4,2 В. Все в допустимых рамках. Что касается силы тока, то контроллер заряда TP 4056 как раз расчитан на 1А. Так что не понимаю, в чем конкретно она в корне не правильная??? Поясните пожалуйста!
Нормальный 18650 отдаёт до 30А и больше без проблем, так что не парься. Даже самый дешманский для фонариков ампер 5 отдаст точно. Только нужно ещё поставить step-down 5-вольтовый чтоб заряжать аккум через клемы +/- со стороны micro-usb, вот такой пойдёт https://ru.aliexpress.com/item/Mini360-HM-DC-DC-23/32921703886.html?Единственное что, если в ардуинке стоит кварц на 16МГц, при низком заряде её может проглючить. На таких частотах атмеге надо 5В. Короче надо кварц на 8Мгц при таком варианте питания.
Добрый день форумчане!
Прошу еще вашего совета. В исходном скетче не отрабатывает функция отвечающая за отправку еженедельных сообщений, о состоянии системы строки 85-94. Подскажите в чем я накосячил?
restiv, а нафига вы всю программу забили делеями, как то не совсем кошерно....
Уважаемый, я не увидел никаких проблем в указанном Вами диапазоне, да и в других тоже. Порадовал Ваш пессимизм в 88 строке, что контроллер ни разу за 2 часа не увидит эту строку :)
Оставьте на ночь вывод на порт - херня какая-то.
restiv, а нафига вы всю программу забили делеями, как то не совсем кошерно....
Vvadim к сожалению в написании скетчей я еще очень далек от совершентсва, поэтому пока беру чужие скетчи и переделываю под себя. Так что по делеям - это не я забил.(((
Уважаемый, я не увидел никаких проблем в указанном Вами диапазоне, да и в других тоже. Порадовал Ваш пессимизм в 88 строке, что контроллер ни разу за 2 часа не увидит эту строку :)
Оставьте на ночь вывод на порт - херня какая-то.
Не совсем понял ваши слова насчет 88 строки. Поставлю на день вывод на порт. Понаблюдаю.
Сократил временной интервал до 1 минуты. И наблюдал в монитр порте. Никаких намеков на отработку данного кусочка программы не было.