Статична матрична клавіатура

Матричні клавіатури, на зразок показаної 12-клавішної, зазвичай опитують «динамічно», за допомогою сканування.

Процес опитування складається з послідовного видавання імпульсів на лінії, наприклад, COL0…COL2 і зчитування стану ліній ROW0…ROW3 та, при виявленні натискання, комбінування номерів чи масок цих ліній у скан-код клавіші. Це вимагає наче небагато команд і часу (та енергії) на їх виконання, але…
Якщо у пристрої вже й так використовується динамічна індикація, то таке опитування клавіатури може використовувати той же цикл і ті ж лінії сканування, що використовуються для індикатора, тому опитування клавіатури практично не вимагає додаткових ресурсів.

При необхідності знати стан кожного ключа незалежно, допускаючи довільне натискання багатьох клавіш, то без сканування не обійтися — але тоді послідовно з кожним ключем потрібно встановити діод.

В інших випадках можна обійтися без сканування, «статично», просто зчитуючи стан входів. Нічого не дається надурняк, тут якась кількість внутрішніх ресурсів мікроконтролера розмінюється на декілька транзисторів-резисторів (втім, сумарною вартістю меншою, ніж одна кнопка). Чи вартий того такий розмін, чи ні — вирішувати розробнику, але знати про таку можливість точно варто.

Тут при натисканні однієї клавіші одна з ліній ROW0…ROW3 підключається до бази транзистора, на ній встановлюється невелика напруга, яка зчитується як «0». Транзистор відкривається і подає сигнал «0» на відповідну лінію COL0…COL2. Таким чином, на лініях ROW0…ROW3, COL0…COL2 відразу формується код цієї клавіші.

Використання для опитування клавіатури лише входів дає перевагу у тому разі, коли через нестачу виводів мікроконтролера або необхідність віднесення клавіатури на деяку відстань. У такому випадку часто використовують регістри зсуву і послідовний інтерфейс SPI, але сканування клавіатури потребувало б двох регістрів — перетворювач послідовного коду у паралельний для сканування ліній COL та перетворювач паралельного коду у послідовний для зчитування ліній ROW. При статичному зчитуванні достатньо одного регістра:

Вільний восьмий вхід можна використати для додаткової клавіші-модифікатора або для розширення клавіатури до 15 (3*5) або 16 (4*4) клавіш.

p.s. Швидше за все, зараз у подібній ситуації сам я замість регістра зсуву використав би «аналогове» підключення матриці та якийсь малоногий мікроконтролер, який передавав би код натискання/відпускання лише при зміні стану клавіатури. Але нещодавно наштовхнувся на одному з форумів на свіже обговорення підключення через регістр восьми кнопок, от і згадалося. Вирішив зафіксувати.

Саморобні писачки

Знову саморобні #писачки, зі зроблених нещодавно заготовок.

Приготованої реєчки на ручки для всіх не вистачило, тому один зроблено на ручці від старого писачка, зробленого колись із металевої шторки 3.5-дюймової дискетки. Тут на фото він другий зліва. Оскільки засвердлити тріснуту під гвіздком ручку вже не вдалося б, я її трохи підрізав, підігнув дроти від конуса і примотав тонкою мідною дротиною класичним бандажем.

Sketch for Scratch

У зв’язку з активізацією інтересу батьків до того, щоб у дітей був інтерес до програмування/електроніки/… у поле мого зору знову потрапив Scratch. Але як людина, яка не вміє налагоджувати програми без осцилографа :-) , я відразу почав шукати можливість підключити до нього якісь зовнішні пристрої.

Перше, що трапилося — плата PicoBorad. Необхідні для роботи з нею блоки інсталюються разом з системою Scratch. Але ціна на неї відлякує (після ознайомлення з можливостями ще й дивує).

На щастя, і сама плата, і програма до неї доступні на GitHub та ще й під вільними ліцензіями, тому ними можна скористатися. Для варіанту «зробити за вечір, щоб увімкнути і подивитися» я вибрав Arduino nano та макетну плату для монтажу дротиками. Змінні резистори з припаяними штирями у мене вже були зроблені раніше, тому паяти не довелося зовсім.

