Умный дом на 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
  • 11851

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

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);
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.