RSS блога
Подписка
GPRS-модем Neoway M590 "на колесах". Управление дополнительным отопителем в автомобиле.
- Цена: $3.58
- Перейти в магазин
Дешевые GSM/GPRS модули подробно изучены энтузиастами, в том числе на mysku.club. Создано немало сигнализаций, систем телеметрии и даже интеллектуальный почтовый ящик. Но во всех обзорах, которые я видел, использовался канальный режим передачи данных — либо телефонный звонок либо SMS. Я расскажу о своем опыте пакетной передачи данных, причем через протокол UDP в условиях жестких ограничений на трафик.
Все началось, когда товарищ установил себе в машину недорого купленный по случаю догреватель Webasto Thermo Top C, попутно доукомплектовав его циркуляционным насосом.
Протокол обмена идентифицировать не удалось, равно как и модель автомобиля, на котором он был изначально установлен. Но было экспериментально установлено, что при замыкании одного из пинов на +12 вольт питания отопитель оживал и начинал работать.
Сразу возник вопрос — как им управлять? Первой идеей, лежащей на поверхности, было приспособить 433 МГц радиобрелок, наподобие такого:
Что и было сделано. Практически сразу же обнаружились недостатки данного варианта:
1. Отсутствие шифрование радиообмена и отсутствие уникального идентификатора брелка. Конечно, вряд-ли кто-то специально будет слушать эфир, чтоб склонировать запрос на включение отопителя. Но в условиях города если кто-то рядом точно таким брелком будет включать дома торшер, включится и ваш отопитель, что однажды и произошло.
2. Циркуляционный насос питается от того же реле, что и запуск отопителя. Останавливается насос соответственно тоже в момент команды на остановку отопителя, а хотелось бы, чтоб он поработал еще несколько минут.
3. Недостаток, не связанный напрямую со способом управления отопителем, но требующий решения: отопитель высаживает основной аккумулятор. Увидеть, что двигатель теплый, но стартер уже не способен его провернуть — удовольствие ниже среднего.
4. И наконец, полное отсутствие какой-либо обратной связи. Если автомобиль запаркован в прямой видимости из окна квартиры, факт прохождения команды на включение еще можно отследить по появившемуся пару из выхлопной трубы отопителя. Но часто автомобиль остается на стоянке вне зоны видимости, и нет никакой уверенности, что мы придем именно к теплому автомобилю. Команда на включение может утонуть в городских помехах. Команда может дойти, но отопитель не включится из-за проблем в топливной системе или из-за низкого напряжения аккумулятора.
По итогам первого сезона эксплуатации началось обдумывание вариантов включения отопителя с возможностью обратной связи. Проводились научно-исследовательские и опытно-конструкторские работы с радиомодулями SX1278, результаты были многообещающие, но с моими технологическими возможностями габариты абонентского терминала приемлемыми никак не получались. Таскать на ключах набалдашник размером с Нокию 3310 исключительно ради управления вебастой? Было решено, что оно того не стоит.
Следующей идеей было использование мобильной сети для управления по интернету. Именно она и была реализована. Терминал для управления получался еще большего размера, но он все равно у каждого с собой — это смартфон. В минусы варианта можно записать наличие некоторой пусть небольшой, но абонплаты, в плюсы — расстояние, ограниченное только покрытием мобильной сети и возможность управлять из нескольких мест с нескольких устройств.
Было сформулировано техническое задание:
— отопитель и контроллер будут питаться от отдельной аккумуляторной батареи, благо у VW T4 для этого есть место под водительским сиденьем;
— контроллер измеряет три параметра в автомобиле: температуру теплоносителя и напряжение двух аккумуляторов;
— контроллер устанавливает с сервером соединение по UDP и раз в 10 секунд передает на сервер три измеренных параметра;
— сервер возвращает подтверждение приема, в нем же передается состояние реле отопителя;
— поскольку напряжения обеих батарей известны, бесплатным бонусом можно организовать развязку аккумуляторов: как только напряжение на основной батарее падает ниже установленного предела, реле физически разъединяет батареи;
— для управления основными исполнительными механизмами требуются 3 реле: включение отопителя, включение циркуляционного насоса охлаждающей жидкости, включение аккумуляторов в параллель;
— четвертую свободную релюшку на плате задействуем под физическое выключение-включение питания модема, предполагая, что в плане перезагрузки это надежнее, чем дергание специального пина;
— понадобится интернет-сервер с минимум двумя «белыми» портами: для связи с контроллером и для веб-интерфейса пользователя.
Список компонентов:
1. Arduino Pro Mini — 1 шт.
2. Плата реле 4-канальная — 1 шт.
3. Датчик DS18B20 — 1 шт.
4. Модем M590 — 1 шт.
5. Корпус, провода, изолента, припой, клеммы, USB-UART для программирования Arduino.
Поскольку были нарекания, что схемы, нарисованные во Fritzing, представляют из себя нагромождение проводов и сложны для восприятия, я разделил схему на две части — сигнальную и питающую. Схему подключения к реле исполнительных механизмов приводить не буду, так как реализация зависит от типа применяемых устройств. Достаточно знать, что реле №1 управляет отопителем, реле №2 — циркуляционным насосом, реле №3 — зарядкой дополнительного аккумулятора, реле №4 — перегружает модем.
Сигнальная часть:
Резистивные делители для измерения напряжений аккумуляторов подбираются из расчета, чтобы максимально возможное напряжение аккумулятора (ну скажем, 15 вольт) после деления не превышало 1.1 вольта — опорное напряжение внутреннего источника микроконтроллера. Я использовал 1.1 кОм в нижнем плече и 15 кОм в верхнем. Коэффициент для каждой конкретной пары резисторов нужно вписать в скетч перед его загрузкой (для правильной работы алгоритма развязки аккумуляторов) и в php-скрипт интерфейса пользователя (для правильного отображения напряжения батарей).
Размещать делители нужно по возможности поближе к ардуине, иначе длинные провода собирают помехи, и показания, и без того не сильно точные, начинают «прыгать».
Питание:
Контроллер собран в корпусе от коммутатора D-Link и помещен под водительское сиденье рядом с дополнительным аккумулятором.
Температурный датчик протянут в моторный отсек и прикручен синей изолентой к патрубку возврата охлаждающей жидкости к отопителю.
Фото, сделанное в процессе монтажа:
Скорость обмена модема установлена на 2400 bps, используется программный UART (библиотека SoftSerial).
Скетч инициализирует модем, устанавливает соединение с сервером, затем каждые 10 секунд считывает температуру охлаждающей жидкости и напряжения аккумуляторов, после чего передает их на сервер.
Получив от сервера единственный символ ответа, анализирует его. Если этот символ — единица, то включает отопитель и циркуляционный насос. Если этот символ — ноль, то выключает отопитель, через 5 минут выключает циркуляционный насос.
Если в течение 2 минут не получено ни одного ответа от сервера, считает, что модем повис и дергает его питание.
Если на протяжении 5 секунд напряжение основной батареи более 13,2 вольта, замыкает вместе основную и дополнительную батарею. Если на протяжении 5 секунд напряжение объединенной батареи менее 12,8 вольта, разъединяет батареи.
Серверная часть для обработки UDP-подключения написана на языке C и работает на VPS под управлением Debian. Обязанность сервера — получив пакет, выделить из него фрагменты, соответствующие переданной температуре, напряжениям и состояниям реле, и разложить их по соответствующим файлам. Затем взять из файла состояние отопителя и передать его контроллеру в виде одного символа.
Интерфейс пользователя написан на языке PHP и располагается в домашнем каталоге веб-сервера. Цель скрипта — вытащить из файлов «сырые» значения температуры, напряжений и состояний, привести их к «человекочитаемому» виду и отобразить. При нажатии на кнопку запуска отопителя положить единичку в файл состояния отопителя. При нажатии на кнопку остановки отопителя положить нолик в файл состояния отопителя.
Получилось конечно брутальненько:
Но я не хипстер, всяческим цветным кнопкам и прочим AJAXам не обучен.
В таком виде устройство эксплуатируется уже около месяца. Никаких фатальных недостатков за это время не обнаружено. Включает-выключает, температуру-напряжения показывает. Обнаружился полезный побочный эффект — с утра на холодной машине можно узнать фактическую температуру за окном прямо со смартфона, не подходя к оконному термометру.
Немного о расходе трафика.
Каждые 10 секунд передается запрос и принимается ответ. В запросе 28 байт заголовок и 7 байт полезной нагрузки. В ответе 28 байт заголовок и 2 байта полезной нагрузки. Итого 65 байт каждые 10 секунд. 390 байт в минуту, 561 600 байт в сутки, 17 409 600 байт за 31 день. Расчеты практически совпадают с данными оператора:
На момент написания статьи за неполные 13 дней месяца было израсходовано 5.5 мегабайт из включенных в абонплату 50 (тариф «Легко сказать» МТС Беларусь) при теоретически возможных 7 Мб.
Разницу списываю на нахождение автомобиля вне зоны покрытия сотовой связи.
Возможные доработки и улучшения.
Без особых трудозатрат контроллер можно дополнить GPS-модулем для слежения за перемещением. Можно использовать дополнительные реле для управления автомобильным оборудованием — мигать поворотниками, включать вентилятор печки и т.п. — у кого какие потребности и фантазия.
Для еще большей экономии трафика можно попытаться реализовать механизм KeepAlive — слать пакеты раз в несколько минут только для контроля состояния соединения.
Наконец, можно вскрыть родной протокол управления отопителем и снимать данные температуры по K-Line/CAN прямо со встроенного датчика, избавившись от костыля в виде внешнего DS18B20.
Все началось, когда товарищ установил себе в машину недорого купленный по случаю догреватель Webasto Thermo Top C, попутно доукомплектовав его циркуляционным насосом.
Протокол обмена идентифицировать не удалось, равно как и модель автомобиля, на котором он был изначально установлен. Но было экспериментально установлено, что при замыкании одного из пинов на +12 вольт питания отопитель оживал и начинал работать.
Сразу возник вопрос — как им управлять? Первой идеей, лежащей на поверхности, было приспособить 433 МГц радиобрелок, наподобие такого:
Что и было сделано. Практически сразу же обнаружились недостатки данного варианта:
1. Отсутствие шифрование радиообмена и отсутствие уникального идентификатора брелка. Конечно, вряд-ли кто-то специально будет слушать эфир, чтоб склонировать запрос на включение отопителя. Но в условиях города если кто-то рядом точно таким брелком будет включать дома торшер, включится и ваш отопитель, что однажды и произошло.
2. Циркуляционный насос питается от того же реле, что и запуск отопителя. Останавливается насос соответственно тоже в момент команды на остановку отопителя, а хотелось бы, чтоб он поработал еще несколько минут.
3. Недостаток, не связанный напрямую со способом управления отопителем, но требующий решения: отопитель высаживает основной аккумулятор. Увидеть, что двигатель теплый, но стартер уже не способен его провернуть — удовольствие ниже среднего.
4. И наконец, полное отсутствие какой-либо обратной связи. Если автомобиль запаркован в прямой видимости из окна квартиры, факт прохождения команды на включение еще можно отследить по появившемуся пару из выхлопной трубы отопителя. Но часто автомобиль остается на стоянке вне зоны видимости, и нет никакой уверенности, что мы придем именно к теплому автомобилю. Команда на включение может утонуть в городских помехах. Команда может дойти, но отопитель не включится из-за проблем в топливной системе или из-за низкого напряжения аккумулятора.
По итогам первого сезона эксплуатации началось обдумывание вариантов включения отопителя с возможностью обратной связи. Проводились научно-исследовательские и опытно-конструкторские работы с радиомодулями SX1278, результаты были многообещающие, но с моими технологическими возможностями габариты абонентского терминала приемлемыми никак не получались. Таскать на ключах набалдашник размером с Нокию 3310 исключительно ради управления вебастой? Было решено, что оно того не стоит.
Следующей идеей было использование мобильной сети для управления по интернету. Именно она и была реализована. Терминал для управления получался еще большего размера, но он все равно у каждого с собой — это смартфон. В минусы варианта можно записать наличие некоторой пусть небольшой, но абонплаты, в плюсы — расстояние, ограниченное только покрытием мобильной сети и возможность управлять из нескольких мест с нескольких устройств.
Было сформулировано техническое задание:
— отопитель и контроллер будут питаться от отдельной аккумуляторной батареи, благо у VW T4 для этого есть место под водительским сиденьем;
— контроллер измеряет три параметра в автомобиле: температуру теплоносителя и напряжение двух аккумуляторов;
— контроллер устанавливает с сервером соединение по UDP и раз в 10 секунд передает на сервер три измеренных параметра;
— сервер возвращает подтверждение приема, в нем же передается состояние реле отопителя;
— поскольку напряжения обеих батарей известны, бесплатным бонусом можно организовать развязку аккумуляторов: как только напряжение на основной батарее падает ниже установленного предела, реле физически разъединяет батареи;
— для управления основными исполнительными механизмами требуются 3 реле: включение отопителя, включение циркуляционного насоса охлаждающей жидкости, включение аккумуляторов в параллель;
— четвертую свободную релюшку на плате задействуем под физическое выключение-включение питания модема, предполагая, что в плане перезагрузки это надежнее, чем дергание специального пина;
— понадобится интернет-сервер с минимум двумя «белыми» портами: для связи с контроллером и для веб-интерфейса пользователя.
Список компонентов:
1. Arduino Pro Mini — 1 шт.
2. Плата реле 4-канальная — 1 шт.
3. Датчик DS18B20 — 1 шт.
4. Модем M590 — 1 шт.
5. Корпус, провода, изолента, припой, клеммы, USB-UART для программирования Arduino.
Поскольку были нарекания, что схемы, нарисованные во Fritzing, представляют из себя нагромождение проводов и сложны для восприятия, я разделил схему на две части — сигнальную и питающую. Схему подключения к реле исполнительных механизмов приводить не буду, так как реализация зависит от типа применяемых устройств. Достаточно знать, что реле №1 управляет отопителем, реле №2 — циркуляционным насосом, реле №3 — зарядкой дополнительного аккумулятора, реле №4 — перегружает модем.
Сигнальная часть:
Резистивные делители для измерения напряжений аккумуляторов подбираются из расчета, чтобы максимально возможное напряжение аккумулятора (ну скажем, 15 вольт) после деления не превышало 1.1 вольта — опорное напряжение внутреннего источника микроконтроллера. Я использовал 1.1 кОм в нижнем плече и 15 кОм в верхнем. Коэффициент для каждой конкретной пары резисторов нужно вписать в скетч перед его загрузкой (для правильной работы алгоритма развязки аккумуляторов) и в php-скрипт интерфейса пользователя (для правильного отображения напряжения батарей).
Размещать делители нужно по возможности поближе к ардуине, иначе длинные провода собирают помехи, и показания, и без того не сильно точные, начинают «прыгать».
Питание:
Контроллер собран в корпусе от коммутатора D-Link и помещен под водительское сиденье рядом с дополнительным аккумулятором.
Температурный датчик протянут в моторный отсек и прикручен синей изолентой к патрубку возврата охлаждающей жидкости к отопителю.
Фото, сделанное в процессе монтажа:
Скетч для Arduino
#include <SoftwareSerial.h>
#include <Regexp.h>
#include <OneWire.h>
SoftwareSerial mySerial(10,11);
OneWire ds(2);
String s;
int mode = 0;
unsigned long millis5;
unsigned long conntimeout;
unsigned long pumptimeout;
int u0, u0prev, u1;
byte data[2];
byte chargerelay = 0;
byte pumprelay = 0;
byte heaterrelay = 0;
void setup()
{
mySerial.begin(2400);
Serial.begin (115200);
pinMode(6, OUTPUT);
digitalWrite(6, HIGH);
pinMode(7, OUTPUT);
digitalWrite(7, HIGH);
pinMode(8, OUTPUT);
digitalWrite(8, HIGH);
pinMode(9, OUTPUT);
digitalWrite(9, HIGH);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
analogReference(INTERNAL);
u0 = analogRead(0);
u1 = analogRead(1);
ds.reset();
ds.write(0xCC);
ds.write(0x44);
millis5 = millis();
conntimeout = millis();
}
void loop() {
char c;
char buf [100] = "";
MatchState ms;
if (mySerial.available() > 0) {
c = mySerial.read();
Serial.print©;
s += c;
if ((c == '\n') || (c == '>')) {
s.toCharArray(buf, s.length());
ms.Target(buf);
if ( (mode == 6) && (ms.Match("UDPRECV:1,1,(%d)") > 0)){
if (ms.Match("UDPRECV:1,1,0") > 0) {
if (heaterrelay) pumptimeout = millis();
heaterrelay = 0;
digitalWrite(9, HIGH);
}
if (ms.Match("UDPRECV:1,1,1") > 0) {
heaterrelay = 1;
digitalWrite(9, LOW);
pumprelay = 1;
digitalWrite(8, LOW);
}
conntimeout = millis();
}
if ( (mode == 7) && (ms.Match("UDPSEND") > 0)){
mode = 6;
}
if ( (mode == 6) && (c == '>')) {
mode = 7;
millis5 = millis();
}
if ( (mode == 5) && (ms.Match("UDPSETUP:1,OK") > 0)) {
conntimeout = millis();
mode = 6;
millis5 = millis();
}
if ( (mode == 4) && (ms.Match("OK") > 0)) {
conntimeout = millis();
mode = 5;
millis5 = millis();
}
if ( (mode == 3) && (ms.Match("OK") > 0)) {
conntimeout = millis();
mode = 4;
millis5 = millis();
}
if ( (mode == 2) && (ms.Match("OK") > 0)) {
conntimeout = millis();
mode = 3;
millis5 = millis();
}
if ( (mode == 1) && (ms.Match("OK") > 0)) {
conntimeout = millis();
mode = 2;
millis5 = millis();
}
if ( (mode == 0) && ms.Match("PBREADY") > 0) {
conntimeout = millis();
mode = 1;
millis5 = millis();
}
s = "";
}
}
if (millis()-millis5 > 5000) {
u0prev = u0;
u0 = analogRead(0);
u1 = analogRead(1);
//Коэффициент резистивного делителя вычисляется исходя из имеющихся номиналов резисторов
if ((u0prev*0.0157 > 13.2) && (u0*0.0157 > 13.2)) {
chargerelay = 1;
digitalWrite(7, LOW);
}
if ((u0prev*0.0157 < 12.8) && (u0*0.0157 < 12.8)) {
chargerelay = 0;
digitalWrite(7, HIGH);
}
if (mode == 7) {
ds.reset();
ds.write(0xCC);
ds.write(0xBE);
data[0] = ds.read();
data[1] = ds.read();
ds.reset();
ds.write(0xCC);
ds.write(0x44);
char buf[10]="________#";
buf[0] = (data[0] & 0b00111111) + 0x30;
buf[1] = (((data[0] & 0b11000000) >> 6) | ((data[1] & 0b00001111) << 2)) + 0x30;
buf[2] = ((data[1] & 0b11110000) >> 4) + 0x30;
buf[3] = (char)(u0 & 0b0000000000111111) + 0x30;
buf[4] = (char)(((u0 & 0b0000001111000000) >> 6) | ((u1 & 0b0000000000000011) << 4)) + 0x30;
buf[5] = (char)((u1 & 0b0000000011111100) >> 2) + 0x30;
buf[6] = (char)((u1 & 0b0000001100000000) >> 8) + 0x30;
buf[7] = (char)(heaterrelay + pumprelay *2 + chargerelay * 4 + 0x30);
mySerial.print(buf);
}
if (mode == 6) {
mySerial.print("AT+UDPSEND=1,8\r");
Serial.println("Sent AT+UDPSEND=1,8");
}
if (mode == 5) {
mySerial.print("AT+UDPSETUP=1,12.34.56.78,1234\r");
Serial.println("Sent AT+UDPSETUP=1,12.34.56.78,1234");
}
if (mode == 4) {
mySerial.print("AT+XIIC=1\r");
Serial.println("Sent AT+XIIC=1");
}
if (mode == 3) {
mySerial.print("AT+CGDCONT=1,\"IP\",\"my.operator.apn\"\r");
Serial.println("Sent AT+CGDCONT=1,\"IP\",\"my.operator.apn\"");
}
if (mode == 2) {
mySerial.print("AT+XISP=0\r");
Serial.println("Sent AT+XISP=0");
}
if (mode == 1) {
mySerial.print("ATE0\r");
Serial.println("Sent ATE0");
}
//Помпа работает еще 5 минут после отключения подогревателя
if (pumprelay && !heaterrelay) {
if (millis() - pumptimeout > 300000) {
pumprelay = 0;
digitalWrite(8, HIGH);
}
}
millis5 = millis();
}
if (millis() - conntimeout > 120000) {
// 120 секунд не было принято ни одного байта. Дергаем питание модема и инициализируемся заново.
digitalWrite(6, LOW);
delay(1000);
digitalWrite(6, HIGH);
mode = 0;
conntimeout = millis();
}
}
Скорость обмена модема установлена на 2400 bps, используется программный UART (библиотека SoftSerial).
Скетч инициализирует модем, устанавливает соединение с сервером, затем каждые 10 секунд считывает температуру охлаждающей жидкости и напряжения аккумуляторов, после чего передает их на сервер.
Получив от сервера единственный символ ответа, анализирует его. Если этот символ — единица, то включает отопитель и циркуляционный насос. Если этот символ — ноль, то выключает отопитель, через 5 минут выключает циркуляционный насос.
Если в течение 2 минут не получено ни одного ответа от сервера, считает, что модем повис и дергает его питание.
Если на протяжении 5 секунд напряжение основной батареи более 13,2 вольта, замыкает вместе основную и дополнительную батарею. Если на протяжении 5 секунд напряжение объединенной батареи менее 12,8 вольта, разъединяет батареи.
Исходный код UDP-сервера
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#define BUFLEN 512
#define PORT 1234
void diep(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_me, si_other;
int s, i, slen=sizeof(si_other);
char buf[BUFLEN];
char fbuf[BUFLEN]=" \n";
FILE *flo, *fts, *fte, *fu0, *fu1, *fbi, *fco;
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(PORT);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, &si_me, sizeof(si_me))==-1)
diep("bind");
i = 1;
for (;;) {
if (recvfrom(s, buf, BUFLEN, 0, &si_other, &slen)==-1) diep("recvfrom()");
signed short temp = (buf[0] - 0x30) | ((buf[1] - 0x30) << 6) | ((buf[2] - 0x30) << 12);
int u0 = ((buf[3] - 0x30) | (((buf[4] - 0x30) & 0b00001111) << 6));
int u1 = ((((buf[4] - 0x30) & 0b00110000) >> 4) | ((buf[5] - 0x30) << 2) | ((buf[6] - 0x30) << 8 ));
int bits = buf[7] - 0x30;
time_t t = time(NULL);
struct tm *ptm = gmtime(&t);
sprintf(fbuf, "%04d%02d%02d%02d%02d%02d,%d,%d,%d,%d,%s:%d\n",
ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec,
temp, u0, u1, bits,
inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
flo = fopen("/var/log/udpser.log", "a");
fwrite(fbuf, 1, strlen(fbuf), flo);
fclose(flo);
sprintf(fbuf, "%d", t);
fts = fopen("/etc/udpser/ts.txt", "w");
fwrite(fbuf, 1, strlen(fbuf), fts);
fclose(fts);
fte = fopen("/etc/udpser/te.txt", "w");
sprintf(fbuf, "%d", temp);
fwrite(fbuf, 1, strlen(fbuf), fte);
fclose(fte);
fu0 = fopen("/etc/udpser/u0.txt", "w");
sprintf(fbuf, "%d", u0);
fwrite(fbuf, 1, strlen(fbuf), fu0);
fclose(fu0);
fu1 = fopen("/etc/udpser/u1.txt", "w");
sprintf(fbuf, "%d", u1);
fwrite(fbuf, 1, strlen(fbuf), fbi);
fclose(fu1);
fbi = fopen("/etc/udpser/bi.txt", "w");
sprintf(fbuf, "%d", bits);
fwrite(fbuf, 1, 1, fbi);
fclose(fbi);
fco = fopen("/etc/udpser/co.txt", "r");
fread(buf, 1, 1, fco);
fclose(fco);
if (sendto(s, buf, 1, 0, &si_other, slen)==-1) diep("sendto()");
i = i + 1;
}
close(s);
return 0;
Серверная часть для обработки UDP-подключения написана на языке C и работает на VPS под управлением Debian. Обязанность сервера — получив пакет, выделить из него фрагменты, соответствующие переданной температуре, напряжениям и состояниям реле, и разложить их по соответствующим файлам. Затем взять из файла состояние отопителя и передать его контроллеру в виде одного символа.
Исходный код интерфейса пользователя
<?php
if ($_POST["q"] != "") {
file_put_contents('/etc/udpser/co.txt', $_POST["q"]);
echo "<head><meta http-equiv=\"Refresh\" content=\"2\" /></head>";
echo "<body>Запрос обработан</body>";
exit(0);
};
$lasttimestamp = file_get_contents("/etc/udpser/ts.txt");
echo "<head><meta http-equiv=\"Refresh\" content=\"10\" /></head>";
echo "<body>";
echo "<table border=0><tr align=\"left\">";
echo "<th>Последнее обновление: </th><th>";
echo time()-intval($lasttimestamp)." сек. назад</th></tr>";
echo "<tr align=\"left\"><th>Температура: </th><th>".number_format((float)file_get_contents("/etc/udpser/te.txt")*0.0625, 4, '.', '')." °С</th></tr>";
echo "<tr align=\"left\"><th>Основной аккумулятор: </th><th>";
echo number_format((float)intval(file_get_contents("/etc/udpser/u0.txt"))*0.01552, 2, '.', '')." вольт</th></tr>";
echo "<tr align=\"left\"><th>Доп. аккумулятор: </th><th>";
echo number_format((float)intval(file_get_contents("/etc/udpser/u1.txt"))*0.01560, 2, '.', '')." вольт</th></tr>";
$bits = intval(file_get_contents("/etc/udpser/bi.txt"));
echo "<tr align=\"left\"><th>Нагреватель: </th>";
if ($bits & 1) {
echo "<th>ВКЛ</th>";
} else {
echo "<th>ВЫКЛ</th>";
}
echo "</tr>";
echo "<tr align=\"left\"><th>Насос: ";
if ($bits & 2) {
echo "<th>ВКЛ</th>";
} else {
echo "<th>ВЫКЛ</th>";
}
echo "</tr>";
echo "<tr align=\"left\"><th>Зарядка: ";
if ($bits & 4) {
echo "<th>ВКЛ</th>";
} else {
echo "<th>ВЫКЛ</form></th>";
}
echo "</tr></table>
";
$command = intval(file_get_contents("/etc/udpser/co.txt"));
if (!$command) {
echo "<form method=post><input type=hidden name=\"q\" value=1><input type=submit value=\"Запросить включение нагревателя\"></form>";
} else {
echo "<form method=post><input type=hidden name=\"q\" value=0><input type=submit value=\"Запросить выключение нагревателя\"></form>";
}
echo "</body>";
// echo "<input type=\"button\" value=\"Refresh Page\" onClick=\"window.location.reload()\"";
?>
Интерфейс пользователя написан на языке PHP и располагается в домашнем каталоге веб-сервера. Цель скрипта — вытащить из файлов «сырые» значения температуры, напряжений и состояний, привести их к «человекочитаемому» виду и отобразить. При нажатии на кнопку запуска отопителя положить единичку в файл состояния отопителя. При нажатии на кнопку остановки отопителя положить нолик в файл состояния отопителя.
Получилось конечно брутальненько:
Но я не хипстер, всяческим цветным кнопкам и прочим AJAXам не обучен.
В таком виде устройство эксплуатируется уже около месяца. Никаких фатальных недостатков за это время не обнаружено. Включает-выключает, температуру-напряжения показывает. Обнаружился полезный побочный эффект — с утра на холодной машине можно узнать фактическую температуру за окном прямо со смартфона, не подходя к оконному термометру.
Немного о расходе трафика.
Каждые 10 секунд передается запрос и принимается ответ. В запросе 28 байт заголовок и 7 байт полезной нагрузки. В ответе 28 байт заголовок и 2 байта полезной нагрузки. Итого 65 байт каждые 10 секунд. 390 байт в минуту, 561 600 байт в сутки, 17 409 600 байт за 31 день. Расчеты практически совпадают с данными оператора:
На момент написания статьи за неполные 13 дней месяца было израсходовано 5.5 мегабайт из включенных в абонплату 50 (тариф «Легко сказать» МТС Беларусь) при теоретически возможных 7 Мб.
Разницу списываю на нахождение автомобиля вне зоны покрытия сотовой связи.
Возможные доработки и улучшения.
Без особых трудозатрат контроллер можно дополнить GPS-модулем для слежения за перемещением. Можно использовать дополнительные реле для управления автомобильным оборудованием — мигать поворотниками, включать вентилятор печки и т.п. — у кого какие потребности и фантазия.
Для еще большей экономии трафика можно попытаться реализовать механизм KeepAlive — слать пакеты раз в несколько минут только для контроля состояния соединения.
Наконец, можно вскрыть родной протокол управления отопителем и снимать данные температуры по K-Line/CAN прямо со встроенного датчика, избавившись от костыля в виде внешнего DS18B20.
Самые обсуждаемые обзоры
+75 |
3859
147
|
+56 |
4040
70
|
Но текущую схему я тоже взял не с потолка. По гистерезису «13.2 / 12.8» работает устройство развязки аккумуляторов, многократно проверенное и не имеющее особых нареканий.
И смотрите предыдущий комментарий — это не я придумал. Вряд-ли люди просто так взяли и вбили 12,8 — 13,2. Скорее всего они экспериментировали с разными напряжениями, и пришли к таким цифрам методом проб и ошибок.
Например, так: вы завели машину и куда-то на ней поехали. Батареи отлично заряжаются, реле замкнуто, все счастливы. Вы приехали куда-то, заглушили двигатель, и тут — ой блин, совсем забыл же что срочно надо было заехать в ...! — снова запускаете двигатель.
Батареи полностью заряжены, напряжение еще о-го-го! — так как генератор выключился лишь несколько секунд назад… следовательно, контакты реле еще замкнуты…
… и ловят через себя «бонус» в половину (или меньше, или больше — зависит от соотношения «свежести» новой и старой батареи) стартерного тока. Но даже сотни ампер прекрасно хватит, чтобы сплавить контакты китайского реле намертво, а затем поджечь изоляцию ваших проводов — и где? Прямо под сиденьем…
Дело, конечно, ваше… но лично мне думается, что вопрос безопасности стоит немножко додумать. Например, подключившись к «центральному замку» и зажиганию: если двери машины отперты и зажигание выключено, выключаем реле батарей независимо от напряжения; если зажигание включено и напряжение выше порога «есть зарядка», включаем реле. И если хочется чтобы на стоянке батареи тоже были соединены — включаем реле по условию «зажигание выключено, двери заперты более чем 20 секунд, напряжение выше порога».
:-D ;-)
Все и делалось ради нормальной обратной связи. Слать СМС — обычно это дополнительные деньги. Обратный звонок — тоже. Или предлагаете «кидать глухарей»? Один глухарь — система запустилась, температура растет. Два глухаря — что-то пошло не так.
Стоит посмотреть нет ли у кого-то из ваших операторов аналога тарифа «Умное устройство», что бы не ужиматься с трафиком или смсками в подобных девайсах
А если уж совсем нищебродствовать, то есть тарифы с бонусами за входящие из других сетей. С основного телефона с безлимитом во все сети «назвонить» бонусов, и потом пользоваться за них интернетом.
Я просто обратил внимание, что могут существовать тарифы типа «Умное устройство», где может быть вкусней по условиям
Хотя тут другая проблема — уже лет 20 собираюсь пошутить про IPv6, все никак не соберусь.
www.google.com/intl/en/ipv6/statistics.html
25% у гугла обращений и то за счет США
В РФ я знаю одного(!!!!) провайдера, который дает нативный IPv6, при чем недавно эти чудаки ввели за IPv6 плату в 50 рублей в месяц за /56
Например, что скоро без него даже попрошайкам милостыню подавать нельзя будет.
А так бы да, и памяти ардуины не надо никакой дополнительной. TCP поднимается AT-командами точно так же, как и UDP. И серверной части на С не надо. mysite.com/set.php?t=-5.34&v0=12.57 и все дела.
на
и так далее.
Почему сервер не захотели сделать на php?
Почему UDP?
Можно. Но смысла столько же, сколько крутить педали велосипеда руками, а рулем управлять ногами :-D
Веб-сервер находит файл page.php и просит движок PHP его исполнить. Результаты исполнения сервер отдает веб-браузеру, после этого процесс прибивается. Все. Как в этом же файле слушать UDP порт, я не знаю.
А в чём проблема? Разве вызывает сложность разделить код на тот который будет выполняться из вебморды и из консоли?
ЗЫ. Ни чего не имею против текущей реализации.
if (i_am_frontend) {
сюда код фронтенда;
}
else {
сюда код системного сервиса;
}
Но это только если нам религия запрещает больше одного файла создавать.
IMHO, разумно было бы режим онлайн-мониторинга «по требованию» включать (для отладки или если есть подозрения в нештатном функционировании), а в остальное время пользоваться SMS-каналом.
Раз уж вы используете модули, сделайте для них плату. Это не таких мощных усилий требует как кажется.
Есть SprintLayout, есть DipTrace…
Я не сколько про эстетику сколько про удобство монтажа. Воткнул и всё. Никаких соплей и раздумий «а не отвалится ли
это всё при вибрации».
А по поводу супрессоров… Делителем 15 вольт превращаются в 1.1 вольта. Сколько надо подать на аналоговый вход атмеги, чтоб гарантированно ее сжечь? вольт 11? Это значит до делителя 150 вольт. Где в автомобиле такие напряжения, кроме катушки зажигания?
Но, на самом деле, «сжечь» в вашем случае — это вряд ли. А вот подвесить — запросто, AVR это любят.
И чтобы два раза не вставать — про точность измерений.
Во-первых, можно измерять не «только когда нужно», а постоянно, и усреднять результаты — тогда влияние случайностей будет сильно нивелировано.
А во-вторых, есть одна «фитча» в Ардуино, связанная с переключением мультиплексора АЦП, приводящая к тому, что первое после переключения значение иногда получается «странным».
Лечится например так:
вместо
u0=analogRead(0);
u1=analogRead(1);
пишем
u0=analogRead(0);
delay(50);
u0=analogRead(0);
u1=analogRead(1);
delay(50);
u1=analogRead(1);
Далее преобразователь напряжения. Кроме собственных сглаживающих конденсаторов у него есть защита по перенапряжению и индуктивность последовательно нагрузке. Что еще хотеть?
И ещё прекрасно работающая на одном авто, начинает выкидывать кренделя на другом.
К сожалению, в старом загрузчике (а я на 99% уверен что у вас прошит именно он) watchdog сломан, и его включение приведет к «бесконечному ребуту».
Выход — зашить optiboot в качестве загрузчика, в нем watchdog работоспособен.
Как все жто проделать, описано очень много где, и вроде даже тут на Муське это было.
А аккумулятор… увы, «как огромный конденсатор» он ведет себя только «около постоянного тока». А для импульсов порядка микро- и даже миллисекунд его «сглаживающие» свойства ничтожны. А «плевки» эдс самоиндукции переключающихся индуктивных нагрузок имеют примерно такую ширину. И сотни вольт амплитуды.
Чтобы двигаться от «да пофигу» в сторону «как надо». Чтобы можно было повторить вашу задумку.
Выполняет свою функцию — ну и отлично.
Конечно, если вдруг придется делать «для чужих», особенно промышленную партию, тогда да — альтиум, герберы, металлизация, паяльная маска, шелкография, корпус под заказ, паспорт изделия, гарантийный талон.
И таймер есть. Но внутри авто на панели. Что неудобно в сильный мороз. Ну и мозги анализируют — не включится при напряжении меньше 12 вроде (точно не помню, для примера), и, если работает, то отключится если напряжение упадет, а при «все норм» — через полчаса отключится. Но это все неважно. Я про «приемо-передатчик» в первую очередь :)
Ну с М590 как повезёт, лучше брать SIM800L, 590 китайцы продают б\у и приколы с ними не редкость. Собственно модем это по сути телефон по функционалу, только без обвязки и строить на нём можно что угодно.
Котёл по команде отключения делает продувку и прокачку жижи ещё пару минут для устранения возможного перегрева. Да и болезнь этих котлов, удыхание терморезистора, лечится заменой, там обычный NTC 10кОм.
Ну и на ардуине прямой смысл делать шину для котла, а не колхозить реле.
Вебасто делает все приблуды для управления, как брелки на 500м с обратной связью, так и GSM вариант, но ценник не вдохновляет.
Жадность опсосов конечно это что-то, передача пары килобайт в сутки обходится рублей в 30 из-за жлобского округления сессий, поэтому ещё подумаешь нужно ли связываться с этим. В Питере Тиньков в 99р в месяц обходится, но это виртуалка на Теле2, охват по области так себе.Мегафон минимум 7р в день.
Для народного мониторинга полагаю вполне подойдет такой тариф.
Мега Умные вещи
20р в неделю или 750р в год.
Мобильный интернет Безлимитно. После израсходования пакета 60 МБ в неделю интернет предоставляется безлимитно на скорости 64 КБ/с.
Написано что не работает на модемах, хотя основа любого устройства использующее сотовую связь это модем. Хз что под этим имелось ввиду, но опыт общения с опсосами есть и добраться до человека который в состоянии понять что ты говоришь и понимающего протокол обмена и ошибки, дело очень непростое
Йопта работает на инфраструктуре мегафона, а не на грустном Теле2
На старте виртуального опсоса от сбербанка был халявный тариф 50 минут и 500мбайт в месяц, это бесплатно и кто взял, у того он работает и сейчас. Проблема лишь в том что виртуальные симки долго стартуют.
Пожалуйста, продублируйте его нам в личные сообщения группы ВКонтакте (vk.me/yota), также указа адрес Вашей дачи.
Мы проверим информацию, посмотрим покрытие сети и, если потребуется, передадим данные ответственным специалистам для дальнейшей оптимизации сети.
Ртк клянётся что использует все вышки всех операторов, что похоже на правду, поскольку все их сети стали появляться. Впрочем скоро всех схавает и будет как было один поставщик всей связи, потом его государство возьмёт под своё крыло, всё идёт к этому. А остальные будут оставлены так, для вида. )
Мегавонь меня реально достала, вечно мелочь по карманам тырят, это с момента её появления традиция. К еле2 таких претензий нет.
меня больше другое интересует, ваши проекты по wifi управлению ) чтобы в окне одного приложения можно было и видеть что на камере и управлять дискретными выходами
что посоветуете?
ну типа IP-танка )
Но навскидку могу порекомендовать WiFi IP-камеру + ESP8266, если я правильно понял ваши потребности.
может и путаю, тогда извините
habr.com/post/153017/
я себе такой танчик сделал
могли поставить уже здесь, как в вашем варианте )
Все остальное сплошные минусы.
Самая дешевая двухсторонняя сигналка+ардуина полностью решат проблему обратной связи, да это будет не очень наглядно когда состояние будет индицироваться иконкой открытой двери или открытого багажника, но это лучше чем привязка к опсосу.
Да и если говорить о деньгах, то время, которое потрачено на вариант с опсосом, стоит значительно дороже чем время, потраченное на вариант с сигналкой. Сколько лично ты времени потратил на софт?
Время у меня получается вроде как бесплатное. А если сигналка стоит долларов 100, то на эти деньги я смогу 20 лет платить и опсосу и хостеру за самый дешевый VPS.
Ну ляжет раз в год опсос и раз в год хостер…
С таким же успехом раз в год может в неподходящий момент сесть батарейка в двухстороннем брелке. И еще раз в год люди в одинаковых ботинках могут диапазон 433 МГц глушилкой задавить перед проездом кого-нибудь важного.
живу в ЧС, врезал в корч предпусковой подогреватель и подключил через вебтаймер к розетке — профит. можно по программе запускать, можно с радио-пульта.
сам человек кузнец своего счастья
кстати, горячо рекомендую проверять ответ от этого градусника на показание -127 градусов, с ним бывает при сбоях.
Его лучше тогда запитать через транзистор и передёргивать ему питание при сбое.
Для надежности можно было поставить два модуля с приемником, реле включить последовательно, а брелок взять с четырьмя кпопками, и тогда можно было бы запрограммировать включение при нажатии обеих кнопок на брелке (последовательно), а отключение по нажатию 3-ей или 4-ой кнопки. И все бы работало железобетонно.
Большое спасибо заранее.
«Белый» айпишник — нынче очень жирно, это 65535 «белых» портов. На дешевых VPS давно 1 ip на несколько пользователей, в пользование каждому выдан только некий поддиапазон портов.
Есть ли подобные платы под обычный размер (не мини, микро)?
Поэтому и ищу под нее плату для экспериментов.
10 секунд в данном случае не догма, точности не нужно, и, следовательно, можно использовать watchdog. Плюс можно прикрутить RTC DS3231, и задавать время запуска прогрева, и не важно, будет ли связь с сервером. Хотя, надо ли оно… Так, мысли вслух. :)