Оскільки і у платі PicoBoard, і в Arduino nano стоїть однаковий процесор, не було потреби навіть перепризначати ніжки і можна було б просто зашити готовий .hex. Але то було б зовсім нецікаво і я вирішив переписати ту коротку програму як arduino-sketch. Ну сподобалася мені назва Sketch for Scratch :-) Заради цього я навіть встановив оболонку Arduino і відновив у платі стертий раніше bootloader.

Вийшов коротенький скетч, який можна подивитися тут » » »

Заготовки для писачків

Накрутив та пропаяв рурки для виготовлення саморобних писачків по описаній раніше технології

Заготовки для писачків

Тепер треба підібрати паличок на ручки, бо ті «стержні» від дитячого ліжечка, з яких я робив раніше, для дитячих пальчиків грубуваті.
Старі дерев’яні ручки під перо-чорнило було б чудово. Можна олівці спробувати.

DIDR0 та PRR

Трохи інший проект, трохи інший мікроконтролер (ATmega168PA, а не ATmega48PA), але знову мікроампери, як і у випадку зі світлодіодом. Тільки тепер головними героями є не світлодіод, який вирішив побути фотодіодом, а два регістри, які посперечатися, хто з них головніший.

Результат той же — завищене споживання. Навіть основна причина та ж сама — проміжна напруга на цифровому вході. На відміну від того світло-фото-діода вона там і повинна бути такою, бо це ще й вхід АЦП. Оскільки входи АЦП штатно повинні приймати «нецифрові» напруги, у мікроконтролері є регістр DIDR0 (Digital Input Disable Register), бітами у якому можна від’єднати від потрібної ніжки цифровий вхід і закоротити його на лінію GND. Звісно, я це знаю і, звісно, маску потрібних ніжок я у регістр записав.

«Але є одне але»
АЦП у цьому проекті потрібен періодично і ненадовго, тому він майже постійно вимкнений бітиком регістра PRR (Power Reduction Register), щоб додатково зекономити дещицю струму. При старті програми АЦП вимкнено. Відповідний фрагмент ініціалізації мікроконтролера виглядав наступним чином:

1
2
3
4
5
6
7
8
     // TIM1 та TIM2 потрібні завжди, інше буде дозволено при потребі
    xouti   ACSR, 1 << ACD
    xouti   PRR, ~((1<<PRTIM2) | (1<<PRTIM1))
     // Порти
    xouti   DIDR0, DIDR0_MASK
    xouti   PORTB, PORTB_PORT_MASK
    xouti   DDRB,  PORTB_DDR_MASK
    xouti   PORTC, PORTC_PORT_MASK

І от що з’ясувалося.
Якщо порядок запису у регістри PRR та DIDR0 такий, як показано вище, то цифрові входи не відключаються від ніжок. В результаті на вході заміру напруги живлення плати при збільшенні напруги струм плати спочатку росте з десь 250 мікроампер до 400, потім спадає до 300, бо напруга на вході АЦП минає середину живлення і наближається до безпечного рівня.
Якщо ж рядок 5 поставити перед рядком 3, то цифрові входи відключаються і залишаються відключеними і після вимикання живлення АЦП. Тобто при встановленні біта PRADC у регістрі PRR сам регістр DIDR0 продовжує працювати і керувати портами, але схеми запису в нього вирубаються начисто.

Мені і в голову не прийшло, що таке може бути — незважаючи на те, що опис регістра DIDR0 розміщено в кінці розділу опису АЦП. Все ж таки керує цей регістр ланцюгами цифрових входів портів, а не аналоговими входами.
Тепер знатиму…

Різновиди писачків

Різні регіони України, різні стилі писанок — і, відповідно, різні #писачки:

Стабілізація вольтдобавки

