Zyxel Keenetic 4G, arduino и датчики температуры ds18b20

Современные роутеры как небольшие компьютеры, которые выполняют узкоспециализированную задачу для раздачи сетевого трафика. На борту такого небольшого устройства установлена ОС Linux, только без графического интерфейса и с урезанной программной частью. Передо мной встал вопрос, а почему бы не подключить arduino к своему роутеру — Zyxel Keenetic 4G? Немного погуглив я наткнулся на замечательный форум, где энтузиасты собирают модифицированные прошивки с поддержкой установки дополнительных,  пакетов для серии Keenetic.

В нашем случае управление Arduino происходит через библиотеку php_serial.class.php и легкого веб сервера на основе Lighttpd + php. С помощью этих инструментов будем подавать команды ардуинке на чтение показаний с двух температурных датчиков (дом, улица) , записывать ответ в базу данных Sqlite3 и выводить на нашу веб-страничку.

Подготовка маршрутизатора

Первым делом необходимо настроить наш маршрутизатор. У Zyxel Keenetic 4G очень маленькая внутренняя память, поэтому приобретете простенький usb-хаб и флешку не большого объема. Все тонкости настройки я не буду расписывать, а лишь поделюсь необходимыми ссылками. Сразу приготовитесь к долгой и утомительной процедуре.

  1. Альтернативная прошивка. Система opkg для установки дополнительных пакетов. (читаем внимательно WIKI, там все расписано)
  2. Устанавливаем Sqlite3 командой opkg install <имя пакета>, где <имя пакета> полный путь к пакету. Все необходимые пакеты берем здесь.
  3. Устанавливаем и настраиваем Lighttpd и php.

Подключение датчиков

Подключаем температурные датчики ds18b20 к arduino. Номинал резисторов — 4,7 кОм

Схема подключения температурных датчиков

Скетч
Заливаем скетч. За основу был взят код из этого урока и немного доработан под нашу задачу.

#include <OneWire.h>

int nc; 
OneWire  ds(10);  // Первый датчик
OneWire  ds2(11);  // Второй датчик
byte addr[8];
byte addr2[8];

void setup(void)
{
  Serial.begin(9600);
  ds.search(addr); 
  ds2.search(addr2);
}
 
void loop(void)
{
  byte i;
  byte present = 0;
  byte data[12];
  int Temp;
  int znak;

  if (Serial.available() > 0) {
    nc = Serial.read();  
    if (nc==1) { 
    ds.reset();
    ds.select(addr);
    ds.write(0x44,1);     
  
    present = ds.reset();
    ds.select(addr);   
    ds.write(0xBE);       
 
    for ( i = 0; i < 9; i++) { 
      data[i] = ds.read();
    }
    
    Temp=(data[1]<<8)+data[0];
    Temp=Temp;
    znak=((Temp%16)*100)/16;
    if (znak<0){
      znak=znak*-1;
    }
    Serial.print(Temp/16);
    Serial.print(".");
    Serial.print(znak);
    Serial.println();
  }

if (nc==2) { 
    ds2.reset();
    ds2.select(addr2);
    ds2.write(0x44,1);        
    present = ds2.reset();
    ds2.select(addr2);   
    ds2.write(0xBE);       
 
    for ( i = 0; i < 9; i++) { 
      data[i] = ds2.read();
    }
    Temp=(data[1]<<8)+data[0];
    Temp=Temp;
    znak=((Temp%16)*100)/16;
    if (znak<0){
      znak=znak*-1;
    }
    Serial.print(Temp/16);
    Serial.print(".");
    Serial.print(znak);
    Serial.println();
  }
 }
}

Передаем команды, принимаем ответы

Скетч принимает две команды — «1» и «2». Для того что бы отправлять команды в Arduino, я использовал обработку кнопок на java script при помощи известной библиотеки Jquery. На моей страничке находятся 2 кнопки и 2 табличных поля в которые выводятся значения с температурных датчиков(см. index.php). При помощь метода POST, скрипт обращается к arduino.php и передает значения наших команд. Здесь происходит передача команд непосредственно в Arduino и чтение ответа в виде температуры, а так же запись в базу данных Sqlite3 (см. arduino.php). Файл readbd.php нужен для первоначального занесения данных температуры в табличку. Красивое оформление кнопок было позаимствовано из статьи «3D кнопки с помощью CSS3».

index.php:

<?php
include("readbd.php");
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ru">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<head>
<link href="style.css" rel="stylesheet" media="all" />
<title>Температура в доме и на улице</title>
<link href="flot/examples/layout.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="jquery.js"></script>
</head>
<body class="body">
<br>
<div class="container">
<header>
   <h1><span>Температура</span></h1>           
</header>
</div>
<div class="ul1" > 
<br>
<table  width="60px" border="0"><tr>
<td><a href="#" id="led6" class="button black" onMouseDown="command(1);">Улица</a></td>
<td><a href="#" id="led6" class="button yellow" onMouseDown="command(2);">Дом</a></td>
</tr><tr>
<td class="c1"><div id="content1" ><?php echo ''.$temp1.""; ?></div></td>
<td class="c1"><div id="content2" ><?php echo ''.$temp2.""; ?></div></td>
</tr>
</table>
</div>
<br>
<script>
function command(id)
 {
     $.ajax({
             type:'POST',
             url:'arduino.php',
             data:{msg:id},
			 cache: false,
			 success: function(html){
			$("#content"+id).html(html);
			}
        })
}		 
</script>

</center>
</body>
</html>

arduino.php:

<?php
include "php_serial.class.php";
$serial = new phpSerial;
//Задаем путь к Arduino (У вас может быть совсем по другому)
$serial->deviceSet("/../../../../dev/ttyACM0");
//Это стандарт
$serial->confBaudRate(9600);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");
$serial->deviceOpen();
//Отправляем команду
$serial->sendMessage(chr($_POST['msg']));
//Читаем ответ Arduino
$read = $serial->readPort();
//Зыкрываем соединение
$serial->deviceClose();
try {   
       // Создаем или открываем созданную ранее базу данных  
      $db = new PDO('sqlite:'.dirname(__FILE__).DIRECTORY_SEPARATOR.'arduino.db');  
       // Создаем таблицу temp, если не найдена   
	  $db->exec('CREATE TABLE IF NOT EXISTS temp (  
                idtemp INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,  
                temperature VARCHAR(255)  NOT NULL,  
                datetime VARCHAR(255)  NOT NULL     
      )'); 
	   $db->exec('CREATE TABLE IF NOT EXISTS temp2 (  
                idtemp INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,  
                temperature VARCHAR(255)  NOT NULL,  
                datetime VARCHAR(255)  NOT NULL     
      )');    
	  //определяем текущцю дату и время 
      $d=date("d.m.y, G:i:s");
	  //Обновляем 
      //$db->exec('UPDATE temp SET temperature="'.$read.'", datetime="'.$d.'" WHERE idtemp='.$_POST['msg'].'');
	  
	  if ($_POST['msg']==1){
	  //Добавляем новую строку в БД
	  $db->exec('INSERT INTO temp (temperature, datetime) VALUES ("'.$read.'","'.$d.'" )');
	  //Получаем последнюю запись
      $st = $db->query('SELECT MAX(idtemp) as id, temperature FROM temp');
	  $results = $st->fetchAll();  
	  foreach ($results as $row) {  
        echo ''.$row['temperature']."\n";	
	    }
	  }
	   if ($_POST['msg']==2){
	  $db->exec('INSERT INTO temp2 (temperature, datetime) VALUES ("'.$read.'","'.$d.'" )');
      $st = $db->query('SELECT MAX(idtemp) as id, temperature as tempe FROM temp2');
	  $results = $st->fetchAll();  
	    foreach ($results as $row) {  
         echo ''.$row['tempe']."\n";	
        }
      }
} catch (PDOException $e) {  
 die($e->getMessage());  
}  
?>

Проблемы с которыми я столкнулся:

  1. Arduino в маршрутизаторе определялся как /dev/ttyACM0, а не /dev/ttyUSB0.
  2. После того как php был написан, постоянно выскакивала ошибка — No stty availible, unable to run.», E_USER_ERROR.
  3. При отсылке команд Arduino постоянно перезагружался.

Решения:

  1. Так как Веб сервер у меня установлен на флешке в своем php скрипте нужно правильно указать путь к устройству. Так же установите права 777 на /dev/ttyACM0 или /dev/ttyUSB0 (зависит от Arduino).
    deviceSet(/../../../../dev/ttyACM0);
  2. В php_serial.class.php убрал кусок кода:
    if($this->_exec("stty --version") === 0)
    {
    register_shutdown_function(array($this, "deviceClose"));
    }
    else
    {
    trigger_error("No stty availible, unable to run.", E_USER_ERROR);
    }
    
  3. После заливки скетча в Arduino между пинами GND и Reset ставим конденсатор на 220 мФ. Это предотвращает перезагрузку во время приема команд.

Пару фоток


Скачать все необходимые файлы

  Arduino_Zyxel_ds18b20.zip (95,9 KiB, 2 439 загрузок)


P.S.
Это лишь небольшой пример того как можно использовать arduino в связке с роутером. Можно написать более серьезные вещи. Управлять любыми приборами в своем доме при помощи веб-интерфейса и Arduino.

Запись опубликована в рубрике Arduino с метками , . Добавьте в закладки постоянную ссылку.

16 комментариев: Zyxel Keenetic 4G, arduino и датчики температуры ds18b20

  1. Аметхан говорит:

    Здравствуйте. Прочитав о вашем изобретении, я понял, насколько я дремучий ;). А теперь по существу: можно использовать роутеры TP-Link, D-Link, Asus и др. с USB-портом?

Комментарии запрещены.