Не корректно отрабатывает скетч GSM сигнализации.
- Войдите на сайт для отправки комментариев
Уважаемые форумчане прошу вас подсказать где у меня ошибка в скетче. собрал схему (см. рисунок). Состоит из ардуино нано, GSM модуля SIM800L, контроллера заряда ТР4056 для литиевой батареи, 2 светодиода: красный и зеленый и датчика Холла.
Скетч загрузил такой:
#include <SoftwareSerial.h> // Библиотека програмной реализации обмена по UART-протоколу SoftwareSerial SIM800(8, 9); // RX, TX int flag1=0; //Переменная 1 для выполнения программы сработки 1 int flag2=0; //Переменная 2 для выполнения программы взятия и снятия int flag3=0; //Переменная 3 для выполнения программы контроля входящего напряжени int flag4=0; //Переменная 4 для выполнения программы РЕЛЕ int flag5=0; //Переменная 5 для выполнения программы Розетка int flag6=0; //Переменная 1 для выполнения программы сработки 2 String n1 = "+7777777777"; String n2 = "+7777777778"; String sms0 = "Pod Ohranoi"; String sms1 = "Srabotka1"; String sms2 = "220 Volt Off"; String sms3 = "220 Volt On"; String sms4 = "Snyto"; String sms5 = "Relay1 ON"; String sms6 = "Relay1 OFF"; String sms7 = "Relay2 ON"; String sms8 = "Relay2 OFF"; String sms9 = "The system works normally.OK"; String sms10 = "Srabotka2"; String msgphone = ""; uint8_t hours = 0; // Переменная для счёта кол-ва часов String _response = ""; // Переменная для хранения ответа модуля //long lastUpdate = millis(); // Время последнего обновления long updatePeriod = 15000; // Проверять каждые 15 секунд unsigned long lastUpdate = 0; // Переменная для счёта миллисекунд String phones = "+7777777777, +77777777778"; // Белый список телефонов void setup() { pinMode(2, INPUT); // геркон или объемник 1 pinMode(3, INPUT); // геркон или объемник 2 pinMode(5, INPUT); // +5 вольт с делителя напряжения питания (следит за питанием 220 вольт) pinMode(6, OUTPUT); // Сюда подключаем зеленый Диод черз резистор минус к выходу 6 через резистор 560 Ом pinMode(7, OUTPUT); // Сюда подключаем красный Диод черз резистор минус к выходу 7 через резистор 560 Ом pinMode(10, OUTPUT); // Сюда подключаем выход на реле 1 управления сигнализацией pinMode(11, OUTPUT); // Сюда подключаем выход на реле 2 digitalWrite(10, HIGH); // Выключаем реле 1 - посылаем высокий сигнал digitalWrite(11, HIGH); // Выключаем реле 2 - посылаем высокий сигнал lastUpdate = millis(); // Запоминаем текущее время 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(millis() - lastUpdate >= 3600000) { lastUpdate = millis(); hours++; } if(hours >= 1) // Меняем время контроля системы на свое,144 часа.кол-во часов . { SIM800.println("AT+CMGS=\"" + n1 + "\""); // ...и отправляем полученную команду модему delay(500); // Ждем 0,5 секунд SIM800.println(sms9+ "\r\n" + ((char)26)); // текст смс и После текста отправляем перенос строки и Ctrl+Z delay(5000); // Ждем 5 секунд hours = 0; lastUpdate = millis(); } 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()); // ...и отправляем полученную команду модему }; //Сработка 1 if (digitalRead(2)==HIGH && flag2==1 && flag1==0) { flag1++; digitalWrite(6, LOW); // Выключаем зеленый светодиод digitalWrite(7, HIGH); // Включаем красный светодиод digitalWrite(10, LOW); // Включаем сигнализацию SIM800.println("AT+CMGS=\"" + n1 + "\""); // ...и отправляем полученную команду модему delay(500); // Ждем 0,5 секунд SIM800.println(sms1+ "\r\n" + ((char)26)); // текст смс на номер 1 и После текста отправляем перенос строки и Ctrl+Z delay(5000); // Ждем 5 секунд // SIM800.println("AT+CMGS=\"" + n2 + "\""); // ...и отправляем полученную команду модему // delay(500); // Ждем 0,5 секунд // SIM800.println(sms1+ "\r\n" + ((char)26)); // текст смс на номер 2 и После текста отправляем перенос строки и Ctrl+Z // delay(5000); // Ждем 5 секунд } //Сработка 2 if (digitalRead(3)==HIGH && flag2==1 && flag6==0) { flag6++; digitalWrite(6, LOW); // Выключаем зеленый светодиод digitalWrite(7, HIGH); // Включаем красный светодиод digitalWrite(10, LOW); // Включаем сигнализацию SIM800.println("AT+CMGS=\"" + n1 + "\""); // ...и отправляем полученную команду модему delay(500); // Ждем 0,5 секунд SIM800.println(sms1+ "\r\n" + ((char)26)); // текст смс на номер 1 и После текста отправляем перенос строки и Ctrl+Z delay(5000); // Ждем 5 секунд // SIM800.println("AT+CMGS=\"" + n2 + "\""); // ...и отправляем полученную команду модему // delay(500); // Ждем 0,5 секунд // SIM800.println(sms1+ "\r\n" + ((char)26)); // текст смс на номер 2 и После текста отправляем перенос строки и Ctrl+Z // delay(5000); // Ждем 5 секунд } //Контроль питания отсутствие if (digitalRead(5)==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(5)==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_Relay1 = ""; // Переменная для хранения ответа Реле String my_Relay2 = ""; // Переменная для хранения ответа Розетки String my_status = ""; // Переменная для хранения ответа статуса //Постановка на охрану if (result == "On" && digitalRead(6)==LOW && flag1==0 && flag2==0) { digitalWrite(6, HIGH); // Включаем зеленый светодиод digitalWrite(7, LOW); // выключаем красный светодиод flag2++; delay(2000); // Ждем 2 секундs msgToSend = sms0; // Статус исполнения correct = true; // Флаг корректности команды } //Снятие с охраны if (result == "Off" && flag2==1) { flag1=0; flag2=0; digitalWrite(6, LOW); // выключаем зеленый светодиод digitalWrite(7, LOW); // выключаем красный светодиод delay(1000); // Ждем 1 секунд msgToSend = sms4; // Статус исполнения correct = true; // Флаг корректности команды } //Включение РЕЛЕ 1 if (result == "Relay1 ON" && flag4==0) { flag4=1; digitalWrite(11, LOW); // включаем РЕЛЕ delay(1000); // Ждем 1 секунд msgToSend = sms5; // Статус исполнения correct = true; // Флаг корректности команды } //Выключение РЕЛЕ 1 if (result == "Relay1 OFF" && flag4==1) { flag4=0; digitalWrite(11, HIGH); // выключаем РЕЛЕ delay(1000); // Ждем 1 секунд msgToSend = sms6; // Статус исполнения correct = true; // Флаг корректности команды } //Включение Розетки if (result == "Relay2 ON" && flag5==0) { flag5=1; digitalWrite(10, LOW); // включаем РЕЛЕ delay(1000); // Ждем 1 секунд msgToSend = sms7; // Статус исполнения correct = true; // Флаг корректности команды } //Выключение Розетки if (result == "Relay2 OFF" && flag5==1) { flag5=0; digitalWrite(10, HIGH); // выключаем РЕЛЕ delay(1000); // Ждем 1 секунд msgToSend = sms8; // Статус исполнения correct = true; // Флаг корректности команды } //Статус if (result == "Status") { if (flag2==1 && digitalRead(6)==HIGH){ my_ohr = "Pod Ohranoi"; //Статус на охране } if (flag2==0 && flag1==0 && digitalRead(6)==LOW && digitalRead(7)==LOW) { my_ohr = "Snyto"; //Статус снят с охраны } if (flag2==1 && flag1==1 && digitalRead(6)==LOW && digitalRead(7)==HIGH) { my_ohr = "Srabotka"; // Статус сработки } if (flag3==0) { my_power = "+12Volt Ready"; // Статус наличия питания 12 вольт } if (flag3==1) { my_power = "+12Volt Warning"; // Статус отсутствия питания 12 вольт } if (flag4==1 && digitalRead(10)==HIGH) { my_Relay1 = "Relay1 ON"; // Статус включеного РЕЛЕ } if (flag4==0 && digitalRead(10)==LOW) { my_Relay1 = "Relay1 OFF"; // Статус отключеного РЕЛЕ } if (flag5==1 && digitalRead(11)==HIGH) { my_Relay2 = "Relay2 ON"; // Статус включеного РЕЛЕ } if (flag5==0 && digitalRead(11)==LOW) { my_Relay2 = "Relay2 OFF"; // Статус отключеного РЕЛЕ } msgToSend = (my_ohr + "\r\n" + my_power + "\r\n" + my_Relay1 + "\r\n" + my_Relay2); // Статус исполнения correct = true; // Флаг корректности команды } if (!correct) { msgToSend = "Incorrect command: " + result; // Статус исполнения } //Тут идет проверка номера, если команды отправляет 1 номер, то все в норме, если 2 или 3 и так далее из белого списка, //то ответ дублируется 1 номеру + номер того, кто производит запросы if (msgphone == "+7777777777"){ 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)); } }
Сразу скажу скетч не я сам писал. Нашел здесь на форуме, но он подошел под мои задачи. Я его малость переделал под свои нужды. И все бы было хорошо, если бы не 2 странных глюка:
1. Не приходит контрольная СМС о статусе системы. Это строки 93-105. Я уже пробовал и час ставить, вообще никак не отрабатывается этот кусок.
2. При постановке на охрану сначала зажигается зеленый светодиод, как и должно быть. Но буквально через пару секунд зеленый светодиод гаснет и загорается красный, хотя система все ещё находится под охраной. А по логике красный светодиод должен загораться в случае сработки сигнализации.
Уважаемые знатоки подскажите что у меня не правильно сделано и как это можно исправить пожалуйста.
Не знаю как отредактировать свой пост, но хочу сразу предупредить, чтобы не обращали внимание на пин RST на GSM модуле, на самом деле он не задействован в схеме и не соединен с землей.
А к СОЗДАТЕЛЮ программы не обращались?
Никто, кроме него не знает всех нюансов ЕГО творения.
Я не знаю автора. Когда я нашёл данный скетч здесь на форуме, автор того поста также писал, что он нашёл его на просторах инета.
Доработал схему. Установил мосфет P75N02LDG. Привязал его в свободному пину ардуины и раз в сутки перегружаю модуль. Разобрался с глюками в скетче. Может кому пригодится:
1. Не приходит контрольная СМС о статусе системы. Это строки 93-105. Я уже пробовал и час ставить, вообще никак не отрабатывается этот кусок.
Я добавил отдельный таймер для отсчета времени для перезагрузки модуля. И теперь и модуль перезагружается и смс о статусе приходит.
2. При постановке на охрану сначала зажигается зеленый светодиод, как и должно быть. Но буквально через пару секунд зеленый светодиод гаснет и загорается красный, хотя система все ещё находится под охраной. А по логике красный светодиод должен загораться в случае сработки сигнализации.
Я забыл про второй выход для датчика Холла. Хоть к нему ничего и не подключено, но из-за него и происходит сработка второго датчика и происходит переключение светодиода с зеленого на красный.
Тестирую дальше.