Cubietruck. Практические применения

в 10:54, , рубрики: cubietruck, Гаджеты. Устройства для гиков, датчик движения, умный дом, Электроника для начинающих, метки: , ,

Здравствуй!

4 месяца и два дня прошло с момента первой моей публикации «Cubietruck. 15 поводов приобрести», которая к сожалению зависла в песочнице, хотя и периодически всплывает при поиске в Google.
Очень странно, что на Хабре еще нет новых статей по запросу «Cubietruck». Может быть народ смущается покупать эту железку, не зная ее возможностей?
Сегодня мы этот пробел исправим.
Мы даже перешагнем через стереотип первого классического топика о возможностях железок, не будем моргать светодиодом в классическом понимании, а сразу сделаем чего-нибудь интересного. Например интерактивный выключатель света. А заодно и научимся работать с инфракрасным портом на простом английском языке.

Cubietruck. Практические применения

Какой у нас план?

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

Что нам для этого нужно?

— Сложных систем обнаружения на основе OpenCV или ViBe мы пока проектировать не будем, а вместо этого используем старый дедовский способ — движение наших тел.
— Для резервного управления, пригодилась бы консольпланшет, но их таскать с собой очень неудобно, а ложиться спать, перед этим отмонтировав что-нибудь — это не тру. Поэтому нам нужен пульт ДУ. Забегая наперед, скажу что пульт подойдет любой, от любого устройства. Лишь бы был рабочим, и с ИК.
— Нам нужно целевое устройство, которое мы будем мучать. Пусть это будет какая-нибудь лампа. Или даже светодиод, если мы боимся лезть в 220 В.
— А еще нам нужны коммутаторы, для подачи питания на эти самые реле.
— И конечно же, нам нужен Cubietruck с адекватной ОС на нем. Под адекватной ОС я имею в виду систему, которая скомпилирована со всеми драйверами, устройствами, и почти не требует обработки напильником.

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

— У нас есть PIR датчик движения. Выглядит он вот так.
image

Выдает на выходе ноль, если движения нет, и единицу на протяжении нескольких секунд, если движение есть. Под единицей подразумевается 3.3 вольта, что очень важно для нас, ибо Кубик не толерантен к 5В.

— У нас есть пульт ДУ от DLP проектора Viewsonic. Не очень большой, и не очень маленький. Нам сойдет.
Cubietruck. Практические применения

— У нас есть торшер с УФ-лампой, разукрашенный заботливой супругой, у которого с вилки торчат два проводка, позволяя его включать и выключать по желанию. Почему фотоаппарат делает зеленую фотографию — я пока не знаю.
Cubietruck. Практические применения

— У нас есть двухрелейный блок, который я покупал к Ардуине (не думайте обо мне ничего плохого). Он принимает на свои два входа единицу или ноль, и в зависимости от этого, включает или выключает реле. Реле кстати 250В/10A, что есть хорошо.
Cubietruck. Практические применения

— И наконец у нас есть Cubietruck.

Поехали !

