GSM сигнализация M590+Arduino

kvolk
Offline
Зарегистрирован: 12.06.2017

smesharik пишет:

kvolk пишет:

при такой загруженности памяти, у вас адекватно работает?!

у меня когда SRAM к 70% подходил, перестовал модем присылать сообщения, то пустое, по пару слов

Как видите, за последний месяц жалоб на нестабильную работу двух последних версий прошивок, они отличаются по функционалу, не поступало. У меня "боевая" сигналка в течение последнего месяца не накосячила ни разу.

b707
Offline
Зарегистрирован: 26.05.2017

kvolk пишет:

b707 пишет:

Kvolk, а нафига? все и так работает.

Работает потому что от модема ещё не "прилетело" данных больше чем сам буфер, как только это произойдёт вы без труда сможете понять для чего увеличивается этот буфер. На 590 модеме "мусора" от модема прилетет меньше чем на SIM800L или A6_Mini, поэтому вам буфера хватает.

Пример тут: https://mysku.ru/blog/ebay/43282.html#comment2174532

пример ровно ничего не доказывает, там нет никакий данных, были ли проблемы от маленького буфера и исправились ли они после его увеличения.

У меня модем А6 отлично работает с буфером 64 байта. СМС длиной более 100 байт принимаются легко. Я просто сохраняю СМС на SIM, а читаю тогда, когда контроллер не занят. И ничего не теряется и не переполняется.

 

kvolk пишет:

b707 пишет:

Этим вы просто выкидываете 128 байт оперативки, а ее и так немного.

Вы ошибаетесь.

И в чем же я ошибаюсь? Увеличение буфера на 128 байт не уменьшает оперативку?

Кстати, а что вы свои исходники не показываете? Боитесь, что за кривой код ссаными тряпками закидают? Интересно, как вы читаете СМС, что у вас буфер переполняется...

kvolk
Offline
Зарегистрирован: 12.06.2017

b707 пишет:

пример ровно ничего не доказывает...

Доказывает, проблема решилась после увеличнения буфера, но вы это не хотите видеть.

b707 пишет:

У меня модем А6 отлично работает с буфером 64 байта. СМС длиной более 100 байт принимаются легко.

А у меня 590, сим800 и а6_мини и все они поддерживаются в одной прошивке. Сим800 в отличие от других модемов по умолчанию сильно спамит в порт. В моей реализации для отладки используется "тестовый режим" при включении которого в консоль валится вся инфа от модема.

b707 пишет:

Я просто сохраняю СМС на SIM, а читаю тогда, когда контроллер не занят. И ничего не теряется и не переполняется.

Да делайте как хотите, это ваше право :) Причём тут смс?

b707 пишет:

И в чем же я ошибаюсь?...

В этом:

b707 пишет:

Этим вы просто выкидываете 128 байт оперативки.

Не просто и не выкидываю.

b707 пишет:

Кстати, а что вы свои исходники не показываете? Боитесь, что за кривой код ссаными тряпками закидают? 

Для того чтобы сырой код во время разработки, отладки, допила не растаскивали на куски и не лепили из него подобных "франкенштейнов". В конце концов не хочу, нет желания. Что касается кривого кода и ссаных тряпок - кода вы не видели, значит и утверждать о том, что он кривой не можете.  А вот к тому коду из 206 поста, которым вы тут дружно пользуетесь, который я видел - ссаных тряпок могу подкинуть, поверьте, вам хватит :)

b707 пишет:

Интересно, как вы читаете СМС, что у вас буфер переполняется...

Кто вам вобще сказал что дело в чтении СМС? Дальше носа своего не видите? :)

b707
Offline
Зарегистрирован: 26.05.2017

kvolk, много слов и ничего по делу. Грозите раскритиковать код из поста 206 - да ради бога. с удовольствием послушаю. Люблю учиться. Тем более что свой код вы не показывайте - так хотя бы по замечаниям о чужом коде можно будет оценить ваш уровень...

 

smesharik
Offline
Зарегистрирован: 31.01.2016

может кто то подсказать?!

как мне при приеме переменной, разбить ее на несколько переменных

допустим отправляем смс с кодом: 123456

присвоить A1 = 12, A2=34, A3=56

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А в каком виде Вы её получаете? Какого она типа?

b707
Offline
Зарегистрирован: 26.05.2017

smesharik пишет:

может кто то подсказать?!

как мне при приеме переменной, разбить ее на несколько переменных

допустим отправляем смс с кодом: 123456

присвоить A1 = 12, A2=34, A3=56

А нафига три значения подряд в строчку лепить? Вы же через неделю забудете, какой парметр где, тем более что, подозреваю, оператор "help" у вас в программе не предусмотрен :)

Общепринято посылать переменные, например, в виде пар "параметр=значение", разделяя из запятыми : "A1=12,A2=34,A3=56". Такой формат легко запомнить, и он гибче - порядок и число переменных можно менять.

kvolk
Offline
Зарегистрирован: 12.06.2017

smesharik пишет:

может кто то подсказать?!

как мне при приеме переменной, разбить ее на несколько переменных

допустим отправляем смс с кодом: 123456

присвоить A1 = 12, A2=34, A3=56

Если А1-А3 положительное число не превышающее 255, то как-то так:

  String data = "123456";

  int8_t a1;
  int8_t a2;
  int8_t a3;

void setup() {
  a1 = data.substring(0, 2).toInt();
  //Serial.print("a1 = ");
  //Serial.println(a1);
  a2 = data.substring(2, 4).toInt();
  //Serial.print("a2 = ");
  //Serial.println(a2);
  a3 = data.substring(4, 6).toInt();
  //Serial.print("a3 = ");
  //Serial.println(a3);

}

void loop() {

}

 

kvolk
Offline
Зарегистрирован: 12.06.2017

b707 пишет:

...можно будет оценить ваш уровень...

Я на экзамене или просто обязан вам что-либо доказазывать? :)

pasha413
Offline
Зарегистрирован: 27.11.2016

kvolk, доказывать ничего уже и не надо! вы показали себя самым умным, что у вас супер код, который работает без глюков, а показать нечего.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

kvolk пишет:

Возможно выложу, но не скоро :(

А чё так? Копираст?

kvolk
Offline
Зарегистрирован: 12.06.2017

ЕвгенийП пишет:

А чё так? Копираст?

Да, копипастят налево и направо. Это же очевидно :) Посмотрите первый пост этого топика :)

smesharik
Offline
Зарегистрирован: 31.01.2016

kvolk пишет:

Если А1-А3 положительное число не превышающее 255, то как-то так:

большое вам человеческое спасибо

 

b707 пишет:

А нафига три значения подряд в строчку лепить? Вы же через неделю забудете, какой парметр где, тем более что, подозреваю, оператор "help" у вас в программе не предусмотрен :)

для корректирование времени через смс запрос 073030 т.е. 07:30:30

pasha413
Offline
Зарегистрирован: 27.11.2016

kvolk пишет:

ЕвгенийП пишет:

А чё так? Копираст?

Да, копипастят налево и направо. Это же очевидно :) Посмотрите первый пост этого топика :)


Вот оно что...банальная жадность! Ещё раз: Ардуина - свободная платформа.
Не надо, не выкладывайте свой код. Кто не хочет делать своими руками, пусть просто заливают код и пользуются незная как это устроено.

b707
Offline
Зарегистрирован: 26.05.2017

kvolk пишет:

Если А1-А3 положительное число не превышающее 255, то как-то так:

Почему именно 255? А если автор В ДВУЗНАЧНОМ ЧИСЛЕ хочет передать 512 - уже не сработает? :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

pasha413 пишет:
Ещё раз: Ардуина - свободная платформа.

Лицензия LGPL не требует открывать свой код, разработанный для Ардуино, и позволяет создавать коммерческий продукт.

Русский язык тоже свободная платформа и говорить на нём можно бесплатно. Но, те, кто, например, написали на нём роман или песню, иногда хотят, чтобы их произведение приносило им доход.

Я это не к тому, что я разделяю позицию копирастов, нет, у меня к этому сложное отношение, но я понимаю эту позицию и признаю за людьми право так считать, и так себя вести.

kvolk
Offline
Зарегистрирован: 12.06.2017

 

pasha413 пишет:

Ещё раз: Ардуина - свободная платформа.

Вы действительно считаете что если ардуина свободная платформа, то все программы для этой платформы обязаны предоставляться в виде исходных текстов? :)

kvolk
Offline
Зарегистрирован: 12.06.2017

b707 пишет:

Почему именно 255? 

Потому что int8_t.

b707 пишет:

А если автор В ДВУЗНАЧНОМ ЧИСЛЕ хочет передать 512 - уже не сработает? :)

Это как?

В моём понимании двузначное число состоит из двух цифр, минимальное значение которого равно 10 максимальное 99. Во втором классе меня учили так. 512 - трёхзначное число. 

Я чего-то не знаю?

b707
Offline
Зарегистрирован: 26.05.2017

kvolk пишет:

b707 пишет:

А если автор В ДВУЗНАЧНОМ ЧИСЛЕ хочет передать 512 - уже не сработает? :)

 

Это как?

Это я у вас хотел спросить - как это. Это же вы написали. что двузначное десятичное число не должно превышать 255 :)

kvolk
Offline
Зарегистрирован: 12.06.2017

b707 пишет:

kvolk пишет:

b707 пишет:

А если автор В ДВУЗНАЧНОМ ЧИСЛЕ хочет передать 512 - уже не сработает? :)

 

Это как?

Это я у вас хотел спросить - как это. Это же вы написали. что двузначное десятичное число не должно превышать 255 :)

 

Я написал? Где написано про двузначное число?

kvolk пишет:

Если А1-А3 положительное число не превышающее 255, то как-то так:

 

Ваша цитата :

b707 пишет:

kvolk пишет:

Если А1-А3 положительное число не превышающее 255, то как-то так:

Почему именно 255? А если автор В ДВУЗНАЧНОМ ЧИСЛЕ хочет передать 512 - уже не сработает? :)

Вы наверное прикалываетесь? :) Да вы просто фантазёр :)

b707
Offline
Зарегистрирован: 26.05.2017

Вы не только невнимательный копираст, а еще свои ошибки признавать не любите...

Вот это чей код?

a1 = data.substring(0, 2).toInt();

скольку тут знаков в числе?

kvolk
Offline
Зарегистрирован: 12.06.2017

b707 пишет:

Вы не только невнимательный копираст, а еще свои ошибки признавать не любите...

Вот это чей код?

a1 = data.substring(0, 2).toInt();

скольку тут знаков в числе?

Ну так смысл не в том что там двузначное число, а в том что если изменятся входные данные и вместо двух чисел нужно будет получить число отрицательное или число со значением более 255, то int8_t придётся заменить на что-то более подходящее, иначе этот код работать не будет. Именно из-за int8_t  было акцентировано внимаение на том что число должно быть положительное и не превышающее 255, потому что многие начинающие не знают этих нюансов. А на этой платформе памятью "разбрасываться" нельзя.

b707
Offline
Зарегистрирован: 26.05.2017

kvolk пишет:

Ну так смысл не в том что там двузначное число, а в том что если изменятся входные данные и вместо двух чисел нужно будет получить число отрицательное или число со значением более 255, то int8_t придётся заменить на что-то более подходящее, иначе этот код работать не будет. Именно из-за int8_t  

Вы опять с умным видом пытаетесь поучать других, хотя получается не очень. Я в форме шутки пытался указать вам, что ваш код перестанет работать задолго до числа 255 - именно потому, что вы извлекаете из строки только два знака, а вовсе не из-за выбранного типа int8_t для числовой переменной.

kvolk пишет:

А на этой платформе памятью "разбрасываться" нельзя.

как-нибудь на досуге проверьте, сколько места занимают в памяти ЭТОЙ ПЛАТФОРМЫ типы byte, int8_t и int. Вас ждет удивительное открытие.

b707
Offline
Зарегистрирован: 26.05.2017

b707 пишет:

как-нибудь на досуге проверьте, сколько места занимают в памяти ЭТОЙ ПЛАТФОРМЫ типы byte, int8_t и int. Вас ждет удивительное открытие.

Должен поправится, не вполне прав. на 328й ардуине 8bit data alignment, так что компилятор действительно пытается упаковать два первых типа в 8 бит. Правда это не всегда работает.

kvolk
Offline
Зарегистрирован: 12.06.2017

b707 пишет:

ваш код перестанет работать задолго до числа 255

Код будет работать, так как числа больше 99 там быть не может, минимум 01 - максимум 99. Объясню ещё раз: 255 было упомянуто только из-за ограничения накладываемого на тип данных int8_t.

b707 пишет:

..типы byte, int8_t и int. Вас ждет удивительное открытие.

byte, int8_t - 8 бит. int - 16 бит. Разве не так?

kvolk
Offline
Зарегистрирован: 12.06.2017

smesharik пишет:

для корректирование времени через смс запрос 073030 т.е. 07:30:30

Не пробовали корректировать время при получении  смс сообщения от оператора. В этом сообщении или этом видно когда и в какое время прилетела смс от оператора. Нужно лишь отпарсить и ввести в RTC данные, но ручная корректировка тоже нужна или хотябы корректировка часового пояса.

+CMT: "+7905*******","",«16/12/03,00:09:44+12»

 

b707
Offline
Зарегистрирован: 26.05.2017

kvolk пишет:

Не пробовали корректировать время при получении  смс сообщения от оператора. В этом сообщении или этом видно когда и в какое время прилетела смс от оператора. Нужно лишь отпарсить и ввести в RTC данные,

Это надо ждать прихода "настоящего" СМС. В USSD сообщениях от оператора, например о балансе - нет времени.

мне показалось проще и надежнее делать GPRS запрос типа HEAD - заголовок любой странички с любого www-сайта  - в ответ приходит пара сотен байт, среди которых обязательно есть строка с точным временем и датой.

smesharik
Offline
Зарегистрирован: 31.01.2016

b707 пишет:

kvolk пишет:

Не пробовали корректировать время при получении  смс сообщения от оператора. В этом сообщении или этом видно когда и в какое время прилетела смс от оператора. Нужно лишь отпарсить и ввести в RTC данные,

Это надо ждать прихода "настоящего" СМС. В USSD сообщениях от оператора, например о балансе - нет времени.

мне показалось проще и надежнее делать GPRS запрос типа HEAD - заголовок любой странички с любого www-сайта  - в ответ приходит пара сотен байт, среди которых обязательно есть строка с точным временем и датой.

тогда уже NTP сервер использовать

сделал как kvolk порекомендовал, при любой смс корректируем время от оператора

 if (val.indexOf(F("+cmt")) > -1)     { // при любом обращении к GSM модулю корректирует часы от оператора
        delay(500);
      time.Hours = val.substring(34, 36).toInt();
      time.minutes = val.substring(37, 39).toInt();
      time.settime(-1, time.minutes, time.Hours, -1, -1, -1, -1);
     }

 

Gienekb
Offline
Зарегистрирован: 29.08.2017

kvolk - Я прочитал ваш блог. Уважение. Хорошая и интересная сигнализация. Вы контролируете внешнее напряжение, а pasha413 - контролирует температуру. Удовлетворил бы сочетание этих двух вариантов.

Я проверил вашу сигнализацию. Arduino NANO v.3 и модем M590E. Вы написали, что на D10 - красный светодиод, D11 - синий, D12 - зеленый.

После очередного включения сигнализации загорается зеленый светодиод (правильно).

После команды GuardOn красный светодиод мигает (он должен гореть постоянно?) , а зеленый гаснет. Синий светодиод вообще не загорается. Почему это так происходит?

 

smesharik
Offline
Зарегистрирован: 31.01.2016

Вот как это реализовано у меня со Скатом

kvolk
Offline
Зарегистрирован: 12.06.2017

b707 пишет:

..мне показалось проще и надежнее делать GPRS запрос типа HEAD ...

Довольно интересный способ, получения практически точного времени. 

b707 пишет:

Это надо ждать прихода "настоящего" СМС. В USSD сообщениях от оператора, например о балансе - нет времени.

Сигналка вашими смсками управляется, так что при получении от вас смс она будет обновлять время без лишнего трафик.

Из всех вышеперечисленным методов я бы пожалуй сразу отказался от NTP - очень ресурсоёмкий процесс, и при наличии интернета можно менее затратно парсить заголовки сайтов.

Если бы позволяла память и было бы соединение с инетом - однозначно использовал бы заголовки http для получения практически точного времени.

В случае ограниченного ресурса памяти, использовал бы корректировку из смс. Но тут нужно ещё раз проверить, если выключить модем и отправить на него смс, а потом через пол часа включить - какое время прилетит на модем, время отправки смс или получения модемом смс?

smesharik пишет:

...при любой смс корректируем время от оператора

Проверьте что за время будет прилетать при получении смс с задержкой. Только что нашел свой пост в котором +CMT: "+380958xxxxxx",,«16/02/16,32:05:42+18»    время и дата не являются правильными о_О.

UPD. Всё оказалось проще, на тот момент модема на работе не было, пришлось эмулировать его работу через USB-TTL конвертор, естественно все данные кроме номера взяты "от фонаря" :)

Gienekb пишет:

Вы контролируете внешнее напряжение, а pasha413 - контролирует температуру. Удовлетворил бы сочетание этих двух вариантов.

При наличии контроля температуры "запилить" простой контроль внешнего питания - простая задача, никаких библиотек подключать не надо, всего лишь достаточно мониторить состояние пина.

В моём случае контроль температуры был непозолительной роскошью.

Gienekb пишет:

После команды GuardOn красный светодиод мигает (он должен гореть постоянно?) , а зеленый гаснет. Синий светодиод вообще не загорается. Почему это так происходит?

Мигает синий светодиод - включен тестовый режим.

Светится зелёный светодиод - снято с охраны. Команда LedOff отключает этот светодиод - чтобы ночью несветил :) 

Мигает красный светодиод - поставлено на охрану, основной и/или дополнительный датчики в режиме геркона, цепь одного или обоих герконов разомкнута.

Горит красный светодиод - поставлено на охрану, датчики в режиме геркона замкнуты.

Мигает синий светодиод в течение 2 секунд при замыкании геркона всегда, вне зависимоти от состояния сигнализации (проверка при снятой с охраны сигналке).

smesharik пишет:

Вот как это реализовано у меня со Скатом

Огромный плюс в том, что можно сразу и сирену подключить. Какая автономность? :) 

kvolk
Offline
Зарегистрирован: 12.06.2017

smesharik пишет:

 ...при любой смс корректируем время от оператора

 if (val.indexOf(F("+cmt")) > -1)     { // при любом обращении к GSM модулю корректирует часы от оператора
        delay(500);
      time.Hours = val.substring(34, 36).toInt();
      time.minutes = val.substring(37, 39).toInt();
      time.settime(-1, time.minutes, time.Hours, -1, -1, -1, -1);
     }

Вы на 100% можете быть уверены том что на месте этих символов всегда будут часы, минуты, секунды?

substring(34, 36).toInt();

А если отправить смс с ru номера или ua, правильно ли установится время, длина номера то разная. Конечно же если вы делаете это устройство только для себя, то на эти мелочи можно просто забить, но всё же  попробуйте не привязываться жестко к позиции символа в строке. 

b707
Offline
Зарегистрирован: 26.05.2017

kvolk пишет:

b707 пишет:

Это надо ждать прихода "настоящего" СМС. В USSD сообщениях от оператора, например о балансе - нет времени.

Сигналка вашими смсками управляется, так что при получении от вас смс она будет обновлять время без лишнего трафик.

Я предпочитаю проектировать программы так, чтобы они требовали как можно меньше внимания. Сигналка должна "управляться" самостоятельно, разве что пару тройку СМС послал при запуске, что подобрать параметры - а дальше СМС должны идти только от сигналки к вам - а не обратно.

Я думал о извлечении времени из СМС - этот метод очевиден - но отказался от него. Ситуация, что после каждого перезапуска программы для установки времени мне будет нужно отправить СМС - для меня не подходит.

b707
Offline
Зарегистрирован: 26.05.2017

smesharik пишет:

тогда уже NTP сервер использовать

сделал как kvolk порекомендовал, при любой смс корректируем время от оператора

на модеме А6, к сожалению, нет поддержки UDP стека - а то бы попробовал NTP.

Коррекцию времени вы написали плохо, согласен с замечанием kvolk. Ваш код парсинга времени из СМС крайне ненадежен, рекомендую его переписать. Ищите в строке характерные подстроки, например для времени - три группы цифр, разделенные двумя двоеточиями. Найти соответсвующие символы в строке совсем несложно, примеров кода в сети полно. То что написано у вас - это никуда не годится, никогда не полагайтесь на положение символа.

 

 

kvolk
Offline
Зарегистрирован: 12.06.2017

smesharik пишет:

 

      if (val.indexOf(F("+cmt")) > -1) { // при любом обращении к GSM модулю корректирует часы от оператора
      delay(500);
      time.Hours = val.substring(34, 36).toInt();
      time.minutes = val.substring(37, 39).toInt();
      time.settime(-1, time.minutes, time.Hours, -1, -1, -1, -1);
     }

Посмотрите это сообщение, 21-ая строка кода. Там определяется позиция последовательности символов в строке, добавляется +1. Потом опять позиция поледовательности + длина строки которую необходимо получить. Профит!

Обратите внимание, в коде не все строки хранятся во флэш памяти  F ("bla-bla-bla") - это важно при оптимизации памяти.

b707
Offline
Зарегистрирован: 26.05.2017

kvolk пишет:

Обратите внимание, в коде не все строки хранятся во флэш памяти  F ("bla-bla-bla") - это важно при оптимизации памяти.

kvolk. обьясните пожалуйста, почему важно, что не все строки во флеше? (спрашиваю серьезно, без подкола)

kvolk
Offline
Зарегистрирован: 12.06.2017

b707 пишет:

..почему важно...

Последние 5 месяцев проекта была жесть просто жесть, необходимо было править баги и добавлять функционал практически на одном проценте памяти, в ченджлоге это видно. Иногда было проавильнее пожертвовать оперативной памятью для высвобождения флэш-памяти. Посмотрите на скрины компиляции:

Идентичные константы (строки) в оперативной памяти могут быть использованы в разных местах программы и не будут храниться дважы в ОЗУ. На примере это видно. Например, если используется символ "/" в тексте программы раз 50 или 100, то логичнее пожертвовать одним байтом ОЗУ чем 100 байтами флэш памяти.

b707
Offline
Зарегистрирован: 26.05.2017

kvolk, спасибо за поднятую тему. С интересом потестировал разные варианты. Действительно, макрос F() очень расточителен по отношению к флеш-памяти. Честно говоря, никогда не задумывался об этом. Правда, я обычно не использую F() для повторяющихся строк - не потому. что экономлю флеш, а просто лениво многократно набирать (или копировать) одно и то же :)

Вместо использования F() можно проделать все то же самое "вручную" - повторяющиеся строки  разместить в PROGMEM, а в процедуру print() передавать ссылку. Этот вариант абсолютно идентичен F() для единичной строки, но при многократном использовании не так прожорлив по отношению к флеш - сравните со своим первым и вторым вариантом.

Пример:

const char aa[] PROGMEM = "Bla-bla-bla";

void setup() {
  // put your setup code here, to run once:
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
Serial.println( (const __FlashStringHelper *) aa);
}

void loop() {
  // put your main code here, to run repeatedly:

}

//Скетч использует 1 462 байт (4%) памяти устройства. 
//Глобальные переменные используют 188 байт (9%) динамической памяти

чтобы не загромождать скетч постоянным приведением типов, можно определить  для него макрос

#define PGM_CHR     (const __FlashStringHelper *) 

Serial.println( PGM_CHR aa);

 

kvolk
Offline
Зарегистрирован: 12.06.2017

Да, так эффективнее, хотя и сложнее для новичков.

 

 

b707
Offline
Зарегистрирован: 26.05.2017

kvolk пишет:

Да, так эффективнее, хотя и сложнее для новичков.

Да ну ладно, ничуть не сложнее F() - вместо одного макроса добавляем другой.

Еще раз спасибо за тему, сделал для себя вывод, что для коротких строк любые способы помещения во флеш неээфективны. Учту в своих проектах.

Вы не будете против. если я на эту тему напишу обзорное сообщение для новичков?

 

kvolk
Offline
Зарегистрирован: 12.06.2017

b707 пишет:

что для коротких строк любые способы помещения во флеш неээфективны.

Полностью согласен.

b707 пишет:

Вы не будете против. если я на эту тему напишу обзорное сообщение для новичков?

