Поиск:  
  
Мастерская
Фотогалерея
Поставщики
Книжная полка
Доска объявлений
Форумы
Контакты

  






Логин:

Пароль:



  ***

05.03.2005 - Как я кормлю своих кошек при помощи Линукса


РобоКлуб/Проекты/Разные/05.03.2005 - Как я кормлю своих кошек при помощи Линукса



Как я кормлю своих кошек при помощи Линукса

Позвольте вашему Linux управлять событиями реального мира с магической помощью недорогого микроконтроллера от компании Parallax, программы, написанной на Python и последовательного порта.

Позвольте вашему Linux управлять событиями реального мира с магической помощью недорогого микроконтроллера от компании Parallax, программы, написанной на Python и последовательного порта.

Кошки любят игрушки. Наши кошки, Коттон и Тьюлип, медленно, но верно захламили наш дом своими шариками для пинг-понга, меховыми мышами, колокольчиками, бантиками и всякими штуками для царапания. Наши кошки редко скучают. По выходным мы с женой ублажаем наших котят, расшвыривая их игрушки по всему дому, дразня их бантиками и звоня в колокольчики. Мы чешем им спины и кормим вкусностями. Они оба обожают это вонючее рыбное угощение: нам нужно только потрясти банку и они бросают все, чем бы ни занимались, и бегут на кухню. Их словарный запас теперь состоит из их имен и слов «хорошо» и «угощение».

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

Мы должны работать, но это же не означает, что наши кошки должны обходиться без маленькой вонючей рыбки, так ведь? Почему наша необходимость работать, вызванная экономическими причинами, должна негативно сказываться на их угощении? Разве это не наша обязанность создать для них устройство для кормления кошек на основе Linux и имеющее выход в Интернет?

С чего начнем? Три компонента являются ключом к нашему Интернет-устройству для кормления кошек на основе Linux: логическая схема системы, способ, чтобы общаться с устройством и само устройство, с которым мы будем общаться. В качестве языка программирования я выбрал Python, сообщающийся через последовательный порт с управляемой микроконтроллером кормилкой для кошек моего собственного изобретения. Давайте начнем снизу, с устройства, а потом постепенно будем подниматься вверх, до языка программирования.

Микроконтроллер BASIC Stamp

Впервые я узнал о микроконтроллере BASIC Stamp из статьи в журнале Slashdot, в которой три парня использовали BASIC Stamp для управления монтажным пистолетом. Они, кстати, сделали несколько отличных снимков гвоздей, прямо таки уничтожающих фрукты. Как я вскоре выяснил, микроконтроллеры находятся повсюду. Они представляют собой небольшие логические блоки в наших микроволновках и пультах дистанционного управления. Они крошечные, и зачастую их довольно сложно использовать.

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

Сам по себе STAMP фактически является PIC-микроконтроллером с некоторым количеством памяти. Обычно для программирования микроконтроллера вам нужен язык низкого уровня, такой как Assembly. От стандартного микроконтроллера BASIC STAMP отличает язык интерпретирования, который вы используете для работы. Parallax разработал расширенный вариант BASIC, называемый PBASIC, на котором легко и быстро можно создавать выразительные и полезные программы. В дополнение к Homework Board поставляется непаяный макет электронной схемы, который используется для быстрого монтирования схемы проекта.

У BASIC Stamp есть 16 линий ввода-вывода. Каждый штырек установлен или на +5В или на 0В, в зависимости от программы, которую вы создаете. Допустим, вы хотите сделать так, чтобы светодиод мигал. Вы присоединяете один конец к штырьку ввода-вывода, а другой конец к штырьку заземления. Вы пишите программу, которая говорит, что каждую секунду переключайте штырек ввода-вывода на высокое напряжение, ждите секунду, а потом переключайте на низкое. Теперь замените светодиод сервоприводом - и начало кормилки для кошки положено.

Штырьки ввода-вывода также реагируют на изменения напряжения (+5В или 0В). В PBASIC даже есть встроенная функция, которая позволяет штырькам ввода-вывода читать последовательные данные, в основе которых лежит последовательность высокого/низкого напряжения, из которой составляются двоичные слова. Пока можете сильно не волноваться по поводу последовательных соединений; более подробно мы рассмотрим их в следующем разделе. Сейчас, главное, поймите, что BASIC Stamp легко может получать команды от системы Linux через последовательный кабель и включать привод, который приводит в действие нашу кормилку для кошек.