Не буду останавливаться детально на методах установки ОС на Кубик, вкратце скажу что это Cubian (Дебиан), скачанный с официального сайта (http://cubian.org/downloads/), с небольшими костылями, а именно:
Модуль bcmdhd, который необходим для работы wifi, не запускается, если его прописать в /etc/modules, поэтому его пришлось прописать как modprobe bcmdhd в /etc/rc.local;
В /etc/modules пришлось добавить модуль sunxi-ir, это модуль для работы инфракрасного порта;
Wicd, который стоит там по дефолту, в упор не видел наличие вайфая, даже когда я вручную его сконфигурил и сидел с кубика в интернете. Пришлось в том же /etc/rc.local прописывать вручную поиск точки доступа, подключение к ней, и получение IP-адреса.
В общем небольшие костыли.

Теперь нам нужно проверить базовые способности нашей системы, при помощи консоли, а лучше через SSH (стандартный логин ОС — cubie, pw: cubie). Из под рута:

root@Cubian:/home/cubie# lsmod
Module                  Size  Used by
bcmdhd                541066  0 
cpufreq_conservative     5720  0 
cpufreq_powersave       1242  0 
cpufreq_userspace       3532  0 
cpufreq_fantasy         3855  0 
disp_ump                 854  0 
mali_drm                2638  1 
drm                   213650  2 mali_drm
mali                  113847  0 
ump                    57087  4 mali,disp_ump
gpio_sunxi              8593  59 
sunxi_ir                4037  0 

Для наших целей должны быть обязательно загружены два последних модуля.
Они у нас загружены, и мы готовы двигаться дальше…

cd /dev/input
root@Cubian:/dev/input# ls -l
total 0
drwxr-xr-x 2 root root     60 Mar 16 21:05 by-path
crw------- 1 root root 13, 64 Mar 16 21:05 event0
crw------- 1 root root 13, 65 Mar 16 21:05 event1
crw------- 1 root root 13, 63 Mar 16 21:05 mice

Это список наших устройств ввода. Нас интересуют файлы event*, это устройства-файлы событий, которые происходят при действии устройства ввода. Кто-то из них — наш инфракрасный порт. Это легко проверить с помощью
root@Cubian:/dev/input# cat event1 | hexdump

Теперь если мы нажмем что-нибудь на пульте ДУ, то должны получить примерно следующее:

0000000 28b2 5326 2723 000e 0001 0085 0001 0000
0000010 28b2 5326 272d 000e 0000 0000 0000 0000
где 5326 — код нашего пульта, а 0085 — код нажатой клавиши.

Пульт работает, можно разбираться с GPIO.

Система портов ввода-вывода в этих устройствах для меня непонятна, и пришлось вечерок покурить спеки к Кубику и процессору А20, чтобы понять что к чему.

Итак, приблизительный алгоритм моргания светодиодом следующий:
— активируем необходимый пин. Они ведь многофункциональные. Делается это при помощи например echo 8 > /sys/class/gpio/export
— смотрим, активировался ли этот пин в sysfs…

root@Cubian:/sys/class/gpio# ls /sys/class/gpio | grep gpio8
gpio8_pg2

— идем в спек (http://linux-sunxi.org/Cubietruck#Expansion_Ports), ищем, на какой реальной ноге находится наш PG2. Он на ноге 5, разъема CN9. Это разъем, находящийся возле USB-порта. В дальнейшем, я постараюсь использовать нумерацию ног с реальной платы, а если кому-то интересно, на этом ресурсе можно прочитать что на этой ноге находится.

— даем ОС понять, что пин будет работать на вывод, echo out > /sys/class/gpio/gpio8_pg2/direction
— подключаем что-нибудь тестер на ногу 5.
Cubietruck. Практические применения

— посылаем вывод на эту ногу echo 1 > /sys/class/gpio/gpio8_pg2/value
Напряжение изменилось. Работает. Можно разворачиваться.
Cubietruck. Практические применения

Методом проб и ошибок, я написал тестовый скрипт, который инициализирует все пины в GPIO, его нужно запускать при загрузке, или вручную, до начала работы с пинами.

#!/bin/sh
d=`date`
for i in `seq 1 11`;do
echo $i > /sys/class/gpio/export
echo "GPIO # $i initialized"
sleep 0.5
done

for i in `seq 16 24`;do
echo $i > /sys/class/gpio/export
echo "GPIO # $i initialized"
sleep 0.5
done

for i in `seq 28 61`;do
echo $i > /sys/class/gpio/export
echo "GPIO # $i initialized"
sleep 0.5
done

for i in `seq 64 67`;do
echo $i > /sys/class/gpio/export
echo "GPIO # $i initialized"
sleep 0.5
done

c=`ls /sys/class/gpio`
echo "[$d]" >> /var/log/gpio.log
echo "$c" >> /var/log/gpio.log
echo "[/$d]" >> /var/log/gpio.log
sleep 1

Этот скрипт я запускаю из /etc/rc.local, для удобства сделал вывод в лог.
Вы сразу же заметите, что пины назначаются странным образом, некоторые пропускаются. Именно так, при попытке инициализировать их, система зависает намертво. Причину точную не знаю, скорее всего на этих пинах что-то висит, wifi или даже mmc карта.

Вроде разобрались с инфракрасным портом, и GPIO. Настало время подключить реальные железки.
Модуль реле подключается стандартно, у него всего три выхода: +5В, земля, и сигнал. Землю я беру с одного из пинов UARTa, можно брать откуда угодно. Плюс 5В я беру с 29-го пина, разъема который находится ближе к LAN. Сигнальный провод мы будем подключать к пину 9, разъема куда мы уже подключали наш тестер (ближе к USB, напомню).
Чтобы не отвлекаться на это потом, сразу же подключим наш датчик движения. У него тоже три выхода, +5В, земля и сигнал. Питание подключаем туда же, куда и релейное. А сигнал подключим к 7-му пину, рядом с девятым.
Конечная конструкция, вид спереди:
Cubietruck. Практические применения

Теперь нам надо подключить пульт.
Первое что мне (и наверное вам) пришло на ум — lirc. Приблуда для управления инфракрасным портом. Не подходит. Сложно. Почему — смогу написать в комментах, если повезет. Решение мы возьмем простое, но самописное.
Мы будем использовать python, напару с его волшебной библиотекой evdev, для работы с линуксовыми /dev-устройствами.
Ставим вначале pip (питоновский внутренний установщик, кто не в курсе): apt-get install python-dev
Уже с pip ставим библиотеку evdev: pip install evdev
Вуаля, готово.

Не буду вдаваться в скучные подробности, сразу выложу скрипт и объясню что он делает и как работает. Назову его irda.py.

import string

from evdev import InputDevice
from select import select

dev = InputDevice('/dev/input/event1')

while True:
   r,w,x = select([dev], [], [])
   for event in dev.read():
        if event.type==1 and event.value==1:
                open('/dev/irda', 'w').write(str(event.code))

Этот скрипт считывает ивент устройства ввода (мы выше определили, что у меня это /dev/input/event1) и записывает код ивента в файл /dev/irda. Для удобства.
Не знаю как так совпало, но этот скрипт при нажатии разных клавиш пульта, возвращает разные коды. Это неправильно. По-хорошему, нужно уметь различать код кнопки и код пульта, но это будет позже, наша главная цель — Кубик.

У нас получился файл /dev/irda, в котором всегда хранится код последней нажатой клавиши.
Запускаем этот скрипт, сворачиваем в background по CTRL+Z, и тестируем

root@Cubian:/home/cubie# cat /dev/irda
132

Теперь у нас есть мини-демон, который отслеживает нажатия с пульта, и записывает его в /dev/irda. И ниже мы узнаем, зачем нужен был этот костыль.

Обрабатывать события от пульта, мы будем на самом простом и понятном всем языке — английском bash. Скрипт irda.sh.

#!/bin/bash
echo out > /sys/class/gpio/gpio4_pg6/direction

while [ 1=1 ];do
if [ -e /dev/irda ];then
code=`cat /dev/irda`
rm /dev/irda

if [[ "$code" = "132" ]];then
echo 1 > /sys/class/gpio/gpio4_pg6/value
fi

if [[ "$code" = "135" ]];then
echo 0 > /sys/class/gpio/gpio4_pg6/value
fi

if [[ "$code" = "101" ]];then
c=`cat /dev/movement`
 echo out > /sys/class/gpio/gpio67_ph7/direction
 if [[ $c = "1" ]];then
 echo 0 > /sys/class/gpio/gpio67_ph7/value
 echo 0 > /dev/movement
 else
 echo 1 > /sys/class/gpio/gpio67_ph7/value
 echo 1 > /dev/movement
 fi
fi
echo $code
                        fi
sleep 1
done

Я не программист, поэтому сорри за отступы, попробую пояснить, какой алгоритм я хотел сделать.
Раз в секунду, в бесконечном цикле, программа проверяет наличие файла /dev/irda.
Как только она его находит, она считывает значение нажатой клавиши, и тут же удаляет файл. Это самый простой способ избавиться от эффекта «залипания клавиши пульта», когда программа постоянно видит одно и то же значение.
Стоит отдельно упомянуть о костыле на Python. Он необходим (мне по крайней мере), потому что простой bash, при чтении event, ожидает ввод, и не сможет выполняться дальше, пока не будет событие нажатия.
Одной кнопкой пульта, реле включается. Другой кнопкой — выключается, это можно легко проследить в скрипте.
Последнее условие, с кодом «101» — нам понадобится позже, для выполнения всех пунктов плана. В общих чертах, этот блок оставляет в системе признак вклвыкл.

Теперь запустив этот скрипт, мы можем поклацать реле. Оно клацает. С пультом мы разобрались.

Нас ждет датчик движения, подключенный к пину №7.
Определять движение намного проще, чем нажатие на пульте. Для нетерпеливых, простой скрипт, а объяснение позже. Итак, move.sh

#!/bin/bash
echo in > /sys/class/gpio/gpio6_pg4/direction
echo out > /sys/class/gpio/gpio4_pg6/direction
echo 1 > /sys/class/gpio/gpio4_pg6/value

while [ 1=1 ];do
c=`cat /dev/movement`
if [[ "$c" = "1" ]];then
code=`cat /sys/class/gpio/gpio6_pg4/value`
if [[ "$code" = "1" ]];then
echo 0 > /sys/class/gpio/gpio4_pg6/value
sleep 20
echo 1 > /sys/class/gpio/gpio4_pg6/value
                       fi
                    fi
sleep 1
done

В этом скрипте мы так же само инициализируем пин 7 на ввод (вторая строчка), пин 9 на выход, и в бесконечном цикле ждем, пока в файле /sys/class/gpio/gpio6_pg4/value появится единица, затем на 20 секунд включаем реле, и отключаем. Отдельно стоит упомянуть, что проверка движения произойдет, только если в системе находится признак «вкл», о котором говорилось выше. Такой себе чит.

Собственно, на этом все.
Запустим все три файла:

python irda.py &
./irda.sh &
./move.sh

Подвигаемся перед датчиком движения. Работает.
Включенный во время движения свет, можно отключить нажатием кнопки на пульте, а выключенный — включить. Здесь есть очевидные минусы — скрипт обработки движения всегда выполняет действие последним. То есть если через 20 секунд после движения, свет выключился, мы его включили с пульта и опять выключили принудительно — свет включится во время движения.

Чтобы этого избежать, и был введен чит с /dev/movement. Третьей кнопкой на пульте, попросту отключается система определения движения. Управление с пульта остается рабочим, и детектор движения может быть активирован повторным нажатием кнопки. Для индикации режима, я добавил в скрипт irda.sh работу с /sys/class/gpio/gpio67_ph7. Это зеленый светодиод на Кубике, который будет светиться, если система реагирования на движение активна.

В лучших традициях Хабра, видеопруф.

Youtube:

VK:
vk.com/video21800443_168125094

P.S. Прошу прощения за отвратное качество фото и интерьера, эксперименты изначально не планировались для Хабра.

Автор: ntfs1984

Источник

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


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