Естественно не буду против, это будет очень полезная инфа, особенно для тех кто упирается в ресурс памяти :)

pasha413
Offline
Зарегистрирован: 27.11.2016

немного подправил скетч, команды и функционал не урезал. объединил команды смс и консоли (если команда введена в консоли то смс не оправляется), тем самым немного освободил места.  мастер-номера и баланс теперь приходят в одном смс. теперь команды вкл/выкл понимает: так  dooron и так door on.

на данный момент 

Скетч использует 21538 байт (70%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 941 байт (45%) динамической памяти, оставляя 1107 байт для локальных переменных. Максимум: 2048 байт.

вот скетч:

#include <EEPROM.h> 
#include <OneWire.h>
#include <RCSwitch.h>
#include<SoftwareSerial.h>

OneWire ds(6);                  // датчик температуры подключен к 6 пину, подтяжка 4.7кОм на +.
SoftwareSerial mySerial(7, 8);  // модем подключен к 7 и 8 пинам.
RCSwitch mySwitch = RCSwitch(); // беспроводной датчик двери, пин 2.

#define DOOR 4             // пин 4. концевик двери.
#define PIR 5              // пин 5. датчик движения.
#define GAS 14             // пин A0. датчик дыма.
#define LED 13             // пин 13. состояние системы.
#define BUZ 16             // пин A2. сирена.

// DOOR     - если сработал, на входе "+" HIGH.
// DOOR2    - если сработал, на пин 2 сигнал.
// PIR      - если сработал, на входе "+" HIGH.
// GAS      - если сработал, на входе "+" HIGH.
// BUZ      - если "-" LOW, то горит. 
// LED      - если "-" LOW, то горит.

int8_t Guard = 0;          // 1. охрана:                         1 - вкл, 0 - выкл.
int8_t AlarmRING = 1;      // 2. вызов при сработке:             1 - вкл, 0 - выкл.
int8_t SendSMS = 1;        // 3. отправка смс при сработке:      1 - вкл, 0 - выкл.
int8_t DOORon = 1;         // 4. контроль концевика двери:       1 - вкл, 0 - выкл.    
int8_t DOOR2on = 1;        // 4. контроль концевика двери 2:     1 - вкл, 0 - выкл.    
int8_t PIRon = 1;          // 5. контроль датчика движения:      1 - вкл, 0 - выкл.
int8_t GASon = 1;          // 6. контроль датчика дыма:          1 - вкл, 0 - выкл.
int8_t Sirena = 1;         // 7. сирена:                         1 - вкл, 0 - выкл. 

int8_t DOORFlag = 0;       // флаг состояние датчика двери.
int8_t DOOR2Flag = 0;      // флаг состояние датчика двери 2.
int8_t PIRFlag = 0;        // флаг состояние датчика движения.
int8_t GASFlag = 0;        // флаг состояние датчика газа.
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t PIRState = LOW;     // Состояние датчика движения.
int8_t LEDState = HIGH;    // Состояние светодиода.
int8_t Smoky = LOW;        // Состояние датчика газа.
int8_t Firststart = 1;     // первый старт.
int8_t sendsmscaller = 1;  // отправка смс.

uint32_t msAT = 0;
unsigned long door2 = 3258553; // адрес 433 передатчика геркона двери

char Bal[4] = "";          // для временного хранения номера баланса.   
char Phone[12];            // для временного хранения номера телефона.      
byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ.

String val;                // переменная для хранения пришедших данных.   
String temp;               // температура.
String csq;                // уровень сигнала.   
String LastEvent;          // полное состояние системы.
String EEPhone;            // все номера из EEPROM.
String RingPhone;          // номер звонившего.
String AlarmPhone[5];      // номера для постановки/снятии с охраны и отправки смс.

int p = 0;
int GASThres = 400;           // предельная концентрация газа
int interval_alarm = 20;      // Секунд до отключения "тревожного" пина. 
int previousMillis_alarm = 0;
int interval_led = 1000;      // для мигания LED, 1 сек.
int previousMillis_led = 0;
int interval_door = 10;       // секунд не смотрим на датчик двери.
int previousMillis_door = 0;
int interval_door2 = 20;      // секунд не смотрим на датчик двери 2.
int previousMillis_door2 = 0;
int interval_pir = 20;        // секунд не смотрим на датчик движения.
int previousMillis_pir = 0;
int interval_gas = 60;        // секунд не смотрим на датчик газа.
int previousMillis_gas = 0;

/* EEPROM Data:
  № ячейки - значение:
  0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию.
  1 - Guard = 0;       // охрана:             0 - выкл.
  2 - AlarmRING = 1;   // звонок:             1 - вкл. 
  3 - SendSMS = 1;     // отправка смс:       1 - вкл.
  4 - DOORon = 1;      // концевик двери:     1 - вкл.
  5 - DOOR2on = 1;     // концевик двери 2:   1 - вкл.
  6 - PIRon = 1;       // датчик движения:    1 - вкл.
  7 - GASon = 1;       // датчик дыма:        1 - вкл.
  8 - Sirena = 1;      // сирена:             1 - вкл.
  10 - Firststars = 1; // первый запуск       1.
  20 - ячейка памяти баланса,
  25, 40, 55, 70, 85 - ячейки памяти телефонов.
  100 - ячейка памяти номера последнего звонившего RingPhone.
*/

void setup() { /// === настройка программы === ///
  Serial.begin(9600); 
  Serial.println(F("Alarm  v4.1"));     
  pinMode(DOOR, INPUT_PULLUP);      // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT);           
  pinMode(GAS, INPUT);           
  pinMode(BUZ, OUTPUT);
  pinMode(LED, OUTPUT);             // светодиод горит во время запуска.
    digitalWrite(BUZ, HIGH);        // сирена выкл.
    digitalWrite(PIR, HIGH);        // игнорируем при включении.
  InitModem();                      // запускаем инициализация модема.
  eepromconfig();
  eepromtext();
  eepromphone();
  mySwitch.enableReceive(0);        // 433 приемник на 2 пине
    digitalWrite(LED, HIGH);        // гасим светодиод состояния сигнализации. 
}  
                                 
void loop() {  /// === основной цикл программы === ///
  AlarmPinOff();    // выключаем сирену, если прошло  время.
  if (Guard == 1) { // если на охране
    Detect();       // проверяем датчики.
    Led();          // моргаем светодиодом.
  }
  if (mySerial.available()) {     // если GSM модем что-то послал.
    while (mySerial.available()) {  // сохраняем входную строку в переменную val.
      char ch = mySerial.read();
      val += char(ch);              // собираем принятые символы в строку
      delay(3);
    } 
    if (val.indexOf("+PBREADY") > -1) InitModem();
    if (val.indexOf(F("+CLIP")) > -1) {        // если обнаружен вызов.
  Serial.println(F("Process RING"));                              
      delay(2000);                             // дадим гудок
      mySerial.println(F("ATH"));              // сбрасываем вызов.
      if (CheckPhone() == 1) {                 // проверяем номер, если наш.
  Serial.println(F("Master Ring OK!"));
  MasterRing();                                // меняем состояние охраны
      } else  Serial.println(F("No Master Ring!"));  
    } else if (val.indexOf(F("+CMT")) > -1) {  // если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
  Serial.println(String(F("SMS->")) + val);    // что пришло в смс
        if (CheckPhone() == 1) {               // если СМС от хозяина
  Serial.println(F("Master SMS OK!"));
  Komand();
        } else  Serial.println(F("No Master SMS!"));
      } else if(val.indexOf(F("+CUSD:")) > -1) { // если пришел баланс 
        // команда проверки баланса  AT+CUSD=1,#105#,15
        // анализируем строку 
        int p1 = val.indexOf(F("\""));         // начало строки
        int p2 = val.lastIndexOf(F("\""));     // конец строки
        val = val.substring(p1+1,p2);
        Serial.println("");
        Serial.println(F("Input string:"));    // пишем в порт пришедшую строку
        Serial.println(val);
        String decodestr;
        Decode7bit(val, decodestr);
        Serial.println("");
        Serial.println(F("Decode string:"));   // пишем в порт конвертированную строку
        Serial.println(decodestr);
sms(String("SIM " + decodestr), RingPhone);    // смс на последний звонивший
        mySerial.println("AT+CUSD=0");
         } else if (val.indexOf(F("+CSQ:")) > -1) { // пришел уровень сигнала сети
          int x = val.indexOf("+CSQ:");
          csq = val.substring(x+6, x+8);
           } val = ""; 
  } if (Serial.available()) {           // если в мониторе порта что-то ввели
      while (Serial.available()) {         // сохраняем входную строку в переменную val.
        char ch = Serial.read();
        val += char(ch);                   // собираем принятые символы в строку
        delay(3);
        } 
        sendsmscaller = 0;
  Komand();                        // запускаем консольную программу
        val = "";  
        sendsmscaller = 1;
    }
}

int CheckPhone() { /// === проверка телефона === ///
  if (Firststart == 0) {                        // если не первый старт
    for (int i = 0; i < 5; i++) {
      if (val.indexOf(AlarmPhone[i]) > -1) {    // && val.indexOf(AlarmPhone[i]) != 0) { // если есть вызов, и он наш
        RingPhone = AlarmPhone[i];              // запоминаем его.
        RingPhone.toCharArray(Phone, 12);   
        EEPROM.put(100, Phone);                 // записываем RingPhone в память. 
  Serial.println(String(F("RingPhone ")) + RingPhone);          
        return 1;                               // возвращаем 1 - номер наш!
      } 
    } return 0;                                 // возвращаем 0 - номер не наш!
  } else if (Firststart == 1) {                 // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
      if (val.indexOf("+CLIP: \"7") > -1) {
      int ind = val.indexOf("+CLIP:");          // обрезаем номер 
      String num = val.substring(ind + 8, ind + 19); 
      num.toCharArray(Phone, 12);
      EEPROM.put(25, Phone);                    // пишем номер в EEPROM
      EEPROM.put(100, Phone);                   // записываем RingPhone в память. 
      AlarmPhone[0] = Phone;                    // запишем
      RingPhone = Phone;                        // запоминаем его.
      EEPROM.update(10, 0);                     // обновляем Firststart
      Firststart = 0;                           // пишем 0
  Serial.println(String(F("Master0:")) + AlarmPhone[0]); 
  Serial.println(String(F("Firststart:")) + Firststart);
sms(String("Master0:" + num + " Ok"), num);     // смс на звонивший
//  приходит смс в виде: " Master0:79111234567 Ok "
      }
    } return 1;                               
}

void eepromconfig() { /// === конфигурирование сигнализации === ///
    if (EEPROM.read(0) != 1) {           // если записана не 1
      for (int i = 0 ; i < 512 ; i++) {  // переписываем все ячейки
        EEPROM.write(i, 0);
      }                      // и записываем:
      EEPROM.update(1, 0);   // Guard       охрана выкл.
      EEPROM.update(2, 1);   // AlarmRING   вызов вкл.
      EEPROM.update(3, 1);   // SendSMS     смс вкл.
      EEPROM.update(4, 1);   // DOORon      датчики дверей вкл.
      EEPROM.update(5, 1);   // DOOR2on     датчики дверей вкл.
      EEPROM.update(6, 1);   // PIRon       датчик движения вкл.
      EEPROM.update(7, 1);   // GASon       датчик газа вкл.
      EEPROM.update(8, 1);   // Sirena      сирена вкл.
      EEPROM.update(10, 1);  // Firststart  первый старт!.
      EEPROM.update(20, 0);  // баланс, записываем массив в EEPROM 
      EEPROM.update(0, 1);   // 
  Serial.println(F("EEPROM != 1/ RESET!")); 
    }
    if (EEPROM.read(0) == 1) {
      Guard      = EEPROM.read(1);   // Охрана
      AlarmRING  = EEPROM.read(2);   // Вызов
      SendSMS    = EEPROM.read(3);   // Отправка смс
      DOORon     = EEPROM.read(4);   // Датчик двери
      DOOR2on    = EEPROM.read(5);   // Датчик двери
      PIRon      = EEPROM.read(6);   // Датчик движения
      GASon      = EEPROM.read(7);   // Датчик газа/дыма
      Sirena     = EEPROM.read(8);   // сирена
      Firststart = EEPROM.read(10);  //
    }
}

void eepromtext() { /// === состояние системы === ///
   mySerial.println("AT+CSQ");
   TempC();
   String SIGN = "";         // текущее состояние системы.
   String SIRENA = "";       // аварийная сирена.
   String RING = "";         // текущее состояние вызов.
   String SMS = "";          // текущее состояние смс.
   String Door = "";         // текущее состояние датчика двери.
   String Door2 = "";        // текущее состояние датчика двери.
   String Pir = "";          // текущее состояние датчика движения.
   String Gas = "";          // текущее состояние датчика газа.
   if (Guard == 1) SIGN = String(F("System on\n")); else (SIGN = String(F("System off\n")));
   if (Sirena == 1) SIRENA = String(F("Sirena on\n")); else (SIRENA = String(F("Sirena off\n")));
   if (AlarmRING == 1) RING = String(F("Ring on\n")); else (RING = String(F("Ring off\n")));
   if (SendSMS == 1) SMS = String(F("SMS on\n")); else (SMS = String(F("SMS off\n")));
   if (DOORon == 1) Door = String(F("Door on\n")); else (Door = String(F("Door off\n")));
   if (DOOR2on == 1) Door2 = String(F("Door2 on\n")); else (Door2 = String(F("Door2 off\n")));
   if (PIRon == 1) Pir = String(F("Pir on\n")); else (Pir = String(F("Pir off\n")));
   if (GASon == 1) Gas = String(F("Gas on\n")); else (Gas = String(F("Gas off\n")));
    String System = SIGN + SIRENA + RING + SMS;     // состояние (вкл/выкл) системы.
    String Sensors = Pir + Door + Door2 + Gas + temp;       // состояние (вкл/выкл) датчиков.
    String CSQ = String(F("Signal ")) + csq + "%";
    LastEvent = System + Sensors + CSQ;             // полное состояние системы и датчиков.
  Serial.println(LastEvent);
}

void eepromphone() { /// === чтение мастер-номеров из EEPROM === ///
    for (int i = 0; i < 5 ; i++) {
      EEPROM.get(Adress[i], Phone);        // считываем мастер-номера 
        AlarmPhone[i] = Phone;
    }
    String numbers = "[0] " + AlarmPhone[0] + "\n[1] " + AlarmPhone[1] + "\n[2] " + AlarmPhone[2] + "\n[3] " + AlarmPhone[3] + "\n[4] " + AlarmPhone[4] + "\n";
    EEPROM.get(100, Phone);                // считываем номер последнего звонившего
    RingPhone = Phone;
    String ring = String(F("Ring ")) + RingPhone + "\n";
    EEPROM.get(20, Bal);                   // считываем номер баланса
    String bal = String(F("Balance *")) + Bal + String(F("#\n")); 
    Firststart = EEPROM.read(10);          // cчитаем первый старт
    String FST;
    if (Firststart == 1) FST = String(F("Firststart Yes")); else FST = String(F("Firststart No"));
    EEPhone = numbers + ring + bal + FST;
  Serial.println(EEPhone);                 //  полный список номеров
}

void Detect() { /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  Smoky = analogRead(GAS);
  
  if (DOORon == 1) {
    if (DOORState == HIGH && DOORFlag == 0) {
      previousMillis_door = millis();
      DOORFlag = 1;
  Serial.println(F("Dver' otkrita!"));
  Alarm();                                // 
    }
    if (DOORState == LOW && DOORFlag == 1) {
      int currentMillis_door = millis();
      if (((currentMillis_door - previousMillis_door) / 1000 > interval_door)) {
        DOORFlag = 0;
      }
    }
  }
  if (DOOR2on == 1) {
    if (mySwitch.available()) {
      unsigned long value = mySwitch.getReceivedValue();
      if (value == door2 && DOOR2Flag == 0) {
        previousMillis_door2 = millis();
        DOOR2Flag = 1;
  Serial.println(F("Dver' 2 otkrita!"));
  Alarm();                                // 
      }
      mySwitch.resetAvailable();
    }
    int currentMillis_door2 = millis();
    if (((currentMillis_door2 - previousMillis_door2) / 1000 > interval_door2)) {
      DOOR2Flag = 0;
    }
  }
  if (PIRon == 1) {
    if (PIRState == HIGH && PIRFlag == 0) {
      previousMillis_pir = millis();
      PIRFlag = 1;
  Serial.println(F("Dvizhenie u dveri!"));
  Alarm();                                // 
    }
    if (PIRState == LOW && PIRFlag == 1) {
      int currentMillis_pir = millis();
      if (((currentMillis_pir - previousMillis_pir) / 1000 > interval_door)) {
        PIRFlag = 0; 
      }
    }
  }
  if (GASon == 1) {
    if ((Smoky > GASThres) && GASFlag == 0) {
      previousMillis_gas = millis();
      GASFlag = 1;
      delay(100);
  Serial.println(F("Gas v dome!"));
  Alarm();                                // 
    }
    if ((Smoky < GASThres) && GASFlag == 1) {
      int currentMillis_gas = millis();
      if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_door)) {
        GASFlag = 0; 
      }
    }
  }
}