У продовження теми про транзисторні ключі. Транзистор на схемі у минулому повідомленні на цю тему працює, взагалі кажучи, не у ключовому, а у лінійному режимі. Просто у тих використаннях на вході імпульс, на виході теж.

Проте, такий каскад зі спільною базою, який «перекидає» сигнал через шину живлення і відраховує його від іншої шини, може бути дуже корисним і у лінійних схемах.

Цілком реальна задача — є напруга живлення, наприклад, 12 V. Над нею потрібно зробити вольтдобавку, нехай це буде 6 V. Наче і нескладно — беремо імпульсний стабілізатор step-up, налаштовуємо зворотний зв’язок на напругу 18 V, маємо потрібну додаткову напругу. Але це коли у нас на вході саме 12 V, а не 12-вольтовий акумулятор.

У випадкові акумулятора маємо вхідну напругу під 14 вольт при заряді, а напруга на виході імпульсного стабілізатора збережеться, тобто вольтдобавка знизиться до 4 V. При розряді напруга на акумуляторі може знизитися до 10.5 V, вольтдобавка виросте до 7.5 V. Далеко не завжди це припустимо.
Отже, стабілізувати слід не «верхню» напругу, а різницю між нею та вхідною напругою. Можна поставити диференційний підсилювач, передати ним масштабовану різницю напруг на вхід зворотного зв’язку мікросхеми імпульсного стабілізатора. Крім суттєвого збільшення кількості компонентів це ще може додати мороки зі стабільністю, адже у петлі зворотного зв’язку з’явиться елемент зі складною характеристикою.

Інший шлях — додати один транзистор, як це показано на схемі. Разом з резисторами «звичайного» зворотного зв’язку R2 та R3 цей транзистор утворює точнісінько такий же каскад, як і наведений у згаданому вище дописі, тільки «перекидає» сигнал він тут не відносно землі, а відносно шини вхідної напруги UPOW. Різниця напруг між шинами живлення (з урахуванням падіння напруги на переході база-емітер транзистора) за допомогою резистора R3 перетворюється на струм
   i = (Uadd – Upow – Ube) / R3
який перетворюється назад у напругу на резисторі R2, відраховану від шини GND. Напруга зворотного зв’язку
   Ufb = R2 * (Uadd – Upow – Ube) / R3
тепер пропорційна вольтдобавці, а не верхній напрузі.

Схема має невеликий недолік — напруга Ube залежить від температури і на цю ж величину буде змінюватися різниця (Uadd – Upow). Втім, у дуже широкому діапазоні температур ця зміна не перевищить ±0.2V, а щоб позбавитися цього недоліку, достатньо додати ще один такий же транзистор і один резистор.

Перевага схеми не лише у її простоті (додається всього один копійчаний компонент), а й у тому, що каскад зі спільною базою працює у дуже широкій смузі частот без зсуву фази, не додаючи затримок, тому практично не впливає на частотні характеристики петлі зворотного зв’язку стабілізатора.

Як зробити форму для миколайчиків

Три роки тому у публікації Форма для миколайчиків за п’ять хвилин я дав короткий опис і відеоурок по виготовленню формочки-«дідуся» для «миколайчиків» з консервної банки. Там показано основні операції — як обрізати та вигинати банку. Тепер я хочу нарешті розповісти про весь шлях від малюнка до формочки.


»»» Читати далі…

Свобода панорами

Мабуть, мені раніше треба було про це тут написати. Все ж таки хтось мене та читає, може б і дослухався.
Цю петицію я підписав у перший день збору підписів, ще в кінці серпня. Прошу підтримати. Часу залишилося небагато, а народ більше готовий підписувати покарання Гондурасу Тимошенкою, ніж реально потрібні речі.

Прошу Президента України визначити як невідкладний законопроект №1677 “Про внесення доповнень до Закону України “Про авторське право та суміжні права” (щодо свободи панорами)”.

