пʼятниця, 14 грудня 2012 р.
The show must go on
Словом, вийшла сяка-така цяцька, яку ще допилювати й допилювати. Зустрічайте магазин кондитерської сировини http://iryska.com.ua. Якщо потекла слинка, познайомлю зі своєю дружиною!
середа, 18 серпня 2010 р.
Кубик Рубика у терміналі
Відірвався від літа на кілька годин щоб побавитися компілятором поза роботою. Ціль — емулятор кубика Рубика у терміналі. Чому в терміналі? Тому що для любителів графіки вже є готовий gnubik.
Отже, тягнемо репозитарій:
$ git clone http://github.com/sakhnik/rubik.git Cloning into rubik... remote: Counting objects: 134, done. remote: Compressing objects: 100% (44/44), done. remote: Total 134 (delta 89), reused 127 (delta 86) Receiving objects: 100% (134/134), 20.77 KiB, done. Resolving deltas: 100% (89/89), done.
Збираємо бінарник і маємо улюблену головоломку:
$ cd rubik $ ./autogen.sh $ make $ ./src/rubik
Підтримуються такі команди (див. main.cc):
| Команда | Дія |
|---|---|
| q | Вийти |
| # | Змішати |
| #N | Змішати, виконавши N поворотів |
| u | Повернути попередній хід |
| uN | Повернути N попередніх ходів |
| f | Повернути передню грань за годинниковою стрілкою |
| F | Повернути передню грань проти годинникової стрілки |
| fN | Повернути N передню грань за годинниковою стрілкою. N=1 — передня, N=−1 — задня. |
| FN | Повернути N передню грань проти годинникової стрілки |
| sN | Повернути N бічну грань за годинниковою стрілкою. N=1 — ліва, N=−1 — права. |
| SN | Повернути N бічну грань проти годинникової стрілки |
| tN | Повернути N верхню грань за годинниковою стрілкою. N=1 — верхня, N=−1 — нижня. |
| TN | Повернути N верхню грань проти годинникової стрілки |
| x,y чи z | Глянути на куб з іншої сторони |
Гм, треба буде цю таблицю включити в саму програму.
пʼятниця, 9 липня 2010 р.
пʼятниця, 23 квітня 2010 р.
Eclipse + Vim = eclim
З тих пір як перейшов на розробку для Linux, перестав користуватися інтегрованими середовищами розробки. Основними інструментами стали vim, git, grep, BBv2, зрідка gdb. Це все чудово, але іноді відчувалася нестача контекстної підказки під час кодування. Спробував було взяти eclipse, так він не дуже зручний для роботи в chroot-пісочниці, та й велика частина проекту — це скрипти оболонки.
Проте щойно надибав дуже цікавий проект eclim. Назва підказує, що йдеться про поєднання середовища eclipse із текстовим редактором vim. Багатообіцяюче, чи не так? Вони пропонують встановити додаток до vim, запустити спеціальну службу eclimd,… Profit!
Відверто, не обманули. І хоч з’явилися кілька набридливих дрібниць у vim, результат перевершив сподівання.
середа, 21 квітня 2010 р.
Про велосипеди
Мова піде про винахід колеса для кожного окремого воза. Вкотре знадобилася функція, яка б виконувала mkdir -p, тобто рекурсивно створювала директорії по заданому шляху. mkdir(2) справляється тільки тоді, коли всі батьківські директорії вже існують, а нам саме треба створити бракуючі.
Найдоступніші замінники:
system ("mkdir -p a/b/c/d")Для простої операції створює процес оболонки, а та ще один для mkdir — зажирно.
boost::filesystem::create_directories ("a/b/c/d")Цей тягне за собою не потрібну ні для чого іншого бібліотеку, жаба душить. Крім того, немає можливості задати права доступу до нових каталогів.
Ретельніший пошук показав, що у світі Unix кожен сам собі пише потрібну приблуду. А раз так, то й я не хотів зостатися осторонь. Нічого в ній особливого немає, тому прошу смакувати (C++):
//
// Mkdir.cc
//
// Created: 21.04.2010
// Author: A. Sakhnik
//
#include "Mkdir.hh"
#include <fcntl.h>
#include <errno.h>
#include <string>
#include <syslog.h>
using namespace std;
static int mkdir_if_missing (char const* path, mode_t mode)
{
struct stat buf;
if (-1 != ::lstat (path, &buf))
{
if (S_ISDIR (buf.st_mode))
return 0; // The path is a directory, OK
errno = ENOTDIR;
return -1; // The path exists, and isn't a directory
}
if (errno != ENOENT)
return -1; // Something bad happened
if (-1 == ::mkdir (path, mode))
return -1; // Wasn't able to create the directory
return 0; // We were lucky enough indeed
}
// Create directory recursively
int mkdir_p (char const* path, mode_t mode)
{
string parents; // Partial paths a, a/b, a/b/c etc
for (const char *next = strchr (path, '/'), *prev = path;
next;
prev = next, next = strchr (next + 1, '/'))
{
parents.insert (parents.end(), prev, next); // Consider next component
if (parents.empty())
continue; // Omit root directory for absolute path
if (-1 == mkdir_if_missing (parents.c_str(), mode))
return -1;
}
return mkdir_if_missing (path, mode); // Create final component
}
// vim: set et ts=4 sw=4:
пʼятниця, 9 квітня 2010 р.
Годинник-1.0
Нарешті стартовий годинник готовий. Досягнута головна мета — познайомитися з мікроконтролерною технікою, пригадати електроніку. Впаявши деталі на плату, виявив, що схематичних помилок немає, все запрацювало відразу. Але трохи схибив при монтажі, бо деякі деталі мають більший розмір, ніж їх підошва. Довелося “ретельно обробити терпугом”.
До цих пір я ще не пробував виготовити друковану плату самостійно, то дві третіх вартості приладу складає саме вона. Сподіваюся скоро виправити цей технологічний недолік.
Програмування — це найлегша частина проекту. Місця на кристалі багато, то крім обов’язкової частини додав бонус: при увімкненні на дисплеї показується біжучий рядок із надписом “Зелеста”, наскільки це можливо на семисегментному індикаторі. Правда, заставку можна вимкнути в режимі налаштування.
Технічні характеристики приладу:
| Напруга живлення | 6 В |
| Споживаний струм | ~200 мА (точно не рахував) |
| Висота знаків | 38 мм (1,5") |
| Кількість знаків | 5 |
| Точність годинника | 15 ppm (~1 с/добу) |
| Стартовий сигнал | Через кожні 30, 60, 120 секунд |
| Клавіші керування | Дві: “Режим” та “Старт/Вибір” |
Корпусу поки немає (а моїми руками й не буде), то розміри рахувати не буду.
А поки прилад готується до можливого завтрашнього бойового хрещення на київському спринті, поділюся намірами. Закортіло зібрати портативну радіостанцію, бо є практична потреба. Але першим кроком стане простий FM передавач. Хочеться мати безпровідні аудіо колонки, щоб можна було повзати по квартирі з лаптопом, не тягаючи за собою дріт.
Наостанок порада для господарів (самого нещодавно осяяло). Якщо треба чекати на завершення тривалої операції, наприклад, компіляції чи збірки пакунку, можна поставити звукове сповіщення:
[~]$ make; canberra-gtk-play --id=complete
Дзенькне так, що не пропустиш (перевірено у Fedora 12).
Очевидно,
довге заклинання можна перетворити в коротку команду,
призначивши alias
чи створивши скрипт у ~/bin.
пʼятниця, 19 березня 2010 р.
З поверненням, Fedora
Років зо два тому почали на роботі використовувати Ubuntu, то весь цей час вона була основною оперційною системою на домашньому лаптопі. Зручна, надійна, з багатою бібліотекою прикладних програм. Але тільки побачив Fedora, мене здолала заздрість: пакунки поновлюються частіше, і всі ходові програми на один випуск новіші.
Поставив, і вже два тижні користуюся Fedora 12. Для порівняння ось два зображення одного шматка схеми USBasp в Ubuntu та новій системі:
Нарешті, надійшла пора випускати у світ спроектований стартовий годинник. Вже тиждень потію над схемою та друкованою платою. Це вже четверта плата на моєму рахунку, і цього разу вдалося щось нове: жодного перехідного отвору! Ще треба дещо додати, двічі перевірити, прогнати через DRC (перевірку правил проектування), і можна буде замовляти.
неділя, 10 січня 2010 р.
Синтаксичний розбір із Spirit2
Мабуть, із самого початку для синтаксичного розбору на C++ я використовував boost::spirit. Вірою і правдою він служив аж п’ять років, і от вийшла цілком нова його версія під гордим номером 2. Старий код, звісно, продовжує працювати, якщо трохи підпиляти оголошення простору імен. А от мене здолала цікавість, що ж такого особливого нагородили в новій.
Відверто, відкриття перевершило всі сподівання. Новинка дозволяє писати вражаюче лаконічний код. Тобто, задум автора видно навіть при поверхневому перегляді. Важче вже збагнути, як ця магія працює, і треба бути готовим танцювати навколо із бубном, якщо щось не вдається відразу.
Для прикладу візьмімо клапоть коду розроблюваної версії IPMP2. Треба розібрати отримані із запиту HTTP GET аргументи та заповнювати вектор пар “ключ-значення”. Spirit2 підходить для цього, як лікар прописав. Ось опис граматики:
namespace qi = boost::spirit::qi;
// Магічне оголошення граматики
template <typename IterT, typename ParamsT>
struct CgiGram : qi::grammar<IterT, ParamsT()>
{
// В конструкторі описуємо цю граматику
// Крім того зазначаємо початкове правило
CgiGram () : CgiGram::base_type (start)
{
using namespace qi;
start %= parm % '&'; // Починаємо зі списку параметрів,
// розділених символом '&'
parm %= *chr // Параметр — це пара ключ-значення,
>> '=' // а між ними '='
>> *chr
;
chr %= char_('+') [_val = ' '] // Або це '+' → ' '
| '%' >> attr_cast<char>(xchar) // Або символ з ASCII коду
| (char_ - char_("=&")) // Або будь-що, окрім =,&
;
}
qi::uint_parser<unsigned, 16, 2, 2> xchar;
qi::rule<IterT, ParamsT()> start; // Стартове правило
qi::rule<IterT, // Правило для параметра
typename ParamsT::value_type()> parm;
qi::rule<IterT, char()> chr; // Правило для символа
};
Отже, сокира є. А як наварити з неї борщу — це домашнє завдання для допитливих.
четвер, 31 грудня 2009 р.
Підсумок-2009
Дві тисячі дев’ятий спливає, то пора підбити якісь підсумки. Всього, звісно, й не згадаєш:
- Навчився працювати з ACE та TAO. Власне, останні робочі дні року витратив, щоб перенести сервер SIA нової платформи на ACE. Краще все-таки стояти на чиїхсь плечах, ніж намагатися дотягнутися самотужки.
- Почав у розробці використовувати автоматизовані тестові сценарії. Ніж самому все перевіряти руками, краще доручу роботу тупому роботу (скрипту) від гріха подалі. І таки справляється! Гора з плечей, коли заходить мова про переробку…
- Став колупатися в мікроелектроніці. Розпочавши із PIC14, перейшов на AVR, поближче до Atmel та GCC. Хочу взяти курс на ARM9 та навчитися заселяти пінгвінів на нього.
- Повністю перейшов на VCS git, який підкупив своєю високою швидкістю, зручністю роботи, гнучкістю. Незамінна штука!
Відверто, детальних планів на наступний рік немає. Звісно, якщо не враховувати:
- Влитися у проект GNOME (необмеженого інтернету у мене до цих пір немає).
- Побудувати свій пристрій з Андроїдом на борту.
Ну, якось так. До зустрічі в дві тисячі десятому!
четвер, 24 грудня 2009 р.
Стягування файлів через telnet
Пригадався епізод із університетських часів. Дуже хотілося знайти собі якісь хороші п’єски для гітари (MIDI), а доступ з мережі університету був обмежений навчальними сайтами. Крім того, коли я був на молодших курсах, до інтернету була підключена тільки станція HP, на яку можна було зайти через текстовий термінал. Ото справжня Unix!
Так, знайомий ще зі школи старшокурсник підказав дуже цікавий спосіб. Треба було зайти на яку-небудь більш відкриту систему по telnet, знайти й стягнути потрібний файл у ній, закодувати його у ASCII інструментом uuencode і роздрукувати його у термінал командою cat. Таким чином, якщо записати сеанс у якийсь файл, то вже локально можна розкодувати файл інструментом uudecode.
Сеанс мав приблизно такий вигляд:
[~]$ telnet grex.org | tee grex.log [grex.org:~]$ wget http://cool.site/file.mid [grex.org:~]$ uuencode file.mid file.mid.uue begin xxx file.mid.uue ... end [grex.org:~]$ logout [~]$ uudecode grex.log -o file.mid
Процес повільний, клопіткий, але дуже цікавий. “Голь на выдумки хитра”!
понеділок, 14 грудня 2009 р.
Помилка і tee в конвеєрі
Чергове “прозріння” граблями в лоб не забарилося. Ситуація, як у M$ Windows: на екрані повідомлення про успішне завершення, а насправді жодних зрушень. Як виявилося, причиною стали наступні рядки у скрипті:
long_operation 2>&1 | tee /var/log/long_operation.log [[ $? -eq 0 ]] && echo "Succeeded"
Якщо виконання “довгої операції” закінчується невдало, то tee сумлінно приховає цей факт, і в будь-якому випадку з’явиться повідомлення про успіх. Отже, таке шоу краще влаштовувати по-іншому:
long_operation >(tee /var/log/long_operation.log) 2>&1 [[ $? -eq 0 ]] && echo "Succeeded"
UPD
Несподівано ікнулося, що це працює не завжди. Тепер використовуємо ${PIPESTATUS[0]}.
субота, 12 грудня 2009 р.
Програматор USBasp
Цього разу плата приїхала рівно за тиждень. І раз чесалися руки, відразу ж взявся її розпаювати. Так виявилися перші ляпи: отвори для стабілітронів я призначив занадто малі. Тобто, я взяв стандартний елементи з бібліотеки (ACY300), а діоди раніше не бачив, тому й не помітив, що насправді ніжки в них товсті. По-друге, діоди чомусь вийшли намальовані в протилежній полярності, хоч на схемі все було гаразд. Видно, не догледів при запуску gsch2pcb.
Але це була дрібна біда: припаяв на поверхню й по тому. А от як під’єднав кабель, то відразу ж дізнався, що напруга від USB не подається, на VCC аж −0,8 В. Мав би вже тоді зробити висновок, що кабель підробний, але ні, подумав, що є ще якась біда зі схемою, і вона віджирає більше, ніж їй може дати мій лаптоп…
Прийшла пора запрограмувати мікроконтролер. Зі схемою Громова можна працювати тільки у Windows, а в мене такої недоробки немає, тому довелося циганити. Відверто, це було непросто: кремінець розпізнавався тільки in vitro, кириличні надписи у вікні програми відображалися ієрогліфами і це ще не все. З горем пополам записав-таки програму, виплавив потрібні перемички і поставив мікросхему назад на її місце.
Знову підключаю до комп’ютера (цього разу іншим кабелем), і знову нічого. Хіба що рівень живлення VCC тепер вже став 5 В. І в системному журналі з’явився запис, що знайдено якийсь прилад, але він, партизан, ні на що не відповідає. Та й діод не світиться, отже, не працює програма. Під’єдную осцилоскоп, і бачу, що ніяким меандром на генераторі тактових імпульсів не пахне, один шум та й годі. Довелося пригадати, з якої коробочки взяв конденсатори, з’ясувати, що ці занадто великої ємності, і перепаяти на потрібні.
Останнім штрихом стала модифікація кабеля. Придбаного за п’ять гривень на радіоринку зовсім не жаль було: розрізав, припаяв навпростець до плати. До речі, кабель просто фантастичний, тобто, його розпаяв справжній фантазер: живлення та земля, D+ та D− були попарно сплутані між собою… О диво, після операції мій лаптоп знайшов і визначив новий пристрій (на платі теж засвітився червоний світлодіод)! Ба, тепер енергії вистачає навіть на програмований мікроконтролер.
[~]$ lsusb | grep USBasp Bus 004 Device 002: ID 16c0:05dc VOTI USBasp AVR Programmer
Працювати з USBavr виявилося досить просто: змінив програму, зібрав її командою make, і записав зміни у мікроконтролер командою make install. Makefile насправді виконує наступне заклинання:
avrdude -c usbasp -p atmega8 -U flash:w:led.hex
Словом, результати:
- У мене з’явився власний програматор AVR десь за сто гривень.
- Вперше вдалося провести цілеспрямоване налагодження схеми. Потикань було багато, але колись минеться.
- Отримав купу задоволення, якого не було б, якби придбав готовий прилад.
понеділок, 7 грудня 2009 р.
Hello, AVR!
У студентів запитують: | ||
| — З анекдоту | ||
Отже, як на мене, AVR більш привабливий для програмування, ніж PIC. GCC — це не хухри́-мухри́. Дай, думаю, спробую, тільки цього разу ніякої комерції, сам зроблю собі програматор. Після недовгих потикань по інтернетрях жереб випав на USBasp.
Прилад не на один день, значить, має бути добротним. Накидав плату на PCB, сконвертував у Гербери, відіслав замовлення у Херсон. Попросили п’ятдесят гривень, отже повністю зібрана цяцька має потягнути десь на сотню.
А поки Протомат трудиться над заготовкою, треба підготуватися і розв’язати проблему курки і яєць. Рішення легко знайти у журналі “Електроніка для всіх”. Так що, спеціально для свого майбутнього програматора довелося зібрати програматор Громова. Звісно, у мене він на макетній платі. До слова, спаяти безконтролерний на FT232RL мені геть не вдалося: надто вже дрібні деталі.
Як і слід було чекати, моделька запрацювала, жваво заблимавши діодом. Щось мені заклинило, і я зашив не ті “переплавки”, і контролер тепер запускається тільки з генератором RC. Але це вже дріб’язок. Чекаю на плату з Херсону.
середа, 2 грудня 2009 р.
Новий співробітник
Есть моск? Поможем научиться и рубить бабло! | ||
| — реклама devclub.com.ua | ||
З великими труднощами, але знайшли-таки нового програміста. А розказати хочу не стільки про нього, а через що йому довелося пройти, щоб приєднатися до української команди компанії Visonic.
За два роки нам вже тричі доводилося когось шукати для розробки на C++ для GNU/Linux, тому цього разу начальник сказав, що все спростимо. Щоб не гаяти час, я мав проводити телефонні співбесіди і вирішувати, чи витрачати на кандидата час. Запрошеним я мав запропонувати набір простих задач десь на півгодини, самому не відволікаючись від звичної роботи. А вже обрана п’ятірка могла потрапити на справжню багатообіцяючу співбесіду до начальника.
Але це було щось із чимось! Тільки дали оголошення, відразу ж посипались тонни відгуків, кожен кращий від іншого. До слова, всього їх отримали ми десь за тридцяток. Як почав я телефонувати, довелося спуститися на грішну українську землю…
Спершу перепитую, чи справді готові програмувати на C++ для Linux (кілька швидко одумалися). Потім різношерстий набір:
- Скільки 28?
- Як записується в signed int число −1?
- Чи може статична функція класу С++ бути віртуальною?
- Що робить функція стандартної бібліотеки С++
remove_if(adjacent_find,equal)? - Які є примітиви синхронізації потоків posix?
Когось запитував більше, когось менше, головне було зрозуміти, чи варто продовжувати. Я цілився на, можливо, не дуже досвідчених, але обов’язково кмітливих претендентів. Головне, щоб роботу робили, а не знали багато розумних слів і загинали пальці…
Напевне, з півтора десятка ми таки запросили в гості практичну частину. І знову почалося розчарування. Задачки були дуже прості, просто візьми й відразу ж скажи відповідь, можливо, крім однієї. Та де там! Тільки двоє спромоглися розв’язати майже все.
TasksВисновки:
Робота мисливців за головами вкрай непроста, особливо, як ті голови ще треба знайти.
Розумні програмісти десь давно працюють, а в постійному пошуку невдахи.
В багатьох випадках вимоги шукачів завищені. Ясно, що знайдуть шукаючі, але хотів би я знати, за що людям гроші платять.
середа, 25 листопада 2009 р.
Макет з клавіатурою
Хоч я й зайнятий останнім часом “по саме нікуди”, проект потрохи розвивається. Тепер макет постійно живиться від акумулятора через лінійний перетворювач напруги. До слова, як спробував побудувати імпульсний (по-ідеї, більш економний), то холостий хід у нього виходив на відмінно, але при навантаженні задихався. (Так хотілося це побачити на власні очі, що притарабанив з роботи осцилоскоп)
По-друге, додав до макету дві кнопки керування. Одна дозволяє перемикати режими, інша підналаштовувати покази годинника чи навіть його запускати/зупиняти. Варто зізнатися, що з спершу нічого не вийшло. Перебудувавши код, щоб на дисплеї друкувалися події, зіткнувся із тим, що час від часу малюється якесь сміття (Welcome to the real concurrent world!). Виявилося, що sdcc генерував non-reentrant код деяких функцій. Отже, довелося його наставити на шлях істинний з --stack-auto, та відмовившись від деяких благ цивілізації. Як би там не було, тепер усе працює, як … годинник ;-)
Чим більше працюю з sdcc, тим більшає спокуса погратися із AVR. Є ж для них нормальний компілятор GCC. Знайду дармовий внутрішньо-схемний програматор — так відразу ж спробую.
Нарешті, про наболіле. Ми знову шукаємо розробника на С++ для Linux. І знову я спантеличений. Надсилають вражаючі резюме, хоч відразу бери й наймай. А як приходять на співбесіду, то з’ясовується, що біти в числі рахувати не вміють; номінальні “знавці STL” не знають, що робить функція remove_if. Куди котиться світ?
неділя, 15 листопада 2009 р.
субота, 14 листопада 2009 р.
Канал через UDP
Півтора року тому для підтримки GPRS знадобилося мені реалізувати специфічний протокол SIA-over-IP. Це до возу приліпили крила й реактивний двигун, так що він тепер літає поруч із лайнерами. Тобто, сто років вже працюють у текстовому форматі SIA різні прилади, так ці самі повідомлення вже можна пропихати й через інтернет.
В документі було написано, що протокол орієнтований на з’єднання TCP, але при необхідності можна ті самі пакети слати у датаграмах UDP. Сказано — зроблено, просто для полегшення власної сверблячки зробив я обидва варіанти, хоч і ніхто не просив.
І от тижнів зо два тому телефонує інженер, який робив цей протокол для приладів, і питає, мовляв, як там у нас на сервері із UDP? Кажу, що все на місці, бери й спробуй… Працювало все нормально, але тільки до тих пір, як спробували під’єднатися до віртуального інтерфейсу. Виявилося, що пакети на сервер таки приходять, той відповідає, але вже через справжній інтерфейс. Тобто, прилад присилає на віртуальну адресу 192.168.38.14, а сервер відповідає із 192.168.38.13. Тому їх не хоче випускати у світ файрвол. Та й сам прилад, мабуть, проігнорував би.
Порившись півдня у інтернетрях, кажу архітекторові, що вся біда у прив’язці приймаючого сокета до IPADDR_ANY, давайте, мовляв, я їх заведу на кожен інтерфейс по одному, буде швидко й найдійно. — Та де там, шукай далі, як правильно обдурювати адресата, переписуючи на конверт зворотню адресу з оригіналу…
Таки надибав! Всі про це знають, але ніхто не каже вголос. Підглянув (thanks OSS!), і за день зробив. Довелося, правда, замінити recvfrom/sendto на recvmsg/sendmsg, у самому повідомленні порпатися у допоміжній інформації (struct in_pktinfo), та ще й самому її підкидати. Але так до кінця й не впевнений, що воно того було варте.
середа, 11 листопада 2009 р.
Перший працюючий годинник
Прислужилося ще одне кругле число. 4 194 304 — це теж степінь двійки, і його можна представити як добуток 4×16×256×256. А на практиці це означає, що взявши кварцовий резонатор з такою власною частотою, мікроконтролер PIC буде виконувати 16×256×256 інструкцій за одну секунду. Налаштовуємо прескалер таймера на поділ частоти на 16, матимемо переповнення восьмирозрядного TMR0 256 разів за секунду. А добитися щосекундного переповнення ще якогось байта — це задача для першокурсника.
Словом, дуже вдалий набір фактів для побудови точного годинника: маємо генератор 1 Гц для відліку секунд, інший з частотою 256 Гц для динамічної індикації на дисплеї. Щось підказує, що це ще далеко не всі можливості…
Отже, вже є перша працююча реалізація годинника. Асемблер я не знаю і вчити не хочу, тому програма написана на C. І то треба було півдесятка років відпрацювати з C++, щоб нарешті оцінити міць і красу С--! Словом, за звичкою прогама виходить модульною з простими інтерфейсами, з прихованою від недружнього світу реалізацією тощо. Але про це вже іншим разом.
Раз візуальний ефект є, беремо далі курс на звуковий супровід. Треба буде десь придбати п’єзо-сирену, і причепити її до схеми.
субота, 7 листопада 2009 р.
Друкована плата для дисплею
Щоб не паяти павутину із проводів, вирішив для дисплею виготовити друковану плату. Крім того дуже хотілося розібратися, як вони проектуються. Та й паяю я препаршиво.
Отже, накидав я схему майбутнього стартового годинника у gschem. Оскільки у стандартній бібліотеці моїх “вісімок” не було, довелося їх намалювати самостійно. Десь у тенетах наткнувся на підказку, що можна деякі цифри поперевертати, щоб отримати двокрапковий роздільник годин, хвилин та секунд.
Потім перегнав схему у програму pcb, заздалегідь по опису деталі (datasheet) описавши слід індикатора. Дисплей — це хороший початок, бо зовсім не треба думати над розміщенням деталей, отже, на одну проблему менше. А от із мережею доріжок довелося покоптитися. Можливо, й можна було б провести всі з’єднання на одній стороні, впаявши кілька додаткових перемичок самостійно, але для мене це не очевидно.
А далі був експорт схеми плати у файли Ґербера, замовлення у Херсоні і два тижні очікування. До слова, виробник мав упоратися за тиждень, тому я незадоволений результатом. Крім того, місцями на платі наскрізні отвори зміщені десь майже на чверть-доріжки (0,25 мм). Прототип все-таки.
Несподівано для себе відкрив, що впаювати в таку плату деталі дуже легко. Звісно, довелося помучитися із першим десятком голок, а на решту пішло хвилин зо десять.
Тепер можна неквапно на макетній платі готувати мікроконтролер.
середа, 4 листопада 2009 р.
Автоматичне тестування у bash
Рік тому з’явилася була ідея створювати для автоматичної перевірки всієї системи невеликі скрипти оболонки Unix. Відверто, з нашим лідером QA ми навіть спромоглися втілити її. Після нескладної підготовки середовища, запускався написаний на bash скрипт, який по SSH керував приладом, заставляючи його відіслати якісь повідомлення. Разом із тим виконував якісь перевірки на сервері. Така нехитра схема нам дозволила автоматизувати рутинні перевірки, і зрештою довести до систему до пуття.
Тепер знову постала необхідність розкопувати старі кулемети. Розробляючи нову версію сервера з нуля, ми зіткнулися із дикою бідою. Дуже важко відслідкувати всі внесені до схеми бази даних зміни і вчасно поновлювати код демонів (хто робив, той зрозуміє). Тому тепер я намагаюся пліч-о-пліч із ручними перевірками “занотовувати” свої дії у скрипти bash. Таким чином легко потім повторювати перевірки щодня. Можливо, в майбутньому автоматизуємо нічні збірки із прогонкою всіх тестів.
Такі тести мали б називатися регресійними модульними, але вони не те саме, що модульні тести вихідного коду. Бінарний модуль — це чорна скринька, але перевіряються внутрішності системи (записи в базі даних, зміни у файловій системі тощо).
Запускаються ці диво-скрипти на перевірюваному розгорнутому сервері, але покладаючись на структуру вихідного коду. Типові приклади дій у скриптах такі:
Визначаються якісь вихідні значення, параметри:
serial=1234567890 msg_idx=1234 cam_cnt=4
Готується оточення, заводяться значення в базу даних, перезапускаються потрібні демони тощо:
echo "Creating database ipmp" mysql << END || die "Failed to recreate the database ipmp" DROP DATABASE IF EXISTS ipmp; `cat $vdns_root/documents/web/ipmp/Ipmp2.sql` END echo "Preparing environment" rm -rf /ha_shared/vdns/eventsPictures mysql ipmp << END || die "Failed to prepare environment" INSERT INTO unit SET utc_id = 1, unt_serial = '$serial', unt_remote_access = 'allow'; END echo "Restarting pnet_server" killall -KILL pnet_server ($vdns_root/src/apps/pnet_server/pnet_server &)|| \ die "Couldn't launch pnet_server" echo "Restarting pnet_notify" killall -KILL pnet_notify ($vdns_root/src/apps/pnet_notify/pnet_notify &) || \ die "Couldn't launch pnet_notify" sleep 2
Від імені приладу відсилається запит:
# Sending error request resp=`curl -s -d asdf "http://localhost:8080/scripts/notify.php"` [[ $? -eq 0 ]] || die "Failed to get error response" [[ "$resp" =~ "<index>-1</index>" ]] || die "Incorrect error response" # Sending request ./send1.sh -a localhost -s $serial -i $msg_idx -c $cam_cnt [[ $? -eq 0 ]] || die "Failed to send the event"
Нарешті, виконуються перевірки ефекту запиту:
echo "Checking events" res=`mysql -s ipmp <<END SELECT etv_id, evt_description, evt_message_index, evt_original_device_name FROM event; END` || die "Failed to check events" diff -uw <(echo "$res") <(cat <<END 31 Fire $msg_idx Control Panel END) [[ $? -eq 0 ]] || die "Event don't match"
Для порівняння табличних даних в нагоді дуже стає команда diff: виходить компактно, інформативно. Краса!