void Alarm() { /// === запускаем сирену и отправку смс === ///
  if (Guard == 1) {
    previousMillis_alarm = millis();
    if (Sirena == 1) digitalWrite(BUZ, LOW);
    Serial.println(F("Alarm!!!"));  
    if (SendSMS == 1) {
      for (int i = 0; i < 5; i++) {           // if (AlarmPhone[i] != 0)  {
        if (DOORFlag == 1) {
sms(String(F("Dver' otkrita!")), AlarmPhone[i]); // смс на все номера
        }
        if (DOOR2Flag == 1) {
sms(String(F("Dver' 2 otkrita!")), AlarmPhone[i]); // смс на все номера
        }
        if (PIRFlag == 1) {
sms(String(F("Dvizhenie y dveri!")), AlarmPhone[i]); // смс на все номера
        }
        if (GASFlag == 1) {
sms(String(F("Gas v dome!")), AlarmPhone[i]); // смс на все номера
        }
      }
    }
    if (AlarmRING == 1) {
      mySerial.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
    }
  }
}

void AlarmPinOff() { /// === если прошло время, отключаем сирену === ///      
  int currentMillis_alarm = millis();
  if (((currentMillis_alarm - previousMillis_alarm) / 1000 > interval_alarm) || Guard == 0) {
    digitalWrite(BUZ, HIGH);
  } 
}

void MasterRing() { /// === мастер звонков === //
  if (Guard == 1) GuardOff();     // меняем состояние
  else if (Guard == 0) GuardOn(); // меняем состояние
}

void GuardOff() { /// === выключение сигнализации === ///
    Guard = 0;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->off. Ring:")) + RingPhone);
    for (int i = 0; i < 5; i++) {                                     // if (AlarmPhone[i] != 0)  {
sms(String(F("System->off ")) + RingPhone + "\n" + temp, AlarmPhone[i]); // смс на все номера
    }
}

void GuardOn() { /// === включение сигнализации === ///       
    Guard = 1;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->on. Ring:")) + RingPhone);
    for (int i = 0; i < 5; i++) {                                    // if (AlarmPhone[i] != 0)  {
sms(String(F("System->on ")) + RingPhone + "\n" + temp, AlarmPhone[i]); // смс на все номера
    }
}

void Led() { /// === состояние светодиода === ///
  if (Guard == 1) {                   // если на охране
  int currentMillis_led = millis();  // светодиод моргает
  //проверяем не прошел ли нужный интервал, если прошел то
    if (currentMillis_led - previousMillis_led > interval_led) {
      // сохраняем время последнего переключения
      previousMillis_led = currentMillis_led;
      // если светодиод не горит, то зажигаем, и наоборот
      if (LEDState == HIGH) LEDState = LOW;
      else LEDState = HIGH;
      digitalWrite(LED, LEDState);
    }
  } else digitalWrite(LED, HIGH); // иначе гасим его
}

void Komand() { /// === мастер смс === ///
    val.toLowerCase();
  if (RingPhone == AlarmPhone[0] || sendsmscaller == 0) {        // команды выполняются только с 0 мастер номера
    if (val.indexOf(F("reset")) > -1)    { // полный сброс ЕЕПРОМ
sms(String("All System Reset!!!"), RingPhone); // смс на последний номер
  Serial.println(F("Reset System!!!"));          
      EEPROM.write(0, 0);
  eepromconfig();
  eepromtext();
  eepromphone();
    }
    if ((p = val.indexOf(F("master"))) > -1)  { // добавление мастер-номера
      master(val.substring(p + 6, p + 7).toInt(), val.substring(p + 8, p + 19));
///// sms типа: " master1:79111234567 " - ячейка + номер
    }
    if ((p = val.indexOf(F("balance:"))) > -1) { // добавление номера баланса
      balnum(val.substring(p + 8, p + 11));
///// sms типа: " balance:100 " - номер баланса
    } 
    if ((p = val.indexOf(F("dell:"))) > -1) { // удаление номера из ячейки     
      dellphone(val.substring(p + 5, p + 6).toInt());
///// sms типа: " dell:1 " - удалить номер из ячейки 1
    } 
    if (val.indexOf(F("phone")) > -1)     { // инфо о номерах системы
  eepromphone();
sms(String(EEPhone), RingPhone); // смс на последний номер
    }
  }  
  if (val.indexOf(F("status")) > -1) {     // инфо о состоянии системы
  eepromconfig();
  eepromtext();
sms(String(LastEvent), RingPhone); // смс на последний номер
  }
  if (val.indexOf(F("money")) > -1)    {   // запрос баланса
  balance();
  }
  if (val.indexOf(F("sirena")) > -1) {     // вкл/выкл сирены
    if (val.indexOf(F("on")) > -1) {       // вкл 
      Sirena = 1;
      EEPROM.update(8, Sirena);                   
  Serial.println(F("Sirena->on"));      
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("Sirena->on" + RingPhone  + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1) {      // выкл
      Sirena = 0;
      EEPROM.update(8, Sirena);                   
  Serial.println(F("Sirena->off"));      
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("sirena->off" + RingPhone  + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("system")) > -1)  {  // вкл/выкл сигнализацию
    if (val.indexOf(F("on")) > -1)  {    // вкл 
  GuardOn();
    }
    if (val.indexOf(F("off")) > -1)  {    // вкл
  GuardOff();
    }
  }
  if (val.indexOf(F("ring")) > -1)   { // вкл/выкл вызов при сработке
    if (val.indexOf(F("on")) > -1)   { // вкл 
      AlarmRING = 1;
      EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing->on"));      
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("Ring->on" + RingPhone  + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1)   { // выкл 
      AlarmRING = 0;
      EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing->off"));      
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("Ring->off" + RingPhone  + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("sms")) > -1)    { // вкл/выкл смс при сработке
    if (val.indexOf(F("on")) > -1)    { // вкл 
      SendSMS = 1;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->on"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("SMS->on" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1)    { // выкл
      SendSMS = 0;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->off"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("SMS->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("door")) > -1) {  // вкл/выкл контроль датчика двери
    if (val.indexOf(F("on")) > -1) {  // выкл
      DOORon = 1;
      EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->on"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("DOOR->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1) {  // выкл контроль датчика двери
      DOORon = 0;
      EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->off"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("DOOR->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("door2")) > -1) {  // вкл/выкл контроль датчика двери 2
    if (val.indexOf(F("on")) > -1) {  // вкл
      DOOR2on = 1;
      EEPROM.update(5, DOOR2on);
  Serial.println(F("DOOR2->on"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("DOOR2->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1) {  // выкл 
      DOOR2on = 0;
      EEPROM.update(5, DOOR2on);
  Serial.println(F("DOOR2->off"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("DOOR2->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("pir")) > -1) {  // вкл/выкл контрол датчика движения
    if (val.indexOf(F("on")) > -1) {  // вкл
      PIRon = 1;
      EEPROM.update(6, PIRon);
  Serial.println(F("PIR->on"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("PIR->on" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1) {  // выкл
      PIRon = 0;
      EEPROM.update(6, PIRon);
  Serial.println(F("PIR->off"));  
      for (int i = 0; i < 5 ; i++) {  // смс на все номера          
sms(String("PIR->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("gas")) > -1) {  // вкл/выкл контроль датчика газа
    if (val.indexOf(F("on")) > -1) {  // вкл 
      GASon = 1;
      EEPROM.update(7, GASon);
  Serial.println(F("GAS->on"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("GAS->on" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1) {  // выкл 
      GASon = 0;
      EEPROM.update(7, GASon);
  Serial.println(F("GAS->off"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("GAS->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
}

void balance() { /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  delay(1000);
  mySerial.println(String(F("AT+CUSD=1,#")) + Bal + String(F("#,15")));
  Serial.println(String("Balance#") + Bal + "#"); 
}

int master (int i, String num) { /// === добавление мастер-номеров === ///
    if (i < 5 && i != 0) {
      num.toCharArray(Phone, 12); // конвертируем
      AlarmPhone[i] = num;        // пишем номер  
  Serial.println(String(F("Master[")) + i + String(F("]:")) + num);
      EEPROM.put(Adress[i], Phone);           // записываем массив в EEPROM 
sms(String(String("Master") + i + ":" + num + " add"), RingPhone); // смс на 0 номер.
sms(String("Master: " + AlarmPhone[i]), AlarmPhone[i]); // смс на добавленный номер.
    } else Serial.println(F("MAX number 4!"));          // 4 номера максимум! 
    // 0 номер можно удалить только через RESET!!!
    return 1;                             
}                              

int dellphone (int i) { /// === удаление мастар-номеров === ///
     if (i < 5 && i != 0) {
  Serial.println(String(F("Master")) + i + String(F(" dell")));
sms(String(String("Master") + i + ":" + AlarmPhone[i] + " dell"), RingPhone); // смс на 0 номер
sms(String("Dell: " + AlarmPhone[i]), AlarmPhone[i]); // смс на удаленный номер.
       EEPROM.put(Adress[i], 0);
       AlarmPhone[i] = "";   // обнулим номер
  } return 1;                          
}

int balnum (String num) { /// === добавляем номер баланса === ///
    num.toCharArray(Bal, 4);   // конвертируем
  Serial.println(String(F("Balance *")) + Bal + "#");
    EEPROM.put(20, Bal);           // записываем массив в EEPROM 
sms(String("Balance:*" + num + "# Ok"), RingPhone); // смс на 0 номер
    return 1;                             
}

void TempC() {      /// === измеряем температуру === ///
  byte data[2];
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);
  delay(750);
  ds.reset();
  ds.write(0xCC);
  ds.write(0xBE);
  data[0] = ds.read();
  data[1] = ds.read();
  int Temp = (data[1] << 8) + data[0];
  Temp = Temp >> 4;
  temp = String(F("Temp ")) + Temp + String(F("*C\n"));
}

void Decode7bit(String &instr, String &outstr) { /// === декодирование баланса === ///
  byte reminder = 0;
  int bitstate = 7;
  for (unsigned int i = 0; i < instr.length(); i++) {
    byte b = instr[i];
    byte bb = b << (7 - bitstate);
    char c = (bb + reminder) & 0x7F;
    outstr += c;
    reminder = b >> bitstate;
    bitstate--;
    if (bitstate == 0) {
      char c = reminder;
      outstr += c;
      reminder = 0;
      bitstate = 7;
    }
  }
}

void InitModem() { /// === инициализация модема === ///
  Serial.println(F("Start GSM"));
  mySerial.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  Serial.println(F("GSM connected"));
  waitRegistration();
  delay(1000); 
}

void waitConnect() { /// === запуск модема === ///
  int countok = 0;
  String str; 
  while(countok < 5) {                   //ждём пять ОК  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) {// Событие срабатывающее каждые 500 мс 
      msAT = ms;
//      Serial.println(">>AT");
      mySerial.println(F("AT"));          // посылаем команду
      str = "";
      delay(100);                      // ждём ответа
      while(mySerial.available()) {
        char ch = mySerial.read();
        str += ch;
      } 
//      Serial.println("C>");
//      Serial.println(str);
      if(str.indexOf(F("OK")) > -1)
        countok++;
      else
        countok = 0;
    }
  }  
  Serial.println(F("Turn on AOH:"));
  mySerial.println(F("AT+CLIP=1"));  // включить АОН
  delay(200);
  Serial.println(F("GSM registration"));
  mySerial.println(F("AT+CMGF=1"));
  delay(200); 
  Serial.println(F("Mode GSM:"));
  mySerial.println(F("AT+CSCS=\"GSM\""));  // кодировка текста - GSM
  delay(300);
  mySerial.println(F("AT+CNMI=2,2,0,0,0"));
  delay(300); 
}

void waitRegistration() { /// === регистрация модема в сети === ///
  bool ok = 0;
  String str;
  while(!ok) {  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс
      msAT = ms;
      Serial.println(F(">>AT+CREG?"));
      mySerial.println(F("AT+CREG?"));      //посылаем команду
      delay(100);                           //Ждём ответа
      str = "";
      while(mySerial.available()) {
           char ch = mySerial.read();
           str += ch;
      } 
      Serial.println(F("R>"));
      Serial.println(str);
      if(str.indexOf(F("+CREG:"))>-1)
        ok = 1;
    }
  }  
}

void sms(String text, String phone) { /// === отправка СМС === ///
  if (phone != 0 && sendsmscaller == 1) {
    phone = "+" + phone;
    Serial.println(F("Start SMS send")); 
    mySerial.println(String(F("AT+CMGS=\"")) + phone + String(F("\"")));
    delay(300);
    mySerial.print(text);
    delay(300);
    mySerial.print((char)26);
    delay(300);
    Serial.println(String(F("SMS sended! Phone: ")) + phone + String(F("; Message: ")) + text);
    delay(5000);
  }
}

 

pasha413
Offline
Зарегистрирован: 27.11.2016

сделал небольшую менюшку на LCD1602 shield 

можно вкл/выкл режимы +  просмотр, пока особо не проверял - некогда.

скетч:

#include <EEPROM.h> 
#include <OneWire.h>
#include <RCSwitch.h>
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

OneWire ds(5);                  // датчик температуры подключен к 5 пину, подтяжка 4.7кОм на +.
SoftwareSerial mySerial(6, 7);  // модем подключен к 6 и 7 пинам.
RCSwitch mySwitch = RCSwitch(); // беспроводной датчик двери, пин 2.
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);

///------ LiquidCrystal -----------------///
/* 
A0 // analogRead: кнопки   SELECT,LEFT,UP,DOWN,RIGHT
4  D4          LiquidCrystal
5  D5          LiquidCrystal
6  D6          LiquidCrystal
7  D7          LiquidCrystal
8  rs          LiquidCrystal
9  enable      LiquidCrystal
10 подсветка=1 LiquidCrystal
*/

int _dA0 = 0;
byte key_N;
byte LED_lcd = 0;    // перем. в 0 окна
byte frame_N = 0;   // номер показ окна

#define A0        17 // analogRead: кнопки   SELECT,LEFT,UP,DOWN,RIGHT
#define btnRIGHT  0  // кнопка RIGHT
#define btnUP     1  // кнопка  UP
#define btnDOWN   2  // кнопка  DOWN
#define btnLEFT   3  // кнопка  LEFT
#define btnSELECT 4  // кнопка  SELECT
#define btnNONE   5  // кнопки  не нажаты

///-----------------------------////
#define DOOR 3             // пин 3. концевик двери.
#define PIR 4              // пин 4. датчик движения.
#define GAS 14             // пин A0. датчик дыма.
#define LED 15             // пин A1. состояние системы.
#define BUZ 16             // пин A2. сирена.

// DOOR     - если сработал, на входе "+" HIGH.
// DOOR2    - если сработал, на пин 2 сигнал.
// PIR      - если сработал, на входе "+" HIGH.
// GAS      - если сработал, на входе "+" HIGH.
// BUZ      - если "-" LOW, то горит. 
// LED      - если "-" LOW, то горит.

int8_t Guard = 0;          // 1. охрана:                         1 - вкл, 0 - выкл.
int8_t AlarmRING = 1;      // 2. вызов при сработке:             1 - вкл, 0 - выкл.
int8_t SendSMS = 1;        // 3. отправка смс при сработке:      1 - вкл, 0 - выкл.
int8_t DOORon = 1;         // 4. контроль концевика двери:       1 - вкл, 0 - выкл.    
int8_t DOOR2on = 1;        // 4. контроль концевика двери 2:     1 - вкл, 0 - выкл.    
int8_t PIRon = 1;          // 5. контроль датчика движения:      1 - вкл, 0 - выкл.
int8_t GASon = 1;          // 6. контроль датчика дыма:          1 - вкл, 0 - выкл.
int8_t Sirena = 1;         // 7. сирена:                         1 - вкл, 0 - выкл. 

int8_t DOORFlag = 0;       // флаг состояние датчика двери.
int8_t DOOR2Flag = 0;      // флаг состояние датчика двери 2.
int8_t PIRFlag = 0;        // флаг состояние датчика движения.
int8_t GASFlag = 0;        // флаг состояние датчика газа.
int8_t DOORState = LOW;    // Состояние концевика двери.
int8_t PIRState = LOW;     // Состояние датчика движения.
int8_t LEDState = HIGH;    // Состояние светодиода.
int8_t Smoky = LOW;        // Состояние датчика газа.
int8_t Firststart = 1;     // первый старт.
int8_t sendsmscaller = 1;  // отправка смс.

uint32_t msAT = 0;
unsigned long door2 = 3258553; // адрес 433 передатчика геркона двери

char Bal[4] = "";          // для временного хранения номера баланса.   
char Phone[12];            // для временного хранения номера телефона.      
byte Adress[5] = {25, 40, 55, 70, 85}; // ячейки для пяти номеров в ЕЕПРОМ.

String val;                // переменная для хранения пришедших данных.   
String temp;               // температура.
String csq;                // уровень сигнала.   
String decodestr;          // баланс на сим.
String LastEvent;          // полное состояние системы.
String EEPhone;            // все номера из EEPROM.
String RingPhone;          // номер звонившего.
String AlarmPhone[5];      // номера для постановки/снятии с охраны и отправки смс.
int p = 0;
int GASThres = 400;           // предельная концентрация газа
int interval_alarm = 20;      // Секунд до отключения "тревожного" пина. 
int previousMillis_alarm = 0;
int interval_led = 1000;      // для мигания LED, 1 сек.
int previousMillis_led = 0;
int interval_door = 10;       // секунд не смотрим на датчик двери.
int previousMillis_door = 0;
int interval_door2 = 20;      // секунд не смотрим на датчик двери 2.
int previousMillis_door2 = 0;
int interval_pir = 20;        // секунд не смотрим на датчик движения.
int previousMillis_pir = 0;
int interval_gas = 60;        // секунд не смотрим на датчик газа.
int previousMillis_gas = 0;

/* EEPROM Data:
  № ячейки - значение:
  0 - если записана не 1, то необходимо затереть eeprom и восстановить стандартную конфигурацию.
  1 - Guard = 0;       // охрана:             0 - выкл.
  2 - AlarmRING = 1;   // звонок:             1 - вкл. 
  3 - SendSMS = 1;     // отправка смс:       1 - вкл.
  4 - DOORon = 1;      // концевик двери:     1 - вкл.
  5 - DOOR2on = 1;     // концевик двери 2:   1 - вкл.
  6 - PIRon = 1;       // датчик движения:    1 - вкл.
  7 - GASon = 1;       // датчик дыма:        1 - вкл.
  8 - Sirena = 1;      // сирена:             1 - вкл.
  10 - Firststars = 1; // первый запуск       1.
  20 - ячейка памяти баланса,
  25, 40, 55, 70, 85 - ячейки памяти телефонов.
  100 - ячейка памяти номера последнего звонившего RingPhone.
*/

void setup() { /// === настройка программы === ///
  Serial.begin(9600); 
  lcd.begin(16, 2);// экран LCD 16x2
  pinMode(10, OUTPUT);
  LED_lcd = 1;
  digitalWrite(10, LED_lcd);
  Serial.println(F("Alarm v4.3")); //
  pinMode(DOOR, INPUT_PULLUP);      // вход датчика двери с подтяжкой на +.
  pinMode(PIR, INPUT);           
  pinMode(GAS, INPUT);           
  pinMode(BUZ, OUTPUT);        
  pinMode(LED, OUTPUT);             // светодиод горит во время запуска.
    digitalWrite(BUZ, HIGH);        // сирена выкл.
    digitalWrite(PIR, HIGH);        // игнорируем при включении.
//  InitModem();                      // запускаем инициализация модема.
  eepromconfig();
  eepromtext();
  eepromphone();
  mySwitch.enableReceive(0);        // 433 приемник на 2 пине
    digitalWrite(LED, HIGH);        // гасим светодиод состояния сигнализации. 
}  
                                 
void loop() {  /// === основной цикл программы === ///
  LCD();
  AlarmPinOff();    // выключаем сирену, если прошло  время.
  if (Guard == 1) { // если на охране
    Detect();       // проверяем датчики.
    Led();          // моргаем светодиодом.
  }
  if (mySerial.available()) {     // если GSM модем что-то послал.
    while (mySerial.available()) {  // сохраняем входную строку в переменную val.
      char ch = mySerial.read();
      val += char(ch);              // собираем принятые символы в строку
      delay(3);
    } 
    if (val.indexOf("+PBREADY") > -1) InitModem();
    if (val.indexOf(F("+CLIP")) > -1) {        // если обнаружен вызов.
  Serial.println(F("Process RING"));                              
      delay(2000);                             // дадим гудок
      mySerial.println(F("ATH"));              // сбрасываем вызов.
      if (CheckPhone() == 1) {                 // проверяем номер, если наш.
  Serial.println(F("Master Ring OK!"));
  MasterRing();                                // меняем состояние охраны
      } else  Serial.println(F("No Master Ring!"));  
    } else if (val.indexOf(F("+CMT")) > -1) {  // если обнаруженa СМС
  Serial.println(F("Process CMT"));                            
  Serial.println(String(F("SMS->")) + val);    // что пришло в смс
        if (CheckPhone() == 1) {               // если СМС от хозяина
  Serial.println(F("Master SMS OK!"));
  Komand();
        } else  Serial.println(F("No Master SMS!"));
      } else if(val.indexOf(F("+CUSD:")) > -1) { // если пришел баланс 
        // команда проверки баланса  AT+CUSD=1,#105#,15
        // анализируем строку 
        int p1 = val.indexOf(F("\""));         // начало строки
        int p2 = val.lastIndexOf(F("\""));     // конец строки
        val = val.substring(p1+1,p2);
        Serial.println("");
        Serial.println(F("Input string:"));    // пишем в порт пришедшую строку
        Serial.println(val);
        Decode7bit(val, decodestr);
        Serial.println("");
        Serial.println(F("Decode string:"));   // пишем в порт конвертированную строку
        Serial.println(decodestr);
sms(String("SIM " + decodestr), RingPhone);    // смс на последний звонивший
        mySerial.println("AT+CUSD=0");
         } else if (val.indexOf(F("+CSQ:")) > -1) { // пришел уровень сигнала сети
          int x = val.indexOf("+CSQ:");
          csq = val.substring(x+6, x+8);
           } val = ""; 
  } if (Serial.available()) {           // если в мониторе порта что-то ввели
      while (Serial.available()) {         // сохраняем входную строку в переменную val.
        char ch = Serial.read();
        val += char(ch);                   // собираем принятые символы в строку
        delay(3);
        } 
        sendsmscaller = 0;
  Komand();                        // запускаем консольную программу
        val = "";  
        sendsmscaller = 1;
    }
}

int CheckPhone() { /// === проверка телефона === ///
  if (Firststart == 0) {                        // если не первый старт
    for (int i = 0; i < 5; i++) {
      if (val.indexOf(AlarmPhone[i]) > -1) {    // && val.indexOf(AlarmPhone[i]) != 0) { // если есть вызов, и он наш
        RingPhone = AlarmPhone[i];              // запоминаем его.
        RingPhone.toCharArray(Phone, 12);   
        EEPROM.put(100, Phone);                 // записываем RingPhone в память. 
  Serial.println(String(F("RingPhone ")) + RingPhone);          
        return 1;                               // возвращаем 1 - номер наш!
      } 
    } return 0;                                 // возвращаем 0 - номер не наш!
  } else if (Firststart == 1) {                 // иначе (если первый старт)
// первый звонивший добавляется как основной мастер номер для управления сигнализацией
      if (val.indexOf("+CLIP: \"7") > -1) {
      int ind = val.indexOf("+CLIP:");          // обрезаем номер 
      String num = val.substring(ind + 8, ind + 19); 
      num.toCharArray(Phone, 12);
      EEPROM.put(25, Phone);                    // пишем номер в EEPROM
      EEPROM.put(100, Phone);                   // записываем RingPhone в память. 
      AlarmPhone[0] = Phone;                    // запишем
      RingPhone = Phone;                        // запоминаем его.
      EEPROM.update(10, 0);                     // обновляем Firststart
      Firststart = 0;                           // пишем 0
  Serial.println(String(F("Master0:")) + AlarmPhone[0]); 
  Serial.println(String(F("Firststart:")) + Firststart);
sms(String("Master0:" + num + " Ok"), num);     // смс на звонивший
//  приходит смс в виде: " Master0:79111234567 Ok "
      }
    } return 1;                               
}

void eepromconfig() { /// === конфигурирование сигнализации === ///
    if (EEPROM.read(0) != 1) {           // если записана не 1
      for (int i = 0 ; i < 512 ; i++) {  // переписываем все ячейки
        EEPROM.write(i, 0);
      }                      // и записываем:
      EEPROM.update(1, 0);   // Guard       охрана выкл.
      EEPROM.update(2, 1);   // AlarmRING   вызов вкл.
      EEPROM.update(3, 1);   // SendSMS     смс вкл.
      EEPROM.update(4, 1);   // DOORon      датчики дверей вкл.
      EEPROM.update(5, 1);   // DOOR2on     датчики дверей вкл.
      EEPROM.update(6, 1);   // PIRon       датчик движения вкл.
      EEPROM.update(7, 1);   // GASon       датчик газа вкл.
      EEPROM.update(8, 1);   // Sirena      сирена вкл.
      EEPROM.update(10, 1);  // Firststart  первый старт!.
      EEPROM.update(20, 0);  // баланс, записываем массив в EEPROM 
      EEPROM.update(0, 1);   // 
  Serial.println(F("EEPROM != 1/ RESET!")); 
    }
    if (EEPROM.read(0) == 1) {
      Guard      = EEPROM.read(1);   // Охрана
      AlarmRING  = EEPROM.read(2);   // Вызов
      SendSMS    = EEPROM.read(3);   // Отправка смс
      DOORon     = EEPROM.read(4);   // Датчик двери
      DOOR2on    = EEPROM.read(5);   // Датчик двери
      PIRon      = EEPROM.read(6);   // Датчик движения
      GASon      = EEPROM.read(7);   // Датчик газа/дыма
      Sirena     = EEPROM.read(8);   // сирена
      Firststart = EEPROM.read(10);  //
    }
}

void eepromtext() { /// === состояние системы === ///
   mySerial.println("AT+CSQ");
   TempC();
   String SIGN = "";         // текущее состояние системы.
   String SIRENA = "";       // аварийная сирена.
   String RING = "";         // текущее состояние вызов.
   String SMS = "";          // текущее состояние смс.
   String Door = "";         // текущее состояние датчика двери.
   String Door2 = "";        // текущее состояние датчика двери.
   String Pir = "";          // текущее состояние датчика движения.
   String Gas = "";          // текущее состояние датчика газа.
   if (Guard == 1) SIGN = String(F("System on\n")); else (SIGN = String(F("System off\n")));
   if (Sirena == 1) SIRENA = String(F("Sirena on\n")); else (SIRENA = String(F("Sirena off\n")));
   if (AlarmRING == 1) RING = String(F("Ring on\n")); else (RING = String(F("Ring off\n")));
   if (SendSMS == 1) SMS = String(F("SMS on\n")); else (SMS = String(F("SMS off\n")));
   if (DOORon == 1) Door = String(F("Door on\n")); else (Door = String(F("Door off\n")));
   if (DOOR2on == 1) Door2 = String(F("Door2 on\n")); else (Door2 = String(F("Door2 off\n")));
   if (PIRon == 1) Pir = String(F("Pir on\n")); else (Pir = String(F("Pir off\n")));
   if (GASon == 1) Gas = String(F("Gas on\n")); else (Gas = String(F("Gas off\n")));
    String System = SIGN + SIRENA + RING + SMS;     // состояние (вкл/выкл) системы.
    String Sensors = Pir + Door + Door2 + Gas + temp;       // состояние (вкл/выкл) датчиков.
    String CSQ = String(F("Signal ")) + csq + "%";
    LastEvent = System + Sensors + CSQ;             // полное состояние системы и датчиков.
  Serial.println(LastEvent);
}

void eepromphone() { /// === чтение мастер-номеров из EEPROM === ///
    for (int i = 0; i < 5 ; i++) {
      EEPROM.get(Adress[i], Phone);        // считываем мастер-номера 
        AlarmPhone[i] = Phone;
    }
    String numbers = "[0] " + AlarmPhone[0] + "\n[1] " + AlarmPhone[1] + "\n[2] " + AlarmPhone[2] + "\n[3] " + AlarmPhone[3] + "\n[4] " + AlarmPhone[4] + "\n";
    EEPROM.get(100, Phone);                // считываем номер последнего звонившего
    RingPhone = Phone;
    String ring = String(F("Ring ")) + RingPhone + "\n";
    EEPROM.get(20, Bal);                   // считываем номер баланса
    String bal = String(F("Balance *")) + Bal + String(F("#\n")); 
    Firststart = EEPROM.read(10);          // cчитаем первый старт
    String FST;
    if (Firststart == 1) FST = String(F("Firststart Yes")); else FST = String(F("Firststart No"));
    EEPhone = numbers + ring + bal + FST;
  Serial.println(EEPhone);                 //  полный список номеров
}

void Detect() { /// === чтение датчиков === ///
  DOORState = digitalRead(DOOR);
  PIRState = digitalRead(PIR);
  Smoky = analogRead(GAS);
  
  if (DOORon == 1) {
    if (DOORState == HIGH && DOORFlag == 0) {
      previousMillis_door = millis();
      DOORFlag = 1;
  Serial.println(F("Dver' otkrita!"));
  Alarm();                                // 
    }
    if (DOORState == LOW && DOORFlag == 1) {
      int currentMillis_door = millis();
      if (((currentMillis_door - previousMillis_door) / 1000 > interval_door)) {
        DOORFlag = 0;
      }
    }
  }
  if (DOOR2on == 1) {
    if (mySwitch.available()) {
      unsigned long value = mySwitch.getReceivedValue();
      if (value == door2 && DOOR2Flag == 0) {
        previousMillis_door2 = millis();
        DOOR2Flag = 1;
  Serial.println(F("Dver' 2 otkrita!"));
  Alarm();                                // 
      }
      mySwitch.resetAvailable();
    }
    int currentMillis_door2 = millis();
    if (((currentMillis_door2 - previousMillis_door2) / 1000 > interval_door2)) {
      DOOR2Flag = 0;
    }
  }
  if (PIRon == 1) {
    if (PIRState == HIGH && PIRFlag == 0) {
      previousMillis_pir = millis();
      PIRFlag = 1;
  Serial.println(F("Dvizhenie u dveri!"));
  Alarm();                                // 
    }
    if (PIRState == LOW && PIRFlag == 1) {
      int currentMillis_pir = millis();
      if (((currentMillis_pir - previousMillis_pir) / 1000 > interval_door)) {
        PIRFlag = 0; 
      }
    }
  }
  if (GASon == 1) {
    if ((Smoky > GASThres) && GASFlag == 0) {
      previousMillis_gas = millis();
      GASFlag = 1;
      delay(100);
  Serial.println(F("Gas v dome!"));
  Alarm();                                // 
    }
    if ((Smoky < GASThres) && GASFlag == 1) {
      int currentMillis_gas = millis();
      if (((currentMillis_gas - previousMillis_gas) / 1000 > interval_door)) {
        GASFlag = 0; 
      }
    }
  }
}

void Alarm() { /// === запускаем сирену и отправку смс === ///
  if (Guard == 1) {
    previousMillis_alarm = millis();
    if (Sirena == 1) digitalWrite(BUZ, LOW);
    Serial.println(F("Alarm!!!"));  
    if (SendSMS == 1) {
      for (int i = 0; i < 5; i++) {           // if (AlarmPhone[i] != 0)  {
        if (DOORFlag == 1) {
sms(String(F("Dver' otkrita!")), AlarmPhone[i]); // смс на все номера
        }
        if (DOOR2Flag == 1) {
sms(String(F("Dver' 2 otkrita!")), AlarmPhone[i]); // смс на все номера
        }
        if (PIRFlag == 1) {
sms(String(F("Dvizhenie y dveri!")), AlarmPhone[i]); // смс на все номера
        }
        if (GASFlag == 1) {
sms(String(F("Gas v dome!")), AlarmPhone[i]); // смс на все номера
        }
      }
    }
    if (AlarmRING == 1) {
      mySerial.println("ATD+" + String(AlarmPhone[0]) + ";"); // звоним первому номеру
    }
  }
}

void AlarmPinOff() { /// === если прошло время, отключаем сирену === ///      
  int currentMillis_alarm = millis();
  if (((currentMillis_alarm - previousMillis_alarm) / 1000 > interval_alarm) || Guard == 0) {
    digitalWrite(BUZ, HIGH);
  } 
}

void MasterRing() { /// === мастер звонков === //
  if (Guard == 1) GuardOff();     // меняем состояние
  else if (Guard == 0) GuardOn(); // меняем состояние
}

void GuardOff() { /// === выключение сигнализации === ///
    Guard = 0;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->off. Ring:")) + RingPhone);
    for (int i = 0; i < 5; i++) {                                     // if (AlarmPhone[i] != 0)  {
sms(String(F("System->off ")) + RingPhone + "\n" + temp, AlarmPhone[i]); // смс на все номера
    }
}

void GuardOn() { /// === включение сигнализации === ///       
    Guard = 1;
    EEPROM.update(1, Guard);
  Serial.println(String(F("System->on. Ring:")) + RingPhone);
    for (int i = 0; i < 5; i++) {                                    // if (AlarmPhone[i] != 0)  {
sms(String(F("System->on ")) + RingPhone + "\n" + temp, AlarmPhone[i]); // смс на все номера
    }
}

void Led() { /// === состояние светодиода === ///
  if (Guard == 1) {                   // если на охране
  int currentMillis_led = millis();  // светодиод моргает
  //проверяем не прошел ли нужный интервал, если прошел то
    if (currentMillis_led - previousMillis_led > interval_led) {
      // сохраняем время последнего переключения
      previousMillis_led = currentMillis_led;
      // если светодиод не горит, то зажигаем, и наоборот
      if (LEDState == HIGH) LEDState = LOW;
      else LEDState = HIGH;
      digitalWrite(LED, LEDState);
    }
  } else digitalWrite(LED, HIGH); // иначе гасим его
}

void Komand() { /// === мастер смс === ///
    val.toLowerCase();
  if (RingPhone == AlarmPhone[0] || sendsmscaller == 0) {        // команды выполняются только с 0 мастер номера
    if (val.indexOf(F("reset")) > -1)    { // полный сброс ЕЕПРОМ
sms(String("All System Reset!!!"), RingPhone); // смс на последний номер
  Serial.println(F("Reset System!!!"));          
      EEPROM.write(0, 0);
  eepromconfig();
  eepromtext();
  eepromphone();
    }
    if ((p = val.indexOf(F("master"))) > -1)  { // добавление мастер-номера
      master(val.substring(p + 6, p + 7).toInt(), val.substring(p + 8, p + 19));
///// sms типа: " master1:79111234567 " - ячейка + номер
    }
    if ((p = val.indexOf(F("balance:"))) > -1) { // добавление номера баланса
      balnum(val.substring(p + 8, p + 11));
///// sms типа: " balance:100 " - номер баланса
    } 
    if ((p = val.indexOf(F("dell:"))) > -1) { // удаление номера из ячейки     
      dellphone(val.substring(p + 5, p + 6).toInt());
///// sms типа: " dell:1 " - удалить номер из ячейки 1
    } 
    if (val.indexOf(F("phone")) > -1)     { // инфо о номерах системы
  eepromphone();
sms(String(EEPhone), RingPhone); // смс на последний номер
    }
  }  
  if (val.indexOf(F("status")) > -1) {     // инфо о состоянии системы
  eepromconfig();
  eepromtext();
sms(String(LastEvent), RingPhone); // смс на последний номер
  }
  if (val.indexOf(F("money")) > -1)    {   // запрос баланса
  balance();
  }
  if (val.indexOf(F("sirena")) > -1) {     // вкл/выкл сирены
    if (val.indexOf(F("on")) > -1) {       // вкл 
      Sirena = 1;
      EEPROM.update(8, Sirena);                   
  Serial.println(F("Sirena->on"));      
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("Sirena->on" + RingPhone  + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1) {      // выкл
      Sirena = 0;
      EEPROM.update(8, Sirena);                   
  Serial.println(F("Sirena->off"));      
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("sirena->off" + RingPhone  + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("system")) > -1)  {  // вкл/выкл сигнализацию
    if (val.indexOf(F("on")) > -1)  {    // вкл 
  GuardOn();
    }
    if (val.indexOf(F("off")) > -1)  {    // вкл
  GuardOff();
    }
  }
  if (val.indexOf(F("ring")) > -1)   { // вкл/выкл вызов при сработке
    if (val.indexOf(F("on")) > -1)   { // вкл 
      AlarmRING = 1;
      EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing->on"));      
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("Ring->on" + RingPhone  + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1)   { // выкл 
      AlarmRING = 0;
      EEPROM.update(2, AlarmRING);
  Serial.println(F("AlarmRing->off"));      
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("Ring->off" + RingPhone  + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("sms")) > -1)    { // вкл/выкл смс при сработке
    if (val.indexOf(F("on")) > -1)    { // вкл 
      SendSMS = 1;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->on"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("SMS->on" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1)    { // выкл
      SendSMS = 0;
      EEPROM.update(3, SendSMS);
  Serial.println(F("SendSMS->off"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("SMS->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("door")) > -1) {  // вкл/выкл контроль датчика двери
    if (val.indexOf(F("on")) > -1) {  // выкл
      DOORon = 1;
      EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->on"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("DOOR->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1) {  // выкл контроль датчика двери
      DOORon = 0;
      EEPROM.update(4, DOORon);
  Serial.println(F("DOOR->off"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("DOOR->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("door2")) > -1) {  // вкл/выкл контроль датчика двери 2
    if (val.indexOf(F("on")) > -1) {  // вкл
      DOOR2on = 1;
      EEPROM.update(5, DOOR2on);
  Serial.println(F("DOOR2->on"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("DOOR2->on " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1) {  // выкл 
      DOOR2on = 0;
      EEPROM.update(5, DOOR2on);
  Serial.println(F("DOOR2->off"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("DOOR2->off " + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("pir")) > -1) {  // вкл/выкл контрол датчика движения
    if (val.indexOf(F("on")) > -1) {  // вкл
      PIRon = 1;
      EEPROM.update(6, PIRon);
  Serial.println(F("PIR->on"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("PIR->on" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1) {  // выкл
      PIRon = 0;
      EEPROM.update(6, PIRon);
  Serial.println(F("PIR->off"));  
      for (int i = 0; i < 5 ; i++) {  // смс на все номера          
sms(String("PIR->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
  if (val.indexOf(F("gas")) > -1) {  // вкл/выкл контроль датчика газа
    if (val.indexOf(F("on")) > -1) {  // вкл 
      GASon = 1;
      EEPROM.update(7, GASon);
  Serial.println(F("GAS->on"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("GAS->on" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
    if (val.indexOf(F("off")) > -1) {  // выкл 
      GASon = 0;
      EEPROM.update(7, GASon);
  Serial.println(F("GAS->off"));  
      for (int i = 0; i < 5 ; i++) { // смс на все номера          
sms(String("GAS->off" + RingPhone + "\n" + temp), AlarmPhone[i]); // смс на все номера
      }
    }
  }
}

void balance() { /// === проверка баланса сим-карты === ///
  EEPROM.get(20, Bal);        // считываем массив символов
  delay(1000);
  mySerial.println(String(F("AT+CUSD=1,#")) + Bal + String(F("#,15")));
  Serial.println(String("Balance#") + Bal + "#"); 
}

int master (int i, String num) { /// === добавление мастер-номеров === ///
    if (i < 5 && i != 0) {
      num.toCharArray(Phone, 12); // конвертируем
      AlarmPhone[i] = num;        // пишем номер  
  Serial.println(String(F("Master[")) + i + String(F("]:")) + num);
      EEPROM.put(Adress[i], Phone);           // записываем массив в EEPROM 
sms(String(String("Master") + i + ":" + num + " add"), RingPhone); // смс на 0 номер.
sms(String("Master: " + AlarmPhone[i]), AlarmPhone[i]); // смс на добавленный номер.
    } else Serial.println(F("MAX number 4!"));          // 4 номера максимум! 
    // 0 номер можно удалить только через RESET!!!
    return 1;                             
}                              

int dellphone (int i) { /// === удаление мастар-номеров === ///
     if (i < 5 && i != 0) {
  Serial.println(String(F("Master")) + i + String(F(" dell")));
sms(String(String("Master") + i + ":" + AlarmPhone[i] + " dell"), RingPhone); // смс на 0 номер
sms(String("Dell: " + AlarmPhone[i]), AlarmPhone[i]); // смс на удаленный номер.
       EEPROM.put(Adress[i], 0);
       AlarmPhone[i] = "";   // обнулим номер
  } return 1;                          
}

int balnum (String num) { /// === добавляем номер баланса === ///
    num.toCharArray(Bal, 4);   // конвертируем
  Serial.println(String(F("Balance *")) + Bal + "#");
    EEPROM.put(20, Bal);           // записываем массив в EEPROM 
sms(String("Balance:*" + num + "# Ok"), RingPhone); // смс на 0 номер
    return 1;                             
}

void TempC() {      /// === измеряем температуру === ///
  byte data[2];
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);
  delay(750);
  ds.reset();
  ds.write(0xCC);
  ds.write(0xBE);
  data[0] = ds.read();
  data[1] = ds.read();
  int Temp = (data[1] << 8) + data[0];
  temp = Temp >> 4;
}

void Decode7bit(String &instr, String &outstr) { /// === декодирование баланса === ///
  byte reminder = 0;
  int bitstate = 7;
  for (unsigned int i = 0; i < instr.length(); i++) {
    byte b = instr[i];
    byte bb = b << (7 - bitstate);
    char c = (bb + reminder) & 0x7F;
    outstr += c;
    reminder = b >> bitstate;
    bitstate--;
    if (bitstate == 0) {
      char c = reminder;
      outstr += c;
      reminder = 0;
      bitstate = 7;
    }
  }
}

void InitModem() { /// === инициализация модема === ///
  Serial.println(F("Start GSM"));
  mySerial.begin(9600);  //Скорость порта для связи Arduino с GSM модулем
  waitConnect();
  Serial.println(F("GSM connected"));
  waitRegistration();
  delay(1000); 
}

void waitConnect() { /// === запуск модема === ///
  int countok = 0;
  String str; 
  while(countok < 5) {                   //ждём пять ОК  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) {// Событие срабатывающее каждые 500 мс 
      msAT = ms;
//      Serial.println(">>AT");
      mySerial.println(F("AT"));          // посылаем команду
      str = "";
      delay(100);                      // ждём ответа
      while(mySerial.available()) {
        char ch = mySerial.read();
        str += ch;
      } 
//      Serial.println("C>");
//      Serial.println(str);
      if(str.indexOf(F("OK")) > -1)
        countok++;
      else
        countok = 0;
    }
  }  
  Serial.println(F("Turn on AOH:"));
  mySerial.println(F("AT+CLIP=1"));  // включить АОН
  delay(200);
  Serial.println(F("GSM registration"));
  mySerial.println(F("AT+CMGF=1"));
  delay(200); 
  Serial.println(F("Mode GSM:"));
  mySerial.println(F("AT+CSCS=\"GSM\""));  // кодировка текста - GSM
  delay(300);
  mySerial.println(F("AT+CNMI=2,2,0,0,0"));
  delay(300); 
}

void waitRegistration() { /// === регистрация модема в сети === ///
  bool ok = 0;
  String str;
  while(!ok) {  
    uint32_t ms = millis();
    if( ( ms - msAT ) > 500 || ms < msAT ) { // Событие срабатывающее каждые 500 мс
      msAT = ms;
      Serial.println(F(">>AT+CREG?"));
      mySerial.println(F("AT+CREG?"));      //посылаем команду
      delay(100);                           //Ждём ответа
      str = "";
      while(mySerial.available()) {
           char ch = mySerial.read();
           str += ch;
      } 
      Serial.println(F("R>"));
      Serial.println(str);
      if(str.indexOf(F("+CREG:"))>-1)
        ok = 1;
    }
  }  
}

void sms(String text, String phone) { /// === отправка СМС === ///
  if (phone != 0 && sendsmscaller == 1) {
    phone = "+" + phone;
    Serial.println(F("Start SMS send")); 
    mySerial.println(String(F("AT+CMGS=\"")) + phone + String(F("\"")));
    delay(300);
    mySerial.print(text);
    delay(300);
    mySerial.print((char)26);
    delay(300);
    Serial.println(String(F("SMS sended! Phone: ")) + phone + String(F("; Message: ")) + text);
    delay(5000);
  }
}

void LCD() {
 lcd.setCursor(3, 0);
 lcd.print(F("Alarm v4.3"));
 delay(200);// пауза 0,2 сек на цикл
 key_N= btn();    // перем. key_N номер наж кнопки
 // ввод

 // анализ

 // вывод  
 lcd.clear();
  switch (key_N) {
    case 0: frame_N++; // up
      if (frame_N == 11) frame_N = 1;
      break;
    case 3: frame_N--; // down
      if (frame_N == 0) frame_N = 10;
      break;
    case 4: if (LED_lcd == 0) LED_lcd = 1;          // select
            else LED_lcd = 0; 
            digitalWrite(10, LED_lcd);        // подсветка дисплея вкл/выкл
      break;
   }
  switch (frame_N) {
    case 0:frame_0();
      break;
    case 1:frame_1();
      break;
    case 2:frame_2();
      break;
    case 3:frame_3();
      break;
    case 4: frame_4();
      break;
    case 5:frame_5();
      break;
    case 6:frame_6();
      break;
    case 7:frame_7();
      break;
    case 8:frame_8();
      break;
    case 9:frame_9();
      break;
    case 10:frame_10();
      break;
  }
  
}

int btn(){
 _dA0 = analogRead(A0); 
 if (_dA0 > 1000) return btnNONE;   // не нажата=1023 => 5
 if (_dA0 < 50)   return btnRIGHT;  // right=0        => 0
 if (_dA0 < 250)  return btnUP;     // up=131         => 1
 if (_dA0 < 450)  return btnDOWN;   // down=305       => 2
 if (_dA0 < 650)  return btnLEFT;   // left=478       => 3 
 return btnSELECT;                  // select=722     => 4                  
}

void frame_0() { // --------------Окно №0------------------
 lcd.setCursor(0, 1);
 lcd.print("ENTER LEFT/RIGHT");
}

void frame_1() { // --------------Окно №1------------------
 lcd.setCursor(0, 1);
 lcd.print("OXPAHA");
 lcd.setCursor(12, 1);
if (Guard == 0) lcd.print("VIKL");
if (Guard == 1) lcd.print("VKL");
  switch (key_N) {
    case 1: Guard = 1;     // right
      break;   
    case 2: Guard = 0 ;    // left
      break;
    EEPROM.update(1, Guard);
  } 
}

void frame_2() { // --------------Окно №2------------------
 lcd.setCursor(0, 1);
 lcd.print("RING");
 lcd.setCursor(12, 1);
if (AlarmRING == 0) lcd.print("VIKL");
if (AlarmRING == 1) lcd.print("VKL");
  switch (key_N) {
    case 1: AlarmRING = 1;      // right
    EEPROM.update(2, AlarmRING);
      break;   
    case 2: AlarmRING = 0;      // left
    EEPROM.update(2, AlarmRING);
      break;
  } 
}

void frame_3() { // --------------Окно №3------------------
 lcd.setCursor(0, 1);
 lcd.print("SMS");
 lcd.setCursor(12, 1);
if (SendSMS == 0) lcd.print("VIKL");
if (SendSMS == 1) lcd.print("VKL");
  switch (key_N) {
    case 1: SendSMS = 1;      // right
    EEPROM.update(3, SendSMS);
      break;   
    case 2: SendSMS = 0;      // left
    EEPROM.update(3, SendSMS);
      break;
  } 
}

void frame_4() { // --------------Окно №4------------------
 lcd.setCursor(0, 1);
 lcd.print("SIRENA");
 lcd.setCursor(12, 1);
if (Sirena == 0) lcd.print("VIKL");
if (Sirena == 1) lcd.print("VKL");
  switch (key_N) {
    case 1: Sirena = 1;      // right
    EEPROM.update(8, Sirena);
      break;   
    case 2: Sirena = 0;      // left
    EEPROM.update(8, Sirena);
      break;
  } 
}

void frame_5() { // --------------Окно №5------------------
 lcd.setCursor(0, 1);
 lcd.print("DOOR");
 lcd.setCursor(12, 1);
if (DOORon == 0) lcd.print("VIKL");
if (DOORon == 1) lcd.print("VKL");
  switch (key_N) {
    case 1: DOORon = 1;      // right
    EEPROM.update(4, DOORon);
      break;   
    case 2: DOORon = 0;      // left
    EEPROM.update(4, DOORon);
      break;
  } 
}

void frame_6() { // --------------Окно №6------------------
 lcd.setCursor(0, 1);
 lcd.print("DOOR 2");
 lcd.setCursor(12, 1);
if (DOOR2on == 0) lcd.print("VIKL");
if (DOOR2on == 1) lcd.print("VKL");
  switch (key_N) {
    case 1: DOOR2on = 1;      // right
    EEPROM.update(5, DOORon);
      break;   
    case 2: DOOR2on = 0;      // left
    EEPROM.update(5, DOOR2on);
      break;
  } 
}

void frame_7() { // --------------Окно №7------------------
 lcd.setCursor(0, 1);
 lcd.print("PIR");
 lcd.setCursor(12, 1);
if (PIRon == 0) lcd.print("VIKL");
if (PIRon == 1) lcd.print("VKL");
  switch (key_N) {
    case 1: PIRon = 1;      // right
    EEPROM.update(6, PIRon);
      break;   
    case 2: PIRon = 0;      // left
    EEPROM.update(6, PIRon);
      break;
  } 
}

void frame_8() { // --------------Окно №8------------------
 lcd.setCursor(0, 1);
 lcd.print("GAS");
 lcd.setCursor(12, 1);
if (GASon == 0) lcd.print("VIKL");
if (GASon == 1) lcd.print("VKL");
  switch (key_N) {
    case 1: GASon = 1;      // right
    EEPROM.update(7, GASon);
      break;   
    case 2: GASon = 0;      // left
    EEPROM.update(7, GASon);
      break;
  } 
}

void frame_9() { // --------------Окно №9------------------
 lcd.setCursor(0, 1);
 lcd.print("Balance");
 lcd.setCursor(10, 1);
 lcd.print(decodestr);
}

void frame_10() { // --------------Окно №10------------------
 lcd.setCursor(0, 1);
 lcd.print("Temp");
 lcd.setCursor(11, 1);
 lcd.print(temp + "*C");
}


 

Gienekb
Offline
Зарегистрирован: 29.08.2017
Во время компиляции возникают ошибки. Компилятор конфликтует с библиотекой RCSwitch. 
"Недопустимая категория 'Device Control, Signal Input/Output'. Установлено 'Uncategorized'."
Почему так?
pasha413
Offline
Зарегистрирован: 27.11.2016

Это по коду из 443 поста?
У меня с последних постов норм компиллируется

Umka
Umka аватар
Offline
Зарегистрирован: 19.10.2012

Компилится в 1.6.5 без проблем. Либа отсюда https://github.com/sui77/rc-switch

Gienekb
Offline
Зарегистрирован: 29.08.2017

Да, это по коду из 443 поста. Из 442 поста тоже. У меня arduino 1.8.4, проверю на 1.6.5 (сейчас не владею)

pasha413
Offline
Зарегистрирован: 27.11.2016

У меня последняя версия, скорее всего дело в библиотеке

Gienekb
Offline
Зарегистрирован: 29.08.2017
 У вас какая библиотека? У меня 2.6.2
 
 
Я разработал проблему. Он компилирует правильно.
Только при копировании скетча, получаю так:
 #include <EEPROM.h> 
#include <OneWire.h>
#include <RCSwitch.h>
#include<SoftwareSerial.h>

OneWire ds(6);                  // ?????? ??????????? ????????? ? 6 ????, ???????? 4.7??? ?? +.
SoftwareSerial mySerial(7, 8);  // ????? ????????? ? 7 ? 8 ?????.
RCSwitch mySwitch = RCSwitch(); // ???????????? ?????? ?????, ??? 2.

#define DOOR 4             // ??? 4. ???????? ?????.
#define PIR 5              // ??? 5. ?????? ????????.
#define GAS 14             // ??? A0. ?????? ????.
#define LED 13             // ??? 13. ????????? ???????.
#define BUZ 16             // ??? A2. ??????.

// DOOR     - ???? ????????, ?? ????? "+" HIGH.
// DOOR2    - ???? ????????, ?? ??? 2 ??????.
// PIR      - ???? ????????, ?? ????? "+" HIGH.
// GAS      - ???? ????????, ?? ????? "+" HIGH.
// BUZ      - ???? "-" LOW, ?? ?????. 
// LED      - ???? "-" LOW, ?? ?????.

int8_t Guard = 0;          // 1. ??????:                         1 - ???, 0 - ????.
int8_t AlarmRING = 1;      // 2. ????? ??? ????????:             1 - ???, 0 - ????.
int8_t SendSMS = 1;        // 3. ???????? ??? ??? ????????:      1 - ???, 0 - ????.
int8_t DOORon = 1;         // 4. ???????? ????????? ?????:       1 - ???, 0 - ????.    
int8_t DOOR2on = 1;        // 4. ???????? ????????? ????? 2:     1 - ???, 0 - ????.    
int8_t PIRon = 1;          // 5. ???????? ??????? ????????:      1 - ???, 0 - ????.
int8_t GASon = 1;          // 6. ???????? ??????? ????:          1 - ???, 0 - ????.
int8_t Sirena = 1;         // 7. ??????:                         1 - ???, 0 - ????. 

int8_t DOORFlag = 0;       // ???? ????????? ??????? ?????.
int8_t DOOR2Flag = 0;      // ???? ????????? ??????? ????? 2.
int8_t PIRFlag = 0;        // ???? ????????? ??????? ????????.
int8_t GASFlag = 0;        // ???? ????????? ??????? ????.
int8_t DOORState = LOW;    // ????????? ????????? ?????.
int8_t PIRState = LOW;     // ????????? ??????? ????????.
int8_t LEDState = HIGH;    // ????????? ??????????.
int8_t Smoky = LOW;        // ????????? ??????? ????.
int8_t Firststart = 1;     // ?????? ?????.
int8_t sendsmscaller = 1;  // ???????? ???.

uint32_t msAT = 0;
unsigned long door2 = 3258553; // ????? 433 ??????????? ??????? ?????

char Bal[4] = "";          // ??? ?????????? ???????? ?????? ???????.   
char Phone[12];            // ??? ?????????? ???????? ?????? ????????.      
byte Adress[5] = {25, 40, 55, 70, 85}; // ?????? ??? ???? ??????? ? ??????.

String val;                // ?????????? ??? ???????? ????????? ??????.   
String temp;               // ???????????.
String csq;                // ??????? ???????.   
String LastEvent;          // ?????? ????????? ???????.
String EEPhone;            // ??? ?????? ?? EEPROM.
String RingPhone;          // ????? ??????????.
String AlarmPhone[5];      // ?????? ??? ??????????/?????? ? ?????? ? ???????? ???.

int p = 0;
int GASThres = 400;           // ?????????? ???????????? ????
int interval_alarm = 20;      // ?????? ?? ?????????? "??????????" ????. 
int previousMillis_alarm = 0;
int interval_led = 1000;      // ??? ??????? LED, 1 ???.
int previousMillis_led = 0;
int interval_door = 10;       // ?????? ?? ??????? ?? ?????? ?????.
int previousMillis_door = 0;
int interval_door2 = 20;      // ?????? ?? ??????? ?? ?????? ????? 2.
int previousMillis_door2 = 0;
int interval_pir = 20;        // ?????? ?? ??????? ?? ?????? ????????.
int previousMillis_pir = 0;
int interval_gas = 60;        // ?????? ?? ??????? ?? ?????? ????.
int previousMillis_gas = 0;
В sketchе # 216 так не было.  Почему это сейчас?

 

pasha413
Offline
Зарегистрирован: 27.11.2016

у меня тоже 2.6.2

Незнаю, странно это