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

uu5jhu
Offline
Зарегистрирован: 21.11.2017

#include <SoftwareSerial.h>
SoftwareSerial mySerial(14, 15); 

byte led = 13;

void setup() {
  delay(2000);  
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
  Serial.begin(9600);  
  mySerial.begin(9600);
  Serial.println();
  Serial.println("Turn on AOH:");
  mySerial.println("AT+CLIP=1");  //включить АОН
  delay(300);
  Serial.println("Text format sms:");
  mySerial.println("AT+CMGF=1"); // текстовый формат SMS
  delay(300);
  Serial.println("Mode GSM:");
  mySerial.println("AT+CSCS=\"GSM\"");  // кодировка текста - GSM
  delay(300);
  Serial.println("SMS to terminal:");
  mySerial.println("AT+CNMI=2,2,0,0,0"); // вывод смс в консоль
  delay(300);
  
}

void loop() 
{
 if(mySerial.available()) //если модуль что-то послал
  {  
    char ch = ' ';
    String val = "";
    
    while(mySerial.available()) 
     {  
       ch = mySerial.read();
       val += char(ch); //собираем принятые символы в строку
       delay(3);
     }

    Serial.print("Sim send> ");
    Serial.println(val);
    
    if(val.indexOf("+CMT") > -1) //если есть входящее sms
     { 
      if(val.indexOf("On") > -1) // смотрим, что за команда
       {  
         Serial.println("On D13");
         digitalWrite(led, HIGH);  //включаем светодиод
       }

      if(val.indexOf("Off") > -1) // смотрим, что за команда
       { 
         digitalWrite(led, LOW);  //выключаем 
         Serial.println("Off D13");
       }
     } 
  }
}

Попробовал сейчас не меняя схемы(нет ни датчиков Темп ни ОС по Напр...) залить найденный и немного изенённый скетч (тот что выше) - при получении смс (ON or OFF) светодиод переключается......

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

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

такой скетч попробуйте, если не работает, проблема в аппартаной части. СМС нужно слать с текстом ON или OFF , управляем  встроенным светодиодом. 

#include <SoftwareSerial.h>
 
SoftwareSerial gprsSerial(14, 15);
 
//для зелёного светодиода будем использовать второй цифровой вход,
//а для жёлтого - третий

 
void setup()
{
    gprsSerial.begin(19200);
    pinMode(13, OUTPUT);
    digitalWrite (13, 0);
    
 
    // Настраиваем приём сообщений с других устройств
    // Между командами даём время на их обработку
    gprsSerial.print("AT+CMGF=1\r");
    delay(300);
    gprsSerial.print("AT+IFC=1, 1\r");
    delay(300);
    gprsSerial.print("AT+CPBS=\"SM\"\r");
    delay(300);
    gprsSerial.print("AT+CNMI=1,2,2,1,0\r");
    delay(500);
}
 
String currStr = "";
// Переменная принимает значение True, если текущая строка является сообщением
boolean isStringMessage = false;
 
void loop()
{
    if (!gprsSerial.available())
        return;
 
    char currSymb = gprsSerial.read();    
    if ('\r' == currSymb) {
        if (isStringMessage) {
            //если текущая строка - SMS-сообщение,
            //отреагируем на него соответствующим образом
            if (!currStr.compareTo("ON")) {
                digitalWrite(13, HIGH);
            } else if (!currStr.compareTo("OFF")) {
                digitalWrite(13, LOW);
            } 
            
            isStringMessage = false;
        } else {
            if (currStr.startsWith("+CMT")) {
                //если текущая строка начинается с "+CMT",
                //то следующая строка является сообщением
                isStringMessage = true;
            }
        }
        currStr = "";
    } else if ('\n' != currSymb) {
        currStr += String(currSymb);
    }
}

 

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

эмм, не успел ответить ))

uu5jhu
Offline
Зарегистрирован: 21.11.2017

Этот Ваш скетч крайний попробовал - РАБОТАЕТ тоже! =))

uu5jhu
Offline
Зарегистрирован: 21.11.2017

ну то есть ON включает и OFF выключает светодиод!

Таже пробовал ещё один (так же с просторов тырнета) скетч для отправки смс с "СИМкарты webasto" - смс отправляет мне на номер с текстом.... (правда с небольшой грамматической ошибкой непонятно почему-то получаю смс)

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

попробуйте почистить еепром сначала вот этим 

/*
 * EEPROM Clear
 *
 * Sets all of the bytes of the EEPROM to 0.
 * Please see eeprom_iteration for a more in depth
 * look at how to traverse the EEPROM.
 *
 * This example code is in the public domain.
 */

#include <EEPROM.h>

void setup() {
  // initialize the LED pin as an output.
  pinMode(13, OUTPUT);
  Serial.begin (9600);
  /***
    Iterate through each byte of the EEPROM storage.

    Larger AVR processors have larger EEPROM sizes, E.g:
    - Arduno Duemilanove: 512b EEPROM storage.
    - Arduino Uno:        1kb EEPROM storage.
    - Arduino Mega:       4kb EEPROM storage.

    Rather than hard-coding the length, you should use the pre-provided length function.
    This will make your code portable to all AVR processors.
  ***/

  for (int i = 0 ; i < EEPROM.length() ; i++) {
    EEPROM.write(i, 0);
  }

  // turn the LED on when we're done
  

  for (int i = 0 ; i < EEPROM.length() ; i++) {
    Serial.print (EEPROM.read(i)); Serial.print (" ");
  }

  digitalWrite(13, HIGH);
}

void loop() {
  /** Empty loop. **/
}

 

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

в сериал мониторе должно появиться много нулей

uu5jhu
Offline
Зарегистрирован: 21.11.2017

Подтверждаю - спустя пару сек побежали нули

uu5jhu
Offline
Зарегистрирован: 21.11.2017

залил снова после чистки v2.1 - ничего увы не поменялось.....ответное смс на WriteNumber1 не получаю

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

недавно собрал пару модулей, всё работало, соберу ещё один, найду косяк, отпишусь

uu5jhu
Offline
Зарегистрирован: 21.11.2017

Может проблема из-за нестыковки уровней Rx Tx или скорости !? Но со светодиодом работает. А вот смс с СИМ получаю hello @ord вместо hello world.....

uu5jhu
Offline
Зарегистрирован: 21.11.2017

ОК. Будет интересно. Хочу пристроить модуль к своему котлу - Thermo Top С...... запускать думаю сигналом +12В на 30 минут.

toc
Offline
Зарегистрирован: 09.02.2013

MaksVV пишет:

Осталось две фичи реализовать  - энергосбережение и контроль зависания и перезагрузки GSM. Всем спасибо, так активно помогаете.

У меня sim900.
Контроль делал так:
1. Раз в минуту посылаю AT. Если модуль ответил OK - хорошо, cчётчик=0. Иначе +1 к счётчику попыток.
2. Если счётчик >= 5, сбрасываю счётчик и "нажимаю" кнопку питания.
Всё работает более года.
Одно такое событие за год произошло.

uu5jhu
Offline
Зарегистрирован: 21.11.2017

В продолжении попытки получения положительного результата обнаружил что общаясь с модулем через переходник UNO с использованием PuTTY обнаружил что на команду:

AT+ICF?

Приходит сообщение об ошибки.... при этом при попытке отправить смс, оно приходит на телефон...

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

Чтобы посмотреть что происходит на Rх  GSM модуля нужно раскоментировать строку 356 скетча 2.1. а строку 137 поменять на 

Serial.begin (19200);

 Соответственно смотреть в сериал мониторе на скорости 19200

uu5jhu
Offline
Зарегистрирован: 21.11.2017

MaksVV пишет:

Чтобы посмотреть что происходит на Rх  GSM модуля нужно раскоментировать строку 356 скетча 2.1. а строку 137 поменять на 

Serial.begin (19200);

 Соответственно смотреть в сериал мониторе на скорости 19200

Приветствую. Поменял скетч. В мониторе вижу что пришла смс WriteNumber1

Но в ответ так же тишина

 


AT+CMGF=1

OK
+IFC=1, 1
AT+CPBS="SM"

OK
AT+GSMBUSY=1

OK
+CMT: "+7978xxxxxxx","","17/11/22,18:30:46+12"
WriteNumber1
uu5jhu
Offline
Зарегистрирован: 21.11.2017

А вот продолжение - отправляю смс с телефона, в мониторе порта вижу, что получает модуль, а в ответ - тишина =(


AT+CMGF=1

OK
+IFC=1, 1
AT+CPBS="SM"

OK
AT+GSMBUSY=1

OK
+CMT: "+7978xxxxxxx","","17/11/22,18:30:46+12"
WriteNumber1

+CMT: "+7978xxxxxxx","","17/11/22,18:34:40+12"
ZAPROS

+CMT: "+7978xxxxxxx","","17/11/22,18:35:26+12"
ZAPROSTEL
MaksVV
Offline
Зарегистрирован: 06.08.2015

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

Serial.println (""); Serial.println (TelNumber1);

должны нули по идее быть

uu5jhu
Offline
Зарегистрирован: 21.11.2017

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

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

то что в строке 140   NastroykaGSM ();

переместить после строки 147 (после  Serial.println (""); Serial.println (TelNumber1);  )

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

uu5jhu
Offline
Зарегистрирован: 21.11.2017

#include <EEPROM.h>
// для GSM модуля *********************
#include <SoftwareSerial.h>
SoftwareSerial mySerial(14, 15); //Rx, Tx
String currStr = "";

String TelNumber1 = "000000000000";

String TelNumber2 = "000000000000";

String BufferNumber = "000000000000";

bool SaveNumber2 = 0;  // флаг когда необходима запись номера#2, он true

int isStringMessage = 0; 
int KTOzapros = 0;
int KTOreport = 1;
//************************


int Protocol = 1; // протокол, по которому будет происходить выход на запуск котла: 1 - импульсный минусовой выход (на впайку в таймер вебасто например)
                  // 2 - по протоколу W-BUS ( котлы TermoTOP EVO)
                  // 3 - по подаче потенциала 12В, т.е. пока висит +12В - котел включен (котлы по аналогу - TermoTOP C,E)

                  
//_______Все для цикла void voltmetr()*************
float vout = 0.0;      // Напряжение на входе аналового входа
float Vpit = 0.0;      // Измеряемое напряжение на выходе ИБП
  int volt = 0;        // Напряжение на входе АЦП

// входы выходы на соостветствующие пины **************
#define DopOn 4      // сюда доп канал от сигналки на включение вебасто
#define DopOff  5    // сюда доп канал от сигналки на выключение вебасто
#define VyhodWebasto  12     // это импульсный минусовой выход вкл/выкл вебасто к таймеру. 
#define VyhodWebastoAnalog  3  // это потенциальный плюсовой выход вкл/выкл вебасто (напрямую к котлу без таймера). 
#define Sost  9      // Сюда состояние вебасто (+12В когда работает)

#define Ohrana  6      // Сюда состояние охраны сигналки
#define Trevoga  7      // Сюда состояние тревоги
#define StartEng 8   // это импульсный минусовой выход вкл/выкл ДВС. подключать на вход событий сиги.
#define IGN 10       // Сюда состояние зажигания
#define Eng 11       // Сюда состояние работы ДВС




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

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

byte VyhlopC[8] ={0x28, 0xFF, 0xE6, 0x14, 0x90, 0x15, 0x04, 0x62}; 
byte EngineC[8] ={0x28, 0xFF, 0x06, 0x15, 0x90, 0x15, 0x04, 0x37}; 
byte UlicaC[8] ={0x28, 0xFF, 0x43, 0x42, 0xA8, 0x15, 0x03, 0x2A};  
byte SalonC[8] ={0x28, 0xFF, 0xE0, 0x19, 0xA8, 0x15, 0x01, 0xA7};  
volatile int  TempVyhlopC = 20;
volatile int  TempEngineC = 20;
volatile int  TempUlicaC = 20;
volatile int  TempSalonC = 20;

// для организации W-BUS и различные таймеры********************
byte Zapusk20[5] = {0xF4,0x03, 0x20, 0x3B, 0xEC} ;
byte Zapusk21[5] = {0xF4,0x03, 0x21, 0x3B, 0xED} ;
byte Stop[4] = {0xF4,0x02, 0x10, 0xE6} ;

bool flagStartPresent = 1;               //флаг что отправляем в момент периодического поддержания связи W-Bus status или start
int StartMessageRepeat = 0;              //количество отправленных сообщений на старт котла
int StopMessageRepeat = 0;               //количество отправленных сообщений на остановку котла

unsigned long TimeWebasto = 1800000;   //время работы котла, 1800000 = 30мин
unsigned long EndReportMillis = 0;     //переменная для таймера отправки отчета об успешности запуска котла
unsigned long EndReportEngine = 0;     //переменная для таймера отправки отчета об успешности запуска ДВС
unsigned long Prev_PeriodW_BusMessage = 0;     //переменная для таймера периодической отправки сообщений состояния котла в шину W-Bus 
unsigned long Prev_PeriodW_BusStartStop = 0;       //переменная для таймера периодической отправки сообщений старта/стопа котла в шину W-Bus 

//для таймера  - активация котла - импульс массы 0,8 сек на провод, впаянный в таймер вебасто)
unsigned long time, timer=0;
bool timerenabled=false;
#define TIMEREXPIRED (time-timer)>800


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


//для таймера  - старт котла по W-BUS )
unsigned long TimeStart_W_BUS, timerStart_W_BUS=0;
bool timerenabledStart_W_BUS=false;
#define TIMEREXPIRED_Start_W_BUS (TimeStart_W_BUS-timerStart_W_BUS)> TimeWebasto 

//**************************


//Основные переменные  
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; //флаг отправлена ли смс о тревоге или нет





// СТАРТОВЫЙ ЦИКЛ
void setup() 
{
 delay (2500);
  WDTCSR=(1<<WDCE)|(1<<WDE); //для датчиков DS18B20
 // WDTCSR=(1<<WDIE)| (1<<WDP2)|(1<<WDP1); // для датчиков DS18B20 (разрешение прерывания + выдержка 1 секунда)
  WDTCSR=(1<<WDIE)| (1<<WDP3)|(1<<WDP0); // для датчиков DS18B20 (разрешение прерывания + выдержка 8 секунд)
  pinMode (DopOn,  INPUT);   digitalWrite (DopOn,  HIGH);
  pinMode (DopOff, INPUT);   digitalWrite (DopOff, HIGH);
  pinMode (Sost,   INPUT);   digitalWrite (Sost,   HIGH);
  pinMode (VyhodWebasto,  OUTPUT);  digitalWrite (VyhodWebasto,  HIGH);
  pinMode (VyhodWebastoAnalog,  OUTPUT);  digitalWrite (VyhodWebastoAnalog,  LOW);
  pinMode (StartEng,  OUTPUT);  digitalWrite (StartEng,  LOW);
  pinMode (13,     OUTPUT);  digitalWrite (13,     LOW);

  pinMode (Ohrana, INPUT);  digitalWrite (Ohrana,  HIGH);
  pinMode (Trevoga, INPUT);  digitalWrite (Trevoga,  HIGH);
  pinMode (IGN, INPUT);  digitalWrite (IGN,  HIGH);
  pinMode (Eng, INPUT);  digitalWrite (Eng,  HIGH);
  



   
  
Serial.begin (19200); // сериал соединение протокол W-Bus
mySerial.begin(19200);           // сериал соединение для gsm модуля
    delay(2000);

TimeWebasto = EEPROM.read(1)*60000UL;
Protocol = EEPROM.read(2);

for (int i=0; i<12; i++) TelNumber1[i] = EEPROM.read (i+10);
for (int i=0; i<12; i++) TelNumber2[i] = EEPROM.read (i+30);
Serial.println (""); Serial.println (TelNumber1);
NastroykaGSM ();  
}








void loop() {

if (Protocol==1||Protocol==3) {webasto = !digitalRead (Sost);
    if (TempVyhlopC - TempUlicaC > 20) startWebasto_OK = 1;
    else startWebasto_OK = 0;}


if (Protocol==2)W_Bus();
//ниже для таймера старта котла по W-BUS и аналогу 
  TimeStart_W_BUS = millis();
  if (timerenabledStart_W_BUS){
   if (TIMEREXPIRED_Start_W_BUS) {
    digitalWrite (VyhodWebastoAnalog,LOW); webasto=0; timerenabledStart_W_BUS = false;}}

//ниже для таймера создания импульса на старт ДВС 
TimeStartEng = millis();
if (timerenabledStartEng) {
if (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 (trevoga && !alarmSMS) AlarmSMS ();
if (!ohrana) alarmSMS = false;

readSMS();
voltmetr();
WebastoOprosImpulse ();


}

void voltmetr()  //____________Цикл "Вольтметр"__измерение напряжения на выходе ИБП
// Взято с <a href="<a href="<a href="<a href="http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html" rel="nofollow">http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html</a>" rel="nofollow"><a href="http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html" rel="nofollow">http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html</a></a>" rel="nofollow"><a href="<a href="http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html" rel="nofollow">http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html</a>" rel="nofollow"><a href="http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html" rel="nofollow">http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html</a></a></a>" rel="nofollow"><a href="<a href="<a href="http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html" rel="nofollow">http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html</a>" rel="nofollow"><a href="http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html" rel="nofollow">http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html</a></a>" rel="nofollow"><a href="<a href="http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html" rel="nofollow">http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html</a>" rel="nofollow"><a href="http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html" rel="nofollow">http://digitrode.ru/computing-devices/mcu_cpu/87-voltmetr-na-arduino.html</a></a></a></a>
{
   volt = analogRead(A7);                       // А7 аналоговый вход вольтметра
   vout = (volt * 4.92) / 1024;             
   Vpit = vout / (9950.0/(98930.0+9950.0));  // По формуле Vpit = vout / (R2/(R1+R2)) 
   if (Vpit<0.09)  Vpit=0.0;                  // Округление до нуля 
}






// Вектор прерывания для Dallas DS18B20
ISR (WDT_vect){ //вектор прерывания WD
static boolean n=0; // флаг работы: запрос температуры или её чтение
n=!n;
if (n) {ds.reset();  // сброс шины
        ds.write(0xCC);//обращение ко всем датчикам
        ds.write(0x44);// начать преобразование (без паразитного питания)  
       }
else   {ds.reset();
        ds.select(VyhlopC);    
        ds.write(0xBE); // Read Scratchpad (чтение регистров)  
        TempVyhlopC =  ds.read() | (ds.read()<<8); //прочитаны 2 байта       
        TempVyhlopC = TempVyhlopC / 16;
        // получение с 2-го датчика
        ds.reset();
        ds.select(EngineC);    
        ds.write(0xBE); // Read Scratchpad (чтение регистров)  
        TempEngineC =  ds.read() | (ds.read()<<8); //прочитаны 2 байта  
        TempEngineC = TempEngineC/16;
        ds.reset();
        ds.select(UlicaC);    
        ds.write(0xBE); // Read Scratchpad (чтение регистров)  
        TempUlicaC =  ds.read() | (ds.read()<<8); //прочитаны 2 байта       
        TempUlicaC = TempUlicaC / 16;
        // получение с 2-го датчика
        ds.reset();
        ds.select(SalonC);    
        ds.write(0xBE); // Read Scratchpad (чтение регистров)  
        TempSalonC =  ds.read() | (ds.read()<<8); //прочитаны 2 байта  
        TempSalonC = TempSalonC/16 ;
}}




                    


void StartWebasto()
{
 if (Protocol==1){ digitalWrite (VyhodWebasto, LOW); 
  timer=time; 
  timerenabled=true;}

 else if (Protocol==2||Protocol==3){
  StartMessageRepeat = 0;
  webasto = 1; digitalWrite (VyhodWebastoAnalog, HIGH);
  timerStart_W_BUS=TimeStart_W_BUS;
  timerenabledStart_W_BUS = true;}
}

void StopWebasto()
{
 if (Protocol==1){ digitalWrite (VyhodWebasto, LOW); 
  timer=time; 
  timerenabled=true;}

 else if (Protocol==2||Protocol==3){
  StopMessageRepeat = 0;
  webasto = 0; digitalWrite (VyhodWebastoAnalog, LOW);
  timerenabledStart_W_BUS = false;}
}




void WebastoOprosImpulse (){

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


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

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





   void NastroykaGSM () {
      mySerial.print(F("AT+CMGF=1\r"));         //устанавливает текстовый режим смс-сообщения
    delay(200);
  mySerial.print(F("+IFC=1, 1\r"));       //устанавливает программный контроль потоком передачи данных
    delay(200);
  mySerial.print(F("AT+CPBS=\"SM\"\r"));    //открывает доступ к данным телефонной книги SIM-карты
    delay(200);
  mySerial.print(F("AT+GSMBUSY=1\r"));   //запрет всех входящих звонков
    delay(300);
  mySerial.print(F("AT+CNMI=1,2,2,1,0\r")); //включает оповещение о новых сообщениях
    delay(300);
  mySerial.print(F("AT+CMGDA=\"DEL ALL\"\r")); // удаляем все смс, ки
   delay(2000);
}

void startNumber1SMS() //__________________Цикл подготовки модуля к отправке СМС-сообщений по первому номеру
{
      mySerial.print(F("AT+CMGF=1\r"));
      delay(200);
  mySerial.print(F("AT+CMGS=\"")); mySerial.print(TelNumber1); mySerial.println("\""); 
      delay(400);
}

void startNumber2SMS() //__________________Цикл подготовки модуля к отправке СМС-сообщений по второму  номеру
{
      mySerial.print(F("AT+CMGF=1\r"));
      delay(200);
      mySerial.print(F("AT+CMGS=\"")); mySerial.print(TelNumber2); mySerial.println(F("\"")); 
      delay(400);
}

void startBufferNumberSMS() //__________________Цикл подготовки модуля к отправке СМС-сообщений по второму  номеру
{
      mySerial.print(F("AT+CMGF=1\r"));
      delay(200);
      mySerial.print(F("AT+CMGS=\"")); mySerial.print(BufferNumber); mySerial.println(F("\"")); 
      delay(400);
}

void WriteNubmer1() {
  
  
  
  
  }


void EndSMS ()
{
   mySerial.println((char)26);                       // Команда отправки СМС
   delay(3000);
   mySerial.print(F("AT+CMGDA=\"DEL ALL\"\r")); // удаляем все смс, ки
   delay(1500);
}


void readSMS() //_____Цикл чтения входящих СМС-сообщений______________     
{
    if (!mySerial.available()) return;
    char currSymb = mySerial.read();
Serial.print (currSymb);
    if ('\r' == currSymb)
       {
         if (isStringMessage!=0&&isStringMessage!=10) //если текущая строка - SMS-сообщение, отреагируем на него соответствующим образом
                {
if (!currStr.compareTo("ZAPROS"))   { SMSzapros();}               // Передача параметров по СМС
else if (!currStr.compareTo("ZAPROSTEL"))   { SMSzaprosTEL();}               // Передача номеров телефонов пользователей по СМС



else if (!currStr.compareTo("Webasto-ON"))  { if (!webasto)  {StartWebasto (); report = true; EndReportMillis = millis(); // если получили команду на включение и вебаста в настоящий момент выключена - включаем
                                                                              if (isStringMessage == 1) {startNumber1SMS(); KTOreport = 1;}
                                                                         else if (isStringMessage == 2) {startNumber2SMS();  KTOreport = 2;}
                                                                         mySerial.println(F("Webasto Vkluchena")); EndSMS();}
                                                                       
                                                   else                     {if (isStringMessage == 1) startNumber1SMS(); 
                                                                        else if (isStringMessage == 2) startNumber2SMS(); 
                                                                        mySerial.println(F("Webasto uzhe vkluchena")); EndSMS();}}

                                                            
               else if (!currStr.compareTo("Webasto-OFF"))   {if (webasto){StopWebasto (); report = false; // если получили команду на выключение и вебаста в настоящий момент включена - выключаем
                                                                              if (isStringMessage == 1) startNumber1SMS(); 
                                                                        else  if (isStringMessage == 2) startNumber2SMS();
                                                                        mySerial.println(F("Webasto Otkluchena")); EndSMS();}


                                                     else                    {if (isStringMessage == 1) startNumber1SMS(); 
                                                                         else if (isStringMessage == 2) startNumber2SMS(); 
                                                                         mySerial.println(F("Webasto uzhe otkluchena")); EndSMS();}}          


                else if (!currStr.compareTo("Engine-ON"))  {if (!engine)  { digitalWrite (StartEng, HIGH);  timerStartEng=TimeStartEng; timerenabledStartEng=true; reportEngine = true; EndReportEngine = millis(); // если получили команду на включение ДВС и он в настоящий момент выключен - включаем
                                                                              if (isStringMessage == 1) {startNumber1SMS();  KTOreport = 1;}
                                                                         else if (isStringMessage == 2) {startNumber2SMS();  KTOreport = 2;}
                                                                         mySerial.println(F("Engine Start")); EndSMS();}
                                                                       
                                                   else                     {if (isStringMessage == 1) startNumber1SMS(); 
                                                                        else if (isStringMessage == 2) startNumber2SMS();
                                                                        mySerial.println(F("Dvigatel uzhe rabotaet")); EndSMS();}}
                                                                                 
               else if (!currStr.compareTo("Engine-OFF"))   {if (engine){ digitalWrite (StartEng, HIGH);  timerStartEng=TimeStartEng; timerenabledStartEng=true; reportEngine = false; // если получили команду на выключение ДВС и он в настоящий момент работает - выключаем
                                                                              if (isStringMessage == 1) startNumber1SMS();
                                                                        else  if (isStringMessage == 2) startNumber2SMS();
                                                                        mySerial.println(F("Dvigatel ostanovlen")); EndSMS();}


                                                     else                    {if (isStringMessage == 1) startNumber1SMS(); 
                                                                         else if (isStringMessage == 2) startNumber2SMS();
                                                                         mySerial.println(F("dvigatel uzhe ostanovlen")); EndSMS(); }}          
                                                    

               else if (!currStr.compareTo("Impulse"))   {Protocol = 1;  EEPROM.write(2,Protocol);     if (isStringMessage == 1) {startNumber1SMS(); mySerial.println(F("zapusk GND_impulse")); EndSMS();}
                                                                        else  if (isStringMessage == 2) {startNumber2SMS(); mySerial.println(F("zapusk GND_impulse")); EndSMS();}}                                                               

               else if (!currStr.compareTo("W-BUS"))   {Protocol = 2; EEPROM.write(2,Protocol);  webasto = 0;  if (isStringMessage == 1) {startNumber1SMS(); mySerial.println(F("zapusk W-BUS")); EndSMS();}
                                                                        else  if (isStringMessage == 2) {startNumber2SMS(); mySerial.println(F("zapusk W_BUS")); EndSMS();}}

               else if (!currStr.compareTo("Potenzial"))   {Protocol = 3; EEPROM.write(2,Protocol);   if (isStringMessage == 1) {startNumber1SMS(); mySerial.println(F("zapusk +12V Potencial")); EndSMS();}
                                                                        else  if (isStringMessage == 2) {startNumber2SMS(); mySerial.println(F("zapusk +12V Potencial")); EndSMS();}} 

               
                else if (currStr.endsWith("min"))   {TimeWebasto = currStr.toInt()*60000UL; // для задания время цикла работы отправить сообщение вида "25 min", где 25 время работы в мин
               if (TimeWebasto>3540000UL) TimeWebasto = 3540000UL;
               if (TimeWebasto<=600000UL) TimeWebasto = 600000UL;
               EEPROM.write(1,TimeWebasto/60000UL);
                     if (isStringMessage == 1)startNumber1SMS(); 
               else  if (isStringMessage == 2) startNumber2SMS(); 
               mySerial.print(F("Webasto time: ")); mySerial.print(TimeWebasto/60000UL); mySerial.print(F("min")); EndSMS();}
               

               else if (!currStr.compareTo("ResetNumbers"))   {if (isStringMessage == 1) {startNumber1SMS(); mySerial.println(F("Phone numbers are erased")); EndSMS(); 
                                                                     
             TelNumber1 = "000000000000"; TelNumber2 = "000000000000"; for (int i=0; i<12; i++) {EEPROM.write (i+10,  TelNumber1[i]); EEPROM.write (i+30,  TelNumber2[i]); }}}

              else if (!currStr.compareTo("WriteNumber2")&& isStringMessage == 1)   { 
                SaveNumber2 = 1; startNumber1SMS(); mySerial.println(F("Otpravte lyuboye SMS s nomera2 dlya sochraneniya nomera")); EndSMS();} 

                                                                        

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



                
         else if (isStringMessage==0) {  if (TelNumber1!="000000000000" && !SaveNumber2 && TelNumber1!="яяяяяяяяяяяя"){
         
                     if (currStr.startsWith("+CMT: \""+TelNumber1)) { isStringMessage = 1; KTOzapros = 1; }   
                else if (currStr.startsWith("+CMT: \""+TelNumber2)) { isStringMessage = 2; KTOzapros = 2; }   
                else if (currStr.startsWith("+CUSD: 0,"))  //если текущая строка начинается с "+CUSD",то следующая строка является запросом баланса
                  {
                       if (KTOzapros == 1) startNumber1SMS();
                  else if (KTOzapros == 2) startNumber2SMS();
                  mySerial.print (currStr);
                  EndSMS();
                  }    
                                                }

                else if    (currStr.startsWith("+CMT:") && !SaveNumber2) { isStringMessage = 10; for (int i =0; i<12; i++) {BufferNumber[i]=currStr[i+7];}}
                else if    (currStr.startsWith("+CMT:") && SaveNumber2) { for (int i =0; i<12; i++) {BufferNumber[i]=currStr[i+7];} TelNumber2 = BufferNumber; for (int i=0; i<12; i++) {EEPROM.write (i+30, BufferNumber[i]);}
              startNumber2SMS(); mySerial.println(F("Vash nomer sochranyon kak Number#2 v pamyati!")); 
              mySerial.print(F("Tel1: ")); mySerial.println(TelNumber1); mySerial.print(F("Tel#2: "));  mySerial.println (TelNumber2); EndSMS(); SaveNumber2 = 0; } 
              
              } 
               
        currStr = "";
      } 
 
    else if ('\n' != currSymb) { currStr += String(currSymb);}
}


void SMSzapros()
{   if (isStringMessage == 10){
 startBufferNumberSMS();

 mySerial.println (F("Tel.number#1 is not has been saving in memory!"));
 mySerial.println (F("For save Tel1 send SMS command \"WriteNumber1\""));
  mySerial.print(F("Tel1: ")); mySerial.println(TelNumber1);
  mySerial.print(F("Tel2: ")); mySerial.println(TelNumber2); 
  }
  
  
  
  else {
  
  if (isStringMessage == 1) { startNumber1SMS();}
  else if (isStringMessage == 2) { startNumber2SMS();}
  else if (isStringMessage == 0) {if  (KTOreport == 1) startNumber1SMS();
                             else if  (KTOreport == 2) startNumber2SMS();}
        if (webasto) { mySerial.println (F("Webasto ON"));
           if (startWebasto_OK) mySerial.println (F("StartWebasto OK"));
           else mySerial.println (F("StartWebasto FAIL"));}
     else mySerial.println (F("Webasto OFF"));  

     if (engine)  mySerial.println (F("Engine ON"));
     else mySerial.println (F("Engine OFF"));  

     if (ignition)  mySerial.println (F("IGN ON"));
     else mySerial.println (F("IGN OFF"));  

     if (ohrana)  mySerial.println (F("OHRANA ON"));
     else mySerial.println (F("OHRANA OFF"));  

     if (trevoga)  mySerial.println (F("Vnimanie!!! Trevoga!!! Sirena Vkl!"));
     
  mySerial.print(F("Battery: ")); mySerial.print (Vpit); mySerial.println(F("V"));
  mySerial.print(F("Engine: ")); mySerial.print (TempEngineC); mySerial.println(F("*C"));
  mySerial.print(F("Vyhlop: ")); mySerial.print (TempVyhlopC); mySerial.println(F("*C"));
  mySerial.print(F("Ulica: ")); mySerial.print (TempUlicaC); mySerial.println(F("*C"));
  mySerial.print(F("Salon: ")); mySerial.print (TempSalonC); mySerial.println(F("*C"));  
  mySerial.print(F("Protocol: "));
       if (Protocol==1) mySerial.println(F("GND Impulse"));
  else if (Protocol==2) mySerial.println(F("W-BUS"));
  else if (Protocol==3) mySerial.println(F("+12V Potencial"));
  mySerial.print(F("Webasto Time: ")); mySerial.print (TimeWebasto/60000UL); mySerial.println(F("min"));
 
  }  
   EndSMS();                                 
}

void SMSzaprosTEL(){
  if (isStringMessage == 1) { startNumber1SMS();}
  else if (isStringMessage == 2) { startNumber2SMS();}
  else if (isStringMessage == 10) { startBufferNumberSMS();}
  
  
  mySerial.print(F("Tel1: ")); mySerial.println(TelNumber1);
  mySerial.print(F("Tel2: ")); mySerial.println(TelNumber2); 
  if (TelNumber1!="000000000000" && TelNumber1!="яяяяяяяяяяяя"){
  mySerial.print(F("Protocol: "));
  if (Protocol==1) mySerial.println(F("GND Impulse"));
  else if (Protocol==2) mySerial.println(F("W-BUS"));
  else if (Protocol==3) mySerial.println(F("+12V Potencial"));
  mySerial.print(F("Webasto Time: ")); mySerial.print (TimeWebasto/60000UL); mySerial.println(F("min"));}
  EndSMS();                                 
  }


void SMSbalance() {
  mySerial.print(F("AT+CMGF=1\r"));
      delay(200);

mySerial.println (F("AT+CUSD=1,\"#100#\""));
    
//mySerial.println("AT+CMGS=\"#100#\"");
//      mySerial.println("ATD#100#");
      //mySerial.println("AT + CMGS = \"111\""); // 
      delay(2000);                              // команда на замену на транслит *111*6*2#
      //mySerial.println ("11");
      //EndSMS();
}


void AlarmSMS() {
 startNumber1SMS();
mySerial.println (F("Vnimanie!!! Trevoga!!! Sirena Vkl!"));
 EndSMS();      
 startNumber2SMS();
mySerial.println (F("Vnimanie!!! Trevoga!!! Sirena Vkl!"));
 EndSMS();      
 alarmSMS = true;
  
}void W_Bus (){
if (webasto) {
    if (StartMessageRepeat<4 && (millis()-Prev_PeriodW_BusStartStop>800)){

 for (int i = 0; i<5; i++) Serial.write (Zapusk21[i]); 
  StartMessageRepeat++; 
  Prev_PeriodW_BusStartStop = millis();
  
    }
  if (StartMessageRepeat>=4){ if (millis()-Prev_PeriodW_BusMessage>5000)  {
    //делаем периодическое поддержание связи W-BUS
    // наверное сканает отправка сообщения о состоянии котла
    // т.е. ,например, отправляем периодически запрос на показания датчиков
    // состоянием работы котла будет наличие или отсутствие пламени
if (flagStartPresent) {for (int i = 0; i<5; i++) Serial.write (Zapusk21[i]); }
//else {for (int i = 0; i<5; i++) Serial.write (StateMessage[i]);}
flagStartPresent = !flagStartPresent;
StopMessageRepeat = 0;
    
    Prev_PeriodW_BusMessage = millis();
    }}}





else if (StopMessageRepeat<4 && (millis()-Prev_PeriodW_BusStartStop>800)){
  for (int i = 0; i<4; i++) Serial.write (Stop[i]); 
StopMessageRepeat++; 
StartMessageRepeat = 0;
   Prev_PeriodW_BusStartStop = millis();
  
  
  }

}




Получился вот такой скетч если правильно Вас понял. Но в терминале ничего нового. Наверное я не правильно Вас понял.
uu5jhu
Offline
Зарегистрирован: 21.11.2017
AT+CMGF=1

OK
+IFC=1, 1
AT+CPBS="SM"

OK
AT+GSMBUSY=1

OK

 

uu5jhu
Offline
Зарегистрирован: 21.11.2017

Ага разобрался перекинул часть программы за "строку 147" - - - - да первые нули

 

000000000000

потом

AT+CMGF=1

OK
+IFC=1, 1
AT+CPBS="SM"

OK
AT+GSMBUSY=1

OK

 

uu5jhu
Offline
Зарегистрирован: 21.11.2017

Получилось вот так:

pinMode (IGN, INPUT);  digitalWrite (IGN,  HIGH);
  pinMode (Eng, INPUT);  digitalWrite (Eng,  HIGH);
  



   
  
Serial.begin (19200); // сериал соединение протокол W-Bus
mySerial.begin(19200);           // сериал соединение для gsm модуля
    delay(2000);
  


Serial.println (""); Serial.println (TelNumber1);

NastroykaGSM ();  

TimeWebasto = EEPROM.read(1)*60000UL;
Protocol = EEPROM.read(2);

for (int i=0; i<12; i++) TelNumber1[i] = EEPROM.read (i+10);
for (int i=0; i<12; i++) TelNumber2[i] = EEPROM.read (i+30);
}








void loop() {

 

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

почистите еепром таким скетчем и заливайте 2.1 без измнений, должно всё заработать по идее



#include <EEPROM.h>

void setup() {
 
  pinMode(13, OUTPUT);
   digitalWrite(13, 0);
  
 

  for (int i = 0 ; i < EEPROM.length() ; i++) EEPROM.write(i, '0'); 
  
  digitalWrite(13, HIGH);
}

void loop() {}

 

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

Когда EEprom был у вас ещё не тронутый (во всех ячейках FF),то заработало бы, если бы вы скетч заливали сразу после копипаста (без сохранения скетча на компе). При сохранении скетча на компе сбивается кодировка символов соответсвующих байту FF (который в еепроме был изначально), т.е. символа "я" и все косяки из-за этого, а потом я вам немного неправильно почистить еепром предложил, поэтому тоже не работало. Исправил в начале темы как еепром чистить до заливки скетча. 

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

uu5jhu пишет:
Получилось вот так:

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

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

uu5jhu
Offline
Зарегистрирован: 21.11.2017

MaksVV пишет:

почистите еепром таким скетчем и заливайте 2.1 без измнений, должно всё заработать по идее



#include <EEPROM.h>

void setup() {
 
  pinMode(13, OUTPUT);
   digitalWrite(13, 0);
  
 

  for (int i = 0 ; i < EEPROM.length() ; i++) EEPROM.write(i, '0'); 
  
  digitalWrite(13, HIGH);
}

void loop() {}

 

 

 

Приветствую. Спасибо Вам огромное за проделанную работу, всё теперь получилось (пошёл покупать недостающие детали и буду собирать до конца – смс ки отправляю – в ответ приходят подтверждения и инфо о состоянии – попробовал пока только с напряжением питания) - давно занялся поиском чего-то подобного для запуска котла по смс. Об arduino узнал недавно и пока что всё в процессе начинания и изучения. Изначально была идея запускать по шине CAN (точнее сказать в моей машине по периферийной шине i-bus через приборную панель) и по CAN отслеживать и отправлять сообщение о состоянии котла, температуре ОЖ и бортовом напряжении. Но для этого, как понимаю, нужно знать протокол обмена… Но с выносными датчиками, кому не лень, тоже всё хорошо.

Готов нарисовать и выложить нарисованную схему, для тех «ленивых» кто спрашивает её, но пока не пойму как прикрепить рисунок.

uu5jhu
Offline
Зарегистрирован: 21.11.2017

По ходу макетирования появилось несколько вопросов.

1. sms на запрос баланса приходят в HEX unicode =(  /лечится заменой оператора или можно программой?/

2. не знаю как на версиях Webasto которые устанавливают как доп, но на "старых" например, моделях БМВ есть несколько условий при которых котёл не будет запущен - (с завода котёл кстати, работал только как "догревайка", но перекодировка творит чудеса и теперь работает ещё и как "автономное отопление" без колхозинга) - одно из них пониженное напряжение питания (недавно у товарища попытались запустить котёл при разряженной АКБ U=11.6V) - сигнал на запуск пришел, а вот котёл не запустился пока не зарядили АКБ. И это считаю правильная задумка - зачем тёплый двигатель, если стартер не крутится. Не увидел организованно ли это в Вашей программе уважаемый автор, но возможно, это будет своим образом аварийная защита, для котлов которые будут рады усадить АКБ в ноль (если такие существуют, конечно)

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

uu5jhu пишет:
Изначально была идея запускать по шине CAN (точнее сказать в моей машине по периферийной шине i-bus через приборную панель) и по CAN отслеживать и отправлять сообщение о состоянии котла, температуре ОЖ и бортовом напряжении. Но для этого, как понимаю, нужно знать протокол обмена… Но с выносными датчиками, кому не лень, тоже всё хорошо.

Я так понимаю котел у вас штатный, да к тому же по CAN управляется . Вы уверены в возможности запуска его по аналогу? Вообще чтобы по CAN запускать конечно нужно знать протокол обмена. Но исследование CAN шины тоже дело интересное, хотя и не лёгкое. Если будет интересно, могу выложить проект CAN хакера на ардуино (там собственно сама ардуино и китайский модуль кана на MCP2515),  который как раз и позволяет выявить из CAN шины нужные сообщения. 

Короче в будущем конечно неплохо было бы дополнить данное устройство CAN шиной, но работы с этим не мало будет, особенно в программной части  - протоколы разных авто. 

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

А вы если только аналог будете использовать вам можно не ставить микруху LM393 и всю её обвязку

 

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

uu5jhu пишет:

По ходу макетирования появилось несколько вопросов.

1. sms на запрос баланса приходят в HEX unicode =(  /лечится заменой оператора или можно программой?/

 

2. не знаю как на версиях Webasto которые устанавливают как доп, но на "старых" например, моделях БМВ есть несколько условий при которых котёл не будет запущен - (с завода котёл кстати, работал только как "догревайка", но перекодировка творит чудеса и теперь работает ещё и как "автономное отопление" без колхозинга) - одно из них пониженное напряжение питания (недавно у товарища попытались запустить котёл при разряженной АКБ U=11.6V) - сигнал на запуск пришел, а вот котёл не запустился пока не зарядили АКБ. И это считаю правильная задумка - зачем тёплый двигатель, если стартер не крутится. Не увидел организованно ли это в Вашей программе уважаемый автор, но возможно, это будет своим образом аварийная защита, для котлов которые будут рады усадить АКБ в ноль (если такие существуют, конечно)

 

1. Намного проще через оператора решить. (Ну всмысле не заменой его, а подбором правильной команды запроса баланса, либо есть такая функция у некоторых перевода на транслит.)  Парсить этот юникод и PDU полный песец. 

2. По напряжению АКБ по идее во всех котлах есть выключение. Я не стал делать выключение по напряжению. Но это не сложно - пару строк добавить. 

 

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

на скорую руку состряпал скетч v2.2  и переделал плату. Добавлено: 

- тактовая кнопка  вкл/выкл с индикацией состояния команды на работу котла;

- рестарт GSM модуля в случае если он не отвечает ("завис") при помощи кратковременного оключения питания средствами реле;

- запись в еепром количество рестартов;

Но это вообще ничего не проверено, т.к. деталей нет и проверить пока некогда

#include <EEPROM.h>
#include <Button.h>

Button test;

// для GSM модуля *********************
#include <SoftwareSerial.h>
SoftwareSerial mySerial(14, 15); //Rx, Tx
String currStr = "";

String TelNumber1 = "000000000000";

String TelNumber2 = "000000000000";

String BufferNumber = "000000000000";

bool SaveNumber2 = 0;  // флаг когда необходима запись номера#2, он true

int isStringMessage = 0; 
int KTOzapros = 0;
int KTOreport = 1;
//************************


int Protocol = 1; // протокол, по которому будет происходить выход на запуск котла: 1 - импульсный минусовой выход (на впайку в таймер вебасто например)
                  // 2 - по протоколу W-BUS ( котлы TermoTOP EVO)
                  // 3 - по подаче потенциала 12В, т.е. пока висит +12В - котел включен (котлы по аналогу - TermoTOP C,E)

                  
//_______Все для цикла void voltmetr()*************
float vout = 0.0;      // Напряжение на входе аналового входа
float Vpit = 0.0;      // Измеряемое напряжение на выходе ИБП
  int volt = 0;        // Напряжение на входе АЦП

// входы выходы на соостветствующие пины **************
#define DopOn 4      // сюда доп канал от сигналки на включение вебасто
#define DopOff  5    // сюда доп канал от сигналки на выключение вебасто
#define VyhodWebasto  12     // это импульсный минусовой выход вкл/выкл вебасто к таймеру. 
#define VyhodWebastoAnalog  3  // это потенциальный плюсовой выход вкл/выкл вебасто (напрямую к котлу без таймера). 
#define Sost  9      // Сюда состояние вебасто (+12В когда работает)

#define Ohrana  6      // Сюда состояние охраны сигналки
#define Trevoga  7      // Сюда состояние тревоги
#define StartEng 8   // это импульсный минусовой выход вкл/выкл ДВС. подключать на вход событий сиги.
#define IGN 10       // Сюда состояние зажигания
#define Eng 11       // Сюда состояние работы ДВС
#define ResetGSM 16       // пин ресета GSM (A2) подключен к реле, разрывающее питание модуля. 
#define StartButton 17       // пин тактовой кнопки (А3) вкл/выкл котла
#define StatusWebastoLED 13  // пин индикация включенности котла





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

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

byte VyhlopC[8] ={0x28, 0xFF, 0xE6, 0x14, 0x90, 0x15, 0x04, 0x62}; 
byte EngineC[8] ={0x28, 0xFF, 0x06, 0x15, 0x90, 0x15, 0x04, 0x37}; 
byte UlicaC[8] ={0x28, 0xFF, 0x43, 0x42, 0xA8, 0x15, 0x03, 0x2A};  
byte SalonC[8] ={0x28, 0xFF, 0xE0, 0x19, 0xA8, 0x15, 0x01, 0xA7};  
volatile int  TempVyhlopC = 20;
volatile int  TempEngineC = 20;
volatile int  TempUlicaC = 20;
volatile int  TempSalonC = 20;

// для организации W-BUS и различные таймеры********************
byte Zapusk20[5] = {0xF4,0x03, 0x20, 0x3B, 0xEC} ;
byte Zapusk21[5] = {0xF4,0x03, 0x21, 0x3B, 0xED} ;
byte Stop[4] = {0xF4,0x02, 0x10, 0xE6} ;

bool flagStartPresent = 1;               //флаг что отправляем в момент периодического поддержания связи W-Bus status или start
int StartMessageRepeat = 0;              //количество отправленных сообщений на старт котла
int StopMessageRepeat = 0;               //количество отправленных сообщений на остановку котла

unsigned long TimeWebasto = 1800000;   //время работы котла, 1800000 = 30мин
unsigned long EndReportMillis = 0;     //переменная для таймера отправки отчета об успешности запуска котла
unsigned long EndReportEngine = 0;     //переменная для таймера отправки отчета об успешности запуска ДВС
unsigned long Prev_PeriodW_BusMessage = 0;     //переменная для таймера периодической отправки сообщений состояния котла в шину W-Bus 
unsigned long Prev_PeriodW_BusStartStop = 0;       //переменная для таймера периодической отправки сообщений старта/стопа котла в шину W-Bus 

//для таймера  - активация котла - импульс массы 0,8 сек на провод, впаянный в таймер вебасто)
unsigned long time, timer=0;
bool timerenabled=false;
#define TIMEREXPIRED (time-timer)>800


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


//для таймера  - старт котла по W-BUS )
unsigned long timerStart_W_BUS=0; bool timerenabledStart_W_BUS=false;
#define TIMEREXPIRED_Start_W_BUS (millis()-timerStart_W_BUS)> TimeWebasto 


//ниже всё для организации ресета GSM модуля, если с ним отсутствует свзяь

unsigned long  prevCheckConnect=0;      // для таймера периодичности проверки (командой "АТ")
int intervalCheck = 10;          // каждые столько мин  будет проверка свзи с GSM (командой "АТ")
unsigned long  timerWaitOK=0;    // для таймера ожидания ответа после посылки команды "АТ"
bool timerenabledWaitOK=false;   // для таймера ожидания ответа после посылки команды "АТ"
int errors=0;                    // количество неответов  от GSM модуля
bool gsmOK = 1;                  // флаг есть свзяь с GSM модулем или нет
bool resettimer = 0;             // для таймера удерживания реле в режиме сброс питания
unsigned long  resetTimer=0;     // для таймера удерживания реле в режиме сброс питания
int ResetNumber = 0;             //количество ресетов GSM модуля для статистики (хранится в еепром)

//**************************


//Основные переменные  
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; //флаг отправлена ли смс о тревоге или нет





// СТАРТОВЫЙ ЦИКЛ
void setup() 
{
 delay (2500);

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(StartButton); // arduino pins connected to button
 
  WDTCSR=(1<<WDCE)|(1<<WDE); //для датчиков DS18B20
 
  WDTCSR=(1<<WDIE)| (1<<WDP3)|(1<<WDP0); // для датчиков DS18B20 (разрешение прерывания + выдержка 8 секунд)
  pinMode (DopOn,  INPUT);   digitalWrite (DopOn,  HIGH);
  pinMode (DopOff, INPUT);   digitalWrite (DopOff, HIGH);
  pinMode (Sost,   INPUT);   digitalWrite (Sost,   HIGH);
  pinMode (VyhodWebasto,  OUTPUT);  digitalWrite (VyhodWebasto,  HIGH);
  pinMode (VyhodWebastoAnalog,  OUTPUT);  digitalWrite (VyhodWebastoAnalog,  LOW);
  pinMode (StartEng,  OUTPUT);  digitalWrite (StartEng,  LOW);
  pinMode (StatusWebastoLED,     OUTPUT);  digitalWrite (StatusWebastoLED,     LOW);
  pinMode (ResetGSM,     OUTPUT);  digitalWrite (ResetGSM,     LOW);

  pinMode (Ohrana, INPUT);  digitalWrite (Ohrana,  HIGH);
  pinMode (Trevoga, INPUT);  digitalWrite (Trevoga,  HIGH);
  pinMode (IGN, INPUT);  digitalWrite (IGN,  HIGH);
  pinMode (Eng, INPUT);  digitalWrite (Eng,  HIGH);
  
  



   
  
Serial.begin (2400, SERIAL_8E1);  // сериал соединение протокол W-Bus
mySerial.begin(19200);           // сериал соединение для gsm модуля
    delay(2000);
  NastroykaGSM ();

TimeWebasto = EEPROM.read(1)*60000UL;
Protocol = EEPROM.read(2);
ResetNumber = EEPROM.read(0);
for (int i=0; i<12; i++) TelNumber1[i] = EEPROM.read (i+10);
for (int i=0; i<12; i++) TelNumber2[i] = EEPROM.read (i+30);

}


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

if (Protocol!=2) {if (TempVyhlopC - TempUlicaC > 20) startWebasto_OK = 1;
                  else startWebasto_OK = 0;}

if (Protocol==1) webasto = !digitalRead (Sost);

if (Protocol==2) W_Bus();

//ниже для таймера старта котла по W-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 (trevoga && !alarmSMS) AlarmSMS ();
if (!ohrana) alarmSMS = false;

if (gsmOK)readSMS();
CheckConnect_GSM();
voltmetr();
WebastoOprosImpulse ();


}

void voltmetr()  //____________Цикл "Вольтметр"__измерение напряжения на выходе ИБП

{
   volt = analogRead(A7);                       // А7 аналоговый вход вольтметра
   vout = (volt * 4.92) / 1024;             
   Vpit = vout / (9950.0/(98930.0+9950.0));  // По формуле Vpit = vout / (R2/(R1+R2)) 
   if (Vpit<0.09)  Vpit=0.0;                  // Округление до нуля 
}






// Вектор прерывания для Dallas DS18B20
ISR (WDT_vect){ //вектор прерывания WD
static boolean n=0; // флаг работы: запрос температуры или её чтение
n=!n;
if (n) {ds.reset();  // сброс шины
        ds.write(0xCC);//обращение ко всем датчикам
        ds.write(0x44);// начать преобразование (без паразитного питания)  
       }
else   {ds.reset();
        ds.select(VyhlopC);    
        ds.write(0xBE); // Read Scratchpad (чтение регистров)  
        TempVyhlopC =  ds.read() | (ds.read()<<8); //прочитаны 2 байта       
        TempVyhlopC = TempVyhlopC / 16;
        // получение с 2-го датчика
        ds.reset();
        ds.select(EngineC);    
        ds.write(0xBE); // Read Scratchpad (чтение регистров)  
        TempEngineC =  ds.read() | (ds.read()<<8); //прочитаны 2 байта  
        TempEngineC = TempEngineC/16;
        ds.reset();
        ds.select(UlicaC);    
        ds.write(0xBE); // Read Scratchpad (чтение регистров)  
        TempUlicaC =  ds.read() | (ds.read()<<8); //прочитаны 2 байта       
        TempUlicaC = TempUlicaC / 16;
        // получение с 2-го датчика
        ds.reset();
        ds.select(SalonC);    
        ds.write(0xBE); // Read Scratchpad (чтение регистров)  
        TempSalonC =  ds.read() | (ds.read()<<8); //прочитаны 2 байта  
        TempSalonC = TempSalonC/16 ;
}}




                    


void StartWebasto()
{
 if (Protocol==1){ digitalWrite (VyhodWebasto, LOW); 
  timer=time; 
  timerenabled=true;}

 else if (Protocol==2||Protocol==3){
  StartMessageRepeat = 0;
  webasto = 1; digitalWrite (VyhodWebastoAnalog, HIGH);
  timerStart_W_BUS=millis();
  timerenabledStart_W_BUS = true;}

  report = true; EndReportMillis = millis();
}

void StopWebasto()
{
 if (Protocol==1){ digitalWrite (VyhodWebasto, LOW); 
  timer=time; 
  timerenabled=true;}

 else if (Protocol==2||Protocol==3){
  StopMessageRepeat = 0;
  webasto = 0; digitalWrite (VyhodWebastoAnalog, LOW);
  timerenabledStart_W_BUS = false;}
   report = false;
}




void WebastoOprosImpulse (){

// опрос допканалов от сигнализации включения/ выключение котла и таймер импульса старт/стоп котла 
  time = millis();
  if (timerenabled) {if (TIMEREXPIRED) {digitalWrite (VyhodWebasto, 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();  }} 

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





   void NastroykaGSM () {
      mySerial.print(F("AT+CMGF=1\r"));         //устанавливает текстовый режим смс-сообщения
    delay(200);
  mySerial.print(F("+IFC=1, 1\r"));       //устанавливает программный контроль потоком передачи данных
    delay(200);
  mySerial.print(F("AT+CPBS=\"SM\"\r"));    //открывает доступ к данным телефонной книги SIM-карты
    delay(200);
  mySerial.print(F("AT+GSMBUSY=1\r"));   //запрет всех входящих звонков
    delay(300);
  mySerial.print(F("AT+CNMI=1,2,2,1,0\r")); //включает оповещение о новых сообщениях
    delay(300);
  mySerial.print(F("AT+CMGDA=\"DEL ALL\"\r")); // удаляем все смс, ки
   delay(2000);
}

void startNumber1SMS() //__________________Цикл подготовки модуля к отправке СМС-сообщений по первому номеру
{
      mySerial.print(F("AT+CMGF=1\r"));
      delay(200);
  mySerial.print(F("AT+CMGS=\"")); mySerial.print(TelNumber1); mySerial.println("\""); 
      delay(400);
}

void startNumber2SMS() //__________________Цикл подготовки модуля к отправке СМС-сообщений по второму  номеру
{
      mySerial.print(F("AT+CMGF=1\r"));
      delay(200);
      mySerial.print(F("AT+CMGS=\"")); mySerial.print(TelNumber2); mySerial.println(F("\"")); 
      delay(400);
}

void startBufferNumberSMS() //__________________Цикл подготовки модуля к отправке СМС-сообщений по второму  номеру
{
      mySerial.print(F("AT+CMGF=1\r"));
      delay(200);
      mySerial.print(F("AT+CMGS=\"")); mySerial.print(BufferNumber); mySerial.println(F("\"")); 
      delay(400);
}

void EndSMS ()
{
   mySerial.println((char)26);                       // Команда отправки СМС
   delay(3000);
   mySerial.print(F("AT+CMGDA=\"DEL ALL\"\r")); // удаляем все смс, ки
   delay(1500);
}


void readSMS() //_____Цикл чтения входящих СМС-сообщений______________     
{
    if (!mySerial.available()) return;
    char currSymb = mySerial.read();
//  Serial.print (currSymb);
    if ('\r' == currSymb)
       {
         if (isStringMessage!=0&&isStringMessage!=10) //если текущая строка - SMS-сообщение, отреагируем на него соответствующим образом
                {
if (!currStr.compareTo("ZAPROS"))   { SMSzapros();}               // Передача параметров по СМС
else if (!currStr.compareTo("ZAPROSTEL"))   { SMSzaprosTEL();}               // Передача номеров телефонов пользователей по СМС



else if (!currStr.compareTo("Webasto-ON"))  { if (!webasto)  {StartWebasto ();  // если получили команду на включение и вебаста в настоящий момент выключена - включаем
                                                                              if (isStringMessage == 1) {startNumber1SMS(); KTOreport = 1;}
                                                                         else if (isStringMessage == 2) {startNumber2SMS();  KTOreport = 2;}
                                                                         mySerial.println(F("Webasto Vkluchena")); EndSMS();}
                                                                       
                                                   else                     {if (isStringMessage == 1) startNumber1SMS(); 
                                                                        else if (isStringMessage == 2) startNumber2SMS(); 
                                                                        mySerial.println(F("Webasto uzhe vkluchena")); EndSMS();}}

                                                            
               else if (!currStr.compareTo("Webasto-OFF"))   {if (webasto){StopWebasto ();  // если получили команду на выключение и вебаста в настоящий момент включена - выключаем
                                                                              if (isStringMessage == 1) startNumber1SMS(); 
                                                                        else  if (isStringMessage == 2) startNumber2SMS();
                                                                        mySerial.println(F("Webasto Otkluchena")); EndSMS();}


                                                     else                    {if (isStringMessage == 1) startNumber1SMS(); 
                                                                         else if (isStringMessage == 2) startNumber2SMS(); 
                                                                         mySerial.println(F("Webasto uzhe otkluchena")); EndSMS();}}          


                else if (!currStr.compareTo("Engine-ON"))  {if (!engine)  { digitalWrite (StartEng, HIGH);  timerStartEng=millis(); timerenabledStartEng=true; reportEngine = true; EndReportEngine = timerStartEng; // если получили команду на включение ДВС и он в настоящий момент выключен - включаем
                                                                              if (isStringMessage == 1) {startNumber1SMS();  KTOreport = 1;}
                                                                         else if (isStringMessage == 2) {startNumber2SMS();  KTOreport = 2;}
                                                                         mySerial.println(F("Engine Start")); EndSMS();}
                                                                       
                                                   else                     {if (isStringMessage == 1) startNumber1SMS(); 
                                                                        else if (isStringMessage == 2) startNumber2SMS();
                                                                        mySerial.println(F("Dvigatel uzhe rabotaet")); EndSMS();}}
                                                                                 
               else if (!currStr.compareTo("Engine-OFF"))   {if (engine){ digitalWrite (StartEng, HIGH);  timerStartEng=millis(); timerenabledStartEng=true; reportEngine = false; // если получили команду на выключение ДВС и он в настоящий момент работает - выключаем
                                                                              if (isStringMessage == 1) startNumber1SMS();
                                                                        else  if (isStringMessage == 2) startNumber2SMS();
                                                                        mySerial.println(F("Dvigatel ostanovlen")); EndSMS();}


                                                     else                    {if (isStringMessage == 1) startNumber1SMS(); 
                                                                         else if (isStringMessage == 2) startNumber2SMS();
                                                                         mySerial.println(F("dvigatel uzhe ostanovlen")); EndSMS(); }}          
                                                    

               else if (!currStr.compareTo("Impulse"))   {Protocol = 1;  EEPROM.write(2,Protocol);     if (isStringMessage == 1) {startNumber1SMS(); mySerial.println(F("zapusk GND_impulse")); EndSMS();}
                                                                        else  if (isStringMessage == 2) {startNumber2SMS(); mySerial.println(F("zapusk GND_impulse")); EndSMS();}}                                                               

               else if (!currStr.compareTo("W-BUS"))   {Protocol = 2; EEPROM.write(2,Protocol);  webasto = 0;  if (isStringMessage == 1) {startNumber1SMS(); mySerial.println(F("zapusk W-BUS")); EndSMS();}
                                                                        else  if (isStringMessage == 2) {startNumber2SMS(); mySerial.println(F("zapusk W_BUS")); EndSMS();}}

               else if (!currStr.compareTo("Potenzial"))   {Protocol = 3; EEPROM.write(2,Protocol);   if (isStringMessage == 1) {startNumber1SMS(); mySerial.println(F("zapusk +12V Potencial")); EndSMS();}
                                                                        else  if (isStringMessage == 2) {startNumber2SMS(); mySerial.println(F("zapusk +12V Potencial")); EndSMS();}} 

               
                else if (currStr.endsWith("min"))   {TimeWebasto = currStr.toInt()*60000UL; // для задания время цикла работы отправить сообщение вида "25 min", где 25 время работы в мин
               if (TimeWebasto>3540000UL) TimeWebasto = 3540000UL;
               if (TimeWebasto<=600000UL) TimeWebasto = 600000UL;
               EEPROM.write(1,TimeWebasto/60000UL);
                     if (isStringMessage == 1)startNumber1SMS(); 
               else  if (isStringMessage == 2) startNumber2SMS(); 
               mySerial.print(F("Webasto time: ")); mySerial.print(TimeWebasto/60000UL); mySerial.print(F("min")); EndSMS();}
               

               else if (!currStr.compareTo("ResetNumbers"))   {if (isStringMessage == 1) {startNumber1SMS(); mySerial.println(F("Phone numbers are erased")); EndSMS(); 
                                                                     
             TelNumber1 = "000000000000"; TelNumber2 = "000000000000"; for (int i=0; i<12; i++) {EEPROM.write (i+10,  TelNumber1[i]); EEPROM.write (i+30,  TelNumber2[i]); }}}

              else if (!currStr.compareTo("WriteNumber2")&& isStringMessage == 1)   { 
                SaveNumber2 = 1; startNumber1SMS(); mySerial.println(F("Otpravte lyuboye SMS s nomera2 dlya sochraneniya nomera")); EndSMS();} 

                                                                        

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



                
         else if (isStringMessage==0) {  if (TelNumber1!="000000000000" && !SaveNumber2 && TelNumber1!="яяяяяяяяяяяя"){
         
                     if (currStr.startsWith("+CMT: \""+TelNumber1)) { isStringMessage = 1; KTOzapros = 1; }   
                else if (currStr.startsWith("+CMT: \""+TelNumber2)) { isStringMessage = 2; KTOzapros = 2; }   
                else if (currStr.startsWith("+CUSD: 0,"))  //если текущая строка начинается с "+CUSD",то следующая строка является запросом баланса
                  {
                       if (KTOzapros == 1) startNumber1SMS();
                  else if (KTOzapros == 2) startNumber2SMS();
                  mySerial.print (currStr);
                  EndSMS();
                  }    
                                                }

                else if    (currStr.startsWith("+CMT:") && !SaveNumber2) { isStringMessage = 10; for (int i =0; i<12; i++) {BufferNumber[i]=currStr[i+7];}}
                else if    (currStr.startsWith("+CMT:") && SaveNumber2) { for (int i =0; i<12; i++) {BufferNumber[i]=currStr[i+7];} TelNumber2 = BufferNumber; for (int i=0; i<12; i++) {EEPROM.write (i+30, BufferNumber[i]);}
              startNumber2SMS(); mySerial.println(F("Vash nomer sochranyon kak Number#2 v pamyati!")); 
              mySerial.print(F("Tel1: ")); mySerial.println(TelNumber1); mySerial.print(F("Tel#2: "));  mySerial.println (TelNumber2); EndSMS(); SaveNumber2 = 0; } 
              
              } 
               
        currStr = "";
      } 
 
    else if ('\n' != currSymb) { currStr += String(currSymb);}
}


void SMSzapros()
{   if (isStringMessage == 10){
 startBufferNumberSMS();

 mySerial.println (F("Tel.number#1 has been no save in memory!"));
 mySerial.println (F("For save Tel#1 send SMS command \"WriteNumber1\""));
  mySerial.print(F("Tel#1: ")); mySerial.println(TelNumber1);
  mySerial.print(F("Tel#2: ")); mySerial.println(TelNumber2); 
  }
  
  
  
  else {
  
  if (isStringMessage == 1) { startNumber1SMS();}
  else if (isStringMessage == 2) { startNumber2SMS();}
  else if (isStringMessage == 0) {if  (KTOreport == 1) startNumber1SMS();
                             else if  (KTOreport == 2) startNumber2SMS();}
        if (webasto) { mySerial.println (F("Webasto ON"));
           if (startWebasto_OK) mySerial.println (F("StartWebasto OK"));
           else mySerial.println (F("StartWebasto FAIL"));}
     else mySerial.println (F("Webasto OFF"));  

     if (engine)  mySerial.println (F("Engine ON"));
     else mySerial.println (F("Engine OFF"));  

     if (ignition)  mySerial.println (F("IGN ON"));
     else mySerial.println (F("IGN OFF"));  

     if (ohrana)  mySerial.println (F("OHRANA ON"));
     else mySerial.println (F("OHRANA OFF"));  

     if (trevoga)  mySerial.println (F("Vnimanie!!! Trevoga!!! Sirena Vkl!"));
     
  mySerial.print(F("Battery: ")); mySerial.print (Vpit); mySerial.println(F("V"));
  mySerial.print(F("Engine: ")); mySerial.print (TempEngineC); mySerial.println(F("*C"));
  mySerial.print(F("Vyhlop: ")); mySerial.print (TempVyhlopC); mySerial.println(F("*C"));
  mySerial.print(F("Ulica: ")); mySerial.print (TempUlicaC); mySerial.println(F("*C"));
  mySerial.print(F("Salon: ")); mySerial.print (TempSalonC); mySerial.println(F("*C"));  
  mySerial.print(F("Protocol: "));
       if (Protocol==1) mySerial.println(F("GND Impulse"));
  else if (Protocol==2) mySerial.println(F("W-BUS"));
  else if (Protocol==3) mySerial.println(F("+12V Potencial"));
  mySerial.print(F("Webasto Time: ")); mySerial.print (TimeWebasto/60000UL); mySerial.println(F("min"));
  mySerial.print(F("Resets: ")); mySerial.println (ResetNumber); 
 
  }  
   EndSMS();                                 
}

void SMSzaprosTEL(){
  if (isStringMessage == 1) { startNumber1SMS();}
  else if (isStringMessage == 2) { startNumber2SMS();}
  else if (isStringMessage == 10) { startBufferNumberSMS();}
  
  
  mySerial.print(F("Tel#1: ")); mySerial.println(TelNumber1);
  mySerial.print(F("Tel#2: ")); mySerial.println(TelNumber2); 
  if (TelNumber1!="000000000000" && TelNumber1!="яяяяяяяяяяяя"){
  mySerial.print(F("Protocol: "));
  if (Protocol==1) mySerial.println(F("GND Impulse"));
  else if (Protocol==2) mySerial.println(F("W-BUS"));
  else if (Protocol==3) mySerial.println(F("+12V Potencial"));
  mySerial.print(F("Webasto Time: ")); mySerial.print (TimeWebasto/60000UL); mySerial.println(F("min"));
  mySerial.print(F("Resets: ")); mySerial.println (ResetNumber); 
  }
  EndSMS();                                 
  }


void SMSbalance() {
  mySerial.print(F("AT+CMGF=1\r"));
      delay(200);

mySerial.println (F("AT+CUSD=1,\"#100#\""));
    
//mySerial.println("AT+CMGS=\"#100#\"");
//      mySerial.println("ATD#100#");
      //mySerial.println("AT + CMGS = \"111\""); // 
      delay(2000);                              // команда на замену на транслит *111*6*2#
      //mySerial.println ("11");
      //EndSMS();
}


void AlarmSMS() {
 startNumber1SMS();
mySerial.println (F("Vnimanie!!! Trevoga!!! Sirena Vkl!"));
 EndSMS();      
 startNumber2SMS();
mySerial.println (F("Vnimanie!!! Trevoga!!! Sirena Vkl!"));
 EndSMS();      
 alarmSMS = true;
}

void W_Bus (){
if (webasto) {
    if (StartMessageRepeat<4 && (millis()-Prev_PeriodW_BusStartStop>800)){

 for (int i = 0; i<5; i++) Serial.write (Zapusk21[i]); 
  StartMessageRepeat++; 
  Prev_PeriodW_BusStartStop = millis();
  
    }
  if (StartMessageRepeat>=4){ if (millis()-Prev_PeriodW_BusMessage>5000)  {
    //делаем периодическое поддержание связи W-BUS
    // наверное сканает отправка сообщения о состоянии котла
    // т.е. ,например, отправляем периодически запрос на показания датчиков
    // состоянием работы котла будет наличие или отсутствие пламени
if (flagStartPresent) {for (int i = 0; i<5; i++) Serial.write (Zapusk21[i]); }
//else {for (int i = 0; i<5; i++) Serial.write (StateMessage[i]);}
flagStartPresent = !flagStartPresent;
StopMessageRepeat = 0;
    
    Prev_PeriodW_BusMessage = millis();
    }}}





else if (StopMessageRepeat<4 && (millis()-Prev_PeriodW_BusStartStop>800)){
  for (int i = 0; i<4; i++) Serial.write (Stop[i]); 
StopMessageRepeat++; 
StartMessageRepeat = 0;
   Prev_PeriodW_BusStartStop = millis();
  
  
  }

}



void CheckConnect_GSM (){
  if (millis()-prevCheckConnect>(unsigned long)intervalCheck*60000UL){ //тут периодически раз в интервал шлем "АТ" для проверки связи
  mySerial.println (F("AT")); 
  timerenabledWaitOK = 1; timerWaitOK = millis();
  gsmOK = false;
  prevCheckConnect = millis(); }

if (timerenabledWaitOK && millis()-timerWaitOK>6000) {//если таймер после отправки "AT" включен и истекло время таймера 6 сек
    timerenabledWaitOK = 0; //обнуляем таймер
    if (!gsmOK) {           // и если GSM так и не ответил, опять отправляем "AT" и включаем таймер
      mySerial.println (F("AT")); 
      timerenabledWaitOK = 1; timerWaitOK = millis();
      errors++; if (errors>5) errors = 5; // +1 к ошибкам связи
      
      }
}


 // если GSM ещё не ответил, проверяем буфер уарт
 if (!gsmOK && !resettimer)  { 
  if (mySerial.available()>0){                                   
    char currSymb = mySerial.read();                           
    if ('\r' == currSymb) {                                      
                                  
if (!currStr.compareTo("OK")) {gsmOK = true; errors=0;} //если GSM отвеитил ОК, то связь есть, ошибки на ноль
       currStr = "";                                           
    }
    
    else if ('\n' != currSymb) {currStr += String(currSymb);}}}
    
    
    if (errors>=5) Restart(); // если количество ошибок связи больше или равно 5, делаем рестарт
    
    }

 void Restart(){
     
if (!resettimer) {digitalWrite (ResetGSM, 1); resettimer = 1; resetTimer = millis();} //разрываем питание GSM, включаем таймер 
else if (millis()- resetTimer>3000 ) { // если таймер в 3 сек кончился, восстанавливаем питание GSM, в еепром +1 к количеству рестартов  
digitalWrite (ResetGSM, 0); 
resettimer = 0; 
errors=0; 
ResetNumber++; 
gsmOK = true; 
EEPROM.write (0, ResetNumber);
delay (3000); NastroykaGSM ();}
           
      
      
      }

плата

uu5jhu
Offline
Зарегистрирован: 21.11.2017

Да, совершенно верно, котёл штатный. Вопрос конечно этот самому интересен будет ли он по +12V запускаться....но скачав документацию (описание + схемы соединений) предполагаю что работать должно. В любом случае скоро узнаем и напишу здесь. Главное чтобы конфликта не было по CAN.

А по поводу использовать MCP2515 - я уже получил из Китая его именно для этих целей, так что выкладывайте прошивку CAN хакера  если найду время с удовольствием посижу с ним. 

Хочу собрать полную схему (с LM393) так как машины меняются а сегодня новые котлы так понимаю уже все работают по W-Bus....возможно пригодится.

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

на портале carhelp.info много полезного найдете на этот счет - как запускать штатные котлы. Вам нужно узнать, есть ли у вашего котла шина W-Bus, если есть, то нужно попробовать запустить диагноситку котла по этой шине оригинальной вебастовской программой WTT при помощи обычного к-лайн адаптера. Если диагностика получится, всё упрощается. 

схема к-лайн 

 

программа Webasto Termo Test 

uu5jhu
Offline
Зарегистрирован: 21.11.2017

ДА, пару лет назад использовал эту программу (WTT) для ремонта своего котла - не пропаяно было хорошо одно сопротивление. На каком-то форуме писал об этом с фото. 

Значит можно попробовать подключиться к шине используя Вашу схему!?

Сейчас уже схему не вспомню но кажется именно по этой шине котёл соединён с приборной панелью и имеет название i-bus а уже приборная панель с CAN шиной. То есть через диагностический разъём авто к котлу с помощью WTT не подключиться, собирал всё дома на столе и подключал.

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

Скетч Can Hacker

#include <can.h>
#include <mcp2515.h>

#include <CanHacker.h>
#include <CanHackerLineReader.h>
#include <lib.h>

#include <SPI.h>
#include <SoftwareSerial.h>

const int SPI_CS_PIN = 10;
const int INT_PIN = 2;

const int SS_RX_PIN = 3;
const int SS_TX_PIN = 4;

CanHackerLineReader *lineReader = NULL;
CanHacker *canHacker = NULL;

SoftwareSerial softwareSerial(SS_RX_PIN, SS_TX_PIN);

void setup() {
    Serial.begin(115200);
    while (!Serial);
    SPI.begin();
    softwareSerial.begin(115200);

    Stream *interfaceStream = &Serial;
    Stream *debugStream = &softwareSerial;
    
    
    canHacker = new CanHacker(interfaceStream, debugStream, SPI_CS_PIN);
    //canHacker->enableLoopback(); // uncomment this for loopback
    lineReader = new CanHackerLineReader(canHacker);
    
    pinMode(INT_PIN, INPUT);
}

void loop() {
    CanHacker::ERROR error;
  
    if (digitalRead(INT_PIN) == LOW) {
        error = canHacker->processInterrupt();
        handleError(error);
    }

    error = lineReader->process();
    handleError(error);
}

void handleError(const CanHacker::ERROR error) {

    switch (error) {
        case CanHacker::ERROR_OK:
        case CanHacker::ERROR_UNKNOWN_COMMAND:
        case CanHacker::ERROR_NOT_CONNECTED:
        case CanHacker::ERROR_MCP2515_ERRIF:
        case CanHacker::ERROR_INVALID_COMMAND:
            return;

        default:
            break;
    }
  
    softwareSerial.print("Failure (code ");
    softwareSerial.print((int)error);
    softwareSerial.println(")");

    digitalWrite(SPI_CS_PIN, HIGH);
    pinMode(LED_BUILTIN, OUTPUT);
  
    while (1) {
        int c = (int)error;
        for (int i=0; i<c; i++) {
            digitalWrite(LED_BUILTIN, HIGH);
            delay(500);
            digitalWrite(LED_BUILTIN, LOW);
            delay(500);
        }
        
        delay(2000);
    } ;
}

библиотеки для скетча CanHacker (уже настроены на кварц 8 Мгц CAN-модуля)

программа CanHacker

Скорость ком порта в программе  CanHacker в настройках делаем 115200

схема подключения 

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

uu5jhu пишет:
Значит можно попробовать подключиться к шине используя Вашу схему!?

Собираете два адаптера из сообщения #84 или легче покупаете, Один для подключения WTT к котлу, второй - чтобы посниффить обмен данными. Когда узнаете какие байты там летают, можно будет запускать котёл по i-bus (полагаю тот же W-bus)

uu5jhu
Offline
Зарегистрирован: 21.11.2017

Спасибо за схему и скетч. Один адаптер есть им собственно и ковыряюсь в авто (прошивка / кодировка блоков) второго нет, попробую купить.... Китай совсем обленил увы, да и часто получается что проще и Дешевле купить готовое устройство чем собирать в одном экземпляре. Исключение составляет - хобби.

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

uu5jhu
Offline
Зарегистрирован: 21.11.2017

Если позволите ещё один момент замечен при проверке. 

Всё прекрасно работает (смс команды) пока не отключить питание. После повторного включения питания и спустя даже 10 минут устройство никак не реагирует на смс команды пока не нажать кнопку Reset на Nano. После этого снова начинает всё работать.

И ещё подскажите в какую строку и что добавить чтобы в мониторе порта увидеть напряжение АКБ (исключительно для настройки) ? Понижающий DC-DC отличается от Вашего и шунтирует входным сопротивлением делитель напряжения. Вместо 13,70 приходит в смс 12,65. Хочу подобрать подстроичником, но каждый раз отправлять смс.......

MaksVV
Offline
Зарегистрирован: 06.08.2015
193 void voltmetr()  //____________Цикл "Вольтметр"__измерение напряжения на выходе ИБП
194  
195 {
196    volt = analogRead(A7);                       // А7 аналоговый вход вольтметра
197    vout = (volt * 4.92) / 1024;            
198    Vpit = vout / (9950.0/(98930.0+9950.0));  // По формуле Vpit = vout / (R2/(R1+R2))
199    if (Vpit<0.09)  Vpit=0.0;                  // Округление до нуля
200 }

вот здесь 4,92 это  напряжение питания на ардуино, реальное измеренное вольтметром , 9950 это реальное измеренное  сопротивление плеча 10К делителя напряжения, 98930 -  это реальное измеренное  сопротивление плеча 100К делителя напряжения. Измерьте и подставьте свои данные, должно быть ближе к правде. Если после этого отличается от реального напряжения, корректируйте ещё значение сопротивлений. 

Скетч для настройки вольтаметра с выводом в терминал. 


#define analogInput A7
float vout = 0.0;
float vin = 0.0;
float R1 = 100000.0; // сопротивление R1 (100K)
float R2 = 10000.0; // сопротивление R2 (10K)
int value = 0;
void setup(){
   pinMode(analogInput, INPUT);
   Serial.begin (9600);
}
void loop(){
   // считывание аналогового значения
   value = analogRead(analogInput);
   vout = (value * 5.0) / 1024.0;
   vin = vout / (R2/(R1+R2)); 
   if (vin<0.09) vin=0.0;// обнуляем нежелательное значение
Serial.print("INPUT V= ");
Serial.println(vin);
delay(500);
}

 

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

uu5jhu пишет:
Всё прекрасно работает (смс команды) пока не отключить питание. После повторного включения питания и спустя даже 10 минут устройство никак не реагирует на смс команды пока не нажать кнопку Reset на Nano. После этого снова начинает всё работать.

вот тут хз, у меня тоже так было на одной ардуино (от robotdyn ), на другой все норм. надо пробовать на другом МК. попробуйте в Setup строка 115 задержку на 6...7 секунд повысить

uu5jhu
Offline
Зарегистрирован: 21.11.2017

Приветствую. Спасибо за скетч - подобрал в программе величинами сопротивлений значение напряжения. Про делитель напряжения как бы всё понятно, но как ранее заметил что DC-DC шунтирует этот делитель и показывает "погоду" вместо напряжения. (Если запитать DC-DC от отдельного источника то проблем нет). В общем сейчас всё хорошо (значения в программе кстати получились далеки от истины).

Появилось время и добрался до авто. Идёт с фишки от котла три провода - один на насос, второй на i-BUS (CAN) и третий на таймер (точнее сказать на связку Telestart + timer) которого нет но можно дооснастить. На схеме этот провод идёт на квадратную фишку таймера на контакт "OUT". Отсюда появился вопрос - по какому протоколу работает связка таймер-котёл? Если W-Bus то можно попробовать подключить выход с Вашей конструкции на этот провод!?

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

А Подозреваю что на проводе OUT должен быть просто потенциал 12в при включении. Но если даже там цифра, мой вариант может и подойдет. По крайней мере так включали некоторые штатные котлы. Машина то какая?

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

Можно просто подать 12в попробовать. По идее на w-bus шине такие уровни сигналов.

toc
Offline
Зарегистрирован: 09.02.2013

MaksVV,
1. Получилось сделать контроль зависаний? Я писал выше #63
2. все возможности по энергосбережению в микроконтроллере AVR описаны тут https://www.gammon.com.au/power

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

toc пишет:
Получилось сделать контроль зависаний?

спасибо по ссылке почитаю. Контроль зависаний попытался сделать. Добавил в скетч (сообщение #82). Нарисовал новую плату с реле. Т.е. питание GSM сидит на нормально-замкнутых контактах реле. При рестарте подается питание на реле и оно размыкает питание GSM. Но это только пробная версия, ещё ничего не проверял. Т.к. нет времени и детали ещё не дошли. 

реле применил миниатюное, такое 

blades
Offline
Зарегистрирован: 21.11.2017

не вижу на плате реле, ткните носом пожалуйста

нет ли в планах нарисовать схему, что бы проще было разбираться откуда куда и зачем?

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

реле между контактами gsm модуля. Если gsm модуль на панельки устанавливать, то он высоко сидит, туда это реле по идее влезть должно, судя по его размерам. 

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

время жалко, а что вам кроме реле не понятно?

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

схема надеюсь нигде не накосячил.