Linux и STAMP

Parallax проделал огромную работу по созданию сообщества по интересам. Две рассылки посвящены продукции этой компании, а на множестве сайтов можно найти идеи для проектов. Хотя наиболее полная среда разработки для BASIC Stamp доступна только при работе с Microsoft Windows, с помощью Parallax был создан bstamp, который позволяет программировать BASIC Stamp в среде Linux. Пример разметки программы и запуска ее представлен ниже:

# bstamp_tokenize catcode.bs2 catcode.tok
PBASIC Tokenizer Library version 1.16
# bstamp_run catcode.tok
Model: Basic Stamp 2
Firmware version BCD = 16
Ack = 0
Ack = 0
Ack = 0
Ack = 0
Ack = 0
Ack = 0
Ack = 0
Ack = 0
Ack = 0
Ack = 0
Ack = 0
Ack = 0
DEBUG OUTPUT: (Нажмите [Control]-[C] для завершения последовательности)
_________________________________________________________
Waiting for Command [Ждет команду]
Received Command: B [получена команда В]
Feed the kitty! [Накормить котенка!]
Waiting for Command [Ждет команду]
Received Command: B [Получена команда В]
Feed the kitty! [Накормить котенка!]
Waiting for Command [Ждет команду]
__________________________________________________________
Received [Control]-[C]! [Получена команда [Сontrol]-[C]!]
Shutting down communication! [Завершение соединения!]

Раскритикованный последовательный кабель

Все, что я знаю о последовательных кабелях, я узнал из великолепной книжки Дэвида Лойера (David S. Lawyer) и Грэга Хэнкинса (Greg Hankins) «Справочник по последовательным кабелям» («Serial Howto»). Это толстенный талмуд, с большим количеством подробно разобранной информации о стандарте RS-232.

Хотя BASIC Stamp соединяется с bstamp через последовательное соединение, последовательный порт, который поставляется вместе с Homework Board, не очень хороший вариант для настоящего последовательного соединения. Parallax выполнил разводку соединений нетрадиционным образом. Для начала, все команды, посылаемые в порт, отражаются обратно к хосту, что делает двустороннее сообщение сложным.

Согласно стандарту RS-232, электрические сигналы, которые передаются по кабелю, должны быть +/- 12В. Из-за этого, если мы подключим последовательное соединение напрямую к нашим штырькам ввода-вывода Stamp, то, скорее всего, он перегорит, так как ожидаемое напряжение составляет +5В. Можно выйти из данного положения, используя переходник, который будет понижать идущий от ПК сигнал до +5В и повышать 5В сигнал, поступающий от Stamp до 12В. Такой чип существует, и называется MAX232. К счастью, вы можете достать совместимый с RS-232 адаптер на основе MAX232, специально созданный для беспаечного макета платы у техасца по имени Al Williams. Устройство называется RS-1, а ссылка на его веб-страницу приведена в списке он-лайновых ресурсов по этой статье.

Начиная с ядра 2.4, Linux именует последовательные порты следующим образом: /dev/ttyS0, 1, 2, 3 и так далее. Эти файлы устройств действуют так же, как и любой другой файл. Вы открываете их, читаете или пишите данные, а потом закрываете. 16К буфера более чем достаточно для большинства последовательных соединений. И это хорошо: вам не нужно беспокоиться, что вы потеряете биты просто потому, что вы не считывали данные в тот самый момент, когда ваше устройство посылало их по проводу. Это также означает, что вам нужно очистить буфер, когда вы готовы к отправке.

Так как порт воспринимается как файл, вам нужно соответствующим образом установить разрешения. В моем случае, так как я, в конечном счете, хочу, чтобы кормилкой управляла программа CGI, то сделал владельцем apache. Если вы работаете в безопасном окружении, то всегда можете использовать chmod 777 /dev/ttyS0, однако это явно небезопасно. Лучше всего сначала решить, что вы хотите делать со своим портом, а потом установить разрешения таким способом, который обеспечит наибольшую безопасность.

Python берет управление в свои руки

Так как Linux воспринимает наш порт как файл, Python легко использовать для сообщения со Stamp. C помощью File object (класс для работы с файлами) легко читать и писать данные в файл:

>>> f = open("/tmp/cotton.txt",'w')
>>> f.write("Cotton loves treats!")
>>> f.close()
>>> f = open("/tmp/cotton.txt",'r')
>>> f.read()
'Cotton loves treats!'
>>> f.close()

Как вы видите, хотя открывать и закрывать файлы легко, этот процесс может стать запутанным, если открываемый файл на самом деле является последовательным портом. К счастью для нас, в скрипте Python надо писать только одну букву за раз, чтобы дать кормилке указание раздать угощение. Как уже было сказано, я хотел использовать по возможности самый устойчивый к ошибкам метод соединения. И все эти открывания и закрывания беспокоили меня. Может быть, кошки захотят нажать кнопку, которая пошлет нам сообщение на работу, кто знает? Смысл в том, что я хотел использовать что-то более относящееся к последовательности, чем прямой дескриптор файла. К счастью, этого хотелось не только мне. Chris Liechti был так любезен, что специально для этой ситуации создал PySerial. Вот пример PySerial в действии:

>>> import serial
>>> sp = serial.Serial(0)
>>> sp.portstr
'/dev/ttyS0'
>>> sp.write("F")
>>> sp.readline()

Фактически мы не открываем /dev/ttyS0, мы открываем 0. PySerial достаточно умен и знает, что мы имеем в виду первый последовательный порт, и, соответственно, открывает его. Также это означает, что PySrial межплатформенен, поэтому вам не нужно знать, что на одном компьютере ваш порт имеет имя /dev/ttyS0, а на другом - /dev/ttya. Со всем этим управляется PySerial.

Теперь, когда Python общается через последовательный порт, нам необходимо сделать так, чтобы он вышел он-лайн. Признаю, я не восторженный поклонник Python в среде CGI. Однако пусть это вас не останавливает; существует рабочая группа, чья задача заключается в улучшении библиотек CGI и несколько интегрированных сред для Python делают CGI необязательным. К тому же, последний релиз mod_python включает в себя Python Server Pages (PSP), похожий на PHP синтаксис для включения Python прямо в HTML страницу. Короче, у вас есть много возможностей, когда дело доходит до использования Python он-лайн. Учитывая наши цели, библиотека Python более чем достаточна, для того, чтобы наши котята были всегда накормлены.

Вот небольшой пример для создания основы кошачьей кормилки:

#!/usr/bin/env python
import serial
import cgi
class Feeder:
def __init__(self):
self.port = serial.Serial(0)
def feed(self):
self.port.write("B")
print 'Content-Type: text/html'
print # Blank line marking end of HTTP headers
cgiParameters = cgi.FieldStorage()
control = Feeder()
control.feed()
print "

Thanks for feeding the kittens!"

В первую очередь, я вставил PySerial и CGI модули, а потом я объявил класс кормилка. Конструктор класса открывает последовательный порт. У класса есть одно правило, «кормить», которое посылает произвольный символ, в данном случае B, по проводу к кормилке. На другом конце, PBASIC старается распознать символ В и когда видит его, выдает угощение.

Пора кормить котят!

Я создал кормилку для кошек в виде «карусели», где угощение будет положено в ячейки, разделенные вращающейся лопаткой, приводимой в действие сервоприводом. Когда лопатка вращается, кусочки угощения падают через прорези в одну из ячеек в миску для еды. Для «карусели» я использовал контейнер, предназначенный для хранения замороженных вафель, прикрепил специально изготовленную режущую вращающуюся лопатку, и все это приводится в действие сервоприводом Parallax. Весь набор, включая схему BASIC Stamp, смонтирован в пластиковом контейнере в моем домашнем кабинете. Контейнер подключен к моему веб-серверу (/dev/ttyS0 для кормилки и /dev/ttyS1 для отладочного порта). Рисунок 1 изображает кормилку для кошек на моей полке. Я использую Fedora Core 1 с Apache 2.0.48.

Рисунок 1. Коттон получает угощение из кормилки.

Изначальной проблемой было то, как я должен определить, что лопатка достаточно провращалась, чтобы сбросить угощение и прекратить вращение? Самым простым решением было поставить маленький датчик на боковую сторону конвейера, который бы определял проходящую перед ним лопатку. Я выбрал датчик Parallax, который в основном используется для нахождения черной линии на поверхности. Я положил плоский черный кусочек от плаката на край каждой лопатки и разместил датчик на дне «карусели». Когда кормилка запускается, датчик определяет, когда первая лопатка проходит мимо; когда вторая лопатка минует датчик, сервопривод останавливается.

Я смонтировал Stamp достаточно быстро, всего лишь через несколько дней экспериментов. Макет платы – это огромный плюс Homework Board. Мне не нужно было паять и распаивать для того, чтобы монтировать и тестировать схемы. Рисунок 2 показывает всю схему. Рисунок 3 является фотографией смонтированного Homework Board.

Рисунок 2. Схема кормилки

Рисунок 3. Завершенная схема

Процесс написания кода для BASIC Stamp в основном состоял из использования команд «вырезать» и «вставить» части кода из примеров с сайта Parallax. Листинг 1 является окончательным кодом, тем самым, который я в итоге использовал. PBASIC во многом опирается на оператор GOTO для управления потоком данных, и мне пришлось к этому некоторое время привыкать.

Листинг 1. PBASIC код для кормилки

'{$STAMP BS2}
cmd VAR Byte
temp VAR Word
LineSnsrPwr CON 10
LineSnsrIn CON 9
Sense VAR Word
SStart VAR Word
main:
DEBUG "Waiting for Command", CR
SERIN 7, 84, [cmd]
DEBUG "Received Command: ", cmd, CR
IF cmd = "B" THEN feed
GOTO main
feed:
DEBUG "Feed the kitty!", CR
HIGH LineSnsrPwr ' activate sensor
HIGH LineSnsrIn ' discharge QTI cap
PAUSE 1
RCTIME LineSnsrIn, 1, SStart
DEBUG "First Reading: ", DEC SStart, CR
GOTO sensor
feed2:
IF Sense < (SStart - 200) THEN pastfirst
IF Sense > (SStart + 200) THEN stopfeed
FOR temp = 1 TO 100
PULSOUT 0,600
GOTO sensor
sensor:
HIGH LineSnsrPwr ' activate sensor
HIGH LineSnsrIn ' discharge QTI cap
PAUSE 1
RCTIME LineSnsrIn, 1, Sense
GOTO feed2
pastfirst:
DEBUG "Past First!", CR
SStart = Sense
GOTO sensor
stopfeed:
DEBUG DEC Sense, CR
GOTO main

Листинг 2 демонстрирует полный код Python, который мы используем для управления кормилкой. Скрипт CGI использует встроенный shelf модуль для Python; он позволит вам хранить активные объекты в dbm-базе данных. В дополнении к этому, я также использую набор шаблонов Cheetah. Строка t = Template(open('feeder.tmpl.py').read()) открывает HTML шаблон под названием feeder.tmpl.py, читает содержимое и использует его как шаблон Cheetah. Формат шаблона выглядит примерно как like

The cats have been fed $fed times

. Когда мы определяем переменную шаблона, t.fed, например, придаем ей значение 5, тогда строка приобретает следующий вид

The cats have been fed 5 times

.

Листинг 2. Окончательный Python CGI код

#!/usr/bin/python
import serial
import cgi
from Cheetah.Template import Template
import shelve
t = Template(open('feeder.tmpl.py').read())
port = serial.Serial(0)
class Feeder:
def __init__(self):
self.total_fed = 0
def feed(self):
self.total_fed = self.total_fed + 1
port.write("B")
def getTotalFed(self):
return self.total_fed
print 'Content-Type: text/html'
print # Blank line marking end of HTTP headers
form = cgi.FieldStorage()
d = shelve.open("feeder.dbm")
if d.has_key("control"):
""" if shelf file exists, open it, otherwise create
it and a new instance of the Feeder class """
control = d['control']
else:
control = Feeder()
d['control'] = control
if form.has_key("command") and \
form['command'].value == 'feed':
""" if we received the feed command,
feed, otherwise, show the index page"""
control.feed()
contents = """


Thanks for the Treat!


Meow!



Back

"""
else:
"""The index welcome page"""
contents = """

Cotton & Tulip Love Treats!



Click the Fish Below to Give
Cotton and Tulip a Treat


Кормилка для кошек работает. Иногда корм заклинивает механизм, но 95% времени кошки получают свое любимое угощение. У нас уже есть планы по созданию кормилки для кошек v. 2.0. Нам бы хотелось добавить видеокамеру, чтобы наблюдать за котятами в течение дня. Как и большинство наших проектов, кормилка находится постоянно в режиме работы. Зайдите на веб-сайт и покормите Коттона и Тьюлипа.



 


Автор конструкции: Chris McAvoy
gale
Linux Journal

Комментарии

Добавить комментарий
Маргарита margo21vek@mail.ru
Вы только разрабатываете проекты? а кто занимается продажами ваших кормушек? Сколько это стоит? Кому принадлежат авторские права?