Позвольте вашему 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 = """
Meow!
Back """ else: """The index welcome page""" contents = """
Click the Fish Below to Give Cotton and Tulip a Treat
Кормилка для кошек работает. Иногда корм заклинивает механизм, но 95% времени кошки получают свое любимое угощение. У нас уже есть планы по созданию кормилки для кошек v. 2.0. Нам бы хотелось добавить видеокамеру, чтобы наблюдать за котятами в течение дня. Как и большинство наших проектов, кормилка находится постоянно в режиме работы. Зайдите на веб-сайт и покормите Коттона и Тьюлипа.
|
|