«Свобода панорами – це можливість вільно фотографувати, змальовувати чи знімати на відео будівлі та скульптури, які перебувають в громадському місці. При цьому авторські права не вважаються порушеними. За чинним законодавством будь-яке фото сучасної будівлі чи пам’ятника може вважатися порушенням авторських прав, якщо ви не маєте дозволу від їх авторів…»

Порти STM32F30x

От не чекав такого.

Є у Cortex-ів M0/M3/M4 така зручна штука, як bit-band, призначена для атомарної роботи з однісіньким бітом IO або пам’яті.
Коротко, для тих, хто не знає — два одномегабайтних регіони адресного простору, в яких цей механізм працює, мають поставлені їм у відповідність 32-мегабайтні регіони bit-band. Кожна адреса 32-бітного слова у цих регіонах відображається на один біт відповідного 1-мегабайтного, тобто старші 20 біт адреси всередині bit-band регіону вибирають слово у відповідному 1-мегабайтному, а молодші 5 —вибирають біт у цьому слові. Звертання на запис десь на апаратному рівні контролера пам’яті призводить до циклу читання-модифікація-запис зі зміною одного біту.

Ну так от, чому я саме про F30x. Попросили тут організувати одному студентові робоче місце з STM32F3DISCOVERY — компілятор-те-се, допомогти стартувати. Вирішив відразу показати scmRTOS як просту-швидку і практично дармову по ресурсах та нескладну в освоєнні міні-RTOS. Порт для Cortex-M4F є, прикладів для STM32F4xx вистачає. Вирішив почати з найпростішого 1-EventFlag (він зовсім простий майже у всіх портах scmRTOS, ускладений я зробив колись для AVR та STM8). Поліз модифікувати startup.c з таблицею векторів, у sysinit.cpp переписав ініціалізацію PLL.
Ну і ще pin.h, C++-ний аналог «Волковських» макросів на препроцесорі мови C для роботи з портами.
Все так наче нормально, GPIO у STM32F30x по організації такі ж, як у STM32F2xx та STM32F4xx — той же принцип, такі ж регістри (практично такі — у F3 повернули назад регістр BRR, який був у STM32F1xx, а у F2 та F4 пропав, скинути біт порту можна лише через верхню половину BSRR).
Підправив базові адреси портів, компілюю, зашиваю… Висить.
Ну, думаю, десь щось або в ініціалізації PLL, або десь у векторах чи в самій rtos щось таки треба міняти. Вирішив мигнути кілька разів світлодіодами до OS::run(), тобто до дозволу переривань під час запуску ОС.
Не мигають.
Перевірив код ініціалізації PLL. Все нормально.
І тут… І тут… І тут до мене доходить, що базові адреси портів дещо незвичні після STM32F1xx та тих, що були у старому pin_stm32F4xx.h у прикладах.

Лізу знову у документацію. Отже:

У кортексів два 1-мегабайтних регіони з відображенням на bit-band
SRAM: 0×20000000-0×20100000 → 0×22000000-0×24000000
PERIPH: 0×40000000-0×40100000 → 0×42000000-0×44000000

У STM32F1xx GPIO на APB2, діапазон 0×40010800-0x400123FF, потрапляє у bit-band
STM32F2xx, STM32F4xx — на AHB1, діапазон 0×40020000-0x400223FF, потрапляє у bit-band
STM32F30x — на AHB2, діапазон 0×48000000-0x480017FF, НЕ потрапляє у bit-band

Таймери-АЦП потрапляють, а це – ні! У таймерів з різних місць атомарно клацати бітиками дозволу/заборони переривань на CC-каналах теж приємно, але ж місця там валом, все б влізло, навіщо було GPIO закидати так далеко?
Довелося переписати весь цей pin.h у стилі «прочитали, наклали маску, врізали біти, записали». Для роботи з виходом атомарність залишається завдяки старим-добрим BRR/BSRR, з усім іншим (перемикання вхід/вихід/альтернативна функція, pull-up/pull-down) тепер треба буде уважно.

p.s. Пора розбиратися з GDB через OpenOCD, ними б я за хвилину проблему знайшов би…

[flagcounter image]