Paranoid App – фреймворк мониторинга дома на Arduino и Raspberry Pi

Добавлено 19 июня 2017 в 00:00

Итак, у вас есть Raspberry Pi и Arduino, и вы хотите разработать систему мониторинга и управления вашим домом. Если я вас правильно понял, то, прочитав эту статью, вы сможете сделать именно то, что хотите.

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

Введение

Прежде всего, почему вы хотите использовать Arduino и Raspberry Pi вместе? Raspberry Pi обладает выводами ввода/вывода общего назначения (GPIO), которые отлично подходят для простых двоичных задач (включить или выключить) и для чтения данных с дешевого датчика температуры. Этого достаточно? Нет! Для более сложных задач вы захотите использовать микроконтроллер для выполнения тяжелой работы. Он имеет аналого-цифровой преобразователь (АЦП, ADC) с несколькими каналами, ШИМ (широтно-импульсно-модулированные, PWM) каналы и очень точную синхронизацию.

Например, если вы захотите измерить потребление электроэнергии в своем доме, вам понадобится трансформатор тока и простая схема, которая выдаст напряжение, которое вы измерите с помощью АЦП. Если вы хотите вывести что-то между 1 и 0, скажем, уменьшить яркость светодиода, вы будете использовать ШИМ выходы. Наконец, вам нужен микроконтроллер, если необходимо что-то с очень точной синхронизацией, например, PID система, мультиплексирование светодиодной матрицы или управление шаговым двигателем. В нашем случае в качестве микроконтроллера мы будем использовать Arduino Uno.

Перечень компронентов и схема

В данном проекте нам понадобится следующее:

  • Arduino Uno (хотя, если хотите, то можете использовать другие продукты Arduino);
  • Raspberry Pi (я использовал Pi Zero, но будет работать и любой другой);
  • источник питания для Rasperry Pi;
  • SD карта с установленной операционной системой Raspbian (Raspbian Lite тоже подойдет);
  • датчики и другие модули для Arduino (тут всё зависит от того, что вы хотите реализовать);
  • базовые знания Arduino IDE, Raspbian, C/C++, HTML и javascript (не пугайтесь; если вы уже знаете C/C++, то этого будет достаточно).

Схема не очень сложна и зависит от того, что вы хотите реализовать. В данном примере я использовал датчик температуры и влажности воздуха и светодиод.

Схема блока управления мониторинга дома
Схема блока управления мониторинга дома

Код Arduino

Для простоты я покажу вам здесь, только как считывать температуру и влажность воздуха с датчика DHT11 и как дистанционно мигать светодиодом. Для вашего реального проекта вам понадобится что-то более сложное, что можно сделать только с Raspberry Pi. Если вы хотите начать с простого, то вот схема:

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

Начнем с основ. Данные передаются по последовательному порту со скоростью передачи 9600 бит/с. В основной функции мы читаем последовательный порт и проверяем, что пришло. Если мы приняли строку "thl", это означает, что нам нужно отправить через последовательный порт данные с датчиков. Чтобы эта функция работала правильно, мы используем цикл while и отправляем данные снова и снова, пока не получим "ok", чтобы узнать, что данные достигли сервера. Если мы получим строку "led", то просто начнем мигать светодиодом. Здесь вы можете добавить любую функцию и строку, которую захотите, – просто не забудьте использовать "thl" для отправки данных.

Что вам нужно знать, так это то, что мы отправляем данные в форме JSON (JavaScript Object Notation). JSON – это открытый формат для передачи объектов данных. Мы используем его, потому что можем легко использовать эти данные в main.html с помощью javascript. Чтобы использовать его, нам понадобится библиотека под названием ArduinoJson, которую вы можете найти в архиве, ссылка на который будет в конце статьи. Функция "send_data()" делает то, что подразумевает ее название: она передает данные через последовательный порт в формате JSON. Чтобы добавить данные, вам просто нужно добавить строку внутри этой функции, которая выглядит так:

root["name_of_data"] = function_that_return_data();

где "function_that_return_data()" выглядит так:

int function_that_return_data()
{
  int data;
  // вставить код, которые считывает данные с датчика и сохраняет их в переменной 'data'
  return (data);
}

Вот и всё, что касается Arduino. Ниже вы можете увидеть точный код, который написан для этого конкретного случая, с датчиком DHT11 и светодиодом.

#include "ArduinoJson.h"
#include "dht.h"

dht DHT; // задать имя вашему датчику DHT

#define DHT11_PIN A0 // вывод для данных DHT11
#define LED_PIN A1   // вывод для светодиода

void send_data();
int get_temperature();
int get_humidity();

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  String str;
  str = Serial.readString(); // прочитать последовательный порт
  str.toLowerCase();         // конвертировать в нижний регистр
  if (str == "thl") 
  {
    do
    {
      str = Serial.readString(); // прочитать последовательный порт снова
      send_data();               // вызвать функцию отправки данных
    } while (str != "ok");       // продолжать отправлять данных, пока не получим "ok"
  }
  if (str == "led") 
  {
    digitalWrite(LED_PIN, HIGH);   // включить светодиод (HIGH это уровень напряжения)
    delay(1000);                   // подождать секунду
    digitalWrite(LED_PIN, LOW);    // выключить светодиод, опустив напряжение до уровня LOW
  }

}
void  send_data()
{
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["temp"] = get_temperature();
  root["humidity"] = get_humidity();
  root.printTo(Serial);
  Serial.println();
}

int get_temperature() // функция, которая возвращает температуру как целое число
{
  int temperature;

  DHT.read11(DHT11_PIN);
  temperature = DHT.temperature;
  return (temperature);
}

int get_humidity() // функция, которая возвращает влажность как целое число
{
  int humidity;

  DHT.read11(DHT11_PIN);
  humidity = DHT.humidity;
  return (humidity);
}

Установка веб-сервера на Raspberry Pi

Мы будем использовать Raspberry Pi в качестве веб-сервера с nginx. Рассмотрим как установить его и другие компоненты, которые нам понадобятся, например, PHP.

Давайте разъясним некоторые основы. Прежде всего, вам нужны установленная операционная система Raspbian на ваш Raspberry Pi и сетевое подключение. Теперь вы можете подключить к плате клавиатуру и монитор и открыть терминал, или сделать, как я, и делать всё через SSH. Какой бы метод вы ни использовали, помните, что все команды должны выполняться как root; в противном случае вы получите ошибку разрешения. Это делается путем написания "sudo" перед командой. Теперь, когда всё сказано, начнем.

Сначала давайте обновим репозиторий и пакеты. Если вы не знакомы с Linux, это означает обновление места, из которого устанавливаются пакеты (приложения), а затем обновление их самих.

sudo apt-get update
sudo apt-get upgrade

Мы хотим установить NGINX, PHP и git (это необязательно, но сделает вашу жизнь проще). На вопрос отвечаем "y" и жмем Enter.

sudo apt-get install nginx php5-fpm git

Теперь нам необходимо изменить каталог NGINX по умолчанию и заставить его работать с PHP.

cd /etc/nginx
sudo nano sites-enabled/default

Вам необходимо, чтобы этот файл выглядел так:

server {
	listen 80; ## listen for ipv4; this line is default and implied
	listen [::]:80 default_server ipv6only=on; ## listen for ipv6
	root /var/www;
	index index.html index.php;
	# Make site accessible from http://localhost/
	server_name _;
	location / {
        	index index.html index.php;
		# First attempt to serve request as file, then as 
		# directory, then fall back to the CMS.
		try_files $uri $uri/index.html;  
	}
	
	location /doc/ {
		alias /usr/share/doc/;
		autoindex on;
		allow 127.0.0.1;
		allow ::1;
		deny all;
	}
	location ~ \.php$ {
		fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_index index.php;
                include fastcgi.conf;
        }
}  

Теперь перезапустим NGINX.

sudo service nginx restart

Чтобы проверить, что всё работате, создайте тестовую страницу PHP.

cd /var/www
sudo nano test.php

И добавьте в файл test.php следующее.

<?php
phpinfo();
?>

Теперь откройте в браузере адрес ip_адрес_raspberry_pi/test.php (например, 192.168.0.2/test.php).

Если вы увидели страницу с информацией о PHP, как та, что показана ниже, то всё работает, и можно переходить к следующему шагу.

Тестовая страница
Тестовая страница

Если что-то не работает, то прочитайте этот раздел статьи снова и перепроверьте, может быть, вы где-то ошиблись и сделали что-то не так.

Последний шаг – это ввести следующую команду, которая открывает доступ к последовательному порту пользователю www-data, который используется NGINX.

sudo usermod -a -G dialout www-data

После этого выполните еще один перезапуск и сделайте перерыв. Вы заслужили это.

Файлы веб-сайта

Подождите, мы почти закончили. Вам просто нужно загрузить файлы на свой Raspberry Pi и отредактировать их под свои нужды.

Вы можете вручную скачать эти файлы и поместить их в каталог /var/www или можете выполнить эту команду и автоматически скачать их с github:

cd /var/www 
sudo git clone https://github.com/alexonaci/Paranoid/tree/AAC

Теперь, когда у нас есть файлы, давайте быстро их просмотрим. Просто чтобы вы знали, мы используем bootstrap для верстки нашего сайта, чтобы он был совместим с мобильными устройствами и хорошо выглядел.

  • каталог /img: содержит изображения иконок и фона для начальной страницы;
  • ArduinoCode.ino: файл скетча для Arduino;
  • PhpSerial.php: PHP библиотека, позволяющая нам общаться с Arduino через последовательный порт, используя PHP;
  • Style.css: CSS для страницы;
  • Main.html: самая главная страница, которая содержит javascript, кнопки и визуальные данные;
  • Relay.php: файл, который инициирует соединение с Arduino.

Вам нужно беспокоиться только о странице main.html; всё остальное оставим как есть. Конечно, если хотите, вы можете настроить их по своему вкусу – это ведь ваш проект в конце концов.

Посмотрим, как добавлять элементы. Чтобы добавить новую кнопку, просто добавьте эту строку:

<div class="col-sm-2" class="jobs">
  <h2 class="header-default" class="jobs-header"><img width=100 src="img/Thumbnail_Image"></h2>
  <button type="button" id="Name_action" class="btn btn-danger">
    <span class="glyphicon glyphicon-off"></span>
    On/Off
  </button>    
</div>

Thumbnail_Image – это путь к изображению, которое вы хотите использовать в качестве иконки (не забудьте поместить его в каталог /img). Name_action – это название того, что вы хотите выбрать для своей кнопки. Здесь вы можете проверить типы кнопок, которые можете использовать.

Перейдите в конец файла, где вы можете увидеть строку "$("#led-button").click(blinkLED);", и добавьте ниже следующее:

$("#Name_action").click(Function_Name);

Теперь добавьте выше функцию, связанную с новой кнопкой:

function Function_Name (){
   $.get(url + "Parameter")	
}

"Parameter" – это строка, которая будет отправлена на вашу плату Arduino через последовательный порт при нажатии кнопки. Она должна быть связана с функцией в коде скетча. Мы говорили об этом в разделе «Код Arduino».

Чтобы добавить на экран новый элемент, который отобразит значение, которое посылает Arduino, например, данные датчика, добавьте этот тип элемента:

<div class="col-sm-2" class="jobs"//>
  <h2 class="header-default" class="jobs-header"><img width=100 src="img/Thumbnail_image"></h2>
  <h3>Display_data: </h3>
  <div id="DataID"></div>
</div>

где "Display_data" – это название, которое будет отображаться перед данными, например, "Температура:"; а DataID – это идентификатор.

Помните, когда я сказал, что мы будем получать данные в формате JSON? Здесь он пригодится. Найдите функцию “getLuminosityTemperatureHumidity()” и просто добавьте в ее конец:

$("#DataID").html(parsedJSON.name_of_data);

Где "name_of_data" – это строка, которую вы выбрали для данных в разделе «Код Arduino».

Есть также еще одна функция, которая будет вызывать данную функцию каждые 10 секунд.

setInterval(getLuminosityTemperatureHumidity,10000);

Если хотите, то можете изменить время.

Всё, что осталось, объяснить, как работает скрипт relay.php. Он открывается каждый раз, когда вызывается функция "getLuminosityTemperatureHumidity()". Для работы он использует библиотеку PhpSerial. Первые 8 строк, начинающиеся с "$serial->", устанавливают последовательное соединение с Arduino.

ВНИМАНИЕ! Каждый раз, когда этот скрипт выполняется, Arduino перезапускается. Если вы этого не хотите, то просто подключите конденсатор 10 мкФ отрицательным выводом на вывод GND, а положительным выводом на вывод RESET.

Продолжим. Строка "sleep(2);" необходима, потому что Arduino не отвечает в первые моменты, после открытия последовательного соединения. После этого мы отправляем параметр, который получили через метод GET, "$_GET["command"]", на Arduino; и если это была команда "thl", считываем данные, приходящие от микроконтроллера, отправляем "ok" и возвращаем данные. Вот и всё.

Вот так ваш проект должен выглядеть после выполнения этих шагов:

Внешний вид тестового приложения на Paranoid App
Внешний вид тестового приложения на Paranoid App
Внешний вид тестового приложения на Paranoid App
Внешний вид тестового приложения на Paranoid App

Отладка

Если у вас возникли проблемы, например, если вы не получили данные, самое простое место для начала отладки – это ваш браузер. Вам необходимо использовать Chrome для данных инструкций: просто нажмите F12, перейдите на вкладку Network, кликните на ней, нажмите F5, чтобы обновить страницу, и кликните на "relay.php?command=thl". Если всё будет работать, данные должны будут появиться как на скриншоте ниже:

Отладка Paranoid App в браузере
Отладка Paranoid App в браузере

Наслаждайтесь вашей системой мониторинга дома. Оставляйте комментарии.

Теги

ArduinoRaspberry PiВеб-серверУмный дом

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.