-
Notifications
You must be signed in to change notification settings - Fork 33
/
Autostart_Sim800L_narodmon.ino
312 lines (259 loc) · 24.8 KB
/
Autostart_Sim800L_narodmon.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
#include <SoftwareSerial.h>
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
/* ----------------------------------------- ИНДИВИДУАЛЬНЫЕ НАСТРОЙКИ !!!--------------------------------------------------------- */
String LAT = ""; // переменная храняжая широту
String LNG = ""; // переменная храняжая долготу
String call_phone= "+375290000000"; // телефон входящего вызова
String SMS_phone = "+375290000000"; // телефон куда отправляем СМС
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 = true; // отправка данных на народмон по умолчанию включена (true), отключена (false)
bool sms_report = true; // отправка 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 = 69.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(3, INPUT_PULLUP); // указываем пин на вход для с внутричипной подтяжкой к +3.3V
pinMode(2, INPUT_PULLUP); // указываем пин на вход для с внутричипной подтяжкой к +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 ; // если нажали на педаль тормоза в режиме прогрева
}
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 (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] > 86) heatingstop(1); // остановка прогрева если температура достигла 70 град
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(3);
} 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, 1000, 5000); // при -15 крутим стартером 5 сек, при +20 крутим 1 сек
StTime = constrain(StTime, 1000, 6000); // ограничиваем диапазон работы стартера от 1 до 6 сек
// StTime = 3000; // для жесткой фиксации по времени
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 (2000); // выключаем зажигание на 2 сек. на всякий случай
digitalWrite(ACC, HIGH), delay (1000); // включаем реле первого положения замка зажигания
Voice(3);
digitalWrite(ON, HIGH), delay (4000); // включаем зажигание, и выжидаем 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) == LOW)) { // если детектировать по лампе зарядки
if (VoltRead() > Vstart) { // если детектировать по напряжению зарядки
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+";"), delay(5000);}