Официальный сайт компании Arduino по адресу arduino.cc
Arduino Pro Mini+SIM800, дополнение к авто сигнализации с автозапуском.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Добрый день!
У большинства авто сигнализаций с авто запуском (сигналок) или отдельных модулей автозапуска, имеется дополнительный вход (проводок - pin) для внешнего дистанционного автозапуска прогрева авто. Достаточно этот pin, замкнуть на массу в течении 2 сек. произойдет запуск авто (если соблюдены все условия запуска для авто сигнализации). Если еще один раз замкнуть данный проводок на массу, произойдет принудительная остановка автозапуска авто.
К авто сигналке был добавлен блок управления из статьи, http://www.rlocman.ru/shem/schematics.html?di=66614, собранный из телефона и обычной логики.
Было решено сменить элементную базу. За основу взяты скетч и схема, https://github.com/martinhol221/SIM800L_DTMF_control, но с сильно урезанным функционалом.
Функции модуля Arduino Pro Mini+SIM800 в следующем.
- При звонке на устройство, происходит авто ответ и проигрывание Voice(1) .arm /*жду команду*/ из памяти SIM800 модуля.
- При подаче DTMF команды 123 /*start*/, проигрывание Voice(7) *все поняла завожу*,
опрос pin A2 (pin A2 =0, ручник, тормоз), включение pin D12, /*starter*/на время 2 сек., через развязывающий диод и управляющий транзистор (на провод сигналки).
Если запуска не произошло, на А3 не появилась 1 (не включилось зажигание авто), то проигрывание Voice(6) (повторный запуск). Значит авто не подготовлено к запуску.
- При появлении на pin A3 = 1 (зажигание от авто), проигрывание Voice(5) (*двигатель запущен*)
- При подаче DTMF команды 321 (stop), проигрывание Voice(6) (*стоп прогрева*), включение pin D11=1 (OUT_4) , на время 2 сек. через развязывающий диод и управляющий транзистор (на провод сигналки).
- При подаче DTMF команды 789 , блокировка двигателя, включение pin D8 (OUT_5, блокировка двигателя), проигрывание Voice(8) *двигатель блокирован *). Подача 1 с D8 на D4 (D4 организован как вход IN_7, пока так проще обрабатывать), с IN_7 -D4 на D9 выдает прерывистый сигнал на реле клаксона и дальнего света авто.
- При подаче DTMF команды 987 , сброс блокировки двигателя.
В приведенном скетче никак не могу осуществить;
Если во время прогрева от arduino, на PSO_Pin - A3 ( зажигание) переключится с 1 на 0 (по какой то причине отключилось зажигание авто или сигналка авто делает следующую попытку запуска) на время
40 сек (приблизительно, все зависит от сигналки) и Feedback_Pin == HIGH - А1 (имитация команды на запуск в arduino, есть прогрев). То нужен сброс прогрева, в скетче arduino (сброс имитации команды прогрева в arduino).
Необходимо задать время через которое выполнится команда
99. if (digitalRead(PSO_Pin) == LOW && digitalRead(Feedback_Pin) == HIGH) && PsoTime
и выполнится
{heatingstop(1);}
Если прошло время отключенного зажигания меньше, необходимо сбросить таймер .
100. digitalRead(PSO_Pin) == HIGH && digitalRead(Feedback_Pin) == HIGH
В процессе отработки скетча выяснил что millis не сбрасывается, а только останавливается, до следующего изменения на PSO_Pin
Если можете, ЛЮДИ ДОБРЫЕ, толкните пожалуйста в нужном направлении. Или прочитать как сделать задержку на выполнение команды, приходящей в течении некоторого времени и сброс цикла если время не прошло. Для меня проще поставить внешний 555 таймер, но есть желание дописать скетч.
Мой полный комплект по ссылке https://yadi.sk/d/zP5XPeUt3X9qaa
#include <SoftwareSerial.h> SoftwareSerial SIM800(7, 6); // для новых плат начиная с версии RX,TX #define ON 10 // иммитация команды на запуск от arduino, через диод c D10 на A1 #define STARTER 12 // через диод с 12-го пина ардуино и транзистор, на пуск автозапуска сигналки #define OUT_4 11 // на стоп автозапуска сигналки, через диод с D11 ардуино и транзистор (доп выход для стопа авто сигналки) #define OUT_5 8 // на реле блокировки двигателя #define OUT_6 9 // на реле дальнего света и клаксона #define IN_7 4 // для управления реле дальнего света и клаксона #define BAT_Pin A0 // на батарею, через делитель напряжения 39кОм / 11 кОм #define Feedback_Pin A1 // на A1 через диод с D10, иммитация команды на запуск от arduino #define STOP_Pin A2 // на концевик педали тормоза для отключения (на нейтрали запрещения) режима прогрева #define PSO_Pin A3 // на провод от замка зажигания, анализ заведенного мотора #define RESET_Pin 5 #define IN_1 3 // на кнопку обратного звонка, кнопка на массу #define PsoTime 1000 /* ----------------------------------------- ИНДИВИДУАЛЬНЫЕ НАСТРОЙКИ !!!--------------------------------------------------------- */ String call_phone= "+79270277340"; // телефон входящего вызова float Vstart = 13.50; // порог распознавания момента запуска по напряжению String pin = ""; // строковая переменная набираемого пинкода float Vbat, VbatStart, V_min ; // переменная хранящая напряжение бортовой сети float m = 69.91; // делитель для перевода АЦП в вольты для резистров 39/11kOm unsigned long Time1, StarterTimeON = 0; unsigned long Time2; //для моргания светодиодом с millis, постоянно проходят импульсы с малой скважностью на OUT_6(9pin) //unsigned long loopTime2; //для моргания светодиодом с millis, //unsigned long PsoTime; //unsigned long PsoTime = 20000; int Timer = 0; // таймер времени прогрева двигателя по умолчанию = 0 int Timer2 = 0; // часовой таймер (60 sec. x 60 min. / 10 = 360 ) bool heating = false; // переменная состояния режим прогрева двигателя bool ring = false; // флаг момента снятия трубки void(* resetFunc) (void) = 0; void setup() { pinMode(ON, OUTPUT); pinMode(STARTER, OUTPUT); pinMode(OUT_4, OUTPUT); pinMode(OUT_5, OUTPUT); pinMode(OUT_6, OUTPUT); pinMode(RESET_Pin, OUTPUT); pinMode(IN_7, INPUT); pinMode(IN_1, INPUT_PULLUP); // указываем пин на вход для с внутричипной подтяжкой к +3.3V delay(100); Serial.begin(9600); //скорость порта // Serial.setTimeout(50); SIM800.begin(9600); //скорость связи с модемом // SIM800.setTimeout(500); // тайм аут ожидания ответа Serial.println("+call_phone+"); SIM800_reset(); } /* --------------------------------------------------- Перезагрузка МОДЕМА SIM800L ------------------------------------------------ */ void SIM800_reset() { delay(2000); SIM800.println("AT+CMGDA=\"DEL ALL\""); // Удаляем все СМС } // обратный звонок при замыкании на массу входа D3, чтобы раз в 3 месяца звонить а то отключат SIM карту void callback() { SIM800.println("ATD" + call_phone + ";"), 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 ; // если нажали на педаль тормоза в режиме прогрева /* //моргаем реле дальнего света и клаксона // хотел сделать с millis() но в этом блоке постоянно проходят импульсы с малой скважностью на OUT_6(9pin) // так же иногда при прогреве проходит импульс по STARTER (12pin) if (digitalRead(IN_7) == LOW) digitalWrite(OUT_6, LOW); { Time2 = millis(); // считываем время, прошедшее с момента запуска программы if(Time2 >= (loopTime2+500)){ // сравниваем текущий таймер с переменной loopTime2 + 0,5 секунды digitalWrite(OUT_6, !digitalRead(OUT_6)); // включаем/выключаем LED знак ! инверсия loopTime2 = Time2;} // в loopTime записываем новое значение } */ //моргаем реле дальнего света и клаксона. из за delay плохо срабатывает сброс блокировки "987", приходится повторять набор команты if (digitalRead(IN_7)==1) digitalWrite(OUT_6, HIGH), delay (500), digitalWrite(OUT_6, LOW), delay (500); } void detection(){ // условия проверяемые каждые 10 сек Vbat = VoltRead(); // замеряем напряжение на батарее Serial.println (""); if (heating == true && Vbat < 11.0 ) heatingstop(1); // остановка прогрева если напряжение просело ниже 11 вольт //если (PSO_Pin, зажигание) переключился с 1 на 0 (по какой то причине отключилось зажигание авто) // и (Feedback_Pin) == HIGH (или heating == true, есть прогрев в arduino). на время больше 40 сек. то нужен сброс прогрева в arduino //нужно сбросить ( "уже прогреваюсь" Voice(5) int PsoTime = millis(); //время останавливается, но не сбрасывается, время не всегда одинаковое if ((digitalRead(PSO_Pin) == LOW && digitalRead(Feedback_Pin) == HIGH) && PsoTime >= 20000) {heatingstop(1);} if (digitalRead(PSO_Pin) == HIGH && digitalRead(Feedback_Pin) == HIGH) {PsoTime = 0;} /* if (digitalRead(PSO_Pin) == LOW && digitalRead(Feedback_Pin) == HIGH) ; //не работает {millis() - Time2 > PsoTime;}; if (digitalRead(PSO_Pin) == HIGH && digitalRead(Feedback_Pin) == HIGH); {Time2 = millis();} ; */ /* int PsoTime = constrain(PsoTime, 20000, 20000); if ((digitalRead(PSO_Pin) == LOW && digitalRead(Feedback_Pin) == HIGH) && PsoTime > 1) {heatingstop(1);} //время срабатывания 4 сек, больше не выходит if ((digitalRead(PSO_Pin) == HIGH && digitalRead(Feedback_Pin) == HIGH) && PsoTime < 1) {PsoTime = 0;} */ } 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) {delay(200), SIM800.println("ATA"), ring = true; } 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("NO CARRIER") > -1 ) {SIM800.println("AT+CLIP=1;+DDET=1"); // Активируем АОН и декодер DTMF } at = ""; // Возвращаем ответ можема в монитор порта , очищаем переменную if (pin.indexOf("789") > -1 ){ pin= "", Voice(8), digitalWrite(OUT_5, HIGH), delay (2000), heatingstop(1), SIM800.println("ATH0"); // блокировка двигателя } else if (pin.indexOf("987") > -1 ){ pin= "", Voice(9), digitalWrite(OUT_5, LOW), delay (2000), SIM800.println("ATH0"); //снятие сблокировки двигателя } else if (pin.indexOf("123") > -1 ){ pin= ""; if (digitalRead(Feedback_Pin) == HIGH) {false;} else {(digitalRead(Feedback_Pin) == LOW); {Voice(7), enginestart(3);}} // запуск на сигналку // "све поняла завожу" } else if (pin.indexOf("321") > -1 ){ pin= ""; // стоп запуска на сигналку if (digitalRead(Feedback_Pin) == LOW) //необходима что бы командой "стоп" не запустить дистанционно двигатель {false;} else {(digitalRead(Feedback_Pin) == HIGH); { Voice(6), digitalWrite(OUT_4, HIGH), delay(2000), heatingstop(1);}} // "стоп прогрева" SIM800.println("ATH0"); } /*------голосовые сообщения при входящем звонке-----------*/ if (ring == true) { ring = false, delay (2000), pin= ""; // обнуляем пин //авто находится в режиме блокирови Voice(8) if (digitalRead(OUT_5) == HIGH) { Voice(8); // "двигатель блокирован" } //включено зажигание авто и нет прогрева от arduino, ( Voice(10) else if (digitalRead(Feedback_Pin) == LOW && digitalRead(PSO_Pin) == HIGH) { Voice(10); // "двигатель уже запущен" } // "привет жду команду" else if (digitalRead(Feedback_Pin) == LOW && digitalRead(OUT_5) == LOW) { Voice(1); } // "уже прогреваюсь" else {Voice(5);} } } void enginestart(int Attempts ) { // программа запуска двигателя /* ----------------------------------------- ПРЕДНАСТРОЙКА ПЕРЕД ЗАПУСКОМ ---------------------------------------------------------*/ //Serial.println("Предпусковая настройка"); detachInterrupt(1); // отключаем аппаратное прерывание, что бы не мешало запуску VbatStart = VoltRead(); // ограничиваем время сигнала запуска на сигналку ( диапазон работы стартера) от 1,5 до 1,5 сек int StTime = constrain(StTime, 1500, 1500); V_min = 14; // переменная хранящая минимальные напряжения в момент старта // если напряжение АКБ больше 10 вольт, зажигание выключено while (Vbat > 10.00 && digitalRead(Feedback_Pin) == LOW){ digitalWrite(ON, HIGH), delay (50); // включаем виртуальное зажигание, с D10 на А1. if (digitalRead(STOP_Pin) == LOW) { // тормоз не нажат или в нейтрали на минус // if (digitalRead(STOP_Pin) == HIGH) { // в нейтрали на плюс +12 StarterTimeON = millis(); digitalWrite(STARTER, HIGH); // на пуск автозапуска сигналки } else { Voice(4); // "я на передаче" heatingstop(1); break; } delay (100); while (millis() < (StarterTimeON + StTime) && digitalRead(PSO_Pin) == LOW) VoltRead(), delay (50); digitalWrite(STARTER, LOW), delay (1000); // Serial.println("пуск автозапуска сигналки выключил, ожидаем 4 сек."); delay (4000); // запуск выключил, ожидаем 4 сек. if (digitalRead(PSO_Pin) == HIGH) { // включилось зажигание от сигналки Serial.println ("Есть запуск!"); Voice(2); // "двигатель запущен" heating = true; break; } // считаем старт успешным, выходим из цикла запуска двигателя // "повторите запуск" Voice(3), heatingstop(1),SIM800.println("ATH0"); // программный сброс если нет запуска(переход но 0 адрес)(нет + от замка зажигания(PSO_Pin) 4 сек ), перезваниваем пробуем еще раз void(* resetFunc) (void) = 0; resetFunc(); } Serial.println ("Выход из запуска"); if (heating == false){ Timer = 0, Voice(6); // "стоп прогрева" } delay(3000), SIM800.println("ATH0"); // вешаем трубку (для SIM800L) } 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); 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");}
Arduino занялся 2 месяца, не на чем было, ну и не интересовался раньше.
Так же где можно прочитать, что прописать в скетче что бы привязка номера телефона была не к программе, а к SIM карте.
Я бы вам советовал для начала изучить, что такое миллис и как он работает.Тогда вы не будете писать фраз типа "миллис не сбрасывается, а только останавливается".(по секрету - миллис не только не сбрасывается, но и не останавливается...)
Может тогда и задачи свои решите.
А код стоило бы сначала отформатировать, прежде чем предлагать кому-то в нем копаться. Про отступы никогда не слыхали? И операторы через запятую перечисляют только (подставьте сами...)
Уважаемый b707, спасибо за замечания. Насчет millis, я имел в виду цикл выполнения.
Отформатировал и подчистил скетч. Изменил схему. Добавил строки 79-97, и 101-103. Удалил лишние порты, которые нужны были при отработке в железе.
Сейчас вроде работает, но при выполнении функции (digitalRead(PSO_Pin) == LOW && digitalRead(Feedback_Pin) == HIGH), заметил что если переключить PSO_Pin, несколько раз (например 3 раза по 20 сек) то время сброса 24_ long Time2, увеличивается на время отключения (+60 сек). С чем это связано.
Также кто нибудь просветит неграмотного, отчего 24_ long Time2 = 32767, и не больше. При большем значении не происходит выполнение строк 79-97 . Происходит какоето битовое переполнение?
Также кто нибудь просветит неграмотного, отчего 24_ long Time2 = 32767, и не больше. При большем значении не происходит выполнение строк 79-97 .
Потому что в строке 92 вы сравниваете переменную Time2 со счетчиком STOP_Head_But, который описан как int. то есть может иметь максимальное значение не больше 32767.
Опишите все переменные, связанные с миллис, миллисекундами, счетчиками и тд - как unsigned long
del