Cubietruck & Raspberry Pi & Arduino

в 22:55, , рубрики: arduino, cubietruck, Raspberry Pi, умный дом, метки: , ,

Доброе время суток!

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

Оговорюсь сразу: этот пост не how-to. Этот пост не претендует на роль универсального решения. И этот пост не ограничен задачей, о которой он рассказывает.

Предисловие.

Любая система умного дома, состоит из нескольких компонентов. И если в умах среднестатистического обывателя, умный дом ассоциируется с набором датчиков, дисплеем, и изредка системами исполнения (например жалюзи), то у меня в уме умный дом больше ассоциируется с Джарвисом (персонаж марвелловского «Железного Человека»).
Ведь задача умного дома вовсе не состоит в выводе состояния датчиков температур, или включении света по хлопку. Она состоит в уникальном комбинировании различных данных, а затем принятии самостоятельного решения на основе этих данных, включая данные, введенные пользователем в процессе работы системы.
Эти задачи как правило решаются центральным компонентом системы, т.е. ее мозгом. Хотя собираются с различных точек дома.

Cubietruck & Raspberry Pi & Arduino
Интересно?
Добро пожаловать под хабракат…

Будет большой ошибкой стандартизировать топологию такой системы. И в самом деле, если например, задача системы умного дома, просто включать свет при движении в коридоре — будет глупо сначала передавать данные с датчика движения в центральную систему, чтобы центральная система осознала что это движение, и передала команду в узел исполнения — релейный блок в коридоре. Такая система должна работать в пределах коридора.
Но если нужно соединить несколько разношерстных компонентов, тогда начинается самое веселое.

Что мы будем делать?

Моргать светодиодом мы не будем. Мы будем моргать LCD-дисплеем.
Но и моргать мы им будем не просто так, а только по определенному действию. Например открытому пламени.

Что у нас есть ?

— У нас есть Cubietruck, знакомый нам с моего предыдущего поста habrahabr.ru/post/216211/;
— Raspberry Pi B512;
— Клон Arduino Nano;
— Дисплейный блок Nokia 5110, 84x48 пикселей, и белой подсветкой;
— Датчик открытого пламени Flame Sensor V.2;
— А еще у нас есть коробка спичек и свеча.

Поехали !

До сборки системы я осознал, что ни на Cubietruck, ни на Raspberry Pi нету аналоговых входов. Поэтому пришлось задействовать Ардуину. Это оказалось для меня самое простое и доступное решение.
К Ардуине я подключил датчик открытого пламени, он занял всего три провода.

Ардуинку к Кубику подключил недолго думая через USB-разъем. Гики скажут, что это не тру, что надо подключать через UART и прочее. И они окажутся правы. Как подключил я — делать не нужно! Тем более не нужно доверять свою жизнь или здоровье, четырехстам восьмидесяти мегабитам!

По-хорошему, дисплейный модуль можно было подключить тоже к Кубику, но мне хотелось усложнить процесс какой-нибудь железячкой.
Поэтому я добавил в систему Raspberry Pi.

На фото, эти устройства лежат рядом, но на самом деле Малинка с дисплеем — независима от остальных, а рядом лежат для удобства съемки.
К сожалению, у меня в доме wi-fi, сетевого кабеля нет, и отдельного wi-fi модуля для Малинки тоже нет. Пришлось обойтись костылем на андроиде в режиме модема.

Итак, будет происходить следующее:
Ардуина будет читать значение датчика открытой температуры. Эти значения (0-1024) она будет посылать в серийный порт, который подключен к Cubietruck. Малинка, в свою очередь, видя значение выше порогового — засветит дисплей.

Матчасть.

Cubietruck & Raspberry Pi & Arduino

Arduino-блок

Arduino Nano использует простой скетч, опрашивающий аналоговый пин, и выводящий значение пина в последовательный порт. Датчик имеет три входа, 5В, Ground, и OUT, который я подключил к пину А0. Не буду углубляться в установку Arduino IDE, она стандартна с убунтовского репа.
Скетч:

const int analogInPin = A0;
void setup() {
  Serial.begin(9600); 
}
void loop() {
  sensorValue = analogRead(analogInPin);            
  Serial.println(sensorValue);      
  delay(10);
}

Cubietruck-блок

Когда Ардуинка вставляется в USB Кубика, Линукс создает устройство /dev/ttyUSB0, которое можно cat'нуть, согласно традициям Линукса, и получить текущее значение с порта.

Для удобства я написал простейший bash-скрипт, постоянно считывающий значение порта, и перезаписывающий последнее значение в файл:

while true; do
        read -n 8 LINE < /dev/ttyUSB0
echo $LINE
        echo $LINE > thermo
done

Отдельно стоит заострить внимание на способе считывания. Я выбрал read, потому что ему можно указать количество символов для считывания.
Если этого не сделать, а сделать через cat — иногда строка, приходящая из последовательного порта, будет неполной, потому что Ардуинка не шлет биты начала и окончания передачи, а просто отправляет в порт то, что видит на пине. Другими словами, устройства не синхронизируются между собой.

Запустив скрипт, и помахав горящей спичкой — мы можем видеть как изменяются наши данные.

root@Cubian:/home/cubie# bash scanUSB.sh 

233
254
239
225
253

Подводный камень.
Датчик открытого пламени — громко сказано. Сие поделие воспринимает пламя, не как тепло, а скорее как свет со спектром короче желтого включительно.
Поэтому, когда в комнате включается свет (лампа накаливания), в любой части комнаты, датчик начинает «фонить» и выдавать около 200 единиц. Если закрыть ладошкой — меньше.
А вот голубое пламя газовой плиты — он не видит. В общем неправильный это датчик открытого пламени.

Raspberry Pi-блок

LCD экран к Raspberry PI подключается по интерфейсу SPI, что не может не удручать. Черно-белый дисплей, 84х48, без всяких кадровых разверток и прочих вкусностей, занимает 8 пинов. Это тоже неправильно.

Схема подключения дисплея Nokia 5110 к Raspberry Pi:

RST: пин 18
CE: пин 24
DC: пин 16
DIN: пин 19
CLK: пин 23
VCC: пин 1 (3.3 В)
LIGHT: пин 12 (это нужно для регулировки яркости, если мы не хотим — можно просто подключить к 3.3 В)
GND: корпус

Ставим WiringPi — либу для работы с GPIO:

git clone git://git.drogon.net/wiringPi
cd wiringPi
./build

Ставим питоновые модули для полноты питона:
sudo apt-get install python-dev python-imaging python-imaging-tk python-pip
sudo pip install wiringpi wiringpi2

Если не был включен ранее, нужно включить модуль spidev:
(Комментим строку blacklist spi-bcm2708)

vi /etc/modprobe.d/raspi-blacklist.conf

Ставим питоновую примочку для работы с SPI:

sudo pip install spidev

Ставим фронтенд для работы с SPI на питоне:

git clone https://github.com/XavierBerger/pcd8544.git
cd pcd8544
./setup.py clean build
sudo ./setup.py install

Теперь ради интереса, мы можем зайти в примеры, и что-нибудь протестировать:

cd examples
sudo ./pi_logo.py

На этом настройка дисплея завершена.

Raspberry Pi-Cubietruck-блок

Есть интересная приблуда, sshfs, она лежит в стандартных репах, и позволяет монтировать к себе любой удаленный каталог, по протоколу ssh.
Этот метод «расшаренного диска», я и решил использовать.
Запускается sshfs проще простого:

mkdir test
sshfs cubie@192.168.1.39:/home/cubie test

Отныне после ввода правильного пароля, у нас на Малинке в папке test будет содержимое Кубикового хомяка.

Все верно. Здесь мы можем обнаружить наш файл «thermo», создающийся скриптом на Кубике.
Здесь же мы создаем простейший скрипт на любом языке, задача которого будет считывать значение из файла thermo, и запускать один из examples, которые мы компилировали 10 строчек назад. Я выбрал PHP:

<?php
$c=file_get_contents("thermo");
if ($c>250) { system('python /home/pi/pcd8544/examples/pi_logo.py');unlink('thermo');}
?>

Запустив его в бесконечном цикле, мы добьемся такого результата, как у меня на видео:

while [ 1 = 1];do php5 test.php;done

Теперь работаю над внедрением базы данных (начну с MySQL) в качестве прослойки, куда датчики могут записывать параметры, другие устройства читать, а релейные устройства исполнять команды, внесенные туда «мозгом» умного дома.

Охотно буду делиться наработками.
Cubietruck & Raspberry Pi & Arduino

Автор: ntfs1984

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js