Умный дом на Arduino и TL-MR3020 без Lighttpd и PHP


Умный дом на Arduino




Это новая версия шаблона для построения простого «умного дома», сделаного на базе ардуино и роутера mr3020.

Визуально и функционально (управление пинами, считывание датчиков) он ничем не отличается от того, что было написано в предыдущих частях, за исключением диммера, который был убран из-за не корректной работы (позже будет переделан).


В прежней реализации использовался сервер Lighttpd, скриптовый язык PHP, утилита stty для настройки порта, а так же небольшой прокси-сервер ser2net, служивший посредником между сервером и ардуиной.

Если у Вас это установленно, то ничего удалять не нужно, просто пропустите установку uHTTPd.

Весь этот «программный комплекс» требовал перенесения файловой системы на флешку, что в свою очередь вынуждало использовать хаб.

Теперь для работы системы, достаточно легкого сервера uHTTPd (используется в OpenWrt для работы Web-интерфейса) и двух маленьких программ. Благодаря этому нет необходимости использовать флешку.



Как это работает?


Ардуина два раза в секунду отправляет данные роутеру (по USB или UART), на роутере программа arduread получает эти данные и записывает их в файл. Клиент подключённый к роутеру, раз в секунду считывает данные из этого файла.

Когда клиент отправляет команду (например включить свет), то её принимает другая программа — arduserver, которая слушает TCP-порт и отправляет ардуине принятые от клиента команды. Ардуина выполняет команду и продолжает отправлять данные, которые опять таки считывает arduread и записывает в файл. Клиент, при следующем запросе, читает из файла уже новые данные и они отображаются на страничке.

Функционально, система может включать/отключать устройства подключённые к ардуине и считавать информацию с датчиков.



Терминология:

Сервер — роутер или любой другой компьютер.
Клиент — устройство (телефон, планшет или компьютер), с которого Вы подключаетесь к серверу.

Soft-сервера — uHTTPd и arduserver.




Ардуина


Всё что делает ардуина — это принимает команды и два раза в секунду отсылает серверу информацию.

Заливаем скетч:


#include <DHT.h>

#include "CyberLib.h"

#define MAXMILLIS 4294967295

#define DHTPIN 9 // пин для подключения датчика

#define DHTTYPE DHT22  
DHT dht(DHTPIN, DHTTYPE);


int hum = 110; // влажность
int thum = 110; // температура

byte d2 = 0; // флаг состояния    
byte d3 = 0;
byte d4 = 0;
byte d5 = 0; 
byte d6 = 0;
byte d7 = 0; 
byte d8 = 0;
byte d9 = 0; 
byte d10 = 0;
byte d11 = 0;
byte d12 = 0;
byte d13 = 0;
byte pir1 = 0;
byte knop1 = 0;
byte knop2 = 0;
byte knop3 = 0;

byte descript[5]; // массив

unsigned long   time; // время

long timelapsed = 0;

int count=0; // счетчик минут

void setup() 
{
  Serial.begin(57600);
  D2_Out; 
  D3_Out;
  D4_Out;
  D5_Out; 
  D6_Out; 
  D7_Out; 
  D8_Out; 
  //D9_Out; // DHT
  D10_Out; 
  D11_Out;
  D12_Out;
  D13_Out;

  thum = dht.readTemperature(); // считываем температуру, сначала делаем это в сетапе, так как следующее чтение будет только через минуту
  hum = dht.readHumidity(); // считываем влажность
}
  
void loop() 
{  

  if (Serial.available()>4) // ждём дескриптор и нужный символ
   {
    if (Serial.read()=='Y') // проверяем первый символ, если это 'Y', то продолжаем принимать, если нет, то выходим из цикла чтения
     {
      for (byte i=0; i < 5; i++)
        {
           descript[i] = Serial.read(); // добавляем символы в массив   
        } 
        
    if((descript[0] =='+') && (descript[1] =='=') && (descript[2] =='Z')) // проверяем дескриптор
     {
      switch (descript[3])
       {
         case 'o': // обновление
         glavnaia(); // отправка ответа
         break;
         
         ////////////// Кнопки ///////////////////
         case 'A': // d2 вкл
         D2_High; 
         d2 = 1; // флаг вкл
         break;
         
         case 'a': 
         D2_Low; 
         d2 = 0; // флаг откл
         break; 
 
         case 'B': // d3
         D3_High;
         d3 = 1;
         break;
         
         case 'b': // d3
         D3_Low;
         d3 = 0;
         break;          
  
         case 'C': // d4
         D4_High;
         d4 = 1;
         break;
         
         case 'c': // d4
         D4_Low;
         d4 = 0;
         break;   

         case 'D': // d5
         D5_High;
         d5 = 1;
         break;
         
         case 'd': // d5
         D5_Low;
         d5 = 0;
         break;  
  
         case 'E': // d6
         D6_High;
         d6 = 1;
         break;
         
         case 'e': // d6
         D6_Low;
         d6 = 0;
         break;   
  
         case 'F': // d7
         D7_High;
         d7 = 1;
         break;
         
         case 'f': // d7
         D7_Low;
         d7 = 0;
         break;  
 
         case 'G': // d8
         D8_High;
         d8 = 1;
         break;
         
         case 'g': // d8
         D8_Low;
         d8 = 0;
         break;  
 
         case 'H': // d9
         //D9_High; // DHT
         //d9 = 1;
         break;
         
         case 'h': // d9
         //D9_Low; // DHT
         //d9 = 0;
         break; 
         
         case 'I': // d10
         D10_High;
         d10 = 1;
         break;
         
         case 'i': // d10
         D10_Low;
         d10 = 0;
         break;         
       
         case 'J': // d11
         D11_High;
         d11 = 1;
         break;
         
         case 'j': // d11
         D11_Low;
         d11 = 0;
         break;  
        
         case 'K': // d12
         D12_High;
         d12 = 1;
         break;
         
         case 'k': // d12
         D12_Low;
         d12 = 0;
         break;         
      
         case 'M': // d13
         D13_High;
         d13 = 1;
         break;
         
         case 'm': // d13
         D13_Low;
         d13 = 0;
         break;
         
         default:
         glavnaia();
       }
     }
   
    else // если дескриптор ложный, то очищаем буфер
      {
        for(byte i=0; i < 255; i++) 
         {
           Serial.read();    
         } 
      } 
     }    // конец if (Serial.read()=='Y')
   }    // конец чтение порта
 
 
 unsigned long currtime = millis(); 
 
 if(currtime > time) timelapsed = (currtime - time); 
 
 else timelapsed = (MAXMILLIS - time + currtime);

 if(timelapsed >= 440)  // функция будет выполняться раз в 2 минуты
   { 
     time = currtime;
     count++;
     if(count == 120)  thum = dht.readTemperature(); 
     if(count == 240)  hum = dht.readHumidity(); 
     if(count > 239) count=0;
     glavnaia(); // отправка данных серверу   
     
   } // конец включения по температуре
   
 } // конец loop

void glavnaia() // отправка данных серверу 
 {
      // сумма проверяется на сервере, на предмет целостности пакета
      int summa = d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9 + d10 + d11 + d12 + d13 + thum + hum + pir1 + knop1 + knop2;
      Serial.print('A');
      Serial.print(" "); 
      Serial.print(summa);
      Serial.print(" ");   
      Serial.print(d2);
      Serial.print(" ");
      Serial.print(d3);
      Serial.print(" ");
      Serial.print(d4);
      Serial.print(" ");
      Serial.print(d5);  
      Serial.print(" ");
      Serial.print(d6);  
      Serial.print(" ");
      Serial.print(d7); 
      Serial.print(" ");
      Serial.print(d8);
      Serial.print(" ");
      Serial.print(d9); 
      Serial.print(" ");
      Serial.print(d10);
      Serial.print(" ");
      Serial.print(d11);
      Serial.print(" ");
      Serial.print(d12);
      Serial.print(" ");
      Serial.print(d13);
      Serial.print(" ");
      Serial.print(thum); 
      Serial.print(" ");
      Serial.print(hum); 
      Serial.print(" ");
      Serial.print(pir1); // не используется
      Serial.print(" ");
      Serial.print(knop1); // не используется
      Serial.print(" ");
      Serial.print(knop2); // не используется
      Serial.print(" ");
      Serial.print(knop3); // не используется
      Serial.print(" ");
      Serial.print(0); // не используется
      Serial.print(" ");
      Serial.print(0); // не используется
      Serial.print(" ");
      Serial.println('Z');    
 }

В скетче используются две библиотеки: (устанавливаются стандартным способом.)

CyberLib — для ускорения ардуины.
DHT — для датчика влажности и температуры (подключение).

Ардуина получает команду включить/выключить пин, выполняет действие и устанавливает соответствующий флаг (d2 = 1; — вкл, d2 = 0; — откл), по этим флагам клиент определяет что включено или выключено.




Сервер


Если у Вас ещё не установлена OpenWrt, то здесь, Вы найдёте исчерпывающую информацию. (переносить систему на флешку не обязательно)


На роутере будут установлены следующие программы:

uHTTPd — легковесный сервер, написанный разработчиками OpenWrt для работы на встраиваемых устройствах, он будет отдавать клиенту основной контент.
Если установлен Lighttpd, то устанавливать uHTTPd не нужно.

arduread — получает данные присланные ардуиной и записывает их в файл file.db. Клиент подключенный к роутеру, раз в секунду считывает данные из этого файла, тем самым получая актуальную информацию.

arduserver — это маленький TCP-сервер, который ожидает соединение на порту 3490 (порт можно указать любой). Когда от клиента прилетает какая-либо команда, arduserver ловит её и отправляет в ардуину.

То есть, на роутере работает arduread — «слушающая» ардуину, и два HTTP-сервера — uHTTPd для отдачи контента и arduserver — принимающий команды для ардуины.



Делаем всё по инструкции!


Обновляем репозиторий:

opkg update



Устанавливаем uHTTPd:
uHTTPd используется в OpenWrt для работы с Web-интерфейсом Luci, поэтому если интерфейс у Вас есть, то значит и сервер уже установлен.

opkg install uhttpd



Засовываем его в автозагрузку и стартуем:

/etc/init.d/uhttpd enable
/etc/init.d/uhttpd start



Если без веб-интерфейса Вам неудобно пользоваться роутером, то ставим Luci:

opkg install luci




Устанавливаем драйвера для ардуины (если знаете какой из них используется в Вашей, то другие ставить не нужно, если нет, то ставьте все).
Если подключаете ардуину к UARTу роутера, то пропустите этот пункт.

opkg install kmod-usb-serial-ftdi kmod-usb-acm kmod-usb-serial-pl2303 kmod-usb-serial-cp210x kmod-usb-serial-ch341 libftdi



После этих операций, на роутере без флешки, останется 372Кб.




Подключите ардуину и убедитесь что она определилась.

ls /dev/tty*




Arduino Nano — ttyUSB0
Arduino Mega — ttyACM0
UART — ttyATH0



Переходим в каталог /tmp

cd /tmp


Скачиваем пакеты arduread и arduserver:

wget http://stdforum.ru/file/arduread_1-1_ar71xx.ipk


wget http://stdforum.ru/file/arduserver_1-1_ar71xx.ipk


Устанавливаем их:

opkg install arduread_1-1_ar71xx.ipk

opkg install arduserver_1-1_ar71xx.ipk




Для большого компа:

Linux


Для других роутеров:

Broadcom

Ralink

Скачайте архив с бинарниками (устанавливать не нужно), распакуйте и скопируйте файлы в корень (/), всё остальное как в статье.


Пишите в комментах для каких роутеров нужны файлы.




Открываем файл /etc/rc.local и вставляем нижеследующие строчки (до exit 0), чтоб было как в примере:

vi /etc/rc.local


Обратите внимание на устройство ttyUSB0, у Вас может быть другое. Так же, если Вы измените название папки с сайтом, то в аргументах arduread нужно указать именно её.

(sleep 20 && /arduread /dev/ttyUSB0 /www/ymdom/file.db )&
(sleep 1 && /arduserver 3490 /dev/ttyUSB0 )&
exit 0

подсказка vi
Нажимаем символ "i".
Вносим изменения.
Нажимаем Esc.
Вводим последовательно символы :wq (: w-сохранить q-выйти)
Нажимаем Enter.
Файл отредактирован.


Создаём папку ymdom в корневой папке сервера /www

mkdir /www/ymdom


Проверим:

ls /www




Переходим в неё:

cd /www/ymdom


И загружаем необходимые файлы:

wget  http://stdforum.ru/file/ymdom/index.html

wget  http://stdforum.ru/file/ymdom/knopki.css

wget  http://stdforum.ru/file/ymdom/style.css

wget  http://stdforum.ru/file/ymdom/jquery.min.js



Проверим:

ls /www/ymdom



Всё на месте :)


Проверим свободное место:



Умный дом занял 24Кб.



Теперь нужно подкорректировать файл index.html, вписав в него ip-адрес роутера (если у Вас выделенный ip и планируете заходить извне, то впишите соответствующие имя или айпишку).

Узнать адрес роутера
ifconfig

ifconfig


vi /www/ymdom/index.html


Строка №31



Менять нужно только адрес 192.168.5.222, порт (3490) трогать не надо.
Если всё же решите поменять порт, то не забудте поменять его в аргументах для запуска программы arduserver, в файле /etc/rc.local (sleep 1 && /arduserver 3490 /dev/ttyUSB0).

Опять же, если будете заходить извне, и «умный дом» подключён к интернету не напрямую, а через другой роутер, то на нём нужно пробросить порт 3490, и 80-ый конечно тоже.


Если подключаете ардуину к UARTу, то нужно в файле /etc/inittab закомментировать последнюю строчку:

vi /etc/inittab

#ttyATH0::askfirst:/bin/ash --login



Перегружаем:

reboot


Заходим в браузере по адрес/ymdom/ и видим…





Строка сверху, это «служебная» информация, пояснения содержатся в комментариях в файле:
index.html

<!doctype html>

<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="ru"> <![endif]-->
<!--[if IE 7]>    <html class="no-js ie7 oldie" lang="ru"> <![endif]-->
<!--[if IE 8]>    <html class="no-js ie8 oldie" lang="ru"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="ru"> <!--<![endif]-->

<head>

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>stD_mr3020</title>
<link rel="author" href="https://plus.google.com/104333559503937496126" />
<link rel="stylesheet" href="style.css" type="text/css" />
<link rel="stylesheet" href="shim.css" type="text/css" />
<link rel="stylesheet" href="knopki.css" type="text/css" />
<link rel="stylesheet" href="slai.css" type="text/css"/>
<script src="jquery.min.js"></script>

<script>
var dlina = 23; /* количество блоков (разделённых пробелами) в ответе от ардуино (нужно менять если добавляете функции в ардуине)  */
var flagobnov = 1;
var slmode = 0;
var simvol = ' ';
var err_con = 0;
var err_tout = 0;
var count_obnov = 0;
var adres = 'http://192.168.5.222:3490/';


$(document).ready(function(){ 

function sendtoardu(){ $.ajax({ type: "POST", url: adres + simvol }); } /* отправка команды в ардуину */

/* d2 */
$(".d2vkl").click(function(){simvol = 'A'; sendtoardu();}); /* нажатие на кнопку, вызывает функцию sendtoardu() */
$(".d2otkl").click(function(){simvol = 'a'; sendtoardu();});

/* d3 */
$(".d3vkl").click(function(){simvol = 'B'; sendtoardu();});
$(".d3otkl").click(function(){simvol = 'b'; sendtoardu();});

/* d4 */
$(".d4vkl").click(function(){simvol = 'C'; sendtoardu();});
$(".d4otkl").click(function(){simvol = 'c'; sendtoardu();});

/* d5 */
$(".d5vkl").click(function(){simvol = 'D'; sendtoardu();});
$(".d5otkl").click(function(){simvol = 'd'; sendtoardu();});

/* d6 */
$(".d6vkl").click(function(){simvol = 'E'; sendtoardu();});
$(".d6otkl").click(function(){simvol = 'e'; sendtoardu();});

/* d7 */
$(".d7vkl").click(function(){simvol = 'F'; sendtoardu();});
$(".d7otkl").click(function(){simvol = 'f'; sendtoardu();});

/* d8 */
$(".d8vkl").click(function(){simvol = 'G'; sendtoardu();});
$(".d8otkl").click(function(){simvol = 'g'; sendtoardu();});

/* d9 */
$(".d9vkl").click(function(){simvol = 'H'; sendtoardu();});
$(".d9otkl").click(function(){simvol = 'h'; sendtoardu();});

/* d10 */
$(".d10vkl").click(function(){simvol = 'I'; sendtoardu();});
$(".d10otkl").click(function(){simvol = 'i'; sendtoardu();});

/* d11 */
$(".d11vkl").click(function(){simvol = 'J'; sendtoardu();});
$(".d11otkl").click(function(){simvol = 'j'; sendtoardu();});

/* d12 */
$(".d12vkl").click(function(){simvol = 'K'; sendtoardu();});
$(".d12otkl").click(function(){simvol = 'k'; sendtoardu();});

/* d13 */
$(".d13vkl").click(function(){simvol = 'M'; sendtoardu();});
$(".d13otkl").click(function(){simvol = 'm'; sendtoardu();});

$(".slip").click(function(){ /* кнопка пуск  */
	$(".pansl").hide();
	flagobnov = 1;
	show();
});

$(".knp1").click(function(){ /* показать панель "кнопки"  */
	$(".panel1").toggle();
});

$(".knp3").click(function(){ /* показать панель "темп"  */
	$(".panel3").toggle();
});

}); /* КОНЕЦ document.ready */

/*обновление*/
show();
setInterval(show,980);  /* частота обновления в милисекундах */
function show(){  /* функция обновления */

    if(flagobnov == 1) { /* это флаг нужен для временного отключения обновления */
            $.ajax({ 
                type: "GET",
	        url: "file.db", /* файл из которого забираются данные */
                timeout:560, /* время (мс), в течении которого функция будет ждать ответа от сервера */          
                cache: false,       
                success: function(data){  
                           var vars = data.split(" "); /* разбор строки прочитаной из файла */
                           if(vars.length == dlina) /* проверка длины данных (количество блоков разделённых пробелом) */
                             {        
                               count_obnov++; /* это просто счётчик обновлений */
                               
                               /* err_con - это счётчик неудачно полученых данных, err_tout - счётчик запросов закончившихся таймаутом */  
                               $('#std').html("Connect! Errcon: " + err_con + " Errtout: " + err_tout + " Obnov: " + count_obnov); 
                            
                               /*d2*/
                               if(vars[2] == 1) { $(".d2otkl").show(); $(".d2vkl").hide(); }  /* в зависимости от принятого флага скрывает/показавыет кнопку вкл или откл */
                               else if(vars[2] == 0) { $(".d2otkl").hide(); $(".d2vkl").show(); } 

                               /*d3*/
                               if(vars[3] == 1) { $(".d3otkl").show(); $(".d3vkl").hide(); }
                               else if(vars[3] == 0) { $(".d3otkl").hide(); $(".d3vkl").show(); }

                               /*d4*/
                               if(vars[4] == 1) { $(".d4otkl").show(); $(".d4vkl").hide(); }
                               else if(vars[4] == 0) { $(".d4otkl").hide(); $(".d4vkl").show(); }

                               /*d5*/
                               if(vars[5] == 1) { $(".d5otkl").show(); $(".d5vkl").hide(); }
                               else if(vars[5] == 0) { $(".d5otkl").hide(); $(".d5vkl").show(); }

                               /*d6*/
                               if(vars[6] == 1) { $(".d6otkl").show(); $(".d6vkl").hide(); }
                               else if(vars[6] == 0) { $(".d6otkl").hide(); $(".d6vkl").show(); }

                               /*d7*/
                               if(vars[7] == 1) { $(".d7otkl").show(); $(".d7vkl").hide(); }
                               else if(vars[7] == 0) { $(".d7otkl").hide(); $(".d7vkl").show(); }

                               /*d8*/
                               if(vars[8] == 1) { $(".d8otkl").show(); $(".d8vkl").hide(); }
                               else if(vars[8] == 0) { $(".d8otkl").hide(); $(".d8vkl").show(); }

                               /*d9*/
                               if(vars[9] == 1) { $(".d9otkl").show(); $(".d9vkl").hide(); }
                               else if(vars[9] == 0) { $(".d9otkl").hide(); $(".d9vkl").show(); }

                               /*d10*/
                               if(vars[10] == 1) { $(".d10otkl").show(); $(".d10vkl").hide(); }
                               else if(vars[10] == 0) { $(".d10otkl").hide(); $(".d10vkl").show(); }
                    
                               /*d11*/
                               if(vars[11] == 1) { $(".d11otkl").show(); $(".d11vkl").hide(); }
                               else if(vars[11] == 0) { $(".d11otkl").hide(); $(".d11vkl").show(); }

                               /*d12*/
                               if(vars[12] == 1) { $(".d12otkl").show(); $(".d12vkl").hide(); }
                               else if(vars[12] == 0) { $(".d12otkl").hide(); $(".d12vkl").show(); }
        
                               /*d13*/
                               if(vars[13] == 1) { $(".d13otkl").show(); $(".d13vkl").hide(); }
                               else if(vars[13] == 0) { $(".d13otkl").hide(); $(".d13vkl").show(); }

                               /* температура */ 
                               $("#thum").html(vars[14] + "`C"); 

                               /* влажность */
                               $("#hum").html(vars[15] + " %");   

                             }
                          else 
                             {
                               err_con++; /* если дынные приняты криво, то пишем ошибку */
                               $('#std').html("NOT dlina! Errcon: " + err_con + " Errtout: " + err_tout + " Obnov: " + count_obnov);
                               /* если МК отвалился, то в файл file.db будет записан код "8888" */
                               if(data == 8888) alert("MK NOT CONNECT"); 
                             } 

                        },
                     error: function(XMLHttpRequest, textStatus, errorThrown)
                        {
                          if(textStatus == "timeout") 
                            {   
                               err_tout++; /* функция ajax не дождалась ответа */
                               $('#std').html("Timeout! Errcon: " + err_con + " Errtout: " + err_tout + " Obnov: " + count_obnov); 
                            } 
                        }
                   });
       
   slmode++; /* спящий режим */
   if(slmode > 10) 
    { 
      $(".pansl").show();
      flagobnov = 0;
      slmode = 0;
    }
  }
}

</script>

</head>
<body>
<v><div id="std"></div></v> 
<div class="knp1" title="Кнопки" >Кнопки</div> 
<div class="knp3" title="Темп" >Темп</div> 
<!-- кнопки -->
<div class="panel1">
<div class="knop d2vkl" title="Вкл D2" >D2</div> <!-- здесь менять названия кнопок -->
<div class="knop d2otkl" title="Откл D2">D2</div> <!-- чтобы убрать кнопку удалите оба блока -->

<div class="knop d3vkl" title="Вкл D3">D3</div>
<div class="knop d3otkl" title="Откл D3">D3</div>

<div class="knop d4vkl" title="Вкл D4">D4</div>
<div class="knop d4otkl" title="Откл D4">D4</div>

<div class="knop d5vkl" title="Вкл D5">D5</div>
<div class="knop d5otkl" title="Откл D5">D5</div>

<div class="knop d6vkl" title="Вкл D6">D6</div>
<div class="knop d6otkl" title="Откл D6">D6</div>

<div class="knop d7vkl" title="Вкл D7">D7</div>
<div class="knop d7otkl" title="Откл D7">D7</div>

<div class="knop d8vkl" title="Вкл D8">D8</div>
<div class="knop d8otkl" title="Откл D8">D8</div>

<div class="knop d9vkl"title="Вкл D9">D9</div>
<div class="knop d9otkl" title="Откл D9">D9</div>

<div class="knop d10vkl" title="Вкл D10">D10</div>
<div class="knop d10otkl" title="Откл D10">D10</div>

<div class="knop d11vkl" title="Вкл D11">D11</div>
<div class="knop d11otkl" title="Откл D11">D11</div>

<div class="knop d12vkl" title="Вкл D12">D12</div>
<div class="knop d12otkl" title="Откл D12">D12</div>

<div class="knop d13vkl" title="Вкл D13">D13</div>
<div class="knop d13otkl" title="Откл D13">D13</div>
</div>

<div class="panel3">
    <vl1><div id="thum" title="температура"></div></vl1>
    <vl2><div id="hum" title="влажность"></div></vl2>
</div>


<div class="pansl">
   <div class="slip" title="спящий режим">ПУСК</div>
</div>
<a href="http://istarik.ru/" > <st>istarik.ru</st>
</body>
</html>




Исходники

Если что-то пошло не так, то в корневой папке появятся файлы Error.log и/или ErrorServer.log:

ls /

vi /Error.log

vi /ErrorServer.log


Расшифровку логов можно подсмотреть в исходниках arduread и arduserver

arduread

#include <string.h>
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <termios.h>  
#include <stdio.h>  
#include <signal.h>  
#include <unistd.h>  
#include <stdlib.h>
#include <time.h>
#define BUFSIZE 128

char bRead[BUFSIZE] = {0,}; 
char er_log_str[50]={0,};
char device[20]={0,};
char papka[128]={0,};
char str_iz_file[100] = {0,};

void error_log() 
{  
    time_t t;
    time(&t);
    FILE *f;
    f = fopen("Error.log", "a"); 
    fprintf(f, "%s. ", er_log_str);
    fprintf(f, "%s", ctime( &t));  
    printf("Write to Error.log\n");
    fclose(f);
    exit(0);
}

void error_to_filebd() 
 {
         FILE *f;
         f = fopen(papka, "w"); 
         fprintf(f, "%s", "8888");
         fclose(f);
         printf("Zapisal Oshibky 8888:\n");
         strncpy(str_iz_file, "Error", 99); 
 }

int  open_port(void)  
{  
   int fd;  
   fd = open(device, O_RDWR | O_NOCTTY |O_NONBLOCK);  
   if(fd == -1) 
     {
       strncpy(er_log_str, "Error - NOT open port", 49);
       error_log();
     }

   else  
    {  
     struct termios options;  
     tcgetattr(fd, &options);  
     cfsetispeed(&options, B57600);  
     cfsetospeed(&options, B57600);  
     options.c_cflag |= (CLOCAL | CREAD); 
     options.c_cflag &= ~PARENB;  
     options.c_cflag &= ~CSTOPB;  
     options.c_cflag &= ~CSIZE;  
     options.c_cflag |= CS8;  
     options.c_cc[VMIN] = 1;  
     options.c_cc[VTIME] = 1;  
     options.c_lflag = ICANON;  
     options.c_oflag = 0;  
     options.c_oflag &= ~OPOST; 
     tcflush(fd, TCIFLUSH);
     tcsetattr(fd, TCSANOW, &options);  
    }  
   return fd;  
}

void main(int argc, char *argv[])  
{  
   if(argc!=3) 
    {
      printf("Primer - ./port /dev/ttyACM1 /www/tim/file.db\n");
      strncpy(er_log_str, "Not argumets", 49);
      error_log();
    }
  
   strncpy(device, argv[1], 19);
   strncpy(papka, argv[2], 127);

   int d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, thum, hum, pir1, knop1, knop2, ar_summ;
   int err_count1 = 0; 
   int err_count2 = 0;
   unsigned int i; 
   int fd = open_port(); 
   sleep(2);
   if (fd < 0)  return; 
   tcflush(fd, TCIFLUSH);


 while(!VINTR) 
  {  
     usleep(470000); 
     read(fd, bRead, BUFSIZE); 

     for(i = 0; i<=strlen(bRead); i++)
      {
        if(bRead[i] == '\r' || bRead[i] == '\n')
         {
            bRead[i] = '\0';
            tcflush(fd, TCIFLUSH); 
            break;
         }
      } 

//////////////////////////// Проверка A-Z /////////////////////////////////////

     char first_sim = '0';  
     if(bRead[0] == 'A' && bRead[strlen(bRead)-1] == 'Z')     
      {
        sscanf(bRead,"%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", &first_sim, &ar_summ, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10, &d11, &d12, &d13, &thum, &hum, &pir1, &knop1, &knop2);
        err_count1 = 0;
        //printf("A-Z\n"); 
      }

     else
      {
        tcflush(fd, TCIFLUSH); 
        memset(bRead, 0, sizeof(bRead)); 
        err_count1++;
        if(err_count1 > 10) 
          {
            err_count1 = 0;
            error_to_filebd();
          }
        //printf("Not A-Z\n"); 
        continue;
      } 

///////////////////////////// Проверка суммы /////////////////////////////////////

     int summa = d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9 + d10 + d11 + d12 + d13 + thum + hum + pir1 + knop1 + knop2;  
     if(summa != ar_summ) 
      {
        tcflush(fd, TCIFLUSH); 
        memset(bRead, 0, sizeof(bRead)); 
        summa=0;
        ar_summ=999; d2=0; d3=0; d4=0; d5=0; d6=0; d7=0; d8=0; d9=0; d10=0; d11=0; d12=0; d13=0; thum=0; hum=0; pir1=0; knop1=0; knop2=0;
        err_count2++;
        if(err_count2 > 10) 
          {
            err_count2 = 0;
            error_to_filebd();
          }

        //printf("Not summa\n"); 
        continue;
      } 
     
     else 
      {
        err_count2 = 0;
        //printf("Summa\n"); 
      }

////////////////////////////// Сравнение строк /////////////////////////////////////

     if(strcmp(bRead, str_iz_file)==0)
       {
         memset(bRead, 0, sizeof(bRead));
         summa=0;
         ar_summ=999; d2=0; d3=0; d4=0; d5=0; d6=0; d7=0; d8=0; d9=0; d10=0; d11=0; d12=0; d13=0; thum=0; hum=0; pir1=0; knop1=0; knop2=0;
         //printf("Stroki odinakovie\n"); 
         continue;
       }

     else
       { 
         //printf("NOT Sravnil\n"); 
         FILE *f;
         f = fopen(papka, "w"); 
         fprintf(f, "%s", bRead);
         fclose(f);
         //printf("Write to filebd\n");
         memcpy(str_iz_file, bRead, sizeof(str_iz_file));  
         //printf("str_iz_file %s\n", str_iz_file); 
         memset(bRead, 0, sizeof(bRead)); 
         summa=0;
         ar_summ=999; d2=0; d3=0; d4=0; d5=0; d6=0; d7=0; d8=0; d9=0; d10=0; d11=0; d12=0; d13=0;
       }
    
    } // Конец основного цикла (while) 

 } // end of main()

// gcc -W -Wall arduread.c -o arduread
// ./arduread /dev/ttyACM0 /www/ymdom/file.db
//  make package/arduread/compile V=s



arduserver

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <time.h>
 
char device[17]={0,};
char er_log_str[51]={0,};

void error_log() 
 {  
    time_t t;
    time(&t);
    FILE *f;
    f = fopen("ErrorServer.log", "a"); 
    fprintf(f, "%s. ", er_log_str);
    fprintf(f, "%s", ctime( &t));  
    printf("Write to ErrorServer.log\n");
    fclose(f);
    exit(0);
 }
 
int main(int argc, char *argv[])
{
  if(argc!=3) 
   {
     printf("Primer - ./arduserver 3490 /dev/ttyACM1\n");
     strncpy(er_log_str, "Not argumets", 50);
     error_log();
   }
  
  strncpy(device, argv[2], 15); 

  int one = 1, client_fd;
  struct sockaddr_in svr_addr, cli_addr;
  socklen_t sin_len = sizeof(cli_addr);
 
  int sock = socket(AF_INET, SOCK_STREAM, 0);
  if(sock < 0) 
   {
     strncpy(er_log_str, "Error - socket", 50);
     error_log();
   }
  
  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
  svr_addr.sin_family = AF_INET;
  svr_addr.sin_addr.s_addr = INADDR_ANY;
  svr_addr.sin_port = htons(atoi(argv[1]));
 
  if(bind(sock, (struct sockaddr *) &svr_addr, sizeof(svr_addr)) == -1) 
   {
     close(sock);
     strncpy(er_log_str, "Error - bind", 50);
     error_log();
   }
 
  listen(sock, 5);

  while (1) 
   {
      client_fd = accept(sock, (struct sockaddr *) &cli_addr, &sin_len);
      if(client_fd == -1) 
       {
         continue;
       }
 
      char buffer[8] = {0,};
      read(client_fd, buffer, 7);
      char to_Ardu[41] = {0,};
      snprintf(to_Ardu, 40, "echo 'Y+=Z%c' > %s", buffer[6], device);
      system(to_Ardu);
      close(client_fd);
   }
}
// gcc -W -Wall  arduserver.c -o arduserver
// ./arduserver 3490 /dev/ttyACM1
//  make package/arduserver/compile V=s



На этом всё.

Задавайте Ваши вопросы в комментариях ниже или на форуме.


  • 0
  • 15340
Telegram-канал istarik

Известит Вас о новых публикациях...


Комментарии (193)

0
Почему все это не сделать на одном ESP8266? Не многие знают как шаманить на роутере через linux команды.
0
Все сделал правильно на Tp-link tl-wr842 и Arduino Nano
При входе на 192.168.1.1/ymdom/
Появляются только две иконки
КНОПКИ
ТЕМП
они не активны и больше ничего нет :(
  • avatar
  • war
0
Если появились /Error.log или /ErrorServer.log, то покажите.
0
Заодно, какая у Вас версия роутера?
0
root@OpenWrt:~# ls /dev/tty*
/dev/tty /dev/ttyS10 /dev/ttyS13 /dev/ttyS2 /dev/ttyS5 /dev/ttyS8
/dev/ttyS0 /dev/ttyS11 /dev/ttyS14 /dev/ttyS3 /dev/ttyS6 /dev/ttyS9
/dev/ttyS1 /dev/ttyS12 /dev/ttyS15 /dev/ttyS4 /dev/ttyS7 /dev/ttyUSB0
root@OpenWrt:~# ls /
Error.log bin lib proc sbin usr
arduread dev mnt rom sys var
arduserver etc overlay root tmp www
root@OpenWrt:~# vi /Error.log
Error — NOT open port. Wed Sep 23 00:22:53 2015
Error — NOT open port. Wed Sep 23 00:22:50 2015
0
Ver 1.1
0
Error — NOT open port. Wed Sep 23 00:22:53 2015
Error — NOT open port. Wed Sep 23 00:22:50 2015
0
Хм, а если так сделать:

cat /dev/ttyUSB0
0
И покажите /etc/rc.local
0
Заработало!
У меня Ардуино нано
на CH340G
установил пакет kmod-usb-serial-ch341 и работает…

Библиотека CyberLib.rar должна быть zip

Какой порт пробрасывать для доступа из вне
3490?

Возможно ли организовать функцию охраны?
0
Сейчас у меня есть оповещение о включении роутера (питания 220В) на почту

echo «Subject: Домашний Сервер > Включено питание 220 Вольт! `date -R`» | ssmtp 55ohrana@gmail.com

Раньше через crontab управлял питанием USB и включал-выключал нагрузку по расписанию
0 21 * * * echo 1 >/sys/class/gpio/gpio6/value
0 7 * * * echo 0 >/sys/class/gpio/gpio6/value
0
kmod-usb-serial-ch341

Но как же тогда у вас устройство виделось?
root@OpenWrt:~# ls /dev/tty*
/dev/tty /dev/ttyS10 /dev/ttyS13 /dev/ttyS2 /dev/ttyS5 /dev/ttyS8
/dev/ttyS0 /dev/ttyS11 /dev/ttyS14 /dev/ttyS3 /dev/ttyS6 /dev/ttyS9
/dev/ttyS1 /dev/ttyS12 /dev/ttyS15 /dev/ttyS4 /dev/ttyS7 /dev/ttyUSB0




Библиотека CyberLib.rar должна быть zip
Не понял.



Пробрасывать надо порт 3490, ну и 80 тоже.



Возможно ли организовать функцию охраны?

Можно.
0
Ещё такой момент… у кого установлен и запущен lighttpd необходимо его убрать из автозагрузки ( /etc/init.d/lighttpd disable), отредактировать файл uhttpd (вернуть обратно порт с 81 на 80) и перезагрузить роутер, а то без этого при попытке зайти /ymdom получаем page not found.
0
Сайт открылся, только почему-то кнопки на сайте не нажимаются(( Error.log не появляется. Подключаюсь к ttyATH0. Пока ничего не помогает…
0
И ещё нет строчки Connect! Errcon…
0
Нужно в файле /etc/inittab закомментировать последнюю строчку:

vi /etc/inittab

#ttyATH0::askfirst:/bin/ash --login
0
она и так закомментирована… а отсутствие датчика температуры никак не может сказаться?
0
Нет.
0
так кнопки и не заработали(( при этом rx/tx на ардуине моргают с периодом в пол секунды. В чём может быть проблема, не подскажите?
0
У Вас наверно роутер не подключён к инету?
Удалите файл index.html и сделайте так:

cd /www/ymdom

wget  http://istarik.ru/file/ymdom/index.html

wget  http://istarik.ru/file/ymdom/jquery.min.js
0
Роутер подключён к инету по wifi, я захожу на него через кабель. Операции проделал. Помогло! Сверху появилась строка состояния и идёт счётчик обновлений. Но при нажатии на кнопку ничего не происходит (т.е. например нажимаю D13, а диод не загорается) Прошу прощения за надоедливость. Просто я в web программировании пока лузер(
0
Может антивирусы…
0
хм… а на ligttpd всё чётко работало
0
Покажите настройки uhttpd.
0
Давайте по порядку, что-куда подключено, куда подключён роутер, с какого устройства заходите и т.д.?
0
В общем так: инет раздаю с телефона по wifi, роутер подключен по wifi к телефону. А на роутер захожу через кабель (lan, rj45) с ПК Win7. С этого же ПК захожу через PuTTY, WinSCP. На сайт ymdom захожу через Crome.
0
config uhttpd main

# HTTP listen addresses, multiple allowed
list listen_http 0.0.0.0:80
# list listen_http [::]:80

# HTTPS listen addresses, multiple allowed
list listen_https 0.0.0.0:443
# list listen_https [::]:443

# Server document root
option home /www

# Reject requests from RFC1918 IP addresses
# directed to the servers public IP(s).
# This is a DNS rebinding countermeasure.
option rfc1918_filter 1
0
А в папке /www/ymdom есть файл file.db, и если есть, то что в нем?
0
И попробуйте другой браузер, фирефокс например.
0
file.db присутствует. в нём: A 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Z
Попробовал браузер IE- эффект тот же((
0
Попробуйте фирефокс.
Что покажет команда:
cat /dev/ttyATH0
0
Попробовал фирефокс- результат тот же. По команде «cat /dev/ttyATH0» с периодом в пол секунды выводится содержимое file.db
0
Какие конкретно диоды моргают на ардуине?
Когда кнопка не нажимается должен мигать только TX, а когда нажимаете должен моргать RX, у Вас так?
0
Кстати, Вы не забыли айпишник поменять в index.html?
0
Мигали оба… при нажатии кнопки ничего не менялось! Ну конечно! Забыл!!)) Всё заработало! Огромнейшее спасибо!!!
0
Получается заработал новый (что вы скидывали сюда) index.html с изменённым адресом
0
В предыдущем варианте библиотека jquery.min.js подгружалась с гугла (это сделано с целью экономии места на роутере) и в Вашем случае почему-то не загружалась, а сейчас «мы» её локализовали на роутере.
То есть до этого в файле index.html было так:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>


Стало так:

<script src="jquery-ui.js"></script>



В общем поздравляю Вас с успехом, будут вопросы — спрашивайте.
0
Вон оно что! Понял!!! Спасибо большое!!!
0
Пожалуйста.
0
Не дождавшись ответа в другом посте, спрошу здесь: возможны ли варианты прошивки Ардуино через роутер, при подключении через UART?
0
Извиняюсь за молчание. Прошить можно, вот здесь об этом написано.
0
Да, я читал эту тему, но, насколько я понял, там описывается прошивка ардуино, подключенному через USB. У меня же Мега подключена через UART.
0
Через уарт сложнее, нужно сымитировать нажатие на кнопку ресет (кратковременно зажать reset на минус). Как это сделать — незнаю, надо думать.
0
Можно через тот же веб интерфейс. На один из пинов через полевик или реле подкючить ресет и землю. Чтобы реле разомкнулось, код нажатия использовать без фиксации бита. После компиляции появляется надпись выгрузка и вот в этот момент нажать кнопку в вебе. Ну это как вариант.
0
Приветствую всех. stD можно получить arduserver & arduread для роутеров на базе ramips rt305x. Использую dir-620_a1.
По поводу кода ардуино, в начале кода, объявляете переменные int thum=110 & hum=110. Мне кажется нет смысла их приравнивать к 110, т.к. в void setup код считывает показания. Да, в предыдущей статье эти цифры играли какую-то роль, т.к. там считывание происходило только через 2 минуты. Но в этой статье считывание производится во время запуска.
0
можно получить arduserver & arduread для роутеров на базе ramips rt305x
Добавил.

Мне кажется нет смысла их приравнивать к 110
Смысл есть. Вобще неплохо было бы "обстодесивать" их перед каждым считыванием.
0
Кстати, если интересно, у меня сделана новая версия, в которой данные читаются не из файла, а из ОЗУ. То есть ненужно дёргать файл и тем самым «изнашивать» железо.
0
Было бы круто увидеть это на деле :)
0
Выложу в обозримом будущем.
0
Добрый день, заинтересовался Вашим проектом умного дома, вопрос в следующем, можно ли реализовать на Вашей системе следующее: есть mega 2560, роутер как в статье, несколько датчиков температуры 22-ых, хочется поставить это в квартире, но чтобы помимо управления со смартфона, было управление с выключателей без фиксации (настенные выключатели света)
0
Огромное спасибо за этот проект! Но у меня по неопытности возник вопрос — tplink 3020 подключен черз uart. При нажатии на кнопки — не происходит никаких изменений в файле file.db
В index.html — ip правильный. С датчиков в броузере показывает температуру и влажность. Куда копать?
И очень интересует версия в которой данные читаются не из файла, а из ОЗУ
0
То есть у Вас кнопки не работают? Попробуйте вот такую команду послать:

echo 'Y+=ZM' > /dev/ttyATH0



Вот это сделано?
vi /etc/inittab

#ttyATH0::askfirst:/bin/ash --login
0
При отправке этой команды «echo 'Y+=ZM' > /dev/ttyATH0» загорается светодиод на плате.
0
::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K shutdown
#ttyATH0::askfirst:/bin/ash --login
А это содержимое файла.
0
И после команды кажется кнопка d13 изменила цвет
0
Всему вина моя невнимательность! В файле /etc/rc.local
в этой строке столо использование USB (sleep 1 && /arduserver 3490 /dev/ttyUSB0), хотя я работаю с UART. Т.е читал я через UART, а писать пытался через USB!
0
Что по поводу «Кстати, если интересно, у меня сделана новая версия, в которой данные читаются не из файла, а из ОЗУ. То есть ненужно дёргать файл и тем самым «изнашивать» железо.»?
комментарий был удален
0
Пока не готова.
0
Будет просто замечательно — если вариант с ОЗУ — заработает. Ведь у меня в роутер всунута простая флешка — она и тупит и не вечна.
0
Не получается пробросить порт 3490. Захожу через роутер с инета. Захожу на порт 36101 — форвард на 80. Страничка видна. Дополнительно зафорвардил 36101 на 3490 — не пашет. Пробовал в html файле менять порт и в файле менял rc.local. Не помогает. А можно как-то придумать что-бы работало без этого порта? без arduserver можно? Ведь сам сервер на 80м порту уже работает. Может его можно настроить — что он сам писал в файл db?
0
Что значит не могу пробросить порт? Я не знаю что сказать.
0
Возможно с портами я и смогу побороть. А что насчет возможности отказаться от arduserver?
0
Чтобы не насиловать флешку можно проделать небольшой трюк, надо во время загрузки скопировать папку ymdom в папку /tmp — это временная папка создающаяся в ОЗУ.

Добавьте в /etc/rc.local (до запуска arduread и arduserver) команду:

cp -vR /www/ymdom/ /tmp/


И измените (в /etc/rc.local) путь к файлу file.db, должно получится вот так:


cp -vR /www/ymdom/ /tmp/
(sleep 20 && /arduread /dev/ttyUSB0 /tmp/ymdom/file.db )&
(sleep 1 && /arduserver 3490 /dev/ttyUSB0 )&
exit 0


Так же в файле /etc/config/uhttpd необходимо изменить рабочую папку сервера /www на /tmp

vi /etc/config/uhttpd



...
        # Server document root
        option home             /tmp # ЭТО
...


Всё, теперь перегрузитесь и проверяйте. У меня сейчас нет роутера, так что жду от вас результата.
0
РАБОТАЕТ! светодиод на флешке не мигает!
0
А как проверить что все в ОЗУ? И еще вопрос — если я хочу сменить порт 3490 — мне это необходимо делать в 2-х файлах или одном?
как понимать эти фразы «Менять нужно только адрес 192.168.5.222, порт (3490) трогать не надо.
Если всё же решите поменять порт, то не забудте поменять его в аргументах для запуска программы arduserver, в файле /etc/rc.local (sleep 1 && /arduserver 3490 /dev/ttyUSB0).

Опять же, если будете заходить извне, и «умный дом» подключён к интернету не напрямую, а через другой роутер, то на нём нужно пробросить порт 3490, и 80-ый конечно тоже. „
0
А вот при запуске админки luci — ошибка «No such file or directory»
0
А как проверить что все в ОЗУ?
Всё в ОЗУ, ничего проверять не нужно. У роутра объём Flash-памяти 4М, однако в папку /tmp можно скопировать файл размером больше 4М. (при вынутой usb-флешке)

если я хочу сменить порт 3490
Поменяйте порт в файле index.html и в (sleep 1 && /arduserver 3490 /dev/ttyUSB0)

А вот при запуске админки luci

Само сабой, файлы luci лежат в папке /www, а сервер настроен на работу в папке /tmp.
0
А можно как-то на php что нибудь вместо arduserver прикрутить? Что все работало только на 80-м порту?
0
Может ser2net можно как-то прикрутить?
0
На 80-ом порту у вас работает основной сервер (uhttpd), который отдаёт контент. Php и ser2net описаны в предыдущих статьях, здесь же сделано так, чтоб избавиться от этого хлама.
Ser2net тоже использует определённый порт. Чем Вам мешает дополнительный порт? Ведь в работе он абсолютно прозрачен.
0
В общем проблема была не с пробрасыванием порта. Поблема была в том — что в index.hyml был указан ip. А в моем случае необходимо было указывать dns имя. Спасибо за помощь!
И еще вопрос — как перенести в ОЗУ, но что-бы luci осталась работоспособной?
0
В самый конец файла /etc/config/uhttpd добавьте это:

vi /etc/config/uhttpd



...
config uhttpd luci

        list listen_http        0.0.0.0:81

        option home             /www

        option rfc1918_filter 1

        option max_requests 3

        option cert             /etc/uhttpd.crt
        option key              /etc/uhttpd.key

        option cgi_prefix       /cgi-bin

        option script_timeout   60

        option network_timeout  30

        option tcp_keepalive    1



Перегрузитесь, luci будет на 81-ом порту. адрес:81

На всякий случай полный листинг uhttpd:


config uhttpd main

        list listen_http        0.0.0.0:80

        list listen_https       0.0.0.0:443

        # Server document root
        option home             /tmp

        option rfc1918_filter 1

        option max_requests 3

        option cert             /etc/uhttpd.crt
        option key              /etc/uhttpd.key

        option cgi_prefix       /cgi-bin

        option script_timeout   60

        option network_timeout  30

        option tcp_keepalive    1

config cert px5g

        # Validity time
        option days             730

        # RSA key size
        option bits             1024

        # Location
        option country          DE
        option state            Berlin
        option location         Berlin

        # Common name
        option commonname       OpenWrt



config uhttpd luci

        list listen_http        0.0.0.0:81

        option home             /www

        option rfc1918_filter 1

        option max_requests 3

        option cert             /etc/uhttpd.crt
        option key              /etc/uhttpd.key

        option cgi_prefix       /cgi-bin

        option script_timeout   60

        option network_timeout  30

        option tcp_keepalive    1

0
Я еще не до конца понял что произошло — но мне кажется что стало просто великолепно! И Админка пашет и ymdom в ОЗУ находится! СПАСИБО!
0
Пожалуйста.

Я еще не до конца понял что произошло

Мы добавили виртуальный хост для luci.
0
Сервер обслуживает два сайта на разных портах. Если есть интерес, тогда начните изучать работу серверов.
0
Значит установил всё на ББ, в верхней строке Connect! Errcon:0 Errtout:0 Obnov:230.
Температура обновляется, но нажатия кнопок не обрабатываются. Через web нажимаю — не включаются. Через консоль включил кнопки, они подсветились. Через web пытаюсь выключить — не выключаются. Таймоут ставил 500, 700, 200 — безрезультатно. Может arduserver как-то не правильно отрабатывает. Вот что выдает htop, а по ходу arduserver не запускается. В процессах висит два процесса arduread /dev/ttyS0 /www/ymdom/file.db. Ведь ардусервер тоже должен висеть в процессах?
0
С ардусервером разобрался — лишний пробел в записи поставил. Всё в процессах висят 2 процесса: ардусервер и ардурид, но нажатия по прежнему не отрабатывают. Куда ещё можно поглядеть?
0
В процессах висит два процесса arduread /dev/ttyS0 /www/ymdom/file.db

Два процесса — это мой косяк, эксперменты ставил… Вобщем сейчас исправлю.

А что у Вас за устройство /dev/ttyS0?



Запустите arduserver из консоли, что скажет?
0
Удалите предыдущие проги и скачайте эти istarik.ru/file/arduredser.zip
0
root@server:/home/killerpaf# sleep 1 && /arduserver 3490 /dev/ttyS0
Write to ErrorServer.log
Кстати в корне нет файла ErrorServer.log.
ttyS0 com порт, ардуина подключена через UART.
0
нашёл в дом каталоге этот файл. вот что в нём error — bind.
0
Не может забиндится, запустите через sudo.
0
Да я и так его из под рута запускаю. Нивкакую через судо тоже error — bind. Что-то мне кажется, что работать эта штука будет только через uhttpd. Ладно, на сегодня наверно пора закончить эксперименты, завтра после работы продолжу. Спокойной ночи.
0
Порт смените. От серверов это не зависит, arduserver это самостоятельный сервер, который слушает порт 3490 и ему до лампочки, что там параллельно работает.
Перед публикацией статьи я всё проверяю на работоспособность.
0
Проверил сегодня — всё работает: и кнопки жмутся и порт не менял. Спс за оперативную помощь и файлы для ББ. Я видел у вас новый проектик появился, и судя по статье он более гибче чем предыдущие.
0
У Вас торрент случайно не работал вчера?
0
Нет, скорее всего заработало сразу после замены первых файлов для ББ, когда создавалось 2 процесса. Видимо поздно уже было — не внимательность моя.
0
Подскажите пожалуйста, как увеличить количество команд, которые понимает ардуина, например чтобы принимался не один символ для управления, а два (к примеру d1 вкл при поступлении AA, выкл при Aa). Заранее спасибо.
0
Переписать программу.
0
И веб-часть тоже надо изменять.

До какого количества хотите увеличить?
0
Привет всем!
Задался целью (да простит меня sTD) поставить знак градуса, чтобы не "'C" было, а "°С" стало.
В index.html, где прописано "'C", стираем символ перед С и, нажав alt, набираем 0176 на цифровой клавиатуре(num lock). В итоге получаем знак "°".
Также методом тыка на ардуино нашёл этот же символ под кодом 223, т.е. чтобы его вывести на дисплей нужно набрать lcd.print(char(223)).
комментарий был удален
0
Привет, это опять я.
Жутко напрягает то, что при нажатии на «темп» не исчезают кнопки, и наоборот. Но… эммм, да простит меня sTD, я поборол сие явление, теперь у меня кнопки не накладываются на температуру. Для этого надо в index.html дописать код. Было:

$(".knp1").click(function(){ /* показать панель "кнопки"  */
	$(".panel1").toggle();
});

$(".knp3").click(function(){ /* показать панель "темп"  */
	$(".panel3").toggle();
});


стало:

$(".knp1").click(function(){ /* показать панель "кнопки"  */
	$(".panel1").toggle();
	$(".panel3").hide();
});

$(".knp3").click(function(){ /* показать панель "темп"  */
	$(".panel1").hide();
	$(".panel3").toggle();
});
0
Клёво.
0
Вот теперь сижу голову ломаю на всплывающими подсказками. Курсор наводишь на влажность, а всплывает температура. Там как-то границы смещены. Вот пытаюсь их переместить, но никак не получается. Может быть вы мне поможете, а то у меня в css вообще навыков 0.
0
Не могу верхнюю границу области, в которую надо мышку навести, чтобы всплыла подсказка, вниз опустить.
0
Привет! Добавил в код показания с ds18b20 и ntc, а также вывод показаний на дисплей. Столкнулся со следующей проблемой и не могу её никак победить: показания ntc выводятся в сериал как «0», а на дисплей измеренную температуру. В выводе в сериал менял местами переменные — результат 0. По коду tempDS — ds18b20 выводит и на дисплей и в сериал, tempA0 — ntc данные выводит только на дисплей, в сериал пишет 0.

#include <DHT.h>
#include <CyberLib.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//#include <EEPROM.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define TempResolution 10
#define DHTPIN 9 // пин для подключения датчика
#define DHTTYPE DHT22  
OneWire dt(8); //пин для ds18b20
DallasTemperature sensors(&dt); 
LiquidCrystal_I2C lcd(0x27,16,2);
DHT dht(DHTPIN, DHTTYPE);
double A=2.7711019E-03, B=2.5316014E-04, C=3.7501045E-11;//коэффициенты зависящие от типа термистора(из даташита или выводятся эмпирически)
float hum; // влажность
float thum; // температура
float tempDS; //температура DS18B20
float tempA0; //температура NTC
byte d2 = 0; // флаг состояния    
byte d3 = 0;
byte d4 = 0;
byte d5 = 0; 
byte d6 = 0;
byte d7 = 0; 
byte d8 = 0;
byte d9 = 0; 
byte d10 = 0;
byte d11 = 0;
byte d12 = 0;
byte d13 = 0;
byte pir1 = 0;
byte knop1 = 0;
byte knop2 = 0;
byte knop3 = 0;

byte descript[5]; // массив

unsigned long   time; // время

long timelapsed = 0;
byte MAXMILLIS;
int count=0; // счетчик минут

void setup() 
{
  Serial.begin(57600);
  sensors.begin();
  sensors.setResolution(TempResolution);
  lcd.init();
  lcd.backlight();
  lcd.print("DS=");
  lcd.setCursor(6,0);
  lcd.print(char(223));
  lcd.print("C");
  lcd.setCursor(9,0);
  lcd.print("T=");
  lcd.setCursor(14,0);
  lcd.print(char(223));
  lcd.print("C");
  lcd.setCursor(0,1);
  lcd.print("A0=");
  lcd.setCursor(6,1);
  lcd.print(char(223));
  lcd.print("C");
  lcd.setCursor(9,1);
  lcd.print("H=");
  lcd.setCursor(15,1);
  lcd.print("%");
  pinMode(A0, INPUT); //пин для ntc
  D2_Out; 
  D3_Out;
  D4_Out;
  D5_Out; 
  D6_Out; 
  D7_Out; 
  //D8_Out; //DS18B20
  //D9_Out; // DHT
  D10_Out; 
  D11_Out;
  D12_Out;
  D13_Out;
  //sensors.requestTemperatures();
  //delay(200);
  //tempDS = sensors.getTempCByIndex(0);
  //delay(200);
  //double tempA0=term1(analogRead(A0));
  //delay(350);
  //thum = dht.readTemperature(); // считываем температуру, сначала делаем это в сетапе, так как следующее чтение будет только через минуту
  //delay(200);
  //hum = dht.readHumidity(); // считываем влажность
}
  
void loop() 
{  
   if (Serial.available()>4) // ждём дескриптор и нужный символ
   {
    if (Serial.read()=='Y') // проверяем первый символ, если это 'Y', то продолжаем принимать, если нет, то выходим из цикла чтения
     {
      for (byte i=0; i < 5; i++)
        {
           descript[i] = Serial.read(); // добавляем символы в массив   
        } 
        
    if((descript[0] =='+') && (descript[1] =='=') && (descript[2] =='Z')) // проверяем дескриптор
     {
      switch (descript[3])
       {
         case 'o': // обновление
         glavnaia(); // отправка ответа
         break;
         
         ////////////// Кнопки ///////////////////
         case 'A': // d2 вкл
         D2_High; 
         d2 = 1; // флаг вкл
         break;
         
         case 'a': 
         D2_Low; 
         d2 = 0; // флаг откл
         break; 
 
         case 'B': // d3
         D3_High;
         d3 = 1;
         break;
         
         case 'b': // d3
         D3_Low;
         d3 = 0;
         break;          
  
         case 'C': // d4
         D4_High;
         d4 = 1;
         break;
         
         case 'c': // d4
         D4_Low;
         d4 = 0;
         break;   

         case 'D': // d5
         D5_High;
         d5 = 1;
         break;
         
         case 'd': // d5
         D5_Low;
         d5 = 0;
         break;  
  
         case 'E': // d6
         D6_High;
         d6 = 1;
         break;
         
         case 'e': // d6
         D6_Low;
         d6 = 0;
         break;   
  
         case 'F': // d7
         D7_High;
         d7 = 1;
         break;
         
         case 'f': // d7
         D7_Low;
         d7 = 0;
         break;  
 
         case 'G': // d8
         //D8_High; //DS18B20
         //d8 = 1;
         break;
         
         case 'g': // d8
         //D8_Low;
         //d8 = 0;
         break;  
 
         case 'H': // d9
         //D9_High; // DHT
         //d9 = 1;
         break;
         
         case 'h': // d9
         //D9_Low; // DHT
         //d9 = 0;
         break; 
         
         case 'I': // d10
         D10_High;
         d10 = 1;
         break;
         
         case 'i': // d10
         D10_Low;
         d10 = 0;
         break;         
       
         case 'J': // d11
         D11_High;
         d11 = 1;
         break;
         
         case 'j': // d11
         D11_Low;
         d11 = 0;
         break;  
        
         case 'K': // d12
         D12_High;
         d12 = 1;
         break;
         
         case 'k': // d12
         D12_Low;
         d12 = 0;
         break;         
      
         case 'M': // d13
         D13_High;
         d13 = 1;
         break;
         
         case 'm': // d13
         D13_Low;
         d13 = 0;
         break;
         
         default:
         glavnaia();
       }
     }
   
    else // если дескриптор ложный, то очищаем буфер
      {
        for(byte i=0; i < 255; i++) 
         {
           Serial.read();    
         } 
      } 
     }    // конец if (Serial.read()=='Y')
   }    // конец чтение порта
 
 
 unsigned long currtime = millis(); 
 
 if(currtime > time) timelapsed = (currtime - time); 
 
 else timelapsed = (MAXMILLIS - time + currtime);

 if(timelapsed >= 440)  // функция будет выполняться раз в 2 минуты
   { 
     time = currtime;
     count++;
     if(count == 10) {double tempA0=term1(A0_Read);
                      if (tempA0<10) {lcd.setCursor(4,1); lcd.print("0"); lcd.setCursor(5,1); lcd.print(tempA0,0);}
                      else if (tempA0<0) {lcd.setCursor(3,1);}
                      else {lcd.setCursor(4,1);}
                            lcd.print(tempA0,0);}
     if(count == 20) {sensors.requestTemperatures();
                     tempDS = sensors.getTempCByIndex(0);
                     if (tempDS<10) {lcd.setCursor(4,0); lcd.print("0"); lcd.setCursor(5,0); lcd.print(tempDS,0);}
                     else if (tempDS<0 | tempDS>99) {lcd.setCursor(3,0);}
                     else {lcd.setCursor(4,0);}
                           lcd.print(tempDS,0);}
     if(count == 30) thum = dht.readTemperature(); 
                     lcd.setCursor(12,0);
                     lcd.print(thum,0);
     if(count == 40) hum = dht.readHumidity();
                     lcd.setCursor(12,1);
                     lcd.print(hum,0); 
     if(count > 39) count=0;
     glavnaia(); // отправка данных серверу   
     
   } // конец включения по температуре
   
 } // конец loop
 
void glavnaia() // отправка данных серверу 
 {
      // сумма проверяется на сервере, на предмет целостности пакета
      int summa = d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9 + d10 + d11 + d12 + d13 + thum + hum + tempA0 + tempDS + knop2;
      Serial.print('A');
      Serial.print(" "); 
      Serial.print(summa);
      Serial.print(" ");   
      Serial.print(d2);
      Serial.print(" ");
      Serial.print(d3);
      Serial.print(" ");
      Serial.print(d4);
      Serial.print(" ");
      Serial.print(d5);  
      Serial.print(" ");
      Serial.print(d6);  
      Serial.print(" ");
      Serial.print(d7); 
      Serial.print(" ");
      Serial.print(d8);
      Serial.print(" ");
      Serial.print(d9); 
      Serial.print(" ");
      Serial.print(d10);
      Serial.print(" ");
      Serial.print(d11);
      Serial.print(" ");
      Serial.print(d12);
      Serial.print(" ");
      Serial.print(d13);
      Serial.print(" ");
      Serial.print(thum,1); 
      Serial.print(" ");
      Serial.print(hum,1); 
      Serial.print(" ");
      Serial.print(tempA0,1); 
      Serial.print(" ");
      Serial.print(tempDS,1); 
      Serial.print(" ");
      Serial.print(knop2); // не используется
      Serial.print(" ");
      Serial.print(knop3); // не используется
      Serial.print(" ");
      Serial.print(0); // не используется
      Serial.print(" ");
      Serial.print(0); // не используется
      Serial.print(" ");
      Serial.println('Z');    
 }

float getR(float V) //функция преобразования значения полученного с аналогового входа в сопротивление терморезистора
{
float result;
result=-9.8*V/(V-1024);
return result;
}

float term1(int AnalogDC)
{
double tempertura;
tempertura = 1 / (A + B * (log(getR(AnalogDC))) + C * (log(getR(AnalogDC)))*(log(getR(AnalogDC)))*(log(getR(AnalogDC))) );
tempertura = tempertura - 273.15;
return tempertura;
}
0
Ошибка у Вас здесь:
if(count == 10) {double tempA0=term1(A0_Read);

Если хотите могу сказать, а если хотите самостоятельно дойти, то промолчу.
0
тип double во всём виноват или. Лучше подскажите, я тут немного не местный в СИ.
0
На дисплей же выводит температуру, а в сериал пишет 0
0
или всему виной А0 в названии переменной?
0
Вы в начале объявили глобальную переменную float tempA0;, а читаете в локальную double tempA0=term1(A0_Read)
Соответственно в ЛСД идёт локальная, а в сериал глобальная, которая не инициализирована == 0.
0
Если уберёте вверху float tempA0;, то выдаст ошибку, так как double tempA0=term1(A0_Read) будет не видна в void glavnaia().
0
Не помогло: изменил в начале на double, запустил: 0.
Поменял в начале на float и float tempA0=term1(A0_Read): 0.
что-то ещё видимо обнуляет ее. может быть в начале массив, там где byte = 0.
0
В строчке if(count == 10) {double tempA0=term1(A0_Read); удалите слово double, в начале скетча напишите double tempA0;
0
ООО аллилуя, вот я «АЛЁША». Спасибо огромное!!!
0
Пожалуйста.
0
Скажите, что за термистор используете (маркировка), точно ли показывает?
0
брал на али. называется NTC-MF52-103 / 3950 10 К. Коэффициенты выводил в маткаде по формуле, подставляя параметры резистора. Точность, ну как сказать, по сравнению с ds18b20 разница в 0 — 1.5 градуса. каждый раз по разному. с DHT22 тоже примерно 1 градус. Я свой за окно вывел, ds в комнате и dht тоже в комнате. Так в принципе по точности устраивает. Если что, брал тут:Your text to link...
0
Калькулятор вот здесь автор пишет разные параметры и характеристики термисторов, а также есть он-лайн калькулятор температуры по сопротивлению.
0
А как подключать, какая обвязка нужна?
0
+5V 10к Pin(analog) NTC -5V. А также схема включения на сайте, где калькулятор, ну и здесь NTC+Arduino
0
Плюсы термисторов: мгновенно реагируют на изменение температуры, ну и дешевизна при хорошей точности. Последнее лично моё мнение.
0
В обозначении моего термистора 3950 — это коэффициент B(T1/T2) при температуре Т2=50 градусов. Т1=25 градусов и сопротивление при Т1 R1=10 kOm
0
Спасибо, буду пробовать.

Плюсы термисторов
:
Да, я знаю, пробовал несколько, нужна точность во всём диапазоне, но проклятая нелинейность бесит.
0
А в каком диапазоне необходимо измерять?
0
От -30 до +110
0
понятно, я пробовал от -22 до + 60 точность от ds18b20 особо не отличалась.
0
Вот спасибо.
0
Приветствую,
После некоторых танцев с бубном, завелось и отлично работает.
Появился такой вопрос, возможно ли изменение управляющего дескриптера (Y+=Z) или же добавления новых типа Y+=A и т.д.
Я подключил библиотеку SoftwareSerial и управляю с дуины другими дуинами. Немного не хватает количества символов. Хотя может быть добавить просто длинны типа — Y+=Zxx?
0
Здравствуйте. Сделайте для одной ардуины дескриптор — (Y+), а для второй — (=Z).
0
Такой «хитрый» дескриптор был сделан для соединения ардуины с уартом роутера. Роутер при загрузки сыплет в уарт кучу всего, и чтоб отсечь это мусор я и придумал Y+=Z.
0
Это как раз понятно. Просто там их не 2 а как минимум 5 будет. С 10 пинами на каждой и 3 командами на пин) подумаю потом, наверно придётся отказаться от третьей команды, и привязать как вы посоветовали дескрипторы к командам, а не к дуинам.
0
Опишите конкретно, что хотите сделать?
0
К роутеру по UART-у прицеплена главная дуина, которая отсылает 3 набора команд (лучше-больше) другим дуинам, к которым подключено до 10 устройств. Конечные дуины сидят на portOne, porttwo и тд. То есть получается минимум 50 кнопок на каждую из команд.
типа —
case 'A': 
          portOne.println("force test  ");

         case 'a': 
         portOne.println("power test  ");
         break;  

         case 'B': 
         portOne.println("state test  ");
         break

При возможности менять дескрипторы, можно было бы забиндить их на допустим на Y+=P

if((descript[0] =='+') && (descript[1] =='=') && (descript[2] =='P')) 
  {
      switch (descript[3])
    {
       
      case 'a':
      portTwo.println("power test    ");


Y+=F —

if((descript[0] =='+') && (descript[1] =='=') && (descript[2] =='F')) 
  {
   switch (descript[3])
    {
      case 'a':
      portTwo.println("force test    ");

и т.д.
Просто слишком много конечных устройств)
Ну и соответсвенно кнопки уже в вебе вязать по группам на дескриптор.
Как то так.
0
Для большого количества команд нужно внести ряд изменений. Я сейчас занят, однако если хотите, то я готов взяться за это. Пишите все детали на почту pccar@mail.ru
0
Спасибо большое, решил уже посылкой двух символов по событию, увеличив descript до 10 знаков, и поставив двойной свич

byte descript[10];
.......

if (Serial.read()=='Y') 
     {
      for (byte i=0; i < 10; i++)
        {
           descript[i] = Serial.read();  
             
                    } 
       
    if((descript[0] =='+') && (descript[1] =='=') && (descript[2] =='Z')) 
     {
      
      switch (descript[3])
       {
                  
         case '1':
         
         
           {
           switch (descript[9])
           {
            case 'a':
            registerWrite(0,0);
            d2 = 1;
            delay(250);
            registerWrite(0,1);
            break;

 

Сначала по кнопке уходит символ 1, потом а. итого на одно значение можно поставить 50 событий. Единственный прикол остался с тем, что дуина иногда ловит символы в обратном порядке, почему-то. То есть сначала -а, потом 1. Решил это просто продублировав действия дескрипта но уже в обратном порядке.
0
У меня готов код для большого кол-ва команд, планировал выложить его с новой статьёй:


#include "CyberLib.h"

char array_in[5] = {0,};
int cod_comand = 0;
unsigned long timme; 

byte d2 = 0;
byte d3 = 0;


void setup()
 {
   timme = millis(); 
   Serial.begin(57600);
   D2_Out;
   D2_Low;
   D3_Out;
   D3_Low;
 }


void loop() 
{   
  if (Serial.available()>3) // приём команд от сервера
   {
    if (Serial.read()=='Y')
     {
       for (byte i=0; i < 3; i++)
        {
           array_in[i] = Serial.read(); 
        } 
      
       if((array_in[0] =='+') && (array_in[1] =='=') && (array_in[2] =='Z')) 
        {
         int i = 0;
         delay_ms(1);

         memset(array_in, 0, sizeof(array_in));
       
         while(Serial.available())
           {
              delay_ms(1);
              array_in[i++] = Serial.read(); 
              if(array_in[i] == '\r' || array_in[i] == '\n')
                {
                  array_in[i] = 0;
                  break;
                }
           }

         sscanf(array_in, "%d",&cod_comand);
         memset(array_in, 0, sizeof(array_in));
    
         switch(cod_comand) 
           {
             case 100:
             D2_High;
             d2 = 1;
             clear_port();
             break;

             case 101:
             D2_Low;
             d2 = 0;
             clear_port();
             break;

             case 102:
             D3_High;
             d3 = 1;
             clear_port();
             break;

             case 103:
             D3_Low;
             d3 = 0;
             clear_port();
             break;


             default:
             clear_port();
             break;
           }          
       }
   
      else 
       {
         clear_port();
       }       
   }   
 }  


 if((millis()-timme) > 440) // интервал отправки данных  
   { 
     timme = millis();
     trans();  
   }   
} //END loop


void clear_port() // очистка буфера
 {
   for(int i=0; i < 64; i++) 
    {
      Serial.read();    
    } 
 }


void trans() // отправка данных серверу 
 {
   Serial.print('A'); 
   Serial.print(' ');   
   Serial.print(0);
   Serial.print(' '); 
   Serial.print(d2);
   Serial.print(' ');
   Serial.print(d3);
   Serial.print(' ');
   Serial.print('Z');   
   Serial.print('\n');  
 }


Получается 899 команд — от 100 до 999 (трёхзначное число).
0
Соответственно из веба отправляете 100 (одна команда), 101 (другая команда) и т.д.
0
Добрый день! Подскажите, для данного скетча, нужно ли вносить изменения в arduread и arduserver?
0
Добрый день!
Использую роутер Netgear WNCE2001 со старой прошивкой openwrt openwrt-14.07-ramips-rt305x-wnce2001-squashfs-factory-worldwide
Так как новая прошивка не сохраняет настройки
Можно ли сделать для него файлы arduread и arduserver
Спасибо.
0
Здравствуйте. Всё получилось, но что-то не работает датчик температуры DHT11.
В скетче ардуины если yt меняешь DHT22 на DHT11, тогда показания отображаются. А если меняешь значение на DHT11, то в показателях нули.
Кроме этого ничего не менял.
ЧЯДНТ?
0
Мне трудно ответить на Ваш вопрос так как никогда даже в руках не держал датчик DHT11. Может китайцы засунули DHT11 в корпус от DHT22.)))
А если попробовать этот датчик с примером из библиотеки?
0
То есть наоборот — DHT22 в корпус от DHT11.)))
0
У получилось с этим скетчем (Библиотека TroykaDHT11):
#include <TroykaDHT11.h>
 
#include "CyberLib.h"

#define MAXMILLIS 4294967295

DHT11 dht(9);
 
int hum = 110; // влажность
int thum = 110; // температура

byte d2 = 0; // флаг состояния    
byte d3 = 0;
byte d4 = 0;
byte d5 = 0; 
byte d6 = 0;
byte d7 = 0; 
byte d8 = 0;
byte d9 = 0; 
byte d10 = 0;
byte d11 = 0;
byte d12 = 0;
byte d13 = 0;
byte pir1 = 0;
byte knop1 = 0;
byte knop2 = 0;
byte knop3 = 0;

byte descript[5]; // массив

unsigned long   time; // время

long timelapsed = 0;

int count=0; // счетчик минут

void setup()
{
  Serial.begin(57600);
  D2_Out; 
  D3_Out;
  D4_Out;
  D5_Out; 
  D6_Out; 
  D7_Out; 
  D8_Out; 
  //D9_Out; //датчик температуры
  D10_Out; 
  D11_Out;
  D12_Out;
  D13_Out;
  
  dht.begin();
  delay(1000);
  dht.read();
  thum = dht.getTemperatureC(); // считываем температуру, сначала делаем это в сетапе, так как следующее чтение будет только через минуту
  hum = dht.getHumidity(); // считываем влажность
}

void loop()
{

  if (Serial.available()>4) // ждём дескриптор и нужный символ
   {
    if (Serial.read()=='Y') // проверяем первый символ, если это 'Y', то продолжаем принимать, если нет, то выходим из цикла чтения
     {
      for (byte i=0; i < 5; i++)
        {
           descript[i] = Serial.read(); // добавляем символы в массив   
        }
        
    if((descript[0] =='+') && (descript[1] =='=') && (descript[2] =='Z')) // проверяем дескриптор
     {
      switch (descript[3])
       {
         case 'o': // обновление
         glavnaia(); // отправка ответа
         break;

         ////////////// Кнопки ///////////////////
         case 'A': // d2 вкл
         D2_High; 
         d2 = 1; // флаг вкл
         break;

         case 'a': 
         D2_Low; 
         d2 = 0; // флаг откл
         break; 

         case 'B': // d3
         D3_High;
         d3 = 1;
         break;
         
         case 'b': // d3
         D3_Low;
         d3 = 0;
         break;          
  
         case 'C': // d4
         D4_High;
         d4 = 1;
         break;
         
         case 'c': // d4
         D4_Low;
         d4 = 0;
         break;   

         case 'D': // d5
         D5_High;
         d5 = 1;
         break;
         
         case 'd': // d5
         D5_Low;
         d5 = 0;
         break;  
  
         case 'E': // d6
         D6_High;
         d6 = 1;
         break;
         
         case 'e': // d6
         D6_Low;
         d6 = 0;
         break;   
  
         case 'F': // d7
         D7_High;
         d7 = 1;
         break;
         
         case 'f': // d7
         D7_Low;
         d7 = 0;
         break;  
 
         case 'G': // d8
         D8_High;
         d8 = 1;
         break;
         
         case 'g': // d8
         D8_Low;
         d8 = 0;
         break;  
 
         case 'H': // d9
         //D9_High; // DHT
         //d9 = 1;
         break;
         
         case 'h': // d9
         //D9_Low; // DHT
         //d9 = 0;
         break; 
         
         case 'I': // d10
         D10_High;
         d10 = 1;
         break;
         
         case 'i': // d10
         D10_Low;
         d10 = 0;
         break;         
       
         case 'J': // d11
         D11_High;
         d11 = 1;
         break;
         
         case 'j': // d11
         D11_Low;
         d11 = 0;
         break;  
        
         case 'K': // d12
         D12_High;
         d12 = 1;
         break;
         
         case 'k': // d12
         D12_Low;
         d12 = 0;
         break;         
      
         case 'M': // d13
         D13_High;
         d13 = 1;
         break;
         
         case 'm': // d13
         D13_Low;
         d13 = 0;
         break;
         
         default:
         glavnaia();
       }
     }
   
    else // если дескриптор ложный, то очищаем буфер
      {
        for(byte i=0; i < 255; i++) 
         {
           Serial.read();
         }
      }
     }    // конец if (Serial.read()=='Y')
   }    // конец чтение порта
 
 
 unsigned long currtime = millis();
 
 if(currtime > time) timelapsed = (currtime - time);
 
 else timelapsed = (MAXMILLIS - time + currtime);

 if(timelapsed >= 440)  // функция будет выполняться раз в 2 минуты
   {
     time = currtime;
     count++;
     if(count == 120)  dht.read(); thum = dht.getTemperatureC(); 
     if(count == 240)  dht.read(); hum = dht.getHumidity(); 
     if(count > 239) count=0;
     glavnaia(); // отправка данных серверу   
     
   } // конец включения по температуре
   
 } // конец loop

void glavnaia() // отправка данных серверу 
 {
      // сумма проверяется на сервере, на предмет целостности пакета
      int summa = d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9 + d10 + d11 + d12 + d13 + thum + hum + pir1 + knop1 + knop2;
      Serial.print('A');
      Serial.print(" ");
      Serial.print(summa);
      Serial.print(" ");
      Serial.print(d2);
      Serial.print(" ");
      Serial.print(d3);
      Serial.print(" ");
      Serial.print(d4);
      Serial.print(" ");
      Serial.print(d5);
      Serial.print(" ");
      Serial.print(d6);
      Serial.print(" ");
      Serial.print(d7);
      Serial.print(" ");
      Serial.print(d8);
      Serial.print(" ");
      Serial.print(d9);
      Serial.print(" ");
      Serial.print(d10);
      Serial.print(" ");
      Serial.print(d11);
      Serial.print(" ");
      Serial.print(d12);
      Serial.print(" ");
      Serial.print(d13);
      Serial.print(" ");
      Serial.print(thum);
      Serial.print(" ");
      Serial.print(hum);
      Serial.print(" ");
      Serial.print(pir1); // не используется
      Serial.print(" ");
      Serial.print(knop1); // не используется
      Serial.print(" ");
      Serial.print(knop2); // не используется
      Serial.print(" ");
      Serial.print(knop3); // не используется
      Serial.print(" ");
      Serial.print(0); // не используется
      Serial.print(" ");
      Serial.print(0); // не используется
      Serial.print(" ");
      Serial.println('Z');
 }


Да датчик то нормальный. Я его проверял уже.

Подскажите нубу для чего Вы задаёте значение 110 переменным thum, hum? =)
0
Если датчик не работает, то будет показывать 110, а такой влажности не может быть.
0
Вот это:

if(count == 120)  dht.read(); thum = dht.getTemperatureC(); 
if(count == 240)  dht.read(); hum = dht.getHumidity();
if(count > 239) count=0;


Сделайте так:

if(count == 120)
 {  
   dht.read(); 
   thum = dht.getTemperatureC();
   hum = dht.getHumidity(); 
 }

if(count > 119) count=0;

0
Здравствуйте!
Скажите, а какой из двух представленных на Вашем сайте вариантов УД лучше?
0
Либо этот, либо вот здесь с конструктором.
0
Я забыл спросить, а какой первый вариант?
0
На сайте два варианта по исполнению 1 — я так понимаю через ser2net и второй вот этот через arduread, ardusend. Какой из них Вам кажется перспективней в плане масштабируемости (например, мне хочется подключить ещё один датчик температуры, чтобы на улице тоже иметь показания). Где лучше в плане развития?
0
Здравствуйте. Этот лучше.
0
Ещё рекомендую посмотреть сюда.
0
Привет, какие arduread и arduserver использовать для роутера Asus wl500gp2(https://wiki.openwrt.org/toh/asus/wl500gp)?
и какая прошивка должна быть на нём? например на прошивке «от Олега» будет работать?
0
взял из ссылки на «Broadcom». в принципе заработало, НО…

при перезагрузке роутера, не срабатывает автозагрузка arduread и arduserver.
если я их из командной строки запускаю, то запускаются и работают.
запускаю так:
./arduread /dev/ttyUSB0 /www/web/file.db
./arduserver 3490 /dev/ttyUSB0

тоже самое в /etc/rc.local не работает.
rc.local:
# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.
(sllep 1 && stty -F /dev/ttyUSB0 cs8 57600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexte
(sleep 20 && ./arduread /dev/ttyUSB0 /www/web/file.db )&
(sleep 1 && ./arduserver 3490 /dev/ttyUSB0 )&
exit 0
думаю что это из-за того что я неправильно установил права.
а сначала вообще не запускалось, пока права не поменял, всё натыкал, стало вручную стартовать



как правильно сделать?
0
заработала автозагрузка, оказывается я не туда скопировал, надо было в корень (/). ну или путь другой прописывать. :)

но вопрос насчет прав у меня остался. какие надо установить, а какие не надо?
0
Права установите 777.
0
спасибо. установил.
chmod 777 arduserver
а в mc всё равно показывает права 100777. я так понимаю это одно и тоже?

я хочу немного переделать arduread и arduserver.
подскажите, в чем их компилировать и как?
и в чем отличия Broadcom от остальных?
0
подскажите, в чем их компилировать и как?

Вот здесь почитайте, там есть раздел «Свой пакет».

и в чем отличия Broadcom от остальных?
Другая архитектура, то есть файл скомпилированный для Broadcom не будет работать на Atheros.
0
Да, чуть не забыл, настройка порта с помощью stty не нужна, моя прога сама всё настраивает, так что можно убрать из автозагрузки строку:

(sllep 1 && stty -F /dev/ttyUSB0 cs8 57600 ignbrk -brkint -icrnl...
0
ясно, понятно, спасибо. уберу.

я хотел передавать от ардуинки 2-х байтное число. не температуру.
в скетче есть:
Serial.print(pir1); // не используется
Serial.print(knop1); // не используется
Serial.print(knop2); // не используется
Serial.print(knop3); // не используется

можно использовать pir1, knop1 — knop3?
если я их задействую, ничего не другой не разломается?
и может и не нужно переделывать arduserver и arduread?
0
Ардуина передаёт данные как строки. Используйте — Serial.print(knop3);
0
Здравствуйте! Прошу помощи по вашей статье.
Сделал всё по мануалу — не установились два пакета из репозитория, но ch341 стоит, ардуино на usb0 видит.
Роутер китайские OYE-0001 на процессоре 7620А, вероятно аналог Asus RT-n14u с OpenWRT на борту.
На странице ymdom выдает errcon, отсутствует связь с МК.
В файле db 8888
При этом файлы логов не создаются.
с USB0 сыпется fffffкракозябрыffff и так далее…
Куда копать? Конденсатор между RST и GND ставил.
Ардуина мигает только Rx…
0
Добрый день.

При работе на странице постоянно появляется кнопка «Пуск» Что это?
0
Это что-то вроде спящего режима, экран (через определённый интервал) закрывается прозрачной панелью с кнопкой «Пуск» и обновление данных приостанавливается. Это чтоб трафик постоянно не потребляла.

В файле index.html есть блок отвечающий за это:


   slmode++; /* спящий режим */
   if(slmode > 10) 
    { 
      $(".pansl").show();
      flagobnov = 0;
      slmode = 0;
    }



Можете отключить или увеличить интервал:


   /*slmode++;  спящий режим */
   if(slmode > 30) 
    { 
      $(".pansl").show();
      flagobnov = 0;
      slmode = 0;
    }

0
Имеется роутер ASUS RT-N14U wiki.openwrt.org/toh/asus/rt-n14u, с Ralink MT7620N на борту и ряд проблем с ним.


Подключен по USB, в устройствах видеться как ttyUSB0.
Установил в корень библиотеки arduread и arduserver.
Заменил, что все что написано в автозагрузке /etc/rc.local не автозагружается и приходиться вызывать все вручную.
Если вызвать вручную "/arduread /dev/ttyUSB0 /www/ymdom/file.db", то пишет «записал ошибку 8888»
Веб морду загружает, есть 2 кнопки, при клике ничего не происходит.
На кнопку «пуск» есть реакция
На ардуине моргает TX, в «cat /dev/ttyUSB0» построчно пишет «A 0 0 0… 0 0 Z»
На команду echo 'Y+=ZM' > /dev/ttyUSB0 включает светодиод и он не тухнет, а в cat'е вместо «0» появляется 1.

Подскажите пожалуйста)
0
Отвечаю сам себе, после пары перезагрузок — роутер начал грузить автобут и морда начала видеть ардуину и управлять ей. Как именно это произошло, я так и не понял.
0
Да, странная ситуация. Напишите если опять будет что-то не так.
0
Здравствуйте!
Прошу помощи.
Сделал всё, как в статье выше. Подключаюсь по UART (ttyATH0). Всё прекрасно работает, но только когда tl-mr3020 подключен по LAN к основному роутеру. При подключении по Wifi сайт www/ymdom открывается, счетчик обновлений идёт (если МК подключен), но на нажатия кнопок ардуина не реагирует. cat /dev/ttyATH0 даёт A 0 0 0… 0 Z (содержимое file.db). Адрес IP в Index.html выставил из wan. По Wifi стрим с вёбкамеры прекрасно передавался, на luci и по SSH тоже прекрасно захожу беспроводным способом.
И ещё одно очень странное наблюдение. В качестве МК использовал Arduino Uno или Mega. Если их запитывать от USB ПК, то D13 при нажатии кнопки, на страничке загорается/гаснет (естественно если роутер при этом подключен через LAN, про вайфай выше написал). Но если ардуину запитать НЕ от ПК, то опять нет реакции на нажатия кнопок (как это вообще работает?)! Скетч и библиотеки использую из статьи. Порты на основном роутере открыл. В фаерволе mr3020 пробовал на wan ставить настройки как на lan. Безрезультатно.
Надеюсь на любую помощь, хотя бы в какую сторону смотреть. Настройки какие нужно выложу.
0
При подключении камеры к USB mr3020 страничка www/ymdom выдаёт MK NOT CONNECT.
0
камера logitech c270. Видео передаю через mjpg streamer

После инициализации выполняется:
mjpg_streamer -i «input_uvc.so -d /dev/video0 -r 640x480 -f 25» -o «output_http.so -w /www/webcam -p 8080»
stty -F /dev/ttyATH0 cs8 57600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts -hupcl
(sleep 20 && /arduread /dev/ttyATH0 /www/ymdom/file.db )&
(sleep 1 && /arduserver 3490 /dev/ttyATH0 )&
exit 0
0
А если так:

(mjpg_streamer -i "input_uvc.so -d /dev/video0 -r 640x480 -f 25" -o "output_http.so -w /www/webcam -p 8080")&
0
Спасибо, даже не ожидал что так быстро ответите! Да, это помогло.
0
Но если ардуину запитать НЕ от ПК, то опять нет реакции на нажатия кнопок

Земли у роутера и ардуины соединены?

По wifi — Не совсем понимаю, что и куда подключено.
0
Земли конечно же соединены :) GND на ардуино с соответствующим штырьком на плате роутера.
УАРТ это можно сказать последний нерешённый вопрос. Но его можно обойти, если запитать ардуину и роутер от одного источника +5В. С Wifi проблем нет, это я напутал вчера.
Попробую сейчас подключаться по USB (и камеру, и ардуину через хаб).
Спасибо за помощь!
0
Попробовал, отиписываюсь:
Made in China Arduino Mega не работает ни в какую, диод D13 дёргается хаотически, MK NOT CONNECT.
Made in Italy (так написано на плате, хотя она с того же алиэкспресса) Arduino Uno работает прекрасно! На меге преобразователь CH340G, на уне какой-то другой с атмеловской маркировкой. Похоже на то, что там под USB отдельная атмега выделена в soic корпусе. Думаю, остановлюсь на таком варианте.
0
Если подключаете ардуину с чипом CH340G по USB, то поставьте между reset и gnd электролитический конденсатор ~10 микрофарад.

Это…
stty -F /dev/ttyATH0 cs8 57600...

… из автозагрузки уберите.

если запитать ардуину и роутер от одного источника

Тут явно проблема с землёй, прозвоните её на роутере.
0
Строчку закомментил сразу же, как перешёл на USB. С электролитом на 10 мкФ попробовал, всё то же самое.

Что касается UART порта, то его земля действительно не прозванивается с землёй питания (которая по mini-usb).
0
Подключил к UART роутера преобразователь UART-USB, отправляю команду «echo 'Y+=Za' > /dev/ttyUSB0» через Putty по SSH, результат смотрю в мониторе порта Arduino IDE. Через тот же монитор порта отправляю команды с ПК в уарт роутера, смотрю через cat /dev/ttyATH0. Если роутер подключен по LAN и без камеры, то всё прекрасно отправляется и принимается обеими сторонами. По wifi не передаётся и не принимается ничего вообще, хоть с камерой, хоть без. По LAN с камерой с роутера на ПК приходят кракозябры, с ПК на роутер не приходит ничего вообще. Преобразователь пробовал на CP2101 и CH340G.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.