#include <SoftwareSerial.h> // кнопка старт на А4 добавленно
SoftwareSerial SIM800(7, 6); // для новых плат начиная с версии RX,TX
#include <DallasTemperature.h> // подключаем библиотеку чтения датчиков температуры
OneWire oneWire(4); // и настраиваем пин 4 как шину подключения датчиков DS18B20
DallasTemperature sensors(&oneWire);
#define ACC 8 // на реле первого положения замка зажигания
#define ON 9 // на реле зажигания, через транзистор с 9-го пина ардуино
#define STARTER 12 // на реле стартера, через транзистор с 12-го пина ардуино
#define OUT_4 11 // на дополнительное реле
#define OUT_5 10 // на реле вебасто или подогрева седушек
#define OUT_6 13 // на светодиод (моргалку)
#define BAT_Pin A0 // на батарею, через делитель напряжения 39кОм / 11 кОм
#define Feedback_Pin A1 // на провод от замка зажигания
#define STOP_Pin A2 // на концевик педали тормоза для отключения режима прогрева
#define PSO_Pin A3 // на прочие датчики через делитель 39 kOhm / 11 kΩ
#define RESET_Pin 5
#define START_Pin A4 // кнопка пуск
/* ----------------------------------------- ИНДИВИДУАЛЬНЫЕ НАСТРОЙКИ !!!--------------------------------------------------------- */
String LAT = ""; // переменная храняжая широту
String LNG = ""; // переменная храняжая долготу
String call_phone= "+79994502930"; // телефон входящего вызова
String SMS_phone = "+79994502930"; // телефон куда отправляем СМС
String MAC = "80-01-AA-00-00-00"; // МАС-Адрес устройства для индентификации на
String SENS = "VasjaPupkin"; // Название устройства (придумать свое Citroen 566 или др. для отображения в программе и на карте)
String APN = "internet.mts.by"; // тчка доступа выхода в интернет вашего сотового оператора
String USER = "mts"; // имя выхода в интернет вашего сотового оператора
String PASS = "mts"; // пароль доступа выхода в интернет вашего сотового оператора
bool n_send = false; // отправка данных на народмон по умолчанию включена (true), отключена (false)
bool sms_report = false; // отправка SMS отчета по умолчанию овключена (true), отключена (false)
float Vstart = 13.50; // поорог распознавания момента запуска по напряжению
String SERVER = "narodmon.ru"; // сервер народмона (на октябрь 2017)
String PORT = "8283"; // порт народмона (на октябрь 2017)
String pin = ""; // строковая переменная набираемого пинкода
float TempDS[11]; // массив хранения температуры c рахных датчиков
float Vbat, VbatStart, V_min ; // переменная хранящая напряжение бортовой сети
float m = 76.91; // делитель для перевода АЦП в вольты для резистров 39/11kOm
unsigned long Time1, StarterTimeON = 0;
int inDS, count = 0;
int interval = 5; // интервал отправки данных на народмон сразу после загрузки
int Timer = 0; // таймер времени прогрева двигателя по умолчанию = 0
int Timer2 = 0; // часовой таймер (60 sec. x 60 min. / 10 = 360 )
bool heating = false; // переменная состояния режим прогрева двигателя
bool SMS_send = false; // флаг разовой отправки СМС
bool ring = false; // флаг момента снятия трубки
void setup() {
pinMode(ACC, OUTPUT);
pinMode(ON, OUTPUT);
pinMode(STARTER, OUTPUT);
pinMode(OUT_4, OUTPUT);
pinMode(OUT_5, OUTPUT); // на вебасту
pinMode(OUT_6, OUTPUT);
// pinMode(RESET_Pin, OUTPUT);
pinMode(START_Pin, INPUT);
pinMode(3, INPUT_PULLUP); // указываем пин на вход для с внутричипной подтяжкой к +3.3V
pinMode(2, INPUT); // указываем пин на вход для с внутричипной подтяжкой к +3.3V
delay(100);
Serial.begin(9600); //скорость порта
// Serial.setTimeout(50);
SIM800.begin(9600); //скорость связи с модемом
// SIM800.setTimeout(500); // тайм аут ожидания ответа
Serial.println("Загрузка v.5.13| MAC:"+MAC+" | TEL:"+call_phone+" | 17/08/2018");
SIM800_reset();
// attachInterrupt(0, close_d, FALLING); // включаем прерывание при переходе 1 -> 0 на D2, или 0 -> 1 на ножке оптопары
// attachInterrupt(1, open_d, FALLING); // включаем прерывание при переходе 1 -> 0 на D3, или 0 -> 1 на ножке оптопары
}
/* --------------------------------------------------- Перезагрузка МОДЕМА SIM800L ------------------------------------------------ */
void SIM800_reset() {
delay(2000); SIM800.println("AT+CMGDA=\"DEL ALL\""); // Удаляем все СМС
//SIM800.println("AT+IPR=9600;E1+CMGF=1;+CSCS=\"gsm\";+CNMI=2,1,0,0,0;+VTD=1;+CMEE=1;&W");
//digitalWrite(RESET_Pin, LOW),delay(2000), digitalWrite(RESET_Pin, HIGH), delay(5000);
}
void loop() {
if (SIM800.available()) resp_modem(); // если что-то пришло от SIM800 в Ардуино отправляем для разбора
if (Serial.available()) resp_serial(); // если что-то пришло от Ардуино отправляем в SIM800
if (millis()> Time1 + 10000) Time1 = millis(), detection(); // выполняем функцию detection () каждые 10 сек
if (heating == true && digitalRead(STOP_Pin)==1) heatingstop(1); // если нажали на педаль тормоза в режиме прогрева
if (digitalRead(STOP_Pin)==1) Timer2 = 0 ; // если нажали на педаль тормоза в режиме прогрева
if (digitalRead(START_Pin)==1) enginestart(1); // если нажали кнопку старт
}
void detection(){ // условия проверяемые каждые 10 сек
Vbat = VoltRead(); // замеряем напряжение на батарее
Serial.print("|int: "), Serial.print(interval);
Serial.print("||Timer:"), Serial.println (Timer);
inDS = 0;
sensors.requestTemperatures(); // читаем температуру с трех датчиков
while (inDS < 10){
TempDS[inDS] = sensors.getTempCByIndex(inDS); // читаем температуру
if (TempDS[inDS] == -127.00){TempDS[inDS]= 80;
break; } // пока не доберемся до неподключенного датчика
inDS++;}
for (int i=0; i < inDS; i++) Serial.print("Temp"), Serial.print(i), Serial.print("= "), Serial.println(TempDS[i]);
Serial.println ("");
//if (TempDS[0] > 70) enginestart(1); // цыклический запуск получился
if (SMS_send == true && sms_report == true) { SMS_send = false; // если фаг SMS_send равен 1 высылаем отчет по СМС
SIM800.println("AT+CMGS=\""+SMS_phone+"\""), delay(100);
SIM800.print("Privet "+SENS+".!");
for (int i=0; i < inDS; i++) SIM800.print("\n Temp"), SIM800.print(i), SIM800.print(": "), SIM800.print(TempDS[i]);
SIM800.print("\n Voltage Now: "), SIM800.print(Vbat), SIM800.print("V.");
SIM800.print("\n Voltage Min: "), SIM800.print(V_min), SIM800.print("V.");
if (digitalRead(Feedback_Pin) == HIGH) SIM800.print("\n Voltage for start: "), SIM800.print(VbatStart), SIM800.print("V.");
if (heating == true) SIM800.print("\n Timer "), SIM800.print(Timer/6), SIM800.print("min.");
SIM800.print("\n Attempts:"), SIM800.print(count);
SIM800.print("\n Uptime: "), SIM800.print(millis()/3600000), SIM800.print("H.");
SIM800.print("\n https://www.google.com/maps/place/"), SIM800.print(LAT), SIM800.print(","), SIM800.print(LNG);
SIM800.print((char)26); }
if (Timer == 12 ) SMS_send = true;
if (Timer > 0 ) Timer--; // если таймер больше ноля SMS_send = true;
if (heating == true && Timer <1) heatingstop(0); // остановка прогрева если закончился таймера
if (heating == true && Vbat < 11.0 ) heatingstop(1); // остановка прогрева если напряжение просело ниже 11 вольт
if (heating == true && TempDS[0] > 70) digitalWrite(OUT_5, HIGH); // выход d10 >= температура достигла 70 град
if (heating == true && TempDS[0] < 70) digitalWrite(OUT_5, LOW);
if (Timer2 == 1) {Timer2 = 1080; if (TempDS[0] < -18) {enginestart(3);}}
if (Timer2 > 1) Timer2--;
if (heating == false) digitalWrite(OUT_6, HIGH), delay (50), digitalWrite(OUT_6, LOW); // моргаем светодиодом когда ждем
// if (heating == true) digitalWrite(OUT_6, HIGH), delay (50), digitalWrite(OUT_6, LOW); // моргаем светодиодом когда греемся
if (n_send == true) interval--;
if (interval <1) interval = 30, SIM800.println ("AT+SAPBR=3,1, \"Contype\",\"GPRS\""), delay (200); // подключаемся к GPRS
if (interval == 28 && n_send == true ) SIM800.println ("AT+SAPBR=0,1");
}
void resp_serial (){ // ---------------- ТРАНСЛИРУЕМ КОМАНДЫ из ПОРТА В МОДЕМ ----------------------------------
String at = "";
// while (Serial.available()) at = Serial.readString();
int k = 0;
while (Serial.available()) k = Serial.read(),at += char(k),delay(1);
SIM800.println(at), at = ""; }
void resp_modem (){ //------------------ НАЛИЗИРУЕМ БУФЕР ВИРТУАЛЬНОГО ПОРТА МОДЕМА------------------------------
String at = "";
// while (SIM800.available()) at = SIM800.readString(); // набиваем в переменную at
int k = 0;
while (SIM800.available()) k = SIM800.read(),at += char(k),delay(1);
Serial.println(at);
if (at.indexOf("+CLIP: \""+call_phone+"\",") > -1 && at.indexOf("+CMGR:") == -1 ) {delay(200), SIM800.println("ATA"), ring = true;
} else if (at.indexOf("+CLIP: \""+SMS_phone+"\",") > -1 && at.indexOf("+CMGR:") == -1 ) {
delay(50), SIM800.println("ATH0");
enginestart(3);
} else if (at.indexOf("+DTMF: ") > -1) {String key = at.substring(at.indexOf("")+9, at.indexOf("")+10);
pin = pin + key;
if (pin.indexOf("*") > -1 ) pin= "";
} else if (at.indexOf("+CMTI: \"SM\",") > -1) {int i = at.substring(at.indexOf("\"SM\",")+5, at.indexOf("\"SM\",")+6).toInt();
delay(2000), SIM800.print("AT+CMGR="), SIM800.println(i); // читаем СМС
} else if (at.indexOf("#123start") > -1 ) {enginestart(5);
} else if (at.indexOf("#123stop") > -1 ) {heatingstop(1);
} else if (at.indexOf("#autoh") > -1 ) {Timer2 = 1080;
} else if (at.indexOf("SMS Ready") > -1 || at.indexOf("NO CARRIER") > -1 ) {SIM800.println("AT+CLIP=1;+DDET=1"); // Активируем АОН и декодер DTMF
/* -------------------------------------- проверяем соеденеиние с ИНТЕРНЕТ ------------------------------------------------------------------- */
} else if (at.indexOf("AT+SAPBR=3,1, \"Contype\",\"GPRS\"\r\r\nOK") > -1 ) {SIM800.println("AT+SAPBR=3,1, \"APN\",\""+APN+"\""),delay (500);
} else if (at.indexOf("AT+SAPBR=3,1, \"APN\",\""+APN+"\"\r\r\nOK") > -1 ) {SIM800.println("AT+SAPBR=1,1"),delay (1800); // устанавливаем соеденение
} else if (at.indexOf("AT+CIPSTART=\"TCP\",\"narodmon.ru\",\"8283\"\r\r\n+CME ERROR: 3") > -1 ) {delay(1000), SIM800.println("AT+CFUN=1,1");
} else if (at.indexOf("CONNECT FAIL") > -1 ) {delay(1000), SIM800.println("AT+CFUN=1,1");
} else if (at.indexOf("AT+SAPBR=1,1\r\r\nOK") > -1 ) {SIM800.println("AT+SAPBR=2,1"), delay (1000); // проверяем статус соединения
} else if (at.indexOf("+SAPBR: 1,1") > -1 ) {SIM800.println("AT+CIPGSMLOC=1,1"), delay (3000); // запрашиваем геолокацию локацию
} else if (at.indexOf("+CIPGSMLOC: 0,") > -1 ) {LAT = at.substring(at.indexOf("+CIPGSMLOC: 0,")+24, at.indexOf("+CIPGSMLOC: 0,")+33);
LNG = at.substring(at.indexOf("+CIPGSMLOC: 0,")+14, at.indexOf("+CIPGSMLOC: 0,")+23);
delay (200), SIM800.println("AT+CIPSTART=\"TCP\",\""+SERVER+"\",\""+PORT+"\""), delay (500);
} else if (at.indexOf("CONNECT OK\r\n") > -1 ) {SIM800.println("AT+CIPSEND"), delay (1200);
} else if (at.indexOf("AT+CIPSEND\r\r\n>") > -1 ) {SIM800.print("#" +MAC+ "#" +SENS); // заголовок пакета
for (int i=0; i < inDS; i++) SIM800.print("\n#Temp"), SIM800.print(i), SIM800.print("#"), SIM800.print(TempDS[i]);
SIM800.print("\n#Vbat#"), SIM800.print(Vbat); // Напряжение аккумулятора
SIM800.print("\n#Uptime#"), SIM800.print(millis()/1000); // Время непрерывной работы
SIM800.print("\n#Timer2#"), SIM800.print(Timer2/6); // Время таймера автопрогрева
SIM800.print("\n#LAT#"), SIM800.print(LAT); // Широта по геолокации
SIM800.print("\n#LNG#"), SIM800.print(LNG); // Долгота по геолокации
SIM800.println("\n##"), SIM800.println((char)26), delay (100); // закрываем пакет
}
at = ""; // Возвращаем ответ можема в монитор порта , очищаем переменную
if (pin.indexOf("123") > -1 ){ pin= "", Voice(2), enginestart(1);
} else if (pin.indexOf("741") > -1 ){ pin= "", Voice(12), delay(1600), n_send = false,SIM800.println("ATH0");
} else if (pin.indexOf("852") > -1 ){ pin= "", Voice(12), delay(1600), n_send = true, SIM800.println("ATH0");
} else if (pin.indexOf("456") > -1 ){ pin= "", Voice(12), delay(1600), Timer2 = 1080, SIM800.println("ATH0");
//} else if (pin.indexOf("951") > -1 ){ pin= "", Voice(12), delay(1000), SIM800.println("AT+CFUN=1,1"); // перезагрузка модема
} else if (pin.indexOf("789") > -1 ){ pin= "", Voice(10), delay(1500), Timer2 = 0, SIM800.println("ATH0"), heatingstop(1);
} else if (pin.indexOf("#") > -1 ){ pin= "", SIM800.println("ATH0"), SMS_send = true;}
if (ring == true) { ring = false, delay (2000), pin= ""; // обнуляем пин
if (heating == false){Voice(1);
}else Voice(8);
}
}
void enginestart(int Attempts ) { // программа запуска двигателя
/* ----------------------------------------- ПРЕДНАСТРОЙКА ПЕРЕД ЗАПУСКОМ ---------------------------------------------------------*/
//Serial.println("Предпусковая настройка");
// detachInterrupt(1); // отключаем аппаратное прерывание, что бы не мешало запуску
VbatStart = VoltRead();
int StTime = map(TempDS[0], 20, -15, 2200, 5000); // при -15 крутим стартером 5 сек, при +20 крутим 1 сек
// StTime = constrain(StTime, 3000); // ограничиваем диапазон работы стартера от 1 до 6 сек
StTime = 2700; // для жесткой фиксации по времени
int z = map(TempDS[0], 0, -25, 0, 5); // задаем количество раз прогрева свечей пропорциолально температуре
z = constrain(z, 0, 5); // огрничиваем попытки от 0 до 5 попыток
Timer = map(TempDS[0], 30, -25, 30, 150); // при -25 крутим прогреваем 30 мин, при +50 - 5 мин
Timer = constrain(Timer, 30, 180); // ограничиваем таймер в зачениях от 5 до 30 минут
count = 0; // переменная хранящая число совершенных попыток запуска
V_min = 14; // переменная хранящая минимальные напряжения в ммент старта
// если напряжение АКБ больше 10 вольт, зажигание выключено, температуры выше -25 град, счетчик числа попыток меньше 5
while (Vbat > 10.00 && digitalRead(Feedback_Pin) == LOW && TempDS[0] > -30 && count < Attempts){
count++, Serial.print ("Попытка №"), Serial.println(count);
digitalWrite(ON, LOW), delay (200); // выключаем зажигание на 2 сек. на всякий случай
digitalWrite(ACC, HIGH), delay (500); // включаем реле первого положения замка зажигания
Voice(3);
digitalWrite(ON, HIGH), delay (2000); // включаем зажигание, и выжидаем 4 сек.
// прогреваем свечи несколько раз пропорционально понижению температуры, греем по 8 сек. с паузой 2 сек.
//int zh = z;
//while (zh > 0) zh--, Voice(3), digitalWrite(ON, LOW), delay(2000), digitalWrite(ON, HIGH), delay(8000);
// если не нажата педаль тормоза или КПП в нейтрали то включаем реле стартера на время StTime
if (digitalRead(STOP_Pin) == LOW) { // в нейтрали на минус
// if (digitalRead(PSO_Pin) == HIGH) { // в нейтрали на плюс +12
// Serial.println("Стартер включил");
Voice(4);
StarterTimeON = millis();
digitalWrite(STARTER, HIGH); // включаем реле стартера
} else {
Voice(7);
heatingstop(1);
count = -1;
break;
}
delay (100);
//float V_stON = VoltRead(); // временно так
while (millis() < (StarterTimeON + StTime) && digitalRead(PSO_Pin) == LOW) VoltRead(), delay (50);
//while (millis() < (StarterTimeON + StTime) && digitalRead(PSO_Pin) == HIGH) VoltRead(), delay (50);
digitalWrite(STARTER, LOW), delay (1000);
//digitalWrite(ACC, HIGH), // включаем реле первого положения замка зажигания
// Serial.println("Стартер выключил, ожидаем 6 сек.");
Voice(12);
delay (6000);
// if (digitalRead(PSO_Pin) != LOW) { // если детектировать по датчику давления масла
if (digitalRead(PSO_Pin) == HIGH) { // если детектировать по лампе зарядки
// если детектировать по напряжению зарядки
Serial.println ("Есть запуск!");
Voice(5);
heating = true;
digitalWrite(OUT_6, HIGH);
break; } // считаем старт успешным, выхдим из цикла запуска двигателя
Voice(6);
StTime = StTime + 200; // увеличиваем время следующего старта на 0.2 сек.
// z++;
heatingstop(0); } // отключаем все реле без бнуления таймера
Serial.println ("Выход из запуска");
if (count != 1) SMS_send = true; // отправляем смс СРАЗУ только в случае незапуска c первой попытки
if (heating == false){ Timer = 0, Voice(10); // обнуляем таймер если запуска не произошло
} else digitalWrite(OUT_6, HIGH); // включаем подогрев седений если все ОК
delay(3000), SIM800.println("ATH0"); // вешаем трубку (для SIM800L)
//attachInterrupt(1, callback, FALLING); // включаем прерывание на обратный звонок
}
float VoltRead() { // замеряем напряжение на батарее и переводим значения в вольты
float ADCC = analogRead(BAT_Pin);
ADCC = ADCC / m ;
Serial.print("Напряжение: "), Serial.print(ADCC), Serial.println("V");
if (ADCC < V_min) V_min = ADCC;
return(ADCC); } // переводим попугаи в вольты
void heatingstop(bool reset_timer) { // программа остановки прогрева двигателя
digitalWrite(ON, LOW), delay (100);
digitalWrite(OUT_6, LOW), delay (100);
digitalWrite(ACC, LOW), delay (100);
digitalWrite(OUT_5, LOW), delay (100);
heating= false, delay(2000);
Serial.println ("Выключить все");
if (reset_timer == true) Timer = 0;
}
void Voice(int Track){
SIM800.print("AT+CREC=4,\"C:\\User\\"), SIM800.print(Track), SIM800.println(".amr\",0,95");}
// функции питания вакуумного насоса ЦЗ в зависимости от внешних прерываний
void close_d () {digitalWrite(OUT_4, HIGH), delay(5500), digitalWrite(OUT_4, LOW);}
void open_d () {digitalWrite(OUT_5, HIGH), delay(5500), digitalWrite(OUT_5, LOW);}
// обратный звонок при появлении напряжения на входе IN1
void callback(){SIM800.println("ATD"+call_phone+";"), digitalWrite(OUT_5, HIGH), delay(5000);}