GSM устройство управления котлами Webasto и не только

Dushman7776
Offline
Зарегистрирован: 13.01.2019

 Команду на стирание ошибки 92 , подавал много раз  в разных режимах работы котла , и в режиме прогрева и в режиме выключения пока продувка шла .и в спящем режиме. Все время не было ответа от котла.

MaksVV
Offline
Зарегистрирован: 06.08.2015

вообще то , судя по логу котел как будто не знает команду нп запрос стирания ошибок 56 03. но все таки отвечает байтом 7F. Так чтотответ ответ от котла на запрос стирания ошибок есть, просто этот ответ отрицательный. Может если с WTT стирать тоже самое будет? 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

WWT нормально стирает, сразу , в прошлый раз у меня тоже эта ошибка вылезла, я  не знаю почему, может девайс зависает, я сегдня утром подал команду на запуск и пошел в гараж, ответные смс приходили что включена и вторая что все ок, а потом минут через 20 я захотел посмотреть температуру , уже на подходе к гаражу , и в этот раз ответной смс не было , когда я пришел в гараж вебаста была выключена , но температура была всего 66 градусов, короче она почему то выключилась сама , недограв двигатель . и вылезла эта ошибка 92 ,  сечас пишет что не активная, но не стирает , в прошлый раз было так же , потом я пробовал подключтитья ваг комом , вылезла ошибка 3А , я отправил смс на стирание и ошибки стрерлись с первого раза. Я понял что нужно попробывать снять лог стирания WTT .

MaksVV
Offline
Зарегистрирован: 06.08.2015

Тут #635 так и не нашел в логе стирание ошибок. Может лог слишком длинный. Сделай короткий лог со стиранием ошибок с WTT

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Как сделать что бы эти ошибки появились , у меня котел установлен так что снять какой нибудь разъем не  реально , пол машины надо разобрать. защиты снимать , сечас есть эта ошибка 92 , попробую подключить WWT  и сразу стереть ее , ничего больше не делать . В том логе небыло ошибок , я в программе нажимал стереть ошибки , но если их нет может прога и не посылала  команду на стирание.

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Да было такое, было 2 ошибки 92 и 3а , послал команду когда котел продувался после прогрева .

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Вот лог общения WTT с котлом , подключил , удалил ошибку 3А (специально шину на массу замыкал) и отключился.

Протоколирование включено: 25.02.19 18:26:41
Диагностирование включено: 25.02.19 18:27:02
W-шина
Активирование ...
Tx: F4 03 51 0A AC 
Rx: 4F 04 D1 0A 40 D0 
Rx: 44 03 C4 3A B9 
Rx: 44 03 C4 3A B9 
Tx: F4 03 51 31 97 
Rx: 4F 12 D1 31 01 0F 17 06 03 04 05 07 08 0B 0C 0D 0E 10 12 A9 
Tx: F4 12 51 30 01 0F 17 06 03 04 05 07 08 0B 0C 0D 0E 10 12 93 
Rx: 4F 86 D1 30 01 39 30 31 39 36 32 39 4A 31 33 00 00 00 00 00 00 00 00 00 00 00 0F 39 30 32 34 33 34 39 41 30 31 00 00 00 00 00 00 00 00 00 00 00 17 39 30 31 39 38 32 37 42 30 37 00 00 00 00 00 00 00 00 00 00 00 06 31 33 31 38 30 35 30 42 30 32 00 00 00 00 00 00 00 00 00 00 00 03 05 17 11 04 08 01 05 08 01 00 07 FF FF FF 08 25 10 13 0B 13 20 32 81 98 0C 43 42 0D 40 0E 54 54 45 56 4F 20 31 47 10 0B 12 7D C1 
Tx: F4 03 50 31 96 
Rx: 4F 44 D0 31 01 02 03 04 0A 0C 0E 10 12 13 14 15 16 19 1A 1D 1E 1F 20 21 22 23 24 25 28 2A 2B 2C 2F 32 33 34 50 51 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73 74 75 76 97 
Tx: F4 03 51 0C AA 
Rx: 4F 0A D1 0C 79 7C E4 23 04 00 00 5E 
Tx: F4 02 38 CE 
Rx: 4F 0B B8 0B 00 00 02 AF 00 00 03 30 69 
Tx: F4 03 51 09 AF 
Rx: 4F 0A D1 09 13 20 32 81 98 43 42 84 
Tx: F4 03 53 02 A6 
Rx: 4F 11 D3 02 2A F8 00 00 FF FE 14 3E 80 00 00 FF FE 05 F2 
Tx: F4 03 57 01 A1 
Rx: 4F 06 D7 01 85 01 FF E4 
Tx: F4 21 50 30 01 02 03 04 0A 0C 0E 10 12 13 1D 1E 1F 23 24 28 2A 2C 32 33 34 51 58 59 5A 5F 60 61 74 75 FD 
Rx: 4F 50 D0 30 01 00 02 00 03 00 04 00 0A 00 0C 3E 0E 30 F2 10 00 12 00 13 01 01 1D 00 00 1E 00 00 1F 00 23 00 24 00 28 71 2A 01 2C 00 32 00 33 00 34 04 1A 51 00 00 00 58 00 94 31 59 00 00 00 5A 00 88 1E 5F 01 63 60 01 63 61 00 00 74 00 75 00 00 16 
Tx: F4 03 56 01 A0 
Rx: 4F 07 D6 01 01 3A 01 01 A4 
Tx: F4 21 50 30 01 02 03 04 0A 0C 0E 10 12 13 1D 1E 1F 23 24 28 2A 2C 32 33 34 51 58 59 5A 5F 60 61 74 75 FD 
Rx: 4F 50 D0 30 01 00 02 00 03 00 04 00 0A 00 0C 3E 0E 30 F2 10 00 12 00 13 01 01 1D 00 00 1E 00 00 1F 00 23 00 24 00 28 71 2A 01 2C 00 32 00 33 00 34 04 1A 51 00 00 00 58 00 94 31 59 00 00 00 5A 00 88 1E 5F 01 63 60 01 63 61 00 00 74 00 75 00 00 16 
Tx: F4 03 56 01 A0 
Rx: 4F 07 D6 01 01 3A 01 01 A4 
Tx: F4 21 50 30 01 02 03 04 0A 0C 0E 10 12 13 1D 1E 1F 23 24 28 2A 2C 32 33 34 51 58 59 5A 5F 60 61 74 75 FD 
Rx: 4F 50 D0 30 01 00 02 00 03 00 04 00 0A 00 0C 3E 0E 30 F2 10 00 12 00 13 01 01 1D 00 00 1E 00 00 1F 00 23 00 24 00 28 71 2A 01 2C 00 32 00 33 00 34 04 1A 51 00 00 00 58 00 94 31 59 00 00 00 5A 00 88 1E 5F 01 63 60 01 63 61 00 00 74 00 75 00 00 16 
Tx: F4 03 56 01 A0 
Rx: 4F 07 D6 01 01 3A 01 01 A4 
Tx: F4 21 50 30 01 02 03 04 0A 0C 0E 10 12 13 1D 1E 1F 23 24 28 2A 2C 32 33 34 51 58 59 5A 5F 60 61 74 75 FD 
Rx: 4F 50 D0 30 01 00 02 00 03 00 04 00 0A 00 0C 3E 0E 30 F2 10 00 12 00 13 01 01 1D 00 00 1E 00 00 1F 00 23 00 24 00 28 71 2A 01 2C 00 32 00 33 00 34 04 1A 51 00 00 00 58 00 94 31 59 00 00 00 5A 00 88 1E 5F 01 63 60 01 63 61 00 00 74 00 75 00 00 16 
Tx: F4 03 56 01 A0 
Rx: 4F 07 D6 01 01 3A 01 01 A4 
Tx: F4 03 56 03 A2 
Rx: 4F 03 D6 03 99 
Tx: F4 03 56 01 A0 
Rx: 4F 04 D6 01 00 9C 
Tx: F4 21 50 30 01 02 03 04 0A 0C 0E 10 12 13 1D 1E 1F 23 24 28 2A 2C 32 33 34 51 58 59 5A 5F 60 61 74 75 FD 
Rx: 4F 50 D0 30 01 00 02 00 03 00 04 00 0A 00 0C 3E 0E 30 F2 10 00 12 00 13 01 01 1D 00 00 1E 00 00 1F 00 23 00 24 00 28 71 2A 00 2C 00 32 00 33 00 34 04 1A 51 00 00 00 58 00 94 31 59 00 00 00 5A 00 88 1E 5F 01 63 60 01 63 61 00 00 74 00 75 00 00 17 
Rx: 44 03 C4 00 83 
Rx: 44 03 C4 00 83 
Tx: F4 03 56 01 A0 
Rx: 4F 04 D6 01 00 9C 
Tx: F4 21 50 30 01 02 03 04 0A 0C 0E 10 12 13 1D 1E 1F 23 24 28 2A 2C 32 33 34 51 58 59 5A 5F 60 61 74 75 FD 
Rx: 4F 50 D0 30 01 00 02 00 03 00 04 00 0A 00 0C 3E 0E 30 F2 10 00 12 00 13 01 01 1D 00 00 1E 00 00 1F 00 23 00 24 00 28 71 2A 00 2C 00 32 00 33 00 34 04 1A 51 00 00 00 58 00 94 31 59 00 00 00 5A 00 88 1E 5F 01 63 60 01 63 61 00 00 74 00 75 00 00 17 
Tx: F4 03 56 01 A0 
Rx: 4F 04 D6 01 00 9C 
Tx: F4 21 50 30 01 02 03 04 0A 0C 0E 10 12 13 1D 1E 1F 23 24 28 2A 2C 32 33 34 51 58 59 5A 5F 60 61 74 75 FD 
Rx: 4F 50 D0 30 01 00 02 00 03 00 04 00 0A 00 0C 3E 0E 30 F2 10 00 12 00 13 01 01 1D 00 00 1E 00 00 1F 00 23 00 24 00 28 71 2A 00 2C 00 32 00 33 00 34 04 1A 51 00 00 00 58 00 94 31 59 00 00 00 5A 00 88 1E 5F 01 63 60 01 63 61 00 00 74 00 75 00 00 17 
Tx: F4 03 56 01 A0 
Rx: 4F 04 D6 01 00 9C 
Tx: F4 21 50 30 01 02 03 04 0A 0C 0E 10 12 13 1D 1E 1F 23 24 28 2A 2C 32 33 34 51 58 59 5A 5F 60 61 74 75 FD 
Rx: 4F 50 D0 30 01 00 02 00 03 00 04 00 0A 00 0C 3E 0E 30 F2 10 00 12 00 13 01 01 1D 00 00 1E 00 00 1F 00 23 00 24 00 28 71 2A 00 2C 00 32 00 33 00 34 04 1A 51 00 00 00 58 00 94 31 59 00 00 00 5A 00 88 1E 5F 01 63 60 01 63 61 00 00 74 00 75 00 00 17 
Tx: F4 03 56 01 A0 
Rx: 4F 04 D6 01 00 9C 
Tx: F4 21 50 30 01 02 03 04 0A 0C 0E 10 12 13 1D 1E 1F 23 24 28 2A 2C 32 33 34 51 58 59 5A 5F 60 61 74 75 FD 
Rx: 4F 50 D0 30 01 00 02 00 03 00 04 00 0A 00 0C 3E 0E 30 F2 10 00 12 00 13 01 01 1D 00 00 1E 00 00 1F 00 23 00 24 00 28 71 2A 00 2C 00 32 00 33 00 34 04 1A 51 00 00 00 58 00 94 31 59 00 00 00 5A 00 88 1E 5F 01 63 60 01 63 61 00 00 74 00 75 00 00 17 
Tx: F4 03 56 01 A0 
Rx: 4F 04 D6 01 00 9C 
Tx: F4 21 50 30 01 02 03 04 0A 0C 0E 10 12 13 1D 1E 1F 23 24 28 2A 2C 32 33 34 51 58 59 5A 5F 60 61 74 75 FD 
Диагностирование окончено: 25.02.19 18:27:30
Rx: 4F 50 
Истечение времени ожидания!
---

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

вот тут все четко . Строка 39 считываем ошибки F4 03 56 01 A0  получаем ответ стр40  4F 07 D6 01 01 3A 01 01 A4

 потом удаляем ошибки стр41.     F4 03 56 03 A2   получаем ответ стр42  4F 03 D6 03 99

Строка 43 опять считываем ошибки F4 03 56 01 A0  получаем ответ стр44 4F 04 D6 01 00 9C всё, ошибок нет. 

 

Я так и делаю в своем скетче. Почему не работает, хз. Попробуй удалить ошибки когда их нет в памяти. Будет ли при этом в шине запрос на удаление ошибок F4 03 56 03 A2 ?

MaksVV
Offline
Зарегистрирован: 06.08.2015

по идее наверное 7F ом должен ответить  на запрос удаления ошибок, если ошибок и так  нет в памяти. Хотя судя по логу #700, ошибка 92 впамяти присутсвовала,  а на запрос удаления 56 03 он отвечал 7F (что значит неизвестный запрос). 

Хрень какаято. Делаем абсолютно тоже самое что и WTT, только у WTT выходит, а у нас нет. 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Я по своему логу , сделанному андроидом вообще понять не могу где там команды , почему то нет этих F4  и 4F  в запросах и ответах , ихъ что не посылает девайс , может из за этого ? 

MaksVV
Offline
Зарегистрирован: 06.08.2015

да просто там он коряво режет сообщения , либо вообщене режет . в середине где нибудь их ищи

MaksVV
Offline
Зарегистрирован: 06.08.2015

либо ты не настроил 2400 8E1

Dushman7776
Offline
Зарегистрирован: 13.01.2019

А где там F7 не вижу что то?

Dushman7776
Offline
Зарегистрирован: 13.01.2019

В настройках порта в программе ставил 2400 8 бит 1 стоп и контроль четности , не знаю почему так там коряво .

MaksVV
Offline
Зарегистрирован: 06.08.2015

Dushman7776 пишет:

А где там F7 не вижу что то?

  не F7, а 7F.  Ищи ctrl+F команду 56 03. после неё увидишь ответ с 7F

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

В данном варианте к-лайн часть нужно подключить не к конвертеру юсб-уартТТЛ, а к ардуиине

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Не про мини нет , заказал парачку , едут с Китая , есть только нано и про микро. ААА понял , получится еще одна ардуино между клайном и юсб конвретером , тогда можно и для нано сделать скетч. А где в  сегоднешнем логе 7F ? 

MaksVV
Offline
Зарегистрирован: 06.08.2015

дак да, нано и надо. В сегодняшнем логе не было 7F. Поэтому я и сказал, что всё чётко. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

дак да, нано и надо. В сегодняшнем логе не было 7F. Поэтому я и сказал, что всё чётко. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

дак да, нано и надо. В сегодняшнем логе не было 7F. Поэтому я и сказал, что всё чётко. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

дак да, нано и надо. В сегодняшнем логе не было 7F. Поэтому я и сказал, что всё чётко. 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

На скетче 3.62 ,не работает сим 800 , при звонке на сим 800 робот отвечает что не в сети , а должен быть занят, потом приходит смс что абанент в сети , но при звонке опять нет в сети, и смс не доходят.

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Ни че не понимаю .  Прошил скетч 3.60 и та же байда . Sim800 не находит сети , вернее как то коряво работает, при звонке на модем, робот отвечает что абонент не в сети ,  и тут же приходит смс что абонент доступен, звоню снова опять не в сети ,если вытащить ардуину из панельки , то  идут длинные гудки. Я сегдня на рабочий ноут поставил ардуино иде , и  с него шил , но программа как то странно компилирует , нет лога компиляции в нижнем окне, а потом говорит что загрузка завершина , я 4 раза прошивал 3.60 и ни чего не изменилось. Утром когда проверял скетч 3.62 так же было , что за глюк.

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Ни че не понимаю .  Прошил скетч 3.60 и та же байда . Sim800 не находит сети , вернее как то коряво работает, при звонке на модем, робот отвечает что абонент не в сети ,  и тут же приходит смс что абонент доступен, звоню снова опять не в сети ,если вытащить ардуину из панельки , то  идут длинные гудки. Я сегдня на рабочий ноут поставил ардуино иде , и  с него шил , но программа как то странно компилирует , нет лога компиляции в нижнем окне, а потом говорит что загрузка завершина , я 4 раза прошивал 3.60 и ни чего не изменилось. Утром когда проверял скетч 3.62 так же было , что за глюк.

MaksVV
Offline
Зарегистрирован: 06.08.2015

tx и rx SIM800 через делители подключены?  если нет  возможно уже глюканул Сим800. 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

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

Dushman7776
Offline
Зарегистрирован: 13.01.2019

попробую еще прозвонить может он постоянных выдергиваний ардуино контакты где пропали . можно еще в терминале сим 800 проверить ат командами.

Dushman7776
Offline
Зарегистрирован: 13.01.2019

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

MaksVV
Offline
Зарегистрирован: 06.08.2015

потому что с ардуиной идёт настройка при старте скетча на отключение входящих вызовов. 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Я видел в скетче строку в функции настройка сим , запрет входящих , но раньше при звонке на модем было занято постоянно , а теперь абонент вне зоны доступа, почему и это было на скетче 3.60 и на 3.50 , после прошивки 3.62 первый раз тоже не работал модем , потом откатился , стало все по старому, а сегодня уторм я проверял 3.62 , он не заработал , откатился на 3.60  на работе все равно не в сети и смски на принимал и не отвечал , а дома прошил все по новой вместе с перепрошивкой епрома , в итоге на смски отвечает, вбил свой номер , котлом управляет, но все равно, при звонке на модем , робот отвечает что не в сети и  если машина в закрытом гараже не удается послать команду на запуск, как будто уровень сигнала очень слабый. Но команды на проверку уровня сигнала в девайсе нет. Вот и гадай слабый сигнал или глюк какой то.

MaksVV
Offline
Зарегистрирован: 06.08.2015

к 3.60 добавил запрос уровня сигнала GSM командой Signal-level

v3.61

char ver[] = "Firmware 3.61";    // версия прошивки



//----------------------------------название ячеек еепром----------------------------------------------------------------
#include <EEPROM.h>
enum Cells {
ResetNumber_cell,      //0
TimeWebasto_cell,      //1
ProtocolSTART_cell,    //2
StartByte_cell,        //3
ProtocolSTATUS_cell,   //4
Heater_cell,           //5
delta_cell,            //6
TelNumber1_cell =20,  //20
TelNumber2_cell =40   //40
};


//-------------------------------------для voltmetr-----------------------------------------------------------------------
                                   
float vout = 0.0;      // Напряжение на входе аналового входа
float Vpit = 0.0;      // Измеряемое напряжение на выходе ИБП
  int volt = 0;        // Напряжение на входе АЦП


//------------------- распиновка ног ардуино (плата весий 8.5-8.8)--------------------------------------------------------

#define OutWebasto_12V      2  // это +12В выход потенциала вкл/выкл вебасто (напрямую к котлу без таймера). 
#define Dallas_pin          3  // пин шины OneWire для датчиков даллас
#define DopOn               4  // сюда доп канал от сигналки на включение вебасто
#define DopOff              5  // сюда доп канал от сигналки на выключение вебасто
#define Ohrana              6  // Сюда состояние охраны сигналки
#define Trevoga             7  // Сюда состояние тревоги
#define IGN                 8  // Сюда состояние зажигания
#define Sost                9  // Сюда состояние вебасто (+12В когда работает)
#define ResetGSM           12  // пин ресета GSM подключен к реле, разрывающее питание модуля. 
#define Eng                14  // (А0) Сюда состояние работы ДВС
#define StatusWebastoLED   15  // (А1) пин LED  индикация включенности котла
#define StartButtonpin     16  // (А2) пин тактовой кнопки вкл/выкл котла 
#define DTR                17  // пин (А3), управляющий энергосберегающим режимом GSM модуля
#define StartEng           18  // (A4) это импульсный минусовой выход вкл/выкл ДВС. подключать на вход событий сиги.
#define OutWebasto_GndImp  19  // (A5) это импульсный минусовой выход вкл/выкл вебасто (к впайке к кнопке таймера).  
#define Voltmeter_pin      A7  // пин, которым измеряем напряжение питания
#define StartButton         0  // программный номер тактовой кнопки вкл/выкл котла 
const bool RelayON =        1; // логика управления реле ресета GSM, в данном случае включается высоким уровнем на пине
#define GSM_RX             10  // пин софт RX Arduino для соединения с TX модуля SIM800
#define GSM_TX             11  // пин софт TX Arduino для соединения с RX модуля SIM800

/*
//------------------- распиновка ног ардуино (плата весий 5)---------------------------------------------------------------

#define Dallas_pin          2  // пин шины OneWire для датчиков даллас
#define OutWebasto_12V      3  // это +12В выход потенциала вкл/выкл вебасто (напрямую к котлу без таймера). 
#define DopOn               4  // сюда доп канал от сигналки на включение вебасто
#define DopOff              5  // сюда доп канал от сигналки на выключение вебасто
#define Ohrana              6  // Сюда состояние охраны сигналки
#define Trevoga             7  // Сюда состояние тревоги
#define StartEng            8  // это импульсный минусовой выход вкл/выкл ДВС. подключать на вход событий сиги.
#define Sost                9  // Сюда состояние вебасто (+12В когда работает)
#define IGN                10  // Сюда состояние зажигания
#define Eng                11  // Сюда состояние работы ДВС
#define OutWebasto_GndImp  12  // это импульсный минусовой выход вкл/выкл вебасто (к впайке к кнопке таймера). 
#define StatusWebastoLED   13  // пин индикация включенности котла
#define ResetGSM           16  // пин ресета GSM (A2) подключен к реле, разрывающее питание модуля. 
#define StartButtonpin     17  // пин тактовой кнопки вкл/выкл котла 
#define DTR                19  // пин (А5), управляющий энергосберегающим режимом GSM модуля
#define StartButton         0  // программный номер тактовой кнопки вкл/выкл котла 
const bool RelayON =        0; // логика управления реле ресета GSM, в данном случае включается низким уровнем на пине
#define GSM_RX             14  // пин софт RX Arduino для соединения с TX модуля SIM800
#define GSM_TX             15  // пин софт TX Arduino для соединения с RX модуля SIM800

*/

//------------------------------------для GSM модуля----------------------------------------------------------------------

#include <SoftwareSerial.h>
      SoftwareSerial SIM800 (GSM_RX, GSM_TX);//Rx, Tx   //UART для соединения с GSM модулем

String currStr = "";
String TelNumber[] = {"", "000000000000", "000000000000", "000000000000"};
byte isStringMessage = 0; 
byte KTOreport = 1;     // флаг кто запросил отчет о запуске котла или ДВС
byte KTOzapros = 0;     // флаг кто запросил баланс или запрос параметров 

uint32_t  prevReset=0;           // для таймера периодичности проверки (командой "АТ")
byte  intervalReset = 2;         // каждые столько мин будет проверка жив ли GSM модуль 
uint32_t  timerWaitOK=0;         // для таймера ожидания ответа после посылки команды "АТ"
bool timerenabledWaitOK=false;   // для таймера ожидания ответа после посылки команды "АТ"
byte NoAnswersGSM=0;             // количество неответов  от GSM модуля
bool gsmOK = 1;                  // флаг есть связь с GSM модулем или нет
bool resettimer = 0;             // для таймера удерживания реле в режиме сброс питания
uint32_t  resetTimer=0;          // для таймера удерживания реле в режиме сброс питания
byte ResetNumber = 0;            // количество ресетов GSM модуля для статистики (хранится в еепром)




//------------------- для шины 1-wire и датчиков DS18B20---------------------------------------------------------------------

#include <OneWire.h>    // библиотека для DS18B20
OneWire ds(Dallas_pin); // датчики DS18B20 на нужный пин

enum TempC {VyhlopC, EngineC, UlicaC, SalonC, size_arrayTemp}; // перечисление нужных температур (в конце размер массива температур)

// ниже соответствие адресов датчиков различным температурам (изначально 0х14=20*С)
byte DS18B20 [size_arrayTemp][10] = {
{0x28, 0xFF, 0xB2, 0xB5, 0xC1, 0x17, 0x05, 0xD1, VyhlopC,  0x14}, 
{0x28, 0xFF, 0xD3, 0xE2, 0xC1, 0x17, 0x04, 0x0D, EngineC,  0x14}, 
{0x28, 0xFF, 0xF8, 0xBC, 0xC1, 0x17, 0x04, 0x48, UlicaC,   0x14},  
{0x28, 0xFF, 0x3F, 0xB7, 0xC1, 0x17, 0x05, 0xF1, SalonC,   0x14}
};
byte delta = 50;  // разница температур выхлопа и улицы, выше которой считается, что пламя в котле есть. 


//---------------------------для организации W-BUS и различные таймеры-----------------------------------------------------------

#include <Button.h>
Button test;

#define K_LINE Serial      //UART для соединения с шиной котла
#define TX 1    
#define NEED 1
#define READY 10

byte header = 0;           // состояние заголовка 
byte message_size = 0;     // размер тела принимаемого сообщения, кол-во байт

byte j = 2;                // инкремент
byte n = 2;
const byte bufsize = 140;  // размер буфера принятого сообщения
byte buf [bufsize] = {0};  // буфер принятого сообщения
byte checksum = 0;         // контрольная сумма входящего сообщения
uint32_t curmillis = 0;    // снимок системного времени
byte delaybyte_TX = 0 ;    // задержка между байтами отправляемого сообщения 
byte waitbyte_RX = 1;      // задержка, мс для успевания заполнения буфера RX (подрегулировать в зависимости от уровня жизнидеятельности на Марсе)
uint32_t timerdelay = 0;   // таймер ожидания байт (для успевания заполнения буфера УАРТ)
bool Delay = 0;            // таймер ожидания байт (для успевания заполнения буфера УАРТ)
#define TIMER_DELAY Delay = 0; timerdelay = curmillis  // включение этого таймера

uint32_t prevRESETheader=0; // таймер сброса заголовка если в момент приёма сообщения данные оборвались
bool RESETheader_timer = 0; // таймер сброса заголовка если в момент приёма сообщения данные оборвались

// команды для котлов ЭВО
byte StartByte = 0x20;
byte HEATER_START[]         {StartByte, 0x3B};
byte HEATER_PRESENCE[]      {0x44, StartByte, 0x00};
byte HEATER_STOP[]          {0x10};
byte HEATER_STATUS_VEVO[]   {0x50, 0x05};
byte HEATER_STATUS_EVO[]    {0x50, 0x30, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x1E, 0x32};
byte HEATER_DTC_REQUEST[]   {0x56, 0x01};
byte HEATER_DTC_ERASE[]     {0x56, 0x03};

// команды для котлов ТТС/TTE
byte START_SESSION[]        {0x81};
byte REQUEST_2A10101[]      {0x2A, 0x01, 0x01};
byte REQUEST_2A10102[]      {0x2A, 0x01, 0x02};
byte REQUEST_2A10105[]      {0x2A, 0x01, 0x05};
byte REQUEST_DTC[]          {0xA1};
byte START_TTC[]            {0x31, 0x22, 0xFF};
byte STOP_TTC[]             {0x31, 0x22, 0x00};


enum needAction_ {NO_ACTION, NEED_SMSZAPROS, NEED_SERVICEINFO, NEED_DTCCLEAR};// возможные действия, стоящие в очереди
byte needAction = NO_ACTION;                                                  // переменная действия, стоящего в очереди

enum ProtocolSTATUS_ {STATUSBUS, ANALOG};                   // возможные протоколы чтения статуса котла
enum ProtocolSTART_  {STARTBUS, IMPULSE, POTENCIAL};        // возможные протоколы запуска котла
enum Heater_         {TTC_E, VEVO, EVO, HYDRONIC};          // тип котла

byte  ProtocolSTATUS = STATUSBUS; 
byte  ProtocolSTART  = STARTBUS;
byte  Heater         = EVO;

bool noData  = 0;                               // флаг пришли ли данные от котла после запроса. 
byte w_bus_init = 0;                            //флаг проведена или нет инициализация шины w-bus (25мс LOW, 25мс HIGH для  ЭВО
                                                //                                            либо 300ms LOW, 50ms HIGH, 25ms LOW, 3025ms HIGH для TTC 
byte requiredmessage =  1;                      //флаг, что отправляем в данный момент поддержание старта, запрос параметров или запрос ошибок
byte StartMessageRepeat = 0;                    //количество отправленных сообщений на старт котла
byte StopMessageRepeat =  4;                    //количество отправленных сообщений на остановку котла

byte  TimeWebasto = 30;                         //время работы котла, = 30мин
uint32_t EndReportMillis = 0;                   //переменная для таймера отправки отчета об успешности запуска котла
uint32_t EndReportEngine = 0;                   //переменная для таймера отправки отчета об успешности запуска ДВС
uint32_t Prev_PeriodW_BusMessage = 0;           //переменная для таймера периодической отправки сообщений состояния котла в шину W-Bus 
uint32_t Prev_PeriodW_BusStartStop = 0;         //переменная для таймера периодической отправки сообщений старта/стопа котла в шину W-Bus 
uint32_t prevdelSMS = 0;                        //переменная для таймера периодического удаления СМС 
uint32_t prevVpit = 0;                          //переменная для таймера периодического измерения напряжения АКБ
uint32_t prevInitreset = 0;                     //переменная для таймера сброса инита шины
bool Initreset = 0;                             //переменная для таймера сброса инита шины
uint32_t timerInit = 0; bool timerInitflag = 0; //для таймера инита шины W-BUS
uint32_t prevNeedTimer = 0; bool NeedTimer = 0; //для таймера задержки функций SMSzapros() и ServiceINFO() на время обновления параметров по шине


uint32_t last_Flame = 0;                        //для таймера сброса флага пламени, если нет ответов от котла

//для таймера создания импульса GND - для протокола запуска котла импульсом GND 
uint32_t timer=0; bool timerenabled=false;
#define TIMEREXPIRED (curmillis-timer)>800

//для таймера  - старт двигателя - импульс +5В на транзистор, в итоге минусовой импульс 1.5 сек на вход событий сигналки для запуска ДВС)
uint32_t  timerStartEng=0; bool timerenabledStartEng=false;
#define TIMEREXPIRED_StartEng (millis()-timerStartEng)>1500

//для таймера  - старт котла по W-BUS )
uint32_t timerStart_W_BUS=0; bool timerenabledStart_W_BUS=false;
#define TIMEREXPIRED_Start_W_BUS (curmillis-timerStart_W_BUS)> (uint32_t)TimeWebasto * 60000UL



//---------------------------------Основные переменные--------------------------------------------------------------------------------  

bool webasto = 0;             // флаг команды на работу Webasto. 0 - котел выключен, 1 - котел включен
bool startWebasto_OK = 0;     // флаг успешного запуска котла
bool report = false;          // флаг нужности отправки отчета false - не нужно отправлять, true - нужно отправлять
bool reportEngine = false;    // флаг нужности отправки отчета false - не нужно отправлять, true - нужно отправлять
bool engine =0;               // флаг работает ли ДВС или нет
bool ignition=0;              // флаг включено ли зажигание или нет
bool ohrana=0;                // флаг включена ли охрана или нет
bool trevoga=0;               // флаг включена ли тревога или нет
bool alarmSMS = 0;            // флаг отправлена ли смс о тревоге или нет

bool waterpump = 0;           // флаг работы циркуляционного насоса
bool plug      = 0;           // флаг работы штифта накаливания
bool airfan    = 0;           // флаг работы нагнетателя воздуха
bool fuelpump  = 0;           // флаг работы топливного насоса
bool blowerfan = 0;           // флаг работы вентилятора печки автомобиля
byte DTC[7] ={0};             // коды неисправностей котла



//---------------------------СТАРТОВЫЙ ЦИКЛ--------------------------------------------------------------------------------------------

void setup() 
{


delay (3500);


test.NO(); 
test.pullUp();
test.duration_bounce       (  50);
test.duration_click_Db     ( 250);
test.duration_inactivity_Up(5000);
test.duration_inactivity_Dn(1000);
test.duration_press        ( 500);
test.button(StartButtonpin);            // в скобках пин тактовой кнопки вкл/выкл котла (программный номер у неё будет 0)
 
pinMode (DopOn,   INPUT_PULLUP); 
pinMode (DopOff,  INPUT_PULLUP); 
pinMode (Sost,    INPUT_PULLUP); 
pinMode (Ohrana,  INPUT_PULLUP); 
pinMode (Trevoga, INPUT_PULLUP); 
pinMode (IGN,     INPUT_PULLUP); 
pinMode (Eng,     INPUT_PULLUP); 
  
pinMode (OutWebasto_12V,     OUTPUT);  digitalWrite (OutWebasto_12V,      LOW);
pinMode (StartEng,           OUTPUT);  digitalWrite (StartEng,            LOW);
pinMode (13,                 OUTPUT);  digitalWrite (13,                  LOW);
pinMode (StatusWebastoLED,   OUTPUT);  digitalWrite (StatusWebastoLED,    LOW);
pinMode (OutWebasto_GndImp,  OUTPUT);  digitalWrite (OutWebasto_GndImp,   HIGH);
pinMode (DTR,                OUTPUT);  digitalWrite (DTR,                 HIGH);  // делаем высокий, а низкий уровень будет для пробуждения GSM из "спячки"
pinMode (ResetGSM,           OUTPUT);  digitalWrite (ResetGSM,        !RelayON);  // реле ресет на данный момент делаем "неактивно"


   SIM800.begin(19200);           // сериал соединение для gsm модуля
   delay(100);
   NastroykaGSM ();


TimeWebasto =    EEPROM.read(TimeWebasto_cell);
ProtocolSTART  = EEPROM.read(ProtocolSTART_cell);
ProtocolSTATUS = EEPROM.read(ProtocolSTATUS_cell);
ResetNumber =    EEPROM.read(ResetNumber_cell);
StartByte =      EEPROM.read(StartByte_cell);
Heater =         EEPROM.read(Heater_cell);
delta  =         EEPROM.read(delta_cell);
for (int i=0; i<12; i++) TelNumber[1][i] = EEPROM.read (i+TelNumber1_cell);
for (int i=0; i<12; i++) TelNumber[2][i] = EEPROM.read (i+TelNumber2_cell);


        if (Heater == EVO || Heater == VEVO) K_LINE.begin(2400, SERIAL_8E1);
   else if (Heater == TTC_E) K_LINE.begin(10400);


for (byte i=0; i<20; i++) {digitalWrite (13, !digitalRead(13)); delay (80);}
digitalWrite (13,0);
}



//------------------------------------------ЛУП-----------------------------------------------------------------------------------


void loop() {
curmillis = millis();
test.read();

digitalWrite (StatusWebastoLED, webasto);
//digitalWrite (13, startWebasto_OK);
//digitalWrite (13, webasto);


//если нажали тактовую кнопку меняем состояние котла на противоположное 
if (test.event_press_short (StartButton)) {
  if (!webasto) {StartWebasto(); report = false;}
  else StopWebasto();
    }

if (ProtocolSTATUS==ANALOG) {if (Temper(VyhlopC) - Temper(UlicaC) > delta) startWebasto_OK = 1;
                             else startWebasto_OK = 0;}

if (ProtocolSTART==IMPULSE) webasto = !digitalRead (Sost);

Heater_BUS();

//ниже для таймера старта котла по шине и аналогу 
 
  if (timerenabledStart_W_BUS && TIMEREXPIRED_Start_W_BUS) StopWebasto();

//ниже для таймера создания импульса на старт ДВС 

if (timerenabledStartEng && TIMEREXPIRED_StartEng) {digitalWrite (StartEng, LOW); timerenabledStartEng=false;}
    
 engine =  !digitalRead (Eng);
 ignition= !digitalRead (IGN); 
 ohrana=   !digitalRead (Ohrana);  
 trevoga=  !digitalRead (Trevoga);
  
if (webasto && report) timerReport ();
if (reportEngine) timerReportEngine ();
if (!ohrana) alarmSMS = false;


   if (trevoga && !alarmSMS) AlarmSMS ();
   if (gsmOK)readSMS();
   Reset_gsm();
   delSMS();


WebastoOprosImpulse ();
izmereniya();

}


//-----------------------------------------------------------конец луп-------------------------------------------------------------



void izmereniya() { 

if (millis()-prevVpit>7000){

//измерение напряжения борт сети
if (ProtocolSTATUS==ANALOG){
   volt = analogRead(Voltmeter_pin);                      
   vout = (volt * 4.13) / 1024;             
   Vpit = vout / (9700.0/(98930.0+9700.0));  // По формуле Vpit = vout / (R2/(R1+R2)) 
   if (Vpit<0.09)  Vpit=0.0;                  // Округление до нуля 
}  

// ниже измерение датчиков даллас
static bool n=0;        // флаг работы: запрос температуры или её чтение
n=!n;
if (n) {ds.reset();     // сброс шины
        ds.write(0xCC); // обращение ко всем датчикам
        ds.write(0x44); // начать преобразование (без паразитного питания)  
       }
else   {
  for (byte i=0; i<size_arrayTemp; i++){  
    int Temper_ = 20; byte buff[9];
    ds.reset();
    ds.select(DS18B20[i]);
    ds.write(0xBE); // чтение регистров датчиков
    for (byte j=0; j<9; j++) buff[j]=ds.read(); // читаем все 9 байт от датчика
    ds.reset();
    if (OneWire::crc8(buff, 8) == buff[8]){     // если контрольная сумма совпадает 
          if (DS18B20[i][8]==EngineC && ProtocolSTATUS==STATUSBUS){} // если данные берём по шине, то t двигла не мереем
          else {
          Temper_ = buff[0]|(buff[1]<<8);       // читаем температуру из первых двух байт (остальные были нужны только для проверки CRC)
          Temper_ = Temper_ / 16;
          if (Temper_<150 && Temper_>-55) DS18B20[i][9] = Temper_;}
}}}


prevVpit=millis();
}}



int8_t Temper (const byte &addressTemp) {for(byte j=0; j<size_arrayTemp; j++){if(DS18B20[j][8]==addressTemp)return(int8_t)DS18B20[j][9];} return-99;}



void WebastoOprosImpulse (){

// опрос допканалов от сигнализации включения/ выключение котла и таймер импульса старт/стоп котла 
  
  if (timerenabled) {if (TIMEREXPIRED) {digitalWrite (OutWebasto_GndImp, HIGH); timerenabled=false;}}
  else  {if (!digitalRead (DopOn)  && !webasto) {StartWebasto(); KTOreport = 1;}
         if (!digitalRead (DopOff) && webasto) StopWebasto();
         }}


// цикл таймера отправки отчета об успешности запуска котла (отчёт через 6 мин после старта)
void timerReport () {
   if(millis() - EndReportMillis > 360000UL) 
   {EndReportMillis = millis(); report = false; SMSzapros();  }} 

// цикл таймера отправки отчета об успешности запуска ДВС  (отчёт через 60сек после старта)                       
void timerReportEngine () {
   if(millis() - EndReportEngine > 90000ul) 
   {EndReportEngine = millis(); reportEngine = false; SMSzapros();}} 





   void NastroykaGSM () {
  digitalWrite (DTR, LOW);      // выводим из спячки GSM модуль
    delay (150);
  SIM800.println(F("AT"));                    //просто AT для разогреву
    delay(250);
  SIM800.println(F("AT+CMGF=1"));             //устанавливает текстовый режим смс-сообщения
    delay(250);
  SIM800.println(F("AT+IFC=0, 0"));           //отключает программный контроль потоком передачи данных
    delay(250);
  SIM800.println(F("AT+GSMBUSY=1"));          //запрет всех входящих звонков
    delay(250);
  SIM800.println(F("AT+CNMI=1,2,2,1,0"));     //включает оповещение о новых сообщениях
    delay(250);
  SIM800.println(F("AT+CMGDA=\"DEL ALL\""));  // удаляем все смс, ки
   delay(1500);
  SIM800.println(F("AT+CSCLK=1"));            //включает энергосберегающий режим 
  delay(150);
  digitalWrite (DTR, HIGH);     // вводим в спячку GSM модуль высоким уровнем на пине DTR
  
}

void startSMS(byte stat) //__________________Цикл подготовки модуля к отправке СМС-сообщений по первому номеру
{
    if (stat==0) stat = KTOreport;
     digitalWrite (DTR, LOW); // выводим из спячки GSM модуль
         delay (150);
     SIM800.print(F("AT+CMGF=1\r"));
         delay(200);
     SIM800.print(F("AT+CMGS=\"")); SIM800.print(TelNumber[stat]); SIM800.println("\""); 
         delay(200);
}



void EndSMS ()
{
   SIM800.println((char)26);                       // Команда отправки СМС
   delay(1500);
   digitalWrite (DTR, HIGH); // вводим в спячку SIM800 модуль 
   
}

void delSMS ()
{
if (millis() - prevdelSMS > 7200000ul){  //раз в 2 часа 
 digitalWrite (DTR, LOW); // выводим из спячки SIM800 модуль
    delay (150);
 SIM800.print(F("AT+CMGDA=\"DEL ALL\"\r")); // удаляем все смс, ки
   delay(1500);
 digitalWrite (DTR, HIGH); // вводим в спячку SIM800 модуль 
   delay (150);

  prevdelSMS = millis();}
}


void readSMS() //_____Цикл чтения входящих СМС-сообщений______________     
{
    if (!SIM800.available()) return;
    static bool SaveNumber2 = 0;      // флаг когда необходима запись номера#2, он true
    char currSymb = SIM800.read();
//K_LINE.print (currSymb);
    if ('\r' == currSymb)
       {
         if (isStringMessage!=0&&isStringMessage!=3) //если текущая строка - SMS-сообщение, отреагируем на него соответствующим образом
                {
if      (!currStr.compareTo("ZAPROS"))       {if (webasto)SMSzapros(); else {NeedTimer = 1; prevNeedTimer = curmillis; needAction = NEED_SMSZAPROS; w_bus_init = 1;}}              // Передача параметров по СМС
else if (!currStr.compareTo("ZAPROSTEL"))    {SMSzaprosTEL();}           // Передача номеров телефонов пользователей по СМС
else if (!currStr.compareTo("Service-info")) {if (webasto) ServiceINFO(); else {NeedTimer = 1; prevNeedTimer = curmillis; needAction = NEED_SERVICEINFO;w_bus_init = 1;}}            // Передача сервисной информации  по СМС
else if (!currStr.compareTo("GSMResets-0"))  {ResetNumber=0; EEPROM.write (ResetNumber_cell, ResetNumber); ServiceINFO();}     //сброс счетчика ресетов GSM модуля
else if (!currStr.compareTo("Version"))      {startSMS(isStringMessage);  SIM800.println (ver); EndSMS ();}               //запрос версии ПО
else if (!currStr.compareTo("Erase DTC"))    {NeedTimer = 1; prevNeedTimer = curmillis; needAction = NEED_DTCCLEAR; if (w_bus_init == 0) w_bus_init = 1;}    //запрос на стриание ошибок
else if (!currStr.compareTo("Signal-level")) {digitalWrite (DTR, LOW);  delay (150); SIM800.println(F("AT+CSQ")); digitalWrite (DTR, HIGH);}                // запрос уровня сигнала GSM 
                                              
else if (!currStr.compareTo("Webasto-ON"))  { startSMS(isStringMessage); SIM800.println(F("Webasto ")); 
  
           if (!webasto)  {StartWebasto (); KTOreport = isStringMessage;}
           else SIM800.println(F("uzhe ")); SIM800.println (F("vkluchena")); EndSMS();}

                                                            
else if (!currStr.compareTo("Webasto-OFF"))   {startSMS(isStringMessage); SIM800.println(F("Webasto "));  
           if (webasto)StopWebasto ();  // если получили команду на выключение и вебаста в настоящий момент включена - выключаем
           else SIM800.println(F("uzhe "));  SIM800.println(F("otkluchena"));EndSMS();}          

// если получили команду на включение ДВС и он в настоящий момент выключен - включаем
else if (!currStr.compareTo("Engine-ON"))  {startSMS(isStringMessage); SIM800.println(F("Dvigatel "));  
           if (!engine)  { digitalWrite (StartEng, HIGH);  timerStartEng=millis(); timerenabledStartEng=true; reportEngine = true; EndReportEngine = timerStartEng; KTOreport = isStringMessage;} 
           else SIM800.println(F("uzhe ")); SIM800.println(F("start")); EndSMS();}
                                                                                 
else if (!currStr.compareTo("Engine-OFF"))   {startSMS(isStringMessage); SIM800.println(F("Dvigatel "));  
           if (engine){ digitalWrite (StartEng, HIGH);  timerStartEng=millis(); timerenabledStartEng=true; reportEngine = false;} // если получили команду на выключение ДВС и он в настоящий момент работает - выключаем
           else SIM800.println(F("uzhe ")); SIM800.println(F("ostanovlen")); EndSMS();}          
              
else if (!currStr.compareTo("Impulse"))   {if (!webasto) {ProtocolSTART = IMPULSE;  EEPROM.write(ProtocolSTART_cell,ProtocolSTART);     
                                            startSMS(isStringMessage); SIM800.println(F("zapusk GND_impulse")); EndSMS();}}

else if (!currStr.compareTo("Startbus"))  {if (!webasto) {ProtocolSTART = STARTBUS; EEPROM.write(ProtocolSTART_cell,ProtocolSTART);  webasto = 0;  
                                            startSMS(isStringMessage); SIM800.println(F("zapusk BUS")); EndSMS();}}

else if (!currStr.compareTo("Potencial")) {if (!webasto) {ProtocolSTART = POTENCIAL; EEPROM.write(ProtocolSTART_cell,ProtocolSTART);   
                                            startSMS(isStringMessage); SIM800.println(F("zapusk +12V Potencial")); EndSMS();}}

else if (currStr.endsWith("Status"))   {if (!webasto) {byte st = currStr.toInt(); if (st >= STATUSBUS && st<=ANALOG )ProtocolSTATUS = st; EEPROM.write(ProtocolSTATUS_cell,ProtocolSTATUS);   
                                            startSMS(isStringMessage); SIM800.print (F("Status: "));
                                                                             if (ProtocolSTATUS == 0)SIM800.println(F("BUS")); 
                                                                        else if (ProtocolSTATUS == 1)SIM800.println(F("Analog"));
                                                                        EndSMS();}}    


else if (currStr.endsWith("HeaterType")) {if (!webasto) {byte st = currStr.toInt(); if (st >= TTC_E && st<=HYDRONIC) Heater = st; EEPROM.write(Heater_cell,Heater);   
                                            startSMS(isStringMessage); SIM800.print (F("Heater: "));
                                                                             if (Heater == 0)SIM800.println(F("TTC_E")), K_LINE.end(),  K_LINE.begin(10400);
                                                                        else if (Heater == 1)SIM800.println(F("VEVO")),  K_LINE.end(),  K_LINE.begin(2400, SERIAL_8E1);
                                                                        else if (Heater == 2)SIM800.println(F("EVO")),   K_LINE.end(),  K_LINE.begin(2400, SERIAL_8E1);
                                                                        else if (Heater == 3)SIM800.println(F("HYDRONIC"));
                                                                             
                                                                        EndSMS();}}      
                                                                                                                                              
else if (currStr.endsWith("Delta"))   {if (!webasto) {delta = currStr.toInt(); //
               EEPROM.write(delta_cell, delta);  startSMS(isStringMessage);
               SIM800.print(F("DeltaT: ")); SIM800.print(delta); SIM800.print(F("*C")); EndSMS();}}
                                                                                                                                            

               
else if (currStr.endsWith("min"))   {if (!webasto) {TimeWebasto = currStr.toInt(); // для задания время цикла работы отправить сообщение вида "25 min", где 25 время работы в мин
               if (TimeWebasto>59)  TimeWebasto = 59;
               if (TimeWebasto<=15) TimeWebasto = 15;
               EEPROM.write(TimeWebasto_cell,TimeWebasto);
               startSMS(isStringMessage); SIM800.print(F("Webasto time: ")); SIM800.print(TimeWebasto); SIM800.print(F("min")); EndSMS();}}
               
else if (currStr.endsWith("StartByte")) {byte Z =currStr.toInt(); if (Z>=0x14 && Z<=0x17) StartByte= Z+12;
               startSMS(isStringMessage); SIM800.print(F("StartByte: ")); SIM800.print(StartByte, HEX); SIM800.print(F("h")); EndSMS();}

else if (!currStr.compareTo("ResetNumbers"))   {if (isStringMessage == 1) {startSMS(isStringMessage); SIM800.println(F("Phone numbers are erased")); EndSMS(); 
                                                                     
             TelNumber[1] = "000000000000"; TelNumber[2] = "000000000000"; for (int i=0; i<12; i++) {EEPROM.write (i+TelNumber1_cell,  TelNumber[1][i]); EEPROM.write (i+TelNumber2_cell,  TelNumber[2][i]); }}}

else if (!currStr.compareTo("WriteNumber2")&& isStringMessage == 1)   { 
                SaveNumber2 = 1; startSMS(isStringMessage); SIM800.println(F("Otpravte lyuboye SMS s nomera#2 dlya sohraneniya nomera")); EndSMS();} 

                                                                        

                                                     
else if (!currStr.compareTo("Balance"))    SMSbalance();
            isStringMessage = 0;
                }
              
              
else if (isStringMessage==3){ if (!currStr.compareTo("WriteNumber1"))   { TelNumber[1] = TelNumber[3]; for (int i=0; i<12; i++) {EEPROM.write (i+TelNumber1_cell, TelNumber[3][i]);}
              startSMS(1); SIM800.println(F("Tel Number#1 is saving in memory"));  SIM800.print("Tel#1: ");  SIM800.println (TelNumber[1]); EndSMS();
              } 
                                             else if (!currStr.compareTo("ZAPROS"))   { SMSzapros();}   
                                             else if (!currStr.compareTo("ZAPROSTEL"))   { SMSzaprosTEL();}               // Передача номеров телефонов пользователей по СМС            
               isStringMessage = 0;
              
              }           



                
else if (isStringMessage==0) {  if (TelNumber[1]!="000000000000" && !SaveNumber2 && TelNumber[1]!="яяяяяяяяяяяя"){
         
                     if (currStr.startsWith("+CMT: \""+TelNumber[1])) { isStringMessage = 1; KTOzapros = 1; }   
                else if (currStr.startsWith("+CMT: \""+TelNumber[2])) { isStringMessage = 2; KTOzapros = 2; }   
                else if (currStr.startsWith("+CUSD: 0,"))  //если текущая строка начинается с "+CUSD",то следующая строка является запросом баланса
                  {
                       startSMS(KTOzapros);
                  SIM800.print (currStr);
                  EndSMS();
                  }    
               
                else if (currStr.startsWith("+CSQ:")) //если текущая строка начинается с "+CSQ",то значит был запрос на уровень сигнала GSM, отправим ответ запрашивающему
                  {
                  startSMS(KTOzapros);
                  SIM800.print (currStr);
                  EndSMS();
                  }
                                                }

                else if    (currStr.startsWith("+CMT:") && !SaveNumber2) { isStringMessage = 3; for (int i =0; i<12; i++) {TelNumber[3][i]=currStr[i+7];}}
                else if    (currStr.startsWith("+CMT:") && SaveNumber2) { for (int i =0; i<12; i++) {TelNumber[3][i]=currStr[i+7];} TelNumber[2] = TelNumber[3]; for (int i=0; i<12; i++) {EEPROM.write (i+TelNumber2_cell, TelNumber[3][i]);}
              startSMS(2); SIM800.println(F("Vash nomer sochranyon kak Number#2 v pamyati!")); 
              SIM800.print(F("Tel#1: ")); SIM800.println(TelNumber[1]); SIM800.print(F("Tel#2: "));  SIM800.println (TelNumber[2]); EndSMS(); SaveNumber2 = 0; } 
              
              } 
               
        currStr = "";
      } 
 
    else if ('\n' != currSymb && currSymb!=0x13 && currSymb!=0x11)  currStr += String(currSymb);
}



void SMSzaprosTEL(){
  startSMS(isStringMessage);
  PrintNumbers (); 
  EndSMS();                                 
  }


void SMSbalance() {
digitalWrite (DTR, LOW); // выводим из спячки SIM800 модуль
      delay (150);
SIM800.print(F("AT+CMGF=1\r"));
      delay(200);
SIM800.println (F("AT+CUSD=1,\"#100#\""));    // команда на замену на транслит *111*6*2# у МТС 
      delay(1500);  
digitalWrite (DTR, HIGH); // вводим в спячку SIM800 модуль 
      delay (150);  
                             
     
}


void AlarmSMS() {for (byte i = 0; i<2; i++) {startSMS(i+1); SIM800.println (F("Vnimanie!!! Trevoga!!! Sirena Vkl!")); EndSMS();} alarmSMS = true;}
 


void PrintNumbers () {for (byte i=0; i<2; i++) {SIM800.print(F("Tel#")); SIM800.print (i+1); SIM800.print(F(" ")); SIM800.println(TelNumber[i+1]);}}

void SMSzapros()

{

  startSMS(isStringMessage);
  if (isStringMessage == 3){
 
 SIM800.println (F("Tel.number#1 not has been save in memory"));
 SIM800.println (F("For save Tel#1 send SMS command \"WriteNumber1\""));
 PrintNumbers ();
  }
  

  
  
  else {
  
SIM800.print (F("Webasto ")); on_off (webasto);
        if (webasto) { 
           SIM800.print (F("StartWebasto "));
           if (startWebasto_OK) SIM800.println (F("OK"));
           else SIM800.println (F("FAIL"));}
SIM800.print (F("Engine    "));  on_off (engine);
SIM800.print (F("IGN        ")); on_off (ignition);
SIM800.print (F("Ohrana  "));    on_off (ohrana);
     if (trevoga)  SIM800.println (F("Vnimanie!!! Trevoga!!! Sirena Vkl!"));
     
  SIM800.print(F("Battery: "));      if ((needAction>0 && !noData) || needAction == 0 || ProtocolSTATUS == ANALOG) {SIM800.print (Vpit,1); SIM800.println(F(" V"));}
                                else if (needAction>0 && noData && ProtocolSTATUS != ANALOG) SIM800.println(F(" No Data"));
  SIM800.print(F("Engine:  ")); if ((needAction>0 && !noData) || needAction == 0 || ProtocolSTATUS == ANALOG) {SIM800.print (Temper(EngineC));  grad ();}
                                else if (needAction>0 && noData && ProtocolSTATUS != ANALOG) SIM800.println(F(" No Data"));
 if (ProtocolSTATUS == ANALOG){ SIM800.print(F("Vyhlop:  ")); SIM800.print (Temper(VyhlopC));  grad ();}
  SIM800.print(F("Ulica:     ")); SIM800.print (Temper(UlicaC)); grad ();
  SIM800.print(F("Salon:    ")); SIM800.print (Temper(SalonC));  grad ();  

  if (ProtocolSTATUS == STATUSBUS){
  SIM800.print(F("Errors:   ")); if ((needAction>0 && !noData) || needAction == 0) SIM800.println (DTC[0]);
                                else if (needAction>0 && noData) SIM800.println(F(" No Data"));}
  
  
 
  }  
   EndSMS();    
                          
}

void on_off (const bool &stat) {if (stat) SIM800.println (F("ON")); else SIM800.println (F("OFF")); }
void grad () {SIM800.println (F("*C")); }





void ServiceINFO(){
  
       startSMS(isStringMessage);
  SIM800.print(F("Heater:  ")); 
       if (Heater==TTC_E)     SIM800.println(F("TTC/E"));
  else if (Heater==VEVO)      SIM800.println(F("VEVO"));
  else if (Heater==EVO)       SIM800.println(F("EVO"));
  else if (Heater==HYDRONIC)  SIM800.println(F("HYDRONIC"));
  SIM800.print(F("Start:    "));
       if (ProtocolSTART==IMPULSE)   SIM800.println(F("GND Imp"));
  else if (ProtocolSTART==STARTBUS)  {SIM800.print(F("BUS"));
             if (Heater== VEVO || Heater== EVO) {SIM800.print(F(" 0x")); SIM800.println (StartByte, HEX);}
             else SIM800.println();}
  else if (ProtocolSTART==POTENCIAL) SIM800.println(F("Potencial+12V"));
  
  SIM800.print(F("Status:  "));
       if (ProtocolSTATUS==ANALOG)    SIM800.println(F("ANALOG"));
  else if (ProtocolSTATUS==STATUSBUS) SIM800.println(F("BUS"));
  
   
  if (ProtocolSTART!=IMPULSE) {SIM800.print(F("Webasto Time: ")); SIM800.print (TimeWebasto); SIM800.println(F("min"));}
  SIM800.print(F("SIM800 Resets: ")); SIM800.println (ResetNumber); 

  if (ProtocolSTATUS==ANALOG) {SIM800.print(F("DeltaT:  ")); SIM800.print(delta);SIM800.println(F("*C"));}

  if (ProtocolSTATUS==STATUSBUS && !noData) {
    SIM800.print(F("   BurnFAN       ")); on_off (airfan);
    SIM800.print(F("   WaterPUMP ")); on_off (waterpump);
    SIM800.print(F("   PLUG            ")); on_off (plug);
    SIM800.print(F("   FuelPUMP    ")); on_off (fuelpump);
    SIM800.print(F("   Blower          ")); on_off (blowerfan);
    
   SIM800.print (F("Errors:  ")); SIM800.println (DTC[0]);
  if (DTC[0] >0) for (byte i=0; i<DTC[0]; i++) {
  if (DTC[i+1]<=0x0F) SIM800.print(F("0"));
     SIM800.print (DTC[i+1], HEX); 
     if (bitRead(DTC[6], i+1)) SIM800.println (F(" Active")); 
     else SIM800.println (F(" Passive"));      }
                             }
 else if (noData) SIM800.println(F("Heater not answer. No Data"));                                                                               
   EndSMS();    
  
  }

void StartWebasto()
{
 if (ProtocolSTART==IMPULSE){
  
  digitalWrite (OutWebasto_GndImp, LOW); 
  timer=curmillis; 
  timerenabled=true;}

 else {
  StartMessageRepeat = 0;
  webasto = 1; digitalWrite (OutWebasto_12V, HIGH);
  timerStart_W_BUS=millis();
  timerenabledStart_W_BUS = true;}

  report = true; EndReportMillis = millis();
  w_bus_init = NEED;
}

void StopWebasto()
{
 if (ProtocolSTART==IMPULSE){ digitalWrite (OutWebasto_GndImp, LOW); 
  timer=curmillis; 
  timerenabled=true;}

 else {
  StopMessageRepeat = 0;
  webasto = 0; digitalWrite (OutWebasto_12V, LOW);
  timerenabledStart_W_BUS = false;}
   report = false;
   
   
}



void Heater_BUS (){
  
if      (Heater == EVO || Heater == VEVO){
if (webasto) {
    if (StartMessageRepeat<4 && (millis()-Prev_PeriodW_BusStartStop>800) && w_bus_init >= READY){
  sendMessage (HEATER_START, sizeof(HEATER_START)); 
  StartMessageRepeat++; 
  Prev_PeriodW_BusStartStop = millis();
  
    }
  if (StartMessageRepeat>=4){ if (millis()-Prev_PeriodW_BusMessage>4000)  {
    
         if (requiredmessage==1) sendMessage (HEATER_PRESENCE, sizeof(HEATER_PRESENCE));  
    else if (requiredmessage==2) {if (Heater == EVO) sendMessage (HEATER_STATUS_EVO,  sizeof(HEATER_STATUS_EVO));
                                  if (Heater == VEVO)sendMessage (HEATER_STATUS_VEVO, sizeof(HEATER_STATUS_VEVO));}
    else if (requiredmessage==3) sendMessage (HEATER_DTC_REQUEST, sizeof(HEATER_DTC_REQUEST));  
requiredmessage++; if (requiredmessage > 3) requiredmessage = 1;
StopMessageRepeat = 0;
    
    Prev_PeriodW_BusMessage = millis();
    }}}





else if (StopMessageRepeat<4 && (millis()-Prev_PeriodW_BusStartStop>800)){
  sendMessage (HEATER_STOP, sizeof(HEATER_STOP));
StopMessageRepeat++; 
StartMessageRepeat = 0;
   Prev_PeriodW_BusStartStop = millis();
  
  
  }


if (!timerInitflag && w_bus_init==NEED) {K_LINE.end(); pinMode (TX, OUTPUT); digitalWrite(TX, 0); timerInit = millis(); timerInitflag = 1;}
if ( timerInitflag && (millis() - timerInit>24) && w_bus_init==NEED) {timerInit = millis(); digitalWrite(TX, 1); w_bus_init=2; }
if ( timerInitflag && (millis() - timerInit>24) && w_bus_init==2) {K_LINE.begin (2400,SERIAL_8E1 );timerInitflag = 0; w_bus_init=READY; }


if (K_LINE.available()){
    

 // первый старт байт
 if (header == 0 && Delay){TIMER_DELAY ; buf[0]=K_LINE.read();  
         if (buf[0]==0x4F){header = 1; RESETheader_timer=1; prevRESETheader = curmillis; }
         else {header = 0; RESETheader_timer=0;}
         }                  

 // длина сообщения
 if (header == 1 && Delay){TIMER_DELAY ; buf[1]=K_LINE.read(); message_size = buf[1]; if (message_size > bufsize) message_size = bufsize;  header = 4;j=2;n=2;checksum = 0;} 

 // пишем тело сообщения 
 if (header == 4 && Delay && j< message_size+n) {
 buf[j] = K_LINE.read();
 
 if (j<message_size+n-1) checksum^= buf[j]; // подсчёт КС
 
 if (j==message_size+n-1) header = 5; 
 TIMER_DELAY ; j++;} 

 } // end of K_LINE.available()

 // сообщение приняли, действуем
 if (header == 5) {TIMER_DELAY ;  
   
for(byte i = 0; i<n; i++) checksum^=buf[i]; // прибавляем к контрольной сумме старт байты

 // если контрольная сумма верна: 
if ( checksum == buf[message_size+n-1]) {
  
if (Heater == EVO){
    
     if (buf[2]==0xD0 && buf[3]==0x30)                          {    // если получили сообщение с текущими данными
                
                 if  (buf[4] ==0x0A) { 
                          airfan    = (bool)buf[5];                  // получаем флаг работы нагнетателя воздуха
                          plug      = (buf[5] & 0x02)>>1;            // получаем флаг работы штифта накаливания
                          fuelpump  = (buf[5] & 0x04)>>2;            // получаем флаг работы топливного насоса
                          waterpump = (buf[5] & 0x08)>>3;            // получаем флаг работы циркуляционного насоса
                          blowerfan = (buf[6] & 0x10)>>4;            // получаем флаг работы вентилятора печки автомобиля
                  
                                     }
                   
                 if  (buf[6] ==0x0C) {for (byte p=0; p<size_arrayTemp; p++ ) {if (DS18B20[p][8]==EngineC){DS18B20[p][9] = buf[7]-50; break;}    }} // получаем температуру антифриза
                 if  (buf[8]==0x0E) {Vpit = (float)(buf[9]<<8|buf[10])/1000.0;}                 // получаем напряжение борт сети
                 if  (buf[11]==0x10) {startWebasto_OK = (bool)buf[12]; last_Flame = curmillis;} // проверяем наличие пламени                                                
                 
                 if (needAction>0 && needAction<NEED_DTCCLEAR) {w_bus_init = 12; sendMessage (HEATER_DTC_REQUEST, sizeof(HEATER_DTC_REQUEST));}
                                                                }

     if (buf[2]==0xD6 && buf[3]==0x01) {if (needAction>0 && needAction<NEED_DTCCLEAR) w_bus_init = 13;
      for (byte h = 0; h< sizeof(DTC); h++) DTC[h]=0;
      DTC[0] = buf[4];
      for (byte h = 0; h< buf[4]; h++) {DTC[h+1]=buf[h*3+5]; bitWrite (DTC[6], h+1,  (buf[h*3+6] & 0x02)>>1);}
            }  

     if (buf[2]==0xD6 && buf[3]==0x03)  {startSMS (KTOzapros); SIM800.println (F("DTCs are erased!")); EndSMS(); needAction=0; w_bus_init = 10; NeedTimer = 0;  }                   
                                                                
                  }

if (Heater == VEVO){
     if (buf[2]==0xD0 && buf[3]==0x05) {startWebasto_OK = buf[7]; last_Flame = millis();}       // проверяем наличие пламени у VEVO 
                  }
  
  
                                        }   

// если контрольная сумма не совпала: 

//else K_LINE.println("CRC fail!!!" );
  
message_size = 0; header=0; RESETheader_timer=0; j=2; checksum = 0;
}




}// end EVO VEVO


else if (Heater == TTC_E){



  
if (!timerInitflag && w_bus_init==NEED) {K_LINE.end(); pinMode (TX, OUTPUT); digitalWrite(TX, 0); timerInit = millis(); timerInitflag = 1;}
if ( timerInitflag && (millis() - timerInit>299)  && w_bus_init==NEED) {timerInit = millis(); digitalWrite(TX, 1); w_bus_init=2; }
if ( timerInitflag && (millis() - timerInit>49)   && w_bus_init==2) {timerInit = millis(); digitalWrite(TX, 0); w_bus_init=3; }
if ( timerInitflag && (millis() - timerInit>24)   && w_bus_init==3) {timerInit = millis(); digitalWrite(TX, 1); w_bus_init=4; }
if ( timerInitflag && (millis() - timerInit>3024) && w_bus_init==4) {K_LINE.begin (10400); timerInitflag = 0; w_bus_init=READY;  sendMessage (START_SESSION, sizeof(START_SESSION));}

if (K_LINE.available()){
    

 // первый старт байт
 if (header == 0 && Delay){TIMER_DELAY ; buf[0]=K_LINE.read();  
         if (!bitRead (buf[0],6) && bitRead (buf[0],7)){header = 1; RESETheader_timer=1; prevRESETheader = curmillis; }
         
         }                  

 // второй старт байт
 if (header == 1 && Delay){TIMER_DELAY ; buf[1]=K_LINE.read(); if (buf[1]==0xF1){ header = 2;} else {header = 0; RESETheader_timer=0;}} 

 // третий старт байт
 if (header == 2 && Delay){ 
  TIMER_DELAY ;
  buf[2]=K_LINE.read(); 
  if (buf[2]==0x51){ message_size = buf[0]; 
  if (buf[0] !=0x80) {header = 4;  message_size&=~0x80; j=3; n=3;}
  else {header = 3; j=4;n=4;}
  if (message_size > bufsize) message_size = bufsize;  checksum = 0;} else {header = 0; RESETheader_timer=0; }
  
                          }  
// если размер сообщения указан в дополнительном байте (нулевой байт 0x80) читаем этот дополнительный байт:
if (header == 3 && Delay){
  TIMER_DELAY ;
  buf[3]=K_LINE.read(); 
  message_size = buf[3]; 
  if (message_size > bufsize) message_size = bufsize;  
  checksum = 0; header = 4;  
                         }

  // пишем тело сообщения 
 if (header == 4 && Delay && j< message_size+n+1) {
 buf[j] = K_LINE.read(); 
 if (j<message_size+n) checksum+= buf[j]; // подсчёт КС
 
 if (j==message_size+n) header = 5; 
 TIMER_DELAY ; j++;} 

 } // end of K_LINE.available()

 // сообщение приняли, действуем
 if (header == 5) {TIMER_DELAY ;  

for(byte i = 0; i<n; i++) checksum+=buf[i]; // прибавляем к контрольной сумме старт байты

//for (byte i=0; i<message_size+n+1; i++) {Serial.print (buf[i], HEX); Serial.print(" ");}

 // если контрольная сумма верна: 
if (buf[message_size+n] == checksum) {
  
//  if (buf[n]== 0xC1) Serial.println ("StartSession OK!!!");
  
  
  
  
  }   

// если контрольная сумма не совпала: 
//else Serial.println("CRC fail!!!" );
message_size = 0; header=0; RESETheader_timer=0; j=3; checksum = 0;
}

} // end TTC_E

// таймер ожидания байт (для успевания появления данных в буфере UART)
if (!Delay && curmillis - timerdelay > waitbyte_RX) Delay = 1; 

// таймер сброса заголовка если данные оборвались во время приёма заголовка
if (RESETheader_timer && curmillis - prevRESETheader > 500) {RESETheader_timer = 0; header = 0;}   

if (curmillis - last_Flame>20000 && ProtocolSTATUS==STATUSBUS) {startWebasto_OK=0; last_Flame = curmillis;}  // делаем статус "нет пламени" через 20 сек, если не получаем сообщения от котла

if (Initreset && curmillis - prevInitreset>17000) {Initreset = 0; w_bus_init = 0;}  // сброс инита, если прошло более 17 сек после отправки последнего сообщения


if (needAction>0 && needAction < NEED_DTCCLEAR && w_bus_init==10) {if (Heater == EVO) sendMessage (HEATER_STATUS_EVO,  sizeof(HEATER_STATUS_EVO));
                                     if (Heater == VEVO)sendMessage (HEATER_STATUS_VEVO, sizeof(HEATER_STATUS_VEVO));
                                     w_bus_init=11;}
if ((NeedTimer && curmillis - prevNeedTimer>6000) || w_bus_init == 13)  {NeedTimer = 0; 
             if (curmillis - prevNeedTimer>6000) noData = 1; 
             if (needAction == NEED_SMSZAPROS)     SMSzapros();
        else if (needAction == NEED_SERVICEINFO) ServiceINFO();
        else if (needAction == NEED_DTCCLEAR) {startSMS(KTOzapros); SIM800.println (F("DTC not cleared. Heater no answer!")); EndSMS();}
        w_bus_init = 10; noData = 0; needAction = 0; 
        } 
        
 if (needAction==NEED_DTCCLEAR && w_bus_init==10) { sendMessage (HEATER_DTC_ERASE, sizeof(HEATER_DTC_ERASE)); w_bus_init = 20;  }

}


void Reset_gsm (){
  if (millis()-prevReset>(unsigned long)intervalReset*60000UL){
  
  digitalWrite (DTR, LOW); delay (150);
  SIM800.println (F("AT")); 
  timerenabledWaitOK = 1; timerWaitOK = millis();
  gsmOK = false;
  prevReset = millis(); }

 if (timerenabledWaitOK && millis()-timerWaitOK>6000) {
    timerenabledWaitOK = 0;
    if (!gsmOK) {
      SIM800.println (F("AT")); timerenabledWaitOK = 1; timerWaitOK = millis();
      NoAnswersGSM++; if (NoAnswersGSM>4) NoAnswersGSM = 4; 
      
      }
}

  
 if (!gsmOK)  { 
  if (SIM800.available()>0){                                   
    char currSymb = SIM800.read(); 

  

    if ('\r' == currSymb) {                                      
                                  
       if (!currStr.compareTo("OK")) {   gsmOK = true;  timerenabledWaitOK = 0; NoAnswersGSM=0; digitalWrite (DTR, HIGH);}
       currStr = "";                                           
    }
    
    else if ('\n' != currSymb && currSymb!=0x13 && currSymb!=0x11) {currStr += String(currSymb);}}}
    
    
    if (NoAnswersGSM>=4) Reset();
    
    }



 
 void Reset(){
     
      if (!resettimer) {digitalWrite (ResetGSM, RelayON); resettimer = 1; resetTimer = millis();} 
else if (millis()- resetTimer>6000 ) {
resettimer = 0; 
NoAnswersGSM=0; 
ResetNumber++; 
EEPROM.write (ResetNumber_cell, ResetNumber);
digitalWrite (ResetGSM, !RelayON); 
delay (3500); NastroykaGSM ();}
             }




void sendMessage(const byte *command, const size_t size){

 Initreset = 1;  prevInitreset = curmillis;  // включение таймера сброса инита
 
 if (Heater == TTC_E){
  const byte siZe = size+4;
  byte Mes[siZe];
  byte Checksum = 0;
  for(byte i=0; i<siZe; i++) {
    if (i==0) {Mes[i]=size; bitWrite(Mes[i], 7 , 1);}
    if (i==1) Mes[i] = 0x51;
    if (i==2) Mes[i] = 0xF1;    
    if (i==3) {for (byte t=0; t<size; t++ ) {Mes[i]=command[t]; Checksum+=Mes[i] ;K_LINE.write (Mes[i]);  i++;}}
    if (i!=siZe-1) Checksum+=Mes[i];
    else Mes[i] = Checksum;    
    K_LINE.write (Mes[i]); 
      }
  
 }
 else if (Heater == EVO || Heater == VEVO){
  const byte siZe = size+3;
  byte Mes[siZe];
  byte Checksum = 0;
  for(byte i=0; i<siZe; i++) {
    if (i==0) Mes[i] = 0xF4;
    if (i==1) Mes[i]=size+1; 
    if (i==2) {for (byte t=0; t<size; t++ ) {Mes[i]=command[t]; Checksum^=Mes[i] ;K_LINE.write (Mes[i]); i++;}}
    if (i!=siZe-1) Checksum^=Mes[i];
    else Mes[i] = Checksum;    
    K_LINE.write (Mes[i]); 
      }
  
  }
  }

 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Попробовал новый скетч с проверкой уровня сигнала сети  на столе, ответа нет на смс сигнал левел ни чего не приходит, но остальные смски работают . Подключил модем к терминалу, отправил команду AT+CSQ  пришел ответ 22  вроде не сильно слабый сигал, еще попробовал с модема набрать свой номер, но почему то пришел ответ NO CARRIER вроде как повесили трубку , а я ее не брал и не весил , что то модем мой глючит, может питание как нибудь проседает  или модем заглючил.

Dushman7776
Offline
Зарегистрирован: 13.01.2019

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

Dushman7776
Offline
Зарегистрирован: 13.01.2019

И ещё можно перепрошить прошивкой от сим 800с , вроде стабильнее работает. И ещё очень интересно здесь описано как работать с sim800 http://codius.ru/articles/GSM_модуль_SIM800L_часть_2

MaksVV
Offline
Зарегистрирован: 06.08.2015

Dushman7776 пишет:
И ещё нашел информацию про брак и глюки модема , бывает непропай , и ещё советуют питание на модем припаивать , в пинхидерах может контакт пропадать при скачках тока.

дак ты не на плате чтоли тестируешь? Так можно много приколов огребсти. и ты не ответил про согласование уровней тх и rx. Они есть у тебя? 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Dushman7776 пишет:
Попробовал новый скетч с проверкой уровня сигнала сети  на столе, ответа нет на смс сигнал левел ни чего не приходит

поправил скетч 3.61 . (забыл сим800 будить, когда команду посылаю, щас проверил - работает). 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Я тестил на плате , вытащил ардуину из гнезда а ттл- юсб подключил к на выводы rx tx и общую массу на gnd, все подключения через панель куда ардуину пихать , там же делитель уже есть , у меня глюк с модемом в том ,что с ардуино он в сети не регистрируется нормально, делаю дозвон , недоступен, а должен занят быть, а потом сразу смска приходит что абонент снова в сети.

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

попробуй с терминала вручную отправить на модуль все команды по очереди из функции NastroykaGSM().  только пин DTR  SIM800  (пин А3 ардуино) после этого надо на питание посадить. После чего нужно позвонить на SIM800. 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Попробую , может и питание, но без ардуино идут нормальные длинные гудки.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Dushman7776 пишет:
Попробую , может и питание, но без ардуино идут нормальные длинные гудки.

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

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Домой приеду проверю , дома сегодня все оставил.

MaksVV
Offline
Зарегистрирован: 06.08.2015

ещё кое что исправил v3.61 

Вот скетч сниффера шины W-bus, он правильно режет сообщения. Выполнен на альтернативной библе софтсериала , которая умеет 2400 8E1 (вверху выбрать пины RX и TX    К-лайна)



#define GSM_RX             7  // пин софтсериала RX Arduino 
#define GSM_TX             8  // пин софтсериала TX Arduino 

#include <CustomSoftwareSerial.h>
CustomSoftwareSerial* K_LINE;               

      
#define DEBUGSERIAL Serial                             // УАРТ для отправки данных отладки

byte header = 0;           // состояние заголовка 
byte message_size = 0;     // размер тела принимаемого сообщения, кол-во байт

byte j = 2;                // инкремент
byte n = 2;
const byte bufsize = 140;  // размер буфера принятого сообщения
byte buf [bufsize] = {0};  // буфер принятого сообщения
byte checksum = 0;         // контрольная сумма входящего сообщения
uint32_t curmillis = 0;    // снимок системного времени
byte delaybyte_TX = 0 ;    // задержка между байтами отправляемого сообщения 
byte waitbyte_RX = 1;      // задержка, мс для успевания заполнения буфера RX (подрегулировать в зависимости от уровня жизнидеятельности на Марсе)
uint32_t timerdelay = 0;   // таймер ожидания байт (для успевания заполнения буфера УАРТ)
bool Delay = 0;            // таймер ожидания байт (для успевания заполнения буфера УАРТ)
#define TIMER_DELAY Delay = 0; timerdelay = curmillis  // включение этого таймера

uint32_t prevRESETheader=0; // таймер сброса заголовка если в момент приёма сообщения данные оборвались
bool RESETheader_timer = 0; // таймер сброса заголовка если в момент приёма сообщения данные оборвались



void setup() {

K_LINE = new CustomSoftwareSerial(GSM_RX, GSM_TX); 
K_LINE->begin(2400, CSERIAL_8E1);
DEBUGSERIAL.begin (9600);

DEBUGSERIAL.println ("SEC    Start Gebug W-bus: ");
}

void loop() {
 curmillis = millis();
  w_bus_Read ();

}


void w_bus_Read () {
  
  if (K_LINE->available()){
    

 // первый старт байт
 if (header == 0 && Delay){TIMER_DELAY ; buf[0]=K_LINE->read();  
         if (buf[0]==0x4F || buf[0]==0xF4 || buf[0]==0x44){header = 1; RESETheader_timer=1; prevRESETheader = curmillis; }
         else {header = 0; RESETheader_timer=0;}
         }                  

 // длина сообщения
 if (header == 1 && Delay){TIMER_DELAY ; buf[1]=K_LINE->read(); message_size = buf[1]; if (message_size > bufsize) message_size = bufsize;  header = 4;j=2;n=2;checksum = 0;} 

 // пишем тело сообщения 
 if (header == 4 && Delay && j< message_size+n) {
 buf[j] = K_LINE->read(); 
 
 if (j<message_size+n-1) checksum^= buf[j]; // подсчёт КС
 
 if (j==message_size+n-1) header = 5; 
 TIMER_DELAY ; j++;} 

 } // end of K_LINE->available()

 // сообщение приняли, действуем
 if (header == 5) {TIMER_DELAY ; 
   
for(byte i = 0; i<n; i++) checksum^=buf[i]; // прибавляем к контрольной сумме старт байты

DEBUGSERIAL.print(curmillis/1000); DEBUGSERIAL.print("    Rx:       ");
for (byte i = 0; i<buf[1]+2; i++) {
  if (i==2 || i==buf[1]+1) DEBUGSERIAL.print ("    ");
  if (buf[i]<=0x0F) DEBUGSERIAL.print("0"); DEBUGSERIAL.print(buf[i], HEX); DEBUGSERIAL.print(" "); }

 
if ( checksum == buf[message_size+n-1]){ if (buf[0]==0xF4)DEBUGSERIAL.println(" From Device to Heater" );   
                                    else if (buf[0]==0x4F)DEBUGSERIAL.println(" From Heater to Device" );   // если контрольная сумма верна
                                    else if (buf[0]==0x44)DEBUGSERIAL.println(" From Heater to Heater" );  }
else DEBUGSERIAL.println(" CRC fail!!!" );                                            // если контрольная сумма не совпала
  
message_size = 0; header=0; RESETheader_timer=0; j=2; checksum = 0;
}
      
      
// таймер ожидания байт (для успевания появления данных в буфере UART)
if (!Delay && curmillis - timerdelay > waitbyte_RX) Delay = 1; 

// таймер сброса заголовка если данные оборвались во время приёма заголовка
if (RESETheader_timer && curmillis - prevRESETheader > 500) {RESETheader_timer = 0; header = 0;}        
  
  }

 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

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

Dushman7776
Offline
Зарегистрирован: 13.01.2019

А нее вроде нормально откомпилировалась , зачит автоматом подхватила из библиотек

 

Dushman7776
Offline
Зарегистрирован: 13.01.2019

залил исправленный 3.61 , на запрос уровня сигнала отвечает показывает 23 попугая , это хорошо?  При звонке на сим800 модем не перезагружается , так же мигает раз в 3 секунды  . но робот все равно говорит что телефон выключен или вне зоны доступа, а остальные смски отвечает, на живом котле проверю завтра.

Dushman7776
Offline
Зарегистрирован: 13.01.2019

Подключился я к модему без ардуино через сом порт , попробовал позвонить ,идет дозвон , потом ввел все команды из функции настройка жсм кроме команды на удаление всех смс , не понял как ее набирать, но это не важно, и подал на DTR высокий уровень и все дозвона нет и приходит смс после как трубку сбросил что абонент снова в сети,  потом перезапустил модем высокий уровень с  DTR  не снимал . но дозвон пошел ,значит это не модем глючит это что то в инициализации или я не знаю , раньше же по другому работало. Сравнил первые скетчи везде все одинаково. Может прогреть все же модем феном может непропай какой все таки. Придет новый сим 800 сравню их , но это только к середине марта он приедет.                                      

MaksVV
Offline
Зарегистрирован: 06.08.2015

По идее на звонки пофиг. Главное чтобы смс работало. Может в спящем режиме так модуль себя ведёт. Надо почитать. Хотя вообще то все равно по идее должен быть в сети. У меня кстати в сети, при звонке - занято

Dushman7776
Offline
Зарегистрирован: 13.01.2019

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

Dushman7776
Offline
Зарегистрирован: 13.01.2019

проверил все работает, хрен с ними со звонками. Еще бы добить чтобы по w-bus можно было напряжение и температуру мерило на выключенном котле и стало бы идеально.