#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) светодиод переключается......
В программирование пока что нуб поэтому появилось предположение, что, возможно, нужо собрать всю схему до конца.....
Таже пробовал ещё один (так же с просторов тырнета) скетч для отправки смс с "СИМкарты webasto" - смс отправляет мне на номер с текстом.... (правда с небольшой грамматической ошибкой непонятно почему-то получаю смс)
/*
* 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. **/
}
Осталось две фичи реализовать - энергосбережение и контроль зависания и перезагрузки GSM. Всем спасибо, так активно помогаете.
У меня sim900.
Контроль делал так:
1. Раз в минуту посылаю AT. Если модуль ответил OK - хорошо, cчётчик=0. Иначе +1 к счётчику попыток.
2. Если счётчик >= 5, сбрасываю счётчик и "нажимаю" кнопку питания.
Всё работает более года.
Одно такое событие за год произошло.
В продолжении попытки получения положительного результата обнаружил что общаясь с модулем через переходник UNO с использованием PuTTY обнаружил что на команду:
AT+ICF?
Приходит сообщение об ошибки.... при этом при попытке отправить смс, оно приходит на телефон...
Когда EEprom был у вас ещё не тронутый (во всех ячейках FF),то заработало бы, если бы вы скетч заливали сразу после копипаста (без сохранения скетча на компе). При сохранении скетча на компе сбивается кодировка символов соответсвующих байту FF (который в еепроме был изначально), т.е. символа "я" и все косяки из-за этого, а потом я вам немного неправильно почистить еепром предложил, поэтому тоже не работало. Исправил в начале темы как еепром чистить до заливки скетча.
это у вас НЕ получилось, а нули написались в этом случае, потому что вы распечатку в терминал поставили до считываения тел.номера из еепром, а изначально, при старте программы, в переменную тел.номера нули записываются и вы их сразу и распечатали.
PS удалите простыню из сообщения #71, мешает . Кстати когда вставляете скетч, там вверху вкладка правая, можно галочку ставить "свернуть", чтобы под катом было.
почистите еепром таким скетчем и заливайте 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 отслеживать и отправлять сообщение о состоянии котла, температуре ОЖ и бортовом напряжении. Но для этого, как понимаю, нужно знать протокол обмена… Но с выносными датчиками, кому не лень, тоже всё хорошо.
Готов нарисовать и выложить нарисованную схему, для тех «ленивых» кто спрашивает её, но пока не пойму как прикрепить рисунок.
По ходу макетирования появилось несколько вопросов.
1. sms на запрос баланса приходят в HEX unicode =( /лечится заменой оператора или можно программой?/
2. не знаю как на версиях Webasto которые устанавливают как доп, но на "старых" например, моделях БМВ есть несколько условий при которых котёл не будет запущен - (с завода котёл кстати, работал только как "догревайка", но перекодировка творит чудеса и теперь работает ещё и как "автономное отопление" без колхозинга) - одно из них пониженное напряжение питания (недавно у товарища попытались запустить котёл при разряженной АКБ U=11.6V) - сигнал на запуск пришел, а вот котёл не запустился пока не зарядили АКБ. И это считаю правильная задумка - зачем тёплый двигатель, если стартер не крутится. Не увидел организованно ли это в Вашей программе уважаемый автор, но возможно, это будет своим образом аварийная защита, для котлов которые будут рады усадить АКБ в ноль (если такие существуют, конечно)
Изначально была идея запускать по шине CAN (точнее сказать в моей машине по периферийной шине i-bus через приборную панель) и по CAN отслеживать и отправлять сообщение о состоянии котла, температуре ОЖ и бортовом напряжении. Но для этого, как понимаю, нужно знать протокол обмена… Но с выносными датчиками, кому не лень, тоже всё хорошо.
Я так понимаю котел у вас штатный, да к тому же по CAN управляется . Вы уверены в возможности запуска его по аналогу? Вообще чтобы по CAN запускать конечно нужно знать протокол обмена. Но исследование CAN шины тоже дело интересное, хотя и не лёгкое. Если будет интересно, могу выложить проект CAN хакера на ардуино (там собственно сама ардуино и китайский модуль кана на MCP2515), который как раз и позволяет выявить из CAN шины нужные сообщения.
Короче в будущем конечно неплохо было бы дополнить данное устройство CAN шиной, но работы с этим не мало будет, особенно в программной части - протоколы разных авто.
Я хочу допилить хотябы W-BUS, т.к. если сказать по чесноку, в данный момент организовано только включение выключение котла без опроса его реального состояния. Просто у меня нет Webasto Evo чтобы протокол W-BUS помучить.
А вы если только аналог будете использовать вам можно не ставить микруху LM393 и всю её обвязку
По ходу макетирования появилось несколько вопросов.
1. sms на запрос баланса приходят в HEX unicode =( /лечится заменой оператора или можно программой?/
2. не знаю как на версиях Webasto которые устанавливают как доп, но на "старых" например, моделях БМВ есть несколько условий при которых котёл не будет запущен - (с завода котёл кстати, работал только как "догревайка", но перекодировка творит чудеса и теперь работает ещё и как "автономное отопление" без колхозинга) - одно из них пониженное напряжение питания (недавно у товарища попытались запустить котёл при разряженной АКБ U=11.6V) - сигнал на запуск пришел, а вот котёл не запустился пока не зарядили АКБ. И это считаю правильная задумка - зачем тёплый двигатель, если стартер не крутится. Не увидел организованно ли это в Вашей программе уважаемый автор, но возможно, это будет своим образом аварийная защита, для котлов которые будут рады усадить АКБ в ноль (если такие существуют, конечно)
1. Намного проще через оператора решить. (Ну всмысле не заменой его, а подбором правильной команды запроса баланса, либо есть такая функция у некоторых перевода на транслит.) Парсить этот юникод и PDU полный песец.
2. По напряжению АКБ по идее во всех котлах есть выключение. Я не стал делать выключение по напряжению. Но это не сложно - пару строк добавить.
Да, совершенно верно, котёл штатный. Вопрос конечно этот самому интересен будет ли он по +12V запускаться....но скачав документацию (описание + схемы соединений) предполагаю что работать должно. В любом случае скоро узнаем и напишу здесь. Главное чтобы конфликта не было по CAN.
А по поводу использовать MCP2515 - я уже получил из Китая его именно для этих целей, так что выкладывайте прошивку CAN хакера если найду время с удовольствием посижу с ним.
Хочу собрать полную схему (с LM393) так как машины меняются а сегодня новые котлы так понимаю уже все работают по W-Bus....возможно пригодится.
на портале carhelp.info много полезного найдете на этот счет - как запускать штатные котлы. Вам нужно узнать, есть ли у вашего котла шина W-Bus, если есть, то нужно попробовать запустить диагноситку котла по этой шине оригинальной вебастовской программой WTT при помощи обычного к-лайн адаптера. Если диагностика получится, всё упрощается.
ДА, пару лет назад использовал эту программу (WTT) для ремонта своего котла - не пропаяно было хорошо одно сопротивление. На каком-то форуме писал об этом с фото.
Значит можно попробовать подключиться к шине используя Вашу схему!?
Сейчас уже схему не вспомню но кажется именно по этой шине котёл соединён с приборной панелью и имеет название i-bus а уже приборная панель с CAN шиной. То есть через диагностический разъём авто к котлу с помощью WTT не подключиться, собирал всё дома на столе и подключал.
Значит можно попробовать подключиться к шине используя Вашу схему!?
Собираете два адаптера из сообщения #84 или легче покупаете, Один для подключения WTT к котлу, второй - чтобы посниффить обмен данными. Когда узнаете какие байты там летают, можно будет запускать котёл по i-bus (полагаю тот же W-bus)
Спасибо за схему и скетч. Один адаптер есть им собственно и ковыряюсь в авто (прошивка / кодировка блоков) второго нет, попробую купить.... Китай совсем обленил увы, да и часто получается что проще и Дешевле купить готовое устройство чем собирать в одном экземпляре. Исключение составляет - хобби.
Почти закончил собирать плату. Пока провожу эксперименты на столе, надеюсь скоро начнуться полевые испытания!
Если позволите ещё один момент замечен при проверке.
Всё прекрасно работает (смс команды) пока не отключить питание. После повторного включения питания и спустя даже 10 минут устройство никак не реагирует на смс команды пока не нажать кнопку Reset на Nano. После этого снова начинает всё работать.
И ещё подскажите в какую строку и что добавить чтобы в мониторе порта увидеть напряжение АКБ (исключительно для настройки) ? Понижающий DC-DC отличается от Вашего и шунтирует входным сопротивлением делитель напряжения. Вместо 13,70 приходит в смс 12,65. Хочу подобрать подстроичником, но каждый раз отправлять смс.......
вот здесь 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);
}
Всё прекрасно работает (смс команды) пока не отключить питание. После повторного включения питания и спустя даже 10 минут устройство никак не реагирует на смс команды пока не нажать кнопку Reset на Nano. После этого снова начинает всё работать.
вот тут хз, у меня тоже так было на одной ардуино (от robotdyn ), на другой все норм. надо пробовать на другом МК. попробуйте в Setup строка 115 задержку на 6...7 секунд повысить
Приветствую. Спасибо за скетч - подобрал в программе величинами сопротивлений значение напряжения. Про делитель напряжения как бы всё понятно, но как ранее заметил что DC-DC шунтирует этот делитель и показывает "погоду" вместо напряжения. (Если запитать DC-DC от отдельного источника то проблем нет). В общем сейчас всё хорошо (значения в программе кстати получились далеки от истины).
Появилось время и добрался до авто. Идёт с фишки от котла три провода - один на насос, второй на i-BUS (CAN) и третий на таймер (точнее сказать на связку Telestart + timer) которого нет но можно дооснастить. На схеме этот провод идёт на квадратную фишку таймера на контакт "OUT". Отсюда появился вопрос - по какому протоколу работает связка таймер-котёл? Если W-Bus то можно попробовать подключить выход с Вашей конструкции на этот провод!?
А Подозреваю что на проводе OUT должен быть просто потенциал 12в при включении. Но если даже там цифра, мой вариант может и подойдет. По крайней мере так включали некоторые штатные котлы. Машина то какая?
MaksVV,
1. Получилось сделать контроль зависаний? Я писал выше #63
2. все возможности по энергосбережению в микроконтроллере AVR описаны тут https://www.gammon.com.au/power
спасибо по ссылке почитаю. Контроль зависаний попытался сделать. Добавил в скетч (сообщение #82). Нарисовал новую плату с реле. Т.е. питание GSM сидит на нормально-замкнутых контактах реле. При рестарте подается питание на реле и оно размыкает питание GSM. Но это только пробная версия, ещё ничего не проверял. Т.к. нет времени и детали ещё не дошли.
реле между контактами gsm модуля. Если gsm модуль на панельки устанавливать, то он высоко сидит, туда это реле по идее влезть должно, судя по его размерам.
#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) светодиод переключается......
В программирование пока что нуб поэтому появилось предположение, что, возможно, нужо собрать всю схему до конца.....
такой скетч попробуйте, если не работает, проблема в аппартаной части. СМС нужно слать с текстом 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); } }эмм, не успел ответить ))
Этот Ваш скетч крайний попробовал - РАБОТАЕТ тоже! =))
ну то есть ON включает и OFF выключает светодиод!
Таже пробовал ещё один (так же с просторов тырнета) скетч для отправки смс с "СИМкарты webasto" - смс отправляет мне на номер с текстом.... (правда с небольшой грамматической ошибкой непонятно почему-то получаю смс)
попробуйте почистить еепром сначала вот этим
/* * 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. **/ }в сериал мониторе должно появиться много нулей
Подтверждаю - спустя пару сек побежали нули
залил снова после чистки v2.1 - ничего увы не поменялось.....ответное смс на WriteNumber1 не получаю
недавно собрал пару модулей, всё работало, соберу ещё один, найду косяк, отпишусь
Может проблема из-за нестыковки уровней Rx Tx или скорости !? Но со светодиодом работает. А вот смс с СИМ получаю hello @ord вместо hello world.....
ОК. Будет интересно. Хочу пристроить модуль к своему котлу - Thermo Top С...... запускать думаю сигналом +12В на 30 минут.
Осталось две фичи реализовать - энергосбережение и контроль зависания и перезагрузки GSM. Всем спасибо, так активно помогаете.
У меня sim900.
Контроль делал так:
1. Раз в минуту посылаю AT. Если модуль ответил OK - хорошо, cчётчик=0. Иначе +1 к счётчику попыток.
2. Если счётчик >= 5, сбрасываю счётчик и "нажимаю" кнопку питания.
Всё работает более года.
Одно такое событие за год произошло.
В продолжении попытки получения положительного результата обнаружил что общаясь с модулем через переходник UNO с использованием PuTTY обнаружил что на команду:
AT+ICF?
Приходит сообщение об ошибки.... при этом при попытке отправить смс, оно приходит на телефон...
Чтобы посмотреть что происходит на Rх GSM модуля нужно раскоментировать строку 356 скетча 2.1. а строку 137 поменять на
Соответственно смотреть в сериал мониторе на скорости 19200
Чтобы посмотреть что происходит на Rх GSM модуля нужно раскоментировать строку 356 скетча 2.1. а строку 137 поменять на
Соответственно смотреть в сериал мониторе на скорости 19200
Приветствую. Поменял скетч. В мониторе вижу что пришла смс WriteNumber1
Но в ответ так же тишина
А вот продолжение - отправляю смс с телефона, в мониторе порта вижу, что получает модуль, а в ответ - тишина =(
в строку 147 добавьте это, чтобы узнать изначально какой номер из еепрома в переменную считался
Serial.println (""); Serial.println (TelNumber1);должны нули по идее быть
Добавил....ничего нового в терменале увы не появилось
то что в строке 140
NastroykaGSM ();переместить после строки 147 (после Serial.println (""); Serial.println (TelNumber1); )
в сериал порту должен напечататься первым делом номер телефона, вот нужно и посмотреть какой там номер, должны быть все нули
#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(); } } Получился вот такой скетч если правильно Вас понял. Но в терминале ничего нового. Наверное я не правильно Вас понял.Ага разобрался перекинул часть программы за "строку 147" - - - - да первые нули
потом
Получилось вот так:
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() {почистите еепром таким скетчем и заливайте 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() {}Когда EEprom был у вас ещё не тронутый (во всех ячейках FF),то заработало бы, если бы вы скетч заливали сразу после копипаста (без сохранения скетча на компе). При сохранении скетча на компе сбивается кодировка символов соответсвующих байту FF (который в еепроме был изначально), т.е. символа "я" и все косяки из-за этого, а потом я вам немного неправильно почистить еепром предложил, поэтому тоже не работало. Исправил в начале темы как еепром чистить до заливки скетча.
это у вас НЕ получилось, а нули написались в этом случае, потому что вы распечатку в терминал поставили до считываения тел.номера из еепром, а изначально, при старте программы, в переменную тел.номера нули записываются и вы их сразу и распечатали.
PS удалите простыню из сообщения #71, мешает . Кстати когда вставляете скетч, там вверху вкладка правая, можно галочку ставить "свернуть", чтобы под катом было.
почистите еепром таким скетчем и заливайте 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 отслеживать и отправлять сообщение о состоянии котла, температуре ОЖ и бортовом напряжении. Но для этого, как понимаю, нужно знать протокол обмена… Но с выносными датчиками, кому не лень, тоже всё хорошо.
Готов нарисовать и выложить нарисованную схему, для тех «ленивых» кто спрашивает её, но пока не пойму как прикрепить рисунок.
По ходу макетирования появилось несколько вопросов.
1. sms на запрос баланса приходят в HEX unicode =( /лечится заменой оператора или можно программой?/
2. не знаю как на версиях Webasto которые устанавливают как доп, но на "старых" например, моделях БМВ есть несколько условий при которых котёл не будет запущен - (с завода котёл кстати, работал только как "догревайка", но перекодировка творит чудеса и теперь работает ещё и как "автономное отопление" без колхозинга) - одно из них пониженное напряжение питания (недавно у товарища попытались запустить котёл при разряженной АКБ U=11.6V) - сигнал на запуск пришел, а вот котёл не запустился пока не зарядили АКБ. И это считаю правильная задумка - зачем тёплый двигатель, если стартер не крутится. Не увидел организованно ли это в Вашей программе уважаемый автор, но возможно, это будет своим образом аварийная защита, для котлов которые будут рады усадить АКБ в ноль (если такие существуют, конечно)
Я так понимаю котел у вас штатный, да к тому же по CAN управляется . Вы уверены в возможности запуска его по аналогу? Вообще чтобы по CAN запускать конечно нужно знать протокол обмена. Но исследование CAN шины тоже дело интересное, хотя и не лёгкое. Если будет интересно, могу выложить проект CAN хакера на ардуино (там собственно сама ардуино и китайский модуль кана на MCP2515), который как раз и позволяет выявить из CAN шины нужные сообщения.
Короче в будущем конечно неплохо было бы дополнить данное устройство CAN шиной, но работы с этим не мало будет, особенно в программной части - протоколы разных авто.
Я хочу допилить хотябы W-BUS, т.к. если сказать по чесноку, в данный момент организовано только включение выключение котла без опроса его реального состояния. Просто у меня нет Webasto Evo чтобы протокол W-BUS помучить.
А вы если только аналог будете использовать вам можно не ставить микруху LM393 и всю её обвязку
По ходу макетирования появилось несколько вопросов.
1. sms на запрос баланса приходят в HEX unicode =( /лечится заменой оператора или можно программой?/
2. не знаю как на версиях Webasto которые устанавливают как доп, но на "старых" например, моделях БМВ есть несколько условий при которых котёл не будет запущен - (с завода котёл кстати, работал только как "догревайка", но перекодировка творит чудеса и теперь работает ещё и как "автономное отопление" без колхозинга) - одно из них пониженное напряжение питания (недавно у товарища попытались запустить котёл при разряженной АКБ U=11.6V) - сигнал на запуск пришел, а вот котёл не запустился пока не зарядили АКБ. И это считаю правильная задумка - зачем тёплый двигатель, если стартер не крутится. Не увидел организованно ли это в Вашей программе уважаемый автор, но возможно, это будет своим образом аварийная защита, для котлов которые будут рады усадить АКБ в ноль (если такие существуют, конечно)
1. Намного проще через оператора решить. (Ну всмысле не заменой его, а подбором правильной команды запроса баланса, либо есть такая функция у некоторых перевода на транслит.) Парсить этот юникод и PDU полный песец.
2. По напряжению АКБ по идее во всех котлах есть выключение. Я не стал делать выключение по напряжению. Но это не сложно - пару строк добавить.
на скорую руку состряпал скетч 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 ();} }плата
Да, совершенно верно, котёл штатный. Вопрос конечно этот самому интересен будет ли он по +12V запускаться....но скачав документацию (описание + схемы соединений) предполагаю что работать должно. В любом случае скоро узнаем и напишу здесь. Главное чтобы конфликта не было по CAN.
А по поводу использовать MCP2515 - я уже получил из Китая его именно для этих целей, так что выкладывайте прошивку CAN хакера если найду время с удовольствием посижу с ним.
Хочу собрать полную схему (с LM393) так как машины меняются а сегодня новые котлы так понимаю уже все работают по W-Bus....возможно пригодится.
на портале carhelp.info много полезного найдете на этот счет - как запускать штатные котлы. Вам нужно узнать, есть ли у вашего котла шина W-Bus, если есть, то нужно попробовать запустить диагноситку котла по этой шине оригинальной вебастовской программой WTT при помощи обычного к-лайн адаптера. Если диагностика получится, всё упрощается.
схема к-лайн
программа Webasto Termo Test
ДА, пару лет назад использовал эту программу (WTT) для ремонта своего котла - не пропаяно было хорошо одно сопротивление. На каком-то форуме писал об этом с фото.
Значит можно попробовать подключиться к шине используя Вашу схему!?
Сейчас уже схему не вспомню но кажется именно по этой шине котёл соединён с приборной панелью и имеет название i-bus а уже приборная панель с CAN шиной. То есть через диагностический разъём авто к котлу с помощью WTT не подключиться, собирал всё дома на столе и подключал.
Скетч 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
схема подключения
Собираете два адаптера из сообщения #84 или легче покупаете, Один для подключения WTT к котлу, второй - чтобы посниффить обмен данными. Когда узнаете какие байты там летают, можно будет запускать котёл по i-bus (полагаю тот же W-bus)
Спасибо за схему и скетч. Один адаптер есть им собственно и ковыряюсь в авто (прошивка / кодировка блоков) второго нет, попробую купить.... Китай совсем обленил увы, да и часто получается что проще и Дешевле купить готовое устройство чем собирать в одном экземпляре. Исключение составляет - хобби.
Почти закончил собирать плату. Пока провожу эксперименты на столе, надеюсь скоро начнуться полевые испытания!
Если позволите ещё один момент замечен при проверке.
Всё прекрасно работает (смс команды) пока не отключить питание. После повторного включения питания и спустя даже 10 минут устройство никак не реагирует на смс команды пока не нажать кнопку Reset на Nano. После этого снова начинает всё работать.
И ещё подскажите в какую строку и что добавить чтобы в мониторе порта увидеть напряжение АКБ (исключительно для настройки) ? Понижающий DC-DC отличается от Вашего и шунтирует входным сопротивлением делитель напряжения. Вместо 13,70 приходит в смс 12,65. Хочу подобрать подстроичником, но каждый раз отправлять смс.......
193voidvoltmetr()//____________Цикл "Вольтметр"__измерение напряжения на выходе ИБП194195{196volt = analogRead(A7);// А7 аналоговый вход вольтметра197vout = (volt * 4.92) / 1024;198Vpit = vout / (9950.0/(98930.0+9950.0));// По формуле Vpit = vout / (R2/(R1+R2))199if(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); }вот тут хз, у меня тоже так было на одной ардуино (от robotdyn ), на другой все норм. надо пробовать на другом МК. попробуйте в Setup строка 115 задержку на 6...7 секунд повысить
Приветствую. Спасибо за скетч - подобрал в программе величинами сопротивлений значение напряжения. Про делитель напряжения как бы всё понятно, но как ранее заметил что DC-DC шунтирует этот делитель и показывает "погоду" вместо напряжения. (Если запитать DC-DC от отдельного источника то проблем нет). В общем сейчас всё хорошо (значения в программе кстати получились далеки от истины).
Появилось время и добрался до авто. Идёт с фишки от котла три провода - один на насос, второй на i-BUS (CAN) и третий на таймер (точнее сказать на связку Telestart + timer) которого нет но можно дооснастить. На схеме этот провод идёт на квадратную фишку таймера на контакт "OUT". Отсюда появился вопрос - по какому протоколу работает связка таймер-котёл? Если W-Bus то можно попробовать подключить выход с Вашей конструкции на этот провод!?
А Подозреваю что на проводе OUT должен быть просто потенциал 12в при включении. Но если даже там цифра, мой вариант может и подойдет. По крайней мере так включали некоторые штатные котлы. Машина то какая?
Можно просто подать 12в попробовать. По идее на w-bus шине такие уровни сигналов.
MaksVV,
1. Получилось сделать контроль зависаний? Я писал выше #63
2. все возможности по энергосбережению в микроконтроллере AVR описаны тут https://www.gammon.com.au/power
спасибо по ссылке почитаю. Контроль зависаний попытался сделать. Добавил в скетч (сообщение #82). Нарисовал новую плату с реле. Т.е. питание GSM сидит на нормально-замкнутых контактах реле. При рестарте подается питание на реле и оно размыкает питание GSM. Но это только пробная версия, ещё ничего не проверял. Т.к. нет времени и детали ещё не дошли.
реле применил миниатюное, такое
не вижу на плате реле, ткните носом пожалуйста
нет ли в планах нарисовать схему, что бы проще было разбираться откуда куда и зачем?
реле между контактами gsm модуля. Если gsm модуль на панельки устанавливать, то он высоко сидит, туда это реле по идее влезть должно, судя по его размерам.
время жалко, а что вам кроме реле не понятно?
схема надеюсь нигде не накосячил.