#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();
}
}
#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;
<?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()\"";
?>
+39 |
1985
109
|
+104 |
3224
84
|
+44 |
2580
74
|
+34 |
2375
28
|
Но текущую схему я тоже взял не с потолка. По гистерезису «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, и задавать время запуска прогрева, и не важно, будет ли связь с сервером. Хотя, надо ли оно… Так, мысли вслух. :)
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.