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

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

Странно, вечером попробовал с кнопки запустить котел, все включилось и startwebasto Ok, но после остановки котла на сервис инфо и на запрос всё равно отсылает устаревшие данные, получается нет ни какого смысла читать эти данные по шине , они октуальны только когда вебаста работает. Проще по аналогу считывать напряжение и текущие температуры, запуск и определение что котел запустился лучше по шине , тогда можно совсем , убрать родной таймер, а посмотреть как там дела с температурой и вольтами лучше по аналогу читать. Ну а ошибки читать нужная фитча , еще бы команду на стирание и снятие блокировки добавить.

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

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

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

Не понятно почему стартвебастоОК у тебя неправильно показал, когда котел работал. Посмотрел - должен норм показывать.

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

Сам не понял , что это было , вечером с кнопки запустил, потом запрос сделал всё правильно показало, а утром когда за машиной шел , смску на запуск послал , пришел ответ что вебасто он а стартвебасто файл. Если я сейчас отправлю сервис инфо то придет ответ что помпа, бензонасос вентилятор on ,свеча накаливания off и температура 67 градусов. Я сначала подумал что она сама включилась , побежал проверить но всё отключено было.

t1540
Offline
Зарегистрирован: 17.02.2019

какую Arduino ide версия вы используете 

Моя версия 1.8.8 мне выдаёт ошибку


 

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

Вот пробуем эту прошивку. Компилятор должен съесть. Добавлено чтение параметров из шины и удаление ошибок  даже при выключенном котле. Ошибки удалаяем смс командой Erase DTC

v3.60

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



//----------------------------------название ячеек еепром----------------------------------------------------------------
#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();

    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("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("+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]); 
      }
  
  }
  }

 

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

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

Давай-ка по-внимательней. Я тут мозги ломаю, а похоже всё норм работает. В котле пламя не сразу появляется, а минуты через 3 после старта. И даже, когда уже загудело, ещё не сразу параметр пламя становится ДА, т.к. датчик пламени и штифт накаливания это одна деталь, а штифт ещё какое то время греет после воспламенения и измерять наличие пламени в это время не может. Поэтому задержка такая в контроле этого парамтера. Не зря я только через 6 минут после старта отчет сделал. 

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

MaksVV пишет:

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

Давай-ка по-внимательней. Я тут мозги ломаю, а похоже всё норм работает. В котле пламя не сразу появляется, а минуты через 3 после старта. И даже, когда уже загудело, ещё не сразу параметр пламя становится ДА, т.к. датчик пламени и штифт накаливания это одна деталь, а штифт ещё какое то время греет после воспламенения и измерять наличие пламени в это время не может. Поэтому задержка такая в контроле этого парамтера. Не зря я только через 6 минут после старта отчет сделал. 


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

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

Ладно на последнем скетче потестируй, надеюсь будет гуд.

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

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

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

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

уточняй на какой версии скетча. У меня на v3.60 с эмулятором котла всё отлично отрабатывало. Причем если котёл по каким-либо причинам не ответит -  наротив параметров, контролируемых по шине, будет надпись No data . 

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

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

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

Прошил 3.60,проверил , выключенный котел пишет ноу дата температура и напряжение, устаревшие данные не даёт, выключение помпы, вентилятора и бензонасоса видит,а может это такие же устаревшие данные , не знаю как проверить.

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

вообще он не должен писать данные по помпе вентилятору и т.д.  В Service-info внизу  должен в таком случае писать Heater not answer. No Data. 

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

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

По ходу железная вебаста засыпает когда не включена  или не находится на связи с WTT 2.16  , может подавать команду которая программа отсылает при соединении с котолом, по смске zapros ардуина изображает из себя программу диагностики и будит котел . а он отсылает данные о себе.

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

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

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

MaksVV пишет:

вообще он не должен писать данные по помпе вентилятору и т.д.  В Service-info внизу  должен в таком случае писать Heater not answer. No Data. 

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

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

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

Я так его и бужу, как это делаю при запуске.

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

Возможно после инита котел отвечает только на сообщение старта или начала диагностики, а потом уже на все остальное. Добавлю сообщение начала диагностики после инита. Может поможет.

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

Возможно и так , надо попробовать. Жаль у меня нет второй ардунины про мини на руках, было бы оперативнее .Заказал у китайцев еще одну и модем еще один заказал на всякий случай. Жаль что каждый раз для перепрошивки нужно выковыривать ардуину , а так бы вывел провода с разъемом . 

 

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

Я когда отладку делал у меня на w-bus висел девайс, эмулятор котла и юсб-клайн адаптер. Дак вот юсб к-лайн подключен к WTT в режиме монитора w-bus. И у меня все было видно, что на шине творится. Причем даже инит видно - байтом 00 он проскакивает. Так что рекомендую.

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

кстати провода можно вывести от про мини : все для прошивки, кроме питания!! Питание там 4В, если подключить юсб-ттл, то он подаст 5В. Поэтому этот провод не подключаем. Т.е. подключаем GND, TX, RX, DTR. у меня прошивается без вытаскивания. Главное чтобы на к-лайне тишина была, имхо. 

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

только не знаю как к этому котелок отнесется, вот что происходило на шине к-лайн во время прошивки: 

00 F4 0A 50 30 0A 0C 0E 10 12 1E 32 B8 FF EF EF FF EF EF FF EF EF FF FF EF FF FF FF EF EF EF EF EF FF EF EF EF EF EF EF BF FF FF EF FF EF FF FF BF FF FF FF FF FF FF FF FF EF EF FF FF FF EF FF FF EF FF FF EF EF FF FF EF EF EF FF FF FF EF FF EF FF FF EF FF FF FF EF FF FF FF EF FF FF EF EF FF EF EF C8 8E 41 3F 01 61 CD FF D8 79 FF 9C 65 89 D9 48 31 69 EF 99 EF 88 21 63 5D FF 88 DD 89 5D 63 BC 0D 89 60 EF 89 C8 08 30 7F E5 65 3D 88 BF 59 7E 80 BF 08 08 F5 DE A7 53 81 2D FD 23 A7 3F CD 5F DC 38 FF 65 08 F7 CC A6 A9 D6 2D 1B A9 6C E0 22 68 B2 29 7F 70 3F 21 8A BD 6C 2D 7F 2D BF 1C 76 BF 01 31 09 A9 51 0D D3 F6 52 EF 25 78 85 64 83 3F EE F7 A9 BC 29 69 3F 77 D8 E1 08 7E 96 96 19 81 7F D8 78 9D 7F DC 59 11 48 61 15 B2 45 FF A2 23 73 FD B2 A9 63 BF A0 DB 1D EF A8 F0 A5 08 8F FF 0E 88 E8 BF C0 67 D1 C8 AD A8 2D 8D 70 21 BF 21 38 61 3F 69 EB CA B4 D0 F2 67 9A 96 16 90 C8 BF 94 95 48 50 64 FF 5C 89 09 7F 0D 71 4C FD 31 1D 31 96 42 25 3F 01 48 B4 29 0C 31 44 94 E5 98 68 05 E9 24 D3 2D 21 31 93 BC A1 FE 96 2F FF 07 31 29 61 21 45 C3 21 CD 11 0C FF 29 05 FF F9 42 8A FC 8C 2D F4 59 17 44 3F 2D 51 EF 29 09 EF 04 01 FF CF D2 31 BE A9 86 BC 11 3D D8 09 78 D8 29 7F 59 2D FF 56 FF 5C 68 B7 E6 65 A9 3F 9C F2 B8 59 DC 3F 2F 6C 98 7F 5C F3 5D BF 29 39 6C B6 FD 5D A5 EF 93 A1 FC 05 31 91 91 45 89 C5 A3 3F 8E E0 7F 82 21 81 FF 09 2D 0B FF 31 61 D4 09 69 EF 81 85 F5 39 65 DB 29 45 5D E1 1E 0C CB 30 7F 48 29 E3 40 79 09 FF 46 60 7F E7 60 40 29 21 C4 F9 D1 C0 A9 7F 09 27 0C FD 60 3A 1D F5 CA FC 8E 64 1C B1 97 F3 44 0F D3 FF D8 08 93 CD 0C 80 BF 92 69 C2 D0 C8 F1 FF 91 78 BF 8D 34 6C FF A7 68 FB 47 68 88 FF 43 09 6A FD FF 

желательно ещё тумблер вывести, который отсоединяет на время прошивки к-лайн девайса от w-bus. 

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

 Я вывод DTR не подключал, поэтому наверное у меня без зажатия рессета не шьется , я с про мини вообще дел  не имел раньше , только нано и мега , и про микро , а там встроенные на плате ЮСБ-ТТл , а на про микро так вообще юсб встроенное в камень , А можно про микро приспособить под девайс с передлкой платы ?

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

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

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

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

Вот скетч с сообщением старта коммуникации после инита (25мс low 25 мс high) 

v3.62

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



//----------------------------------название ячеек еепром----------------------------------------------------------------
#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 = 15;         // каждые столько мин будет проверка жив ли 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_BEGIN[]         {0x51, 0x0A};
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();

    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("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("+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 >= 9){
  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=9; 
                                                                   if (needAction>0) sendMessage (HEATER_BEGIN, sizeof(HEATER_BEGIN));  }


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 = 9; NeedTimer = 0;  }                   
     
     if (buf[2]==0xD1 && buf[3]==0x0A)  {w_bus_init = 10;   }// если получили ответ на сообщения начала коммуникации                    
                                                                
                  }

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=9;  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 = 9; 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]); 
      }
  
  }
  }

 

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

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

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

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

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

И ещё стирание ошибок на 3.60 не работает пишет ошибки не стерты нет ответа от котла.

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

чтобы понять в чём причина нужно сделать это. 

MaksVV пишет:
Я когда отладку делал у меня на w-bus висел девайс, эмулятор котла и юсб-клайн адаптер. Дак вот юсб к-лайн подключен к WTT в режиме монитора w-bus. И у меня все было видно, что на шине творится. Причем даже инит видно - байтом 00 он проскакивает. Так что рекомендую.

Потому что у меня на эмуле всё четко. Кто знает, может котёл с задержками отвечает или не с первого раза. 

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

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

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

в покое обмена байтами быть не должно.  Когда включаешь котёл, не важно чем - обмен начинает идти раз в 15 сек. (Сначала сообщение на старт, а потом раз в 15 сек поддержание связи старт). Когда идёт диагностика от WTT -  там более частый обмен - раз в секунду примерно сообщения запроса параметров и ошибок. На смартфоне не знаю как подключить юсб к-лайн -  там тоже с этим есть заморочки. А программу для сниффа не обязательно WTT использовать - можно и просто терминал ком порта, в режиме HEX (это я про андроид)

 

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

По моему после нажатия кнопки запустить диагностику в программе монитор порта постоянно что то писал пока не нажмешь закончить диагностику. 

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

Dushman7776 пишет:

По моему после нажатия кнопки запустить диагностику в программе монитор порта постоянно что то писал пока не нажмешь закончить диагностику. 

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

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

Скачал на телефон USB com terminal , сегодня попробую .  Насторойки порта, как я понял,такие скорость 2400 , 8Е1

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

да, все верно

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

Чет ни чего не выходит , наверное я не правильно что то делаю , подцепил я w-bus к-лайн адаптер, запустил на смартфоне программу сериал юсб терминал ,законектился с адаптером на фт 232р, подаю команду на запуск а в мониторе тишина , но котел запустился и работает, может надо не на шину цепляться а на ардуину как нибудь , но есть и хорошие новости , сегодня после манипуляций с к лайн адаптером появилась вторая ошибка 3А, как обычно от моего адаптера, я послал смс на стирание ошибок и они стерлись с первого раза.

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

говорю аппаратно не так просто подцепить юсб устройство к смартфону. Там нужно что то типа OTG или типа того. Не так все просто. 

попробуй ещё раз скетч 3,62. Может временно глючело. Ардуину перезапустить или ещё что. Может юсб-уартТТЛ забыл отключить, например.  

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

гораздо лучше было бы сделать K-лайн блютуз адаптер. Тогда смартфоном легко было бы зацепиться. и провода не мешают. 

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

У меня есть блютуз модуль , может его приспособить, только я думаю что дело в моем шнурке ваговском , у меня после него постоянно ошибка 3А вылазит , можно же прямо на плату девайса на выхода rx,tx повесить юсб-ком конвертер которым я скетчи в ардуино заливаю, я пробовал плату нано3 с прошивкой с первой страницы подцеплять к своему смартфону программа сериал юсб терминал прекрасно видела данные которые ардуино выдавала.

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

тогда проще свой к-лайн адаптер спаять на LM393 и 8 резисторов.   и приспособить к блютуз модулю . Ну или раз говоришь юсб-ттл нормально на телефоне работал, можно к нему приконнектить

#84

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

А есть готовая плата под клайн на lm393? А то не люблю я эти платы рисовать . Хочу сделать типо модуля клайн  по типу ардуиновских к нему можно и блютус модуль и обычный юсб-ком преобразователь подключать а можно в одну коробочку их засунуть и сделать универсальный адаптер. 

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

есть  для юсб уарт.  А также к-лайн шилд для ардуино нано. 

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

Спасибо , я их тоже нашел , вы их раньше выкладывали , у меня только в дипе есть микросхемы , и то даже не LM393  а их аналоги 6914 с какой то японской автомобильной платы спаял , я уже свою платку нарисовал для дип корпуса , завтра вытравлю , а то у нас уже поздно первый час ночи. Может кому сгодитсяhttps://yadi.sk/d/cbjrUg06eRcwHg

Зеркалить не нужно

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

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

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

У меня в городе совсем плохо с радио магазинами, да и детали с японского автопрома надёжнее, сам же рассказывал про подделки . У меня просто очень много этого добра, а старый электролит с какого нибудь японского ЭБУ по параметрам на много лучше нового с магазина. К-ЛАЙН вчера изготовил , сегодня испытаю. А ведь можно бы ло напрямую к rx tx на ардуино проводками подпаяться и читать без всяких клайнов.

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

не понял, к чему нужно было напрямую по Тх Рх? Вроде w-bus собирались сниффить

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

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

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

обмен между WTT и котлом сниффить нет смысла, т.к. в WTT и так весь лог можно посмотреть.  Речь шла засниффить обмен между девайсом  и котлом.  Это можно также сделать посредством подключения  к w-bus третьего абонента, связки: WTT (монитор шины) + usb<->k-line. Но ты сказал, что на андроиде хотел сниффер сделать, т.к. ноута нет. Поэтому стали говорить про терминал на андроиде вместо WTT и типа vagcom не заработал нормально. Тогда я говорю, что надо ещё один к-лайн сделать, чтобы подключить его либо к блютуз адаптеру, либо к юсб-уартТТЛ конвертеру. Вроде так дело было. 

 

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

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

18:12:08.311 Connected to CP210x device
18:12:35.137 00 F4 0A
18:12:35.195 50 30 0A
18:12:35.209 0C 0E 10 12 1E 32 B8 44 03 C4 00 83 44 03 C4 00 83 00 F4 03 20 3B EC 4F 03 A0 3B D7 F4 03 20 3B EC 4F 03 A0 3B D7 F4 03 20 3B EC 4F 03 A0 3B D7 F4 03 20 3B EC F4 04 44 20 00 94 4F 03 A0 3B D7 F4 0A
18:13:23.369 50 30 0A
18:13:23.383 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:13:23.450 0B 0C 3B 0E 2D 5A 10 00 12 00 1E 07 E4 32 00 3E F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:13:35.372 50 30 0A
18:13:35.387 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:13:35.454 0B 0C 3E 0E 2D FA 10 00 12 00 1E 07 DC 32 00 A3 F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:13:47.375 50 30 0A
18:13:47.389 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:13:47.457 0F 0C 3F 0E 2D 00 10 00 12 00 1E 1B BE 32 00 22 F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:13:59.379 50 30 0A
18:13:59.391 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:13:59.459 0F 0C 41 0E 2D 8C 10 00 12 00 1E 20 68 32 00 3D F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:14:11.381 50 30 0A
18:14:11.395 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:14:11.463 0F 0C 46 0E 2D 32 10 00 12 00 1E 23 1B 32 00 F4 F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:14:23.386 50 30 0A
18:14:23.398 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:14:23.468 0F 0C 4B 0E 2D 46 10 00 12 00 1E 22 E0 32 00 77 F4 02 10 E6 4F 02 90 DD 44 02 90 D6 44 02 90 D6 F4 02 10 E6 4F 02 90 DD F4 02 10 E6 4F 02 90 DD F4 02 10 E6 4F 02 90 DD 00 F4 0A
18:15:06.205 50 30 0A
18:15:06.218 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:15:06.286 09 0C 48 0E 2F F8 10 00 12 00 1E 0D 1D 32 00 1C F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C 00 F4 0A
18:16:23.536 50 30 0A
18:16:23.550 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:16:23.618 09 0C 45 0E 2F 9E 10 00 12 00 1E 1B 9C 32 00 E0 F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C 00 F4 03 56 03 A2 00 44 03 C4 00 83 44 03 C4 00 83 00 F4 03 20 3B EC 4F 03 A0 3B D7 F4 02 10 E6 4F 02 90 DD 44 02 90 D6 44 02 90 D6 F4 02 10 E6 4F 02 90 DD F4 02 10 E6 4F 02 90 DD F4 02 10 E6 4F 02 90 DD 00 F4 03 20 3B EC 4F 03 A0 3B D7 F4 03 20 3B EC 4F 03 A0 3B D7 F4 03 20 3B EC 4F 03 A0 3B D7 F4 03 20 3B EC F4 03 56 01 A0 4F 03 A0 3B D7 F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:18:21.597 50 30 0A
18:18:21.611 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:18:21.679 0B 0C 45 0E 2D 32 10 00 12 00 1E 07 E6 32 00 2A F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:18:33.599 50 30 0A
18:18:33.613 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:18:33.681 0B 0C 44 0E 2D 6E 10 00 12 00 1E 07 E5 32 00 74 F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:18:45.602 50 30 0A
18:18:45.616 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:18:45.685 0F 0C 44 0E 2D 00 10 00 12 00 1E 1F 0D 32 00 EE F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 03 56 03 A2 4F 04 7F 56 22 40 F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:18:58.687 50 30 0A
18:18:58.690 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:18:58.758 0F 0C 48 0E 2D 6E 10 00 12 00 1E 22 C0 32 00 7C F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:19:10.680 50 30 0A
18:19:10.693 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:19:10.762 0F 0C 4D 0E 2D 5A 10 00 12 00 1E 22 67 32 00 EA F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 02 10 E6 4F 02 90 DD 44 02 90 D6 44 02 90 D6 F4 02 10 E6 4F 02 90 DD F4 02 10 E6 4F 02 90 DD F4 02 10 E6 4F 02 90 DD 00 F4 03 56 03 A2 4F 04 7F 56 22 40 00 F4 03 56 03 A2 4F 04 7F 56 22 40 00 F4 03 20 3B EC 00 44 03 C4 00 83 44 03 C4 00 83 F4 03 20 3B EC 4F 03 A0 3B D7 F4 03 20 3B EC 4F 03 A0 3B D7 F4 03 20 3B EC F4 04 44 20 00 94 4F 03 A0 3B D7 F4 0A
18:22:10.721 50 30 0A
18:22:10.735 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:22:10.802 0B 0C 46 0E 2C 24 10 00 12 00 1E 07 B7 32 00 6F F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:22:22.725 50 30 0A
18:22:22.740 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:22:22.806 0B 0C 46 0E 2D 46 10 00 12 00 1E 07 D7 32 00 6C F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:22:34.727 50 30 0A
18:22:34.741 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:22:34.810 0F 0C 45 0E 2C 6A 10 00 12 00 1E 1B F7 32 00 7A F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 03 56 03 A2 4F 04 7F 56 22 40 F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:22:46.730 50 30 0A
18:22:46.743 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:22:46.811 0F 0C 48 0E 2D 6E 10 00 12 00 1E 23 00 32 00 BD F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:22:58.732 50 30 0A
18:22:58.746 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:22:58.814 0F 0C 4C 0E 2D 32 10 00 12 00 1E 22 9B 32 00 7F F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 0A
18:23:10.736 50 30 0A
18:23:10.750 0C 0E 10 12 1E 32 B8 4F 13 D0 30 0A
18:23:10.817 0F 0C 50 0E 2C CE 10 00 12 00 1E 23 0B 32 00 0F F4 03 56 01 A0 4F 07 D6 01 01 92 01 01 0C F4 04 44 20 00 94 4F 03 C4 00 88 F4 02 10 E6 4F 02 90 DD 44 02 90 D6 44 02 90 D6 F4 02 10 E6 4F 02 90 DD F4 02 10 E6 4F 02 90 DD F4 02 10 E6 4F 02 90 DD 00 F4 03 56 03 A2 4F 04 7F 56 22 40

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