суботу, 31 грудня 2016 р.

Curiosity -- результати, 9

Увага, це старий текст, написаний на початку 2015-го! З того часу не мав можливості до нього повертатися, але викидати шкода, тому трішки відредагував і викладаю.  З іншого боку, особливих "метанових" новин з того часу мені не траплялося...

Двома найважливішими науковими новинами MSL Curiosity була органіка взагалі, і метан зокрема.

Почнемо із метану. Чого він важливий? Бо це живі істоти, (хай і в минулому) або це вулканізм (на крихітному, вистиглому всередині Марсі?), або ще щось таке ж цікаве. Але все по порядку.

Наочна схема можливих джерел марсіанського метану від NASA:
Кругообіг метану на Марсі. Деталі в тексті. Клікабельно!
(c) NASA / JPL / SAM-GSFC / U. Michigan

вівторок, 27 грудня 2016 р.

Curiosity -- короткий огляд 10

На жаль, мушу визнати, що не маю належних ресурсів -- часу/сил/натхнення, щоб систематично писати тут про прогрес міжпланетних місій. Планую, щоправда, продовжувати (і відпрацювати борги -- Akatsuki, Juno, ExoMars Trace Gas Orbiter) по опису самих міжпланетних станцій -- воно корисно й мені особисто, щоб потім розібратися, що ж та місія робить, а без опису бракує терпцю ознайомлюватися достатньо детально.

Однак, ще один запис про Curiosity колись собі обіцяв зробити -- виконую обіцянку. :-) На жаль, він більш технічний та формальний, ніж попередні -- із згаданих вище причин.

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

908-го сола марсохід зробив чергову, шосту, свердловину (область Telegraph Peak, ближче до вершини Pahrump Hills, соли 903-923), після чого, нарешті, залишив цей регіон, прямуючи до "долини" Artist's Drive. На жаль, в процесі свердління сталося коротке замикання, десь в ударному (перкусійному) механізмі свердла, з яким довелося розбиратися, і повторення тепер є постійною загрозою. CheMin виявив у добутих зразках кристобаліт і кварц. 
Telegraph Peak, Sol 918, 7 березня 2015, Right Navcam. Взято тут.

понеділок, 26 грудня 2016 р.

Curiosity -- короткий огляд 9

Увага, це старий текст, написаний на початку 2015-го! З того часу не мав можливості до нього повертатися, але викидати шкода, тому трішки відредагував і викладаю. Найближчі дні буде ще продовження історії з нього до поточного моменту та ще кілька неопублікованих "космічних" текстів початку 2015-го.

Покинули ми Curiosty на початку 780-х солів. В процесі роботи в останній області, Confidence Hills, розпочалися проблеми із "рукою". Зокрема, не зразу змогли закрити кришку мікроскопа MAHLI. Це могло привести до запилення об'єктиву, тому використання маніпулятора обмежили, до вияснення причини проблем. Паралельно відбувалася підготовча робота до зустрічі із кометою Siding Spring. 780-го марсохід вирушив далі, до Pahrump Hills, проїхавши 22 метри:
Сол 780, місцевість Book Cliffs, NavCam.
(c) NASA / JPL / Emily Lakdawalla
Саме в місці, сфотографованому вище, марсохід і зустрічав комету.

суботу, 3 грудня 2016 р.

Далекомір HC-SR04 -- зміст

Взято тут -- із тексту
якраз про змісти.
Якось так, слово за словом, постів про ультразвуковий далекомір  HC-SR04 написав багато -- робота із ним виявилася напрочуд хорошим педагогічним прикладом. При чому, пости ці сильно розкидані по часу. Тому вирішив створити окремий зміст.

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

Проекти із кодом, який використовується в постах, зазвичай можна скачати за посилання в кінці посту. Історично склалося так, що проекти для CoIDE. В принципі, зараз перейшов на System Workbench for STM32, але якщо б взявся всі пости переносити -- їх написання точно б ніколи не завершилося. Та й STM32VLDiscovery він не підтримує.

Використано мікроконтролери сімейства STM32, детальніше в тексті.

Код, в основному, написаний на С -- використання C++ додало б декілька зайвих рухів, майже не додавши "педагогічної цінності". Однак, в своїх реальних проектах використовую С++. Проекти в міру (сподіваюся -- в міру) неохайні, хоч і старався, щоб зовсім потворними вони не були. Якщо бачите помилки -- пишіть. 

Див. також зміст суміжної серії постів: "Таймери STM32".

понеділок, 28 листопада 2016 р.

Далекомір HC-SR04 -- зовнішні переривання EXTI/HAL

Подивимося, що в порівнянні із використанням CMSIS, надає нам STM32CubeMX разом із HAL для організації обробки переривань від зовнішніх джерел, традиційно -- реалізувавши приклад із попереднього CMSIS-поста.

Периферія сконфігурована як і раніше:
  • Trig -- пін PA10,  вивід. Ми керуватимемо ним третім каналом таймера TIM1.
  • Echo -- PA6, генеруємо переривання.
"Малюємо" відповідну конфігурацію:

неділю, 27 листопада 2016 р.

Далекомір HC-SR04 -- зовнішні переривання EXTI/CMSIS

Взято тут: "STM32 External Interrupt"
Перекласти всю роботу із далекоміром на таймери (чи таймер) -- зручно, але, іноді, надміру складно -- якісь Capture-compare, захоплення ШІМ, інший "страх и ужас". Мікроконтролери мають ще один, простіший спосіб фіксувати тривалість імпульсу -- за допомогою "банального" зовнішнього переривання -- EXTI: фіксується момент зміни стану лінії ECHO з 0 в 1, потім -- назад, тривалість -- різниця часу між ними. Таймер, звичайно, використовується -- для вимірювання часу, але лише як лічильник. 

Спрощений варіант роботи за допомогою переривань було розглянуто в "методичному" пості: "Зовсім просто про далекомір HC-SR04 із GPIO/HAL", тут дотримуватимуся більш систематичного, але дещо заскладного для конкретної простої задачі підходу. 

понеділок, 21 листопада 2016 р.

Далекомір HC-SR04 -- один таймер/HAL

Повторимо зроблене в попередньому пості, із використанням HAL/SMT32CubeMX. Такі, трішки нестандартні, режими роботи, HAL безпосередньо не підтримує, але і не заважає сильно -- все ж, абстракція, надана цією бібліотекою, зовсім тоненька.

Нагадаємо апаратну конфігурацію:
  • TRIG -- PA6 (TIM3_CH1)
  • ECHO -- PB0 (TIM3_CH3)
  • PC8 -- синій світлодіод
  • PC9 -- зелений світлодіод 
За потреби, Cube вміє автоматично робити ремапінг. Тут в ньому потреби немає:

пʼятницю, 18 листопада 2016 р.

Далекомір HC-SR04 -- трасування, додаток

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

Один із способів пошуку помилок у таких програмах -- зберегти послідовність виконання програми в самому мікроконтролері, а потім передати її на комп'ютер -- так зване трасування. Воно використовувалося для створення програм, які працюють із далекоміром з використанням таймерів (чесно кажучи, однотаймерний варіант я б без трасування не зміг би до ладу довести, принаймні, це забрало б на порядок більше часу). Розглянемо використаний там підхід.
Увага: дана реалізація дуже примітивна і має багато недоліків! Створювалася нашвидкоруч і без якихось подальших перспектив. На С++ можна зробити багато краще та надійніше. Та й на чистому С є простір для покращення.
Крім того, навіть ідеально реалізований, цей метод придатний не всюди -- він не підійде, наприклад, для дуже чутливої до часів реакції апаратури, або коли пам'яті не вистачає. Однак, на загал, інструмент зручний.
Отож, поїхали.

середу, 16 листопада 2016 р.

Далекомір HC-SR04 -- один таймер/CMSIS

Приклад скінченного автомата,
який визначає чи двійкове число
має непарну кількість 0.
(c) Wiki
Чим простіший код, тим краще. Код, де пінами ECHO та TRIG керують окремі таймери відносно простий. Однак, з одного боку, таймери -- ресурс цінний та обмежений. На STM32F100, котрим обладнана наша плата, таймерів, здатних генерувати PWM -- десяток, але вони сильно відрізняються за можливостями. Для реальних пристроїв це не так вже і багато! З іншого боку, частина таймерів мають багато каналів. (Для цього контролера п'ять -- по 4 канали, три -- по 2, і три -- єдиний (комплементарні не рахуючи). 

Захоплення ШІМ, на яке ми покладаємося, потребує двох каналів, генерація TRIG -- ще одного. Отож, одного таймера для керування далекоміром має вистачити. 
Заради простоти я не став вішати на четвертий канал ШІМ для візуального відображення віддалі світлодіодом. Залишимо це на домашнє завдання. Видається, це можливо, хоч гарантії, не зробивши, не дам.
Користуватимемося таймером TIM3, його CH1 i CH2 займатимуться захопленням ECHO, а CH3 -- TRIG. Тому, без використання ремапінгу, апаратна конфігурація така:
  • TRIG -- PA6 (TIM3_CH1)
  • ECHO -- PB0 (TIM3_CH3)
  • PC8 -- синій світлодіод
  • PC9 -- зелений світлодіод 
 Думаю, можна зробити краще, вважатимемо приклад нижче лише технологічною демонстрацією.

Логіка роботи програми


вівторок, 15 листопада 2016 р.

Далекомір HC-SR04 -- два таймери/HAL

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

Апаратна конфігурація та ж:
  • TRIG -- PA10  (TIM1_CH3)
  • ECHO -- PA6 (TIM3_CH1, CH2 indirect)
  • Світлодіод, яскравість якого показує віддаль до перешкоди -- PA0 (TIM2_CH1)
  • Світлодіоди плати, як завжди, синій на піні PB8 і зелений на PB9
  • TIM1 генеруватиме імпульс заданої довжини ~ 10-15 мкс, в ролі TRIG, на PA10
  • TIM3 вимірюватиме тривалість імпульсу на лінії ECHO, PA6
  • TIM2 -- PWM (ШІМ) на PA0
 Візуально це виглядатиме так:
Клікабельно!

понеділок, 14 листопада 2016 р.

Далекомір HC-SR04 -- два таймери/CMSIS

Лого однойменної групи. Не маю ні найменшого
уявлення, що у них за музика. Здавалося б, невинне
словосполучення: "Two timers".
Дивимося словники: TheFreeDictionary
та UrbanDictionary
Озброївшись знаннями про таймери, спробуємо вирішити задачу роботи із далекоміром більш елегантно. Спершу зробимо марнотратно -- кожній під-задачі виділимо свій таймер. Насправді, назва посту трішки обманює -- використано аж три таймери, а не два:
  • TIM1 генеруватиме імпульс заданої довжини ~ 10-15 мкс, в ролі TRIG
  • TIM3 вимірюватиме тривалість імпульсу на лінії ECHO
  • TIM2 -- не важливий для власне роботи, тому не врахований в заголовку, візуально показуватиме віддаль до перешкоди, за допомогою світлодіоду та PWM (ШІМ)
Спочатку зробимо це засобами CMSIS.

Апаратна конфігурація відрізняється від попередніх прикладів із використанням GPIO, так як канали таймерів прив'язані до конкретних піні (навіть із ремапінгом варіантів не так багато). Для цього прикладу вона наступна:
  • TRIG -- PA10  (TIM1_CH3)
  • ECHO -- PA6 (TIM3_CH1, CH2 indirect)
  • Світлодіод, яскравість якого показує віддаль до перешкоди -- PA0 (TIM2_CH1)
  • Світлодіоди плати, як завжди, синій на піні PB8 і зелений на PB9

Логіка роботи програми


вівторок, 8 листопада 2016 р.

Таймери STM32 -- зміст

Статей про таймери вийшло багато. Щоб краще орієнтуватися, пасує зробити зміст. Потім треба буде його зробити ще й для постів про далекомір. Аналогічний зміст для постів про далекомір.

Проекти із кодом, який використовується в постах, зазвичай можна скачати за посиланням в кінці посту. Історично склалося так, що більшість проектів проекти для CoIDE. В принципі, зараз перейшов на System Workbench for STM32, але якби взявся всі проекти переносити -- написання цих постів точно ніколи б не завершилося.

Розглядається використання CMSIS та HAL+STM32CubeMX. Код Cube та HAL розтинається та аналізується аж до рівня CMSIS -- безпосередньої маніпуляції регістрами.
На жаль, не передбачено простого візуального способу пропустити цей reverse engineering для тих, кому цікаво лише знайти підказку, як скористатися тією чи іншою можливістю. Однак, в тексті все-таки відділяється опис способі використання від аналізу подробиць роботи.

понеділок, 7 листопада 2016 р.

Таймери STM32 -- порівняння розмірів коду для CMSIS i HAL

В процесі написання серії постів про таймери склалася цікава ситуація. Ми маємо пари однотипних проектів, в одному із яких задача вирішується за допомогою CMSIS, у іншому -- HAL. При чому, для "HAL-проектів", код ініціалізація створювався за допомогою STM32CubeMX,  і є доволі громіздким, як ми не раз могли зауважити.
При чому, певна надія на оптимізатор компілятора залишається, але не надмірна -- оптимізації, які маніпулюють апаратними регістрами він просто "не посміє" робити.
Така ситуація дозволяє подивитися, скільки ж це задоволення -- зручне написання коду ініціалізації, коштує. При чому тут, на відміну від постів про далекомір, розмір C runtime i printf() не вноситиме величезну систематичну "похибку" -- він або присутній, або ні, в обох проектах одночасно.

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

Якщо лінь, переходьте зразу до висновків.

четвер, 27 жовтня 2016 р.

Зовсім просто про акселерометр та магнітометр LSM303DLHC із HAL

Простий акселерометр. (c) Wiki
Плата STM32F3Discovery обладнана двома дуже цікавими сенсорами -- акселерометром і магнітометром, об'єднаними в одному корпусі -- LSM303DLHC та гіродатчиком (MEMS-гіроскопом) L3GD20.

Почнемо із акселерометра-магнітометра.

Документація на нього знаходиться тут: "Ultra compact high performance e-compass: 3D accelerometer and 3D magnetometer module", там же можна скачати офіційну документацію -- так-званий Datasheet (на жаль, посилання доволі швидко псуються, сайт часто реорганізовують, чи що, так що шукайте на сторінці). Щоб зрозуміти, як користуватися описаним в документації, варто почитати так-звані Appnote, наприклад: "AN3192 Application note: Using LSM303DLH for a tilt compensated electronic compass" (На жаль, на цей документ немає посилань із сторінки LSM303DLHC -- все ж, трішки інша модифікація, є хіба значно коротші, виду: "DT0058: Computing tilt measurement and tilt-compensated e-compass"). Бо із самої документації витягнути необхідне трохи важко -- це довідник, а не підручник...

Опишемо коротко його основні характеристики:

четвер, 20 жовтня 2016 р.

Зовсім просто про далекомір HC-SR04 із GPIO/HAL

Взято тут.
Пост: "Далекомір HC-SR04 -- використовуючи GPIO/HAL/STM32CubeMX" написано виходячи із того, що попередні тексти, зокрема: "Далекомір HC-SR04 -- використовуючи GPIO/CMSIS" читачу відомі, виклад зосереджено лише на нюансах роботи з Cube/CoIDE/HAL. 

Для деяких моїх задач це виявилося незручним. Тому вирішив написати даний текст, де розглянуто роботу із далекоміром, не відволікаючись на подробиці реалізації внутрішньої HAL. 

Подробиці генерації проекту та роботи із середовищем тут не описуватимемо, за ними див., посилання вище та "GPIO мікроконтролерів STM32F303 з використанням HAL". Нам достатньо знати, що один пін, в режимі GPIO-Output, виділено під Trig, один -- в режимі GPIO-Input, під Echo:
Звертаюся самі-знаєте-до-кого -- бездумно "перемальовувати" схему із скріншота -- погана ідея. Для запобігання, тут, за можливості, наводжу лише важливі фрагменти.
Підключаємо їх до відповідних пінів далекоміра.  Увага -- він нормально спрацьовує від логічної одинички 3.3В-мікроконтролера, але для свого живлення потребує 5 вольт!

Принципи роботи із даним пристроєм описані тут: "Далекомір HC-SR04 -- огляд", коротко нагадаємо їх:

Мікросекундні затримки та відлік мікросекунд для STM32

Взято тут.
Затримки тривалістю в мікросекунди, які, наприклад, потрібні для роботи із нашим ультразвуковим далекоміром, не підтримуються HAL. При тому, HAL використовує SysTick, конфігуруючи його так, щоб той лічив мілісекунди, а переконфігуровувати його не завжди можна і не завжди хочеться.
Про те, як переконфігурувати, якщо є таке бажання, див. "Далекомір HC-SR04 -- використовуючи GPIO/HAL/STM32CubeMX", після слів "Ось з відліком часу складніше".
Аналогічно, HAL_GetTick() повертає, по замовчуванню, кількість мілісекунд. Це доволі велика одиниця...

В цьому пості розглянемо альтернативи:
  • Активне очікування -- затримку можна зробити, скориставшись так званим busy loop (холостим циклом).
  • Лічильник тактів -- його використання дозволяє вирішити обидві задачі, і створення затримок і відлік часу із мікросекундною точністю. (Старші моделі STM32 обладнані лічильником, схожим на той, який на x86 читає команда RDTSC -- DWT->CYCCNT).
  • Найбільш загальний варіант -- використання повноцінних таймерів.
Закінчимо виклад кодом, що дозволяє легко переключатися між розглянутими варіантами.

середу, 12 жовтня 2016 р.

Таймери STM32 -- remapping/CMSIS

Мультиплексор. Зображення взято тут.
STM32 надають певну гнучкість у тому, які піни прив'язані до яких функцій -- так-званий remapping (перепризначення). STM32CubeMX автоматично користується цією можливістю під час візуального редагування конфігурації. Для кращого розуміння, спробуємо зробити це ж вручну, на рівні CMSIS.

Що це за можливість і де шукати інформацію про неї, вже описувалася в попередньому пості: "Таймери STM32 -- огляд", то я просто зацитую:

четвер, 29 вересня 2016 р.

GPIO мікроконтролерів STM32F303 з використанням HAL

STM32F3Discovery
Виникла чисто практична потреба написати коротке введення в GPIO контролера STM32F303 плати STM32F3Discovery. Подумав, що є сенс зробити його в блозі. 
Серія про таймери, далекомір і продовження -- написана ще весною, але, на жаль, катастрофічно бракує часу довести її до ладу і опублікувати. Вірю, що скоро мені нарешті вдасться це зробити. Done. Див. відповідні теги: таймери, далекомір.
Працюватимемо із використанням візуального генератора конфігурації STM32CubeMX, бібліотеки роботи із периферією HAL та середовища System Workbench for STM32 (SW4STM32). 

Update 20-11-2016: виправлено прикру помилку -- додано заборону переривань при звертанні до змінних, що можуть бути модифіковані в їх обробниках. Прикру -- бо в таких простих прикладах вона себе проявляє рідко, але є дуже "фундаментальною", якщо можна так сказати про помилку.

Update 17-09-2017:  додано вирішення кількох типових проблем, що виникають при роботі із SW4STM32, оновлено пару посилань, дрібні стилістичні зміни.

суботу, 4 червня 2016 р.

Розповіді про операційні системи від Таненбаума

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

Отож, Ендрю Таненбаум, "Сучасні операційні системи" ("Modern Operating Systems"). 

В принципі, автор окремого представлення не потребує -- живий класик комп'ютерних наук. Згадаю лише, що крім авторства ряду класичних підручників (операційні системи, комп'ютерні мережі, тощо) та якісно нового способу викладати теорію ОС, для реалізації якого було написано POSIX-сумісну ОС MINIX, він має відношення і до виникнення ядра GNU/Linux (*) -- Лінус приступив до роботи якраз під впливом книги та самої MINIX, якою скористатися не міг із ліцензійних міркувань -- тоді такої халяви із безліччю хороших та доступних інструментів, як зараз, не було. Детальніше про нього див, наприклад, вікі: "Ендрю Стюарт Таненбаум".
(*) Правильна назва саме така. "Linux" стосується ядра, розробленого Лінусом Торвальдом, а решта інструментів, що "утворюють" повноцінну операційну систему, походять із проекту GNU.
На жаль, українського перекладу поки не існує, мова йтиме про російський переклад та оригінальне англійське видання.

четвер, 31 березня 2016 р.

Таймери STM32 -- одноімпульсний режим/HAL

Черговий пост в серії -- одноімпульсний режим, OPM, із використанням STM32CubeMX/HAL. Вирішимо тих же дві задачі -- реакція на кнопку, із затримкою та реакція на внутрішній тригер, яким служить подія переповнення іншого таймера. 

Запуск OPM кнопкою 

Почнемо із візуальної конфігурації:
Клікабельно! Знадобиться, щоб роздивитися конфігурацію таймера.

понеділок, 28 березня 2016 р.

Таймери STM32 -- одноімпульсний режим/CMSIS

Останні теми, перш ніж повернемося до далекоміра -- вже із новими засобами. Взагалі, якщо чесно, вся ця серія з'явилася через те, що я дуже розсердився, витративши, щоб розібратися із One Pulse Mode (одноімпульсний режим, OPM) кілька повних днів. Тому текст нижче -- спроба розказати про нього максимально детально.

Що це за режим оглядово розповідалося в загальному пості про таймери:
На додачу до всього описаного вище, таймер має спеціальний біт, який вказує -- продовжувати відлік чи зупинятися після події оновлення (забороняючи таймер). З допомогою цієї можливості реалізовано спеціальний, одноімпульсний, режим. По зовнішньому чи внутрішньому сигналу (запустити таймер може зовнішня подія або інший таймер) відбувається затримка (визначається вже згаданим TIMx_CCRx), після чого -- імпульс, тривалістю TIMx_ARRx-TIMx_CCRx. Що таке імпульс визначається тими режимами, якими володіє кожен із каналів -- встановити у активний, пасивний, змінити на протилежний, ШІМ1, ШІМ2, не змінювати нічого, примусовий активний чи пасивний, що значить активний/пасивний визначається полярністю.

Режим одного імпульсу.
(c) STMicroelectronics
Розглянемо два види подій, що запускатимуть OPM -- внутрішня, від іншого таймера та зовнішня -- від кнопки.

Почнемо із простішого і більш корисного -- реакція на зовнішню подію із заданою затримкою.

неділю, 27 березня 2016 р.

Таймери STM32 -- захоплення ШІМ/HAL

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

Черговий такий приклад -- вирішена раніше, засобами CMSIS, задача визначення тривалості натискання кнопки із використанням режиму захоплення ШІМ. Задача, насправді, зовсім трішки відрізняється від "канонічної", із документації -- один таймер генерує ШІМ, інший його ловить, але дає можливість "помацати" таймер руками -- натискаючи кнопку.

суботу, 26 березня 2016 р.

Таймери STM32 -- захоплення ШІМ/CMSIS

За допомогою захоплення вводу, розглянутого недавно, можна організувати потрібні для роботи із далекоміром вимірювання тривалості імпульсів. Реалізувати це можна як програмно (налаштувавши захоплення по спаду і по зростанню сигналу та програмно відстежувати поточний стан) так і апаратно (з'єднавши фізично два канали таймера і на одному захоплювати фронт, на іншому -- спад). Думка, що такі задачі постають, прийшла й розробникам STM32, тому у таймерів є спеціальний режим -- захоплення ШІМ. Зацитую описане в огляді таймерів:
Хитра конфігурація режиму захоплення сигналу -- коли два канали "слухають" той самий вхід, один ловить фронт, другий спад. При тому, початок відліку каналу по фронту очищає лічильник таймера. Тоді подія по спаданню збереже у TIMx_CCRx відповідного каналу тривалість імпульсу, а наступний фронт дасть у TIMx_CCRx каналу, що їх ловить, період. Значно краще все це зрозуміти можна на рисунку із даташіту:


Режим захоплення ШІМ.
(c) STMicroelectronics
Насправді, це всього лиш комбінація вже розглянутого режиму захоплення, різних видів тригерів і реакції на них та під'єднання двох каналів до одного піну.

вівторок, 22 березня 2016 р.

Таймери STM32 -- захоплення вводу/HAL

Попрацюємо тепер із захопленням вводу засобами HAL. Як і в попередньому пості, фіксуватимемо час натискання кнопки. Вся логіка роботи -- та ж, що у згаданому пості -- по натисканню клавіші, під'єднаної до PA0, пін притягується до одинички, таймер у відповідь повинен зберегти момент натискання. В головному циклі програма виводить отримані значення, користуючись Semihosting. 

Традиційно, створюємо проект STM32CubeMX, вибираємо мікроконтролер і т.д. Далі, налаштовуємо таймер та пін кнопки:

понеділок, 21 березня 2016 р.

Таймери STM32 -- захоплення вводу/CMSIS

Для роботи із далекоміром нам треба не тільки подавати імпульс заданої довжини, але і заміряти тривалість імпульсу на Echo, яка визначає час польоту звуку. Хоча це можна зробити і вручну, опитуванням, як раніше, або скориставшись зовнішнім перериванням EXTI, як буде розглянуто в подальшому, цікавіше зробити все автоматично -- за допомогою таймерів, які мають спеціальний режим -- Input capture mode.

Кожен канал має регістр TIMx_CCRx, в який, у режимі захоплення, зберігається значення лічильника в момент приходу сигналу. При тому встановлюється відповідний біт CCXIF у регістрі TIMx_SR та може бути згенеровано переривання чи запит DMA. Якщо під час захоплення біт CCXIF, який автоматично очищається при читанні з TIMx_CCRx чи може бути очищений програмно, все ще рівний 1 -- значить попереднє значення не було прочитано, встановлюється прапорець CCxOF в тому ж регістрі статусу, та може генеруватися відповідне переривання чи запит -- over-capture.
Захоплення може відбуватися по зростанню, (фронту), спаданню сигналу чи і по тому і по тому. Можна встановити фільтр -- кількість вибірок, після якої можна вважати, що сигнал встановився (такий собі захист від дрижання контактів). Можна ділити вхідну частоту на 2, 4 або 8 --- реєструвати кожну другу-четверту-восьму подію.
Почнемо із найпростішого -- запускаємо таймер та зберігаємо значення лічильника у момент натискання кнопки.

середу, 16 березня 2016 р.

Таймери STM32 -- автоматична зупинка/HAL

Аналогічно до відповідного CMSIS-поста, беремо проект, котрий генерує ШІМ, збільшуємо період до видимого оком значення -- нам потрібен один імпульс заданої тривалості, а не власне ШІМ та кажемо зупинятися після переповнення.

Для цього на вкладці pinout слід поставити одну "пташку" -- One Pulse Mode:


Потім, в Configure, налаштовуємо період і тривалість імпульсу:

вівторок, 15 березня 2016 р.

Таймери STM32 -- автоматична зупинка/CMSIS

Цього разу -- зовсім коротка нотатка. Таймери володіють цікавою особливістю -- якщо встановити біт OPM в CR1, таймер автоматично зупинятиметься після події оновлення.

Важливе зауваження -- цей біт, OPM -- One-Pulse Mode, використовується для реалізації однойменного режиму One-pulse mode, який призначений керувати формою імпульсу -- генерувати його у відповідь на подію, із заданою затримкою після події та заданою довжиною. Про цей режим говоритимемо окремо. Цей пост -- своєрідна прелюдія до відповідної розмови -- ми просто навчимо таймер зупинятися. Така можливість теж корисна -- наприклад, для нашого далекоміра немає потреби робити якісь затримки, генерувати хитрі хвилі, абощо, але хотілося б, щоб таймер генерував один імпульс заданої довжини, і хотілося б, щоб він робив це повністю автоматично -- не використовуючи переривання та ручне вмикання-вимикання логічної одинички на піні.

понеділок, 14 березня 2016 р.

Таймери STM32 -- внутрішні тригери/HAL

(c) Wiki
Повторимо "подвиг" CMSIS, розглянутий раніше, зробивши із двох 16-бітних таймерів один 32-бітний, засобами HAL.

Почнемо із візуального конфігурування:


Для головного (master) таймера просто вмикаємо тактування. Підлеглому, slave, вказуємо працювати в режимі External Clock Mode 1 та отримувати тактування від внутрішнього джерела ITR3, котре, як ми знаємо з попереднього поста, під'єднане до TRGO TIM4.

пʼятницю, 11 березня 2016 р.

Таймери STM32 -- внутрішні тригери/CMSIS

Взято тут.
Як вже не раз згадувалося, таймери можуть постачати тактування один одному. Наприклад, один таймер може служити подільником для іншого -- переповнення головного (master) таймера приводить до одного відліку підлеглого (slave). Це дозволяє зробити із двох 16-бітних таймерів один 32-бітний. Хоча, комбінацій master-slave є багато більше -- як підлеглий таймер може реагувати на сигнал, описувалося тут (мова про біти SMS), а за яких умов головний (master) сигнал посилає -- описано нижче.

Подивимося, як користуватися цією можливістю на дещо надуманому прикладі -- мигатимемо світлодіодом у перериванні від TIM1, який буде підлеглим для TIM4.

На відміну від зовнішнього тактування,  розглянутого раніше, тут використано тактування від внутрішніх тригерів -- ITRx.

четвер, 10 березня 2016 р.

Таймери STM32 -- зовнішнє тактування/HAL

Ще один зовнішній годинник.
(c) Wiki
Повторимо зроблене в пості про зовнішнє тактування таймерів з використанням CMSIS за допомогою HAL та STM32CubeMX. Як завжди із графічними утилітами конфігурації і на відміну CMSIS-постів, тут буде багато картинок і мало власного коду. 

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

Звичайно, краще було б зробити окремі проекти для кожного, але це чисто механічна робота, на яку мені бракує сил та часу, а ця серія постів їх і так забагато забрала.

середу, 9 березня 2016 р.

Таймери STM32 -- зовнішнє тактування/CMSIS

Зовнішній годинник, а що? :-)
(c) Wiki
Як вже говорилося раніше, таймери можуть тактуватися не тільки від RCC, але і від інших зовнішніх чи внутрішніх джерел:
  • External clock mode1 -- тактування від входів TI1 або TI2,
  • External clock mode2 -- від піна ETR,
  • Internal trigger clock (ITRx) -- від внутрішніх джерел.
Про внутрішні джерела тактування таймерів поговоримо окремо, а зараз познайомимося із зовнішнім тактуванням на простому прикладі -- підрахунку кількості натискання кнопки. 

вівторок, 8 березня 2016 р.

Таймери STM32 -- ШІМ/HAL

Беремо STM32CubeMX проект із попереднього прикладу (із відліком) та додаємо до нього TIM3, який генеруватиме на своєму каналі CH2, під'єднаному до PA7, PWM (ШІМ), змінюючи яскравість світлодіода, як і в попередньому пості, але засобами HAL.

"Малюємо" проект


Конфігуруємо TIM3

неділю, 6 березня 2016 р.

Таймери STM32 -- ШІМ/CMSIS

Здатність відраховувати час ([1], [2], [3]), звичайно, критична для таймерів, однак, всі, крім базових (та спеціалізованих, типу SysTick та watchdog-ів), вміють більше -- безпосередньо керувати виводами, пінами, мікроконтролера. Один із найпростіших, але дуже потужних, способів такого керування --- генерація ШІМ, широтно-імпульсна модуляції, (англійською -- PWM).

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

суботу, 5 березня 2016 р.

Таймери STM32 -- відлік часу/HAL

Раніше ми розглянули як здійснювати найпростіші операції із таймерами, безпосередньо маніпулюючи їх регістрами. Звичайно, користуючись константами та функціями із CMSIS, але нічим більш високорівневим. Тепер подивимося, як це ж зробити за допомогою HAL. Важливо, що HAL -- лише бібліотека, якою користуватися можна по різному, сама по собі вона особливих переваг не надає. (IMHO, звичайно). Однак, STM32CubeMX вміє генерувати ініціалізацію периферії з візуальних налаштувань, користуючись цією бібліотекою. Це дуже спрощує розробку -- все ж, принаймні для мене, найбільша проблема роботи із такими контролерами -- сотні бітів конфігурації периферії, які слід вмикати і вимикати в правильній послідовності. Cube дозволяє, як мінімум, побачити правильну таку послідовність -- спрощуючи й "ручну" роботу з ними в майбутньому. Як максимум -- просто про це не турбуватися. Додаткова абстракція вносить свої труднощі, але серйозною проблемою це не є -- весь код доступний, навіть без додаткової документації можна розібратися, що-куди-як, а, як буде показано в подальшому, за ввімкненої оптимізації, при всій громіздкості (в порівнянні із ручною маніпуляцією регістрами) коду HAL/STM32CubeMX, зростання розмірів пам'яті обох видів -- цілком скромне. 

Отож, повторимо зроблене в попередньому прикладі, користуючись HAL. 

четвер, 3 березня 2016 р.

Таймери STM32 -- відлік часу/CMSIS

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

Нагадаю, працюватимемо на прикладі STM32F100RB, яким обладнана STM32VLDiscovery. Для інших мікроконтролерів сімейства, скажімо, STM32F303, зміни будуть мінімальними, якщо взагалі будуть, навіть якщо користуватися виключно CMSIS.

Переривання таймерів


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

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

Список таких "комунальних" квартир переривань таймерів для STM32F100RB:
  • TIM1_BRK_TIM15_IRQn, TIM1_UP_TIM16_IRQn, TIM1_TRG_COM_TIM17_IRQn,  TIM1_CC_IRQn -- як бачимо, три із чотирьох переривань єдиного просунутого таймера цього контролера, TIM1, використовуються спільно із іншими таймерами (TIM15/16/17).
  • TIM2_IRQn
  • TIM3_IRQn
  • TIM4_IRQn
  • TIM6_DAC_IRQn -- разом із перериванням від ЦАП (DAC)
  • TIM7_IRQn
Зауважте, що таймери TIM12/13/14 у варіанта мікроконтролера STM32F100RB (у всіх Low i Medium density, якщо точніше) -- відсутні, є лише в High-density STM32F100.

середу, 2 березня 2016 р.

Таймер SysTick

Тактування SysTick. Клікабельно.
Про цей таймер не раз писав раніше, та й інші автори про нього не забували. Однак в цьому блозі про нього завжди говорилося в глибині великих простирадл тексту, вирішив винести в окремий пост.

SysTick timer 

SysTick timer -- простий 24-бітний таймер, частина ядра Cortex M, тому присутній у відповідних мікроконтролерах всіх виробників. Належить до підсистеми контролера переривань, NVIC.

вівторок, 1 березня 2016 р.

Відлік часу без таймерів

Альтернативний спосіб відліку часу
Кам'яна сокира. (c) Wiki

Відмірювати час за допомогою таймерів -- найбільш зручний і коректний спосіб. Однак, іноді він може не підходити, з тих чи інших мотивів. Одна з альтернатив -- чисто програмна затримка. Іншими словами, контролер змушують якийсь час виконувати задані інструкції. Якщо потік виконання один і переривань не виникає, такий спосіб доволі точний (а з перерахунку вимог, щоб він був точним, видно основні його недоліки). Важливо, що на відміну від x86, час виконання інструкцій мікроконтролера значно більш передбачуваний.

Наведений нижче приклад реалізації базується на коді з Leaflab Maple IDE, аналогу оболонки Ардуїно для STM32. Увага: Приклад може бути неточним -- особливо ретельно я не тестував.

Update: Див. також розвиток теми в "Мікросекундні затримки та відлік мікросекунд для STM32".

понеділок, 29 лютого 2016 р.

Таймери STM32 -- огляд

Працюючи із далекоміром, ми використовували те, що називають GPIO -- General Purpose Input-Output. В принципі, сяк-так воно задачу вирішує. Однак, повністю займає процесор, і взагалі -- неестетичне. Мікроконтролери, зазвичай, обладнані значно більш зручними засобами для вирішення таких задач -- таймерами та перериваннями. 

Переривання дозволяють програмі не очікувати на якусь подію, постійно перевіряючи щось типу "а що там на піні зараз? а тепер? а тепер?", а отримати нотифікацію про неї -- виклик певного коду у відповідь на появу події. Вони, безперечно, заслуговують окремої розмови (можливо, найближчим часом), але Cortex-M все організовує так, що обробники переривання  -- звичні С-ні функції, що викликаються у відповідь на подію. А ось таймери -- пристрої складні та різноманітні. Тому поговоримо поки про них. 

суботу, 27 лютого 2016 р.

Далекомір HC-SR04 -- GPIO/висновки

Взято тут.
Як було показано в попередніх постах [1, 2, 3, 4, 5], працювати з HC-SR04 просто. Однак, описаний там спосіб -- з використанням GPIO, зовсім вульгарний. Контролери мають значно вишуканіші засоби вимірювати та керувати тривалістю імпульсів, ніж просто неперервно пильнувати за станом "ніжки": переривання, різноманітні потужні та гнучкі таймерів на додачу до SysTick. Про них і напишемо наступного разу. А тут підведемо підсумки GPIO-підходу. 

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

Розглянемо те, що залишилося. Порівняємо особливості програмування різними способами та відповідні розміри прошивок i RAM. 

Щоб не дублювати весь код, розглянемо дві прості але важливі операції:
  • ініціалізацію піну PB1 на виведення,
  • виведення одиниці, 
 зроблені в рамках різних підходів.

пʼятницю, 26 лютого 2016 р.

Далекомір HC-SR04 -- GPIO/C++

Раз вже цей приклад представлено в стількох варіантах, продемонструю, як C++ може бути корисним під час роботи з контролерами. Людина із ніком fede.tft запропонувала цікавий підхід спрощення роботи з STM32 і подібними пристроями, з використанням шаблонів та інших сучасних фішок С++: "STM32 GPIOs and Template Metaprogramming". Замість або плутаного, або багатослівного, підходів, описаних в попередніх постах, без втрати продуктивності (!), можна робити так:

typedef Gpio<GPIOB_BASE,1>  trig;
trig::mode(Mode::OUTPUT);
trig::high();
trig::low();

typedef Gpio<GPIOB_BASE,2>  echo;
echo::mode(Mode::INPUT);
if( echo::value() )
{
...
}

середу, 24 лютого 2016 р.

Далекомір HC-SR04 -- використовуючи GPIO/HAL/STM32CubeMX

Як вже говорилося, CMSIS -- занадто низькорівнева, SPL від неї не далеко втекла. Після років роздумів та роботи, інженери STMicroelecronics випустили чергову спробу --- пакет STM32Cube. Він складається із двох частин: 
  • Коду для мікроконтролерів: бібліотеки, призначеної замінити SPL -- HAL, (Hardware Abstraction Layer) та всіляких middleware ("проміжних")  компонент -- бібліотеку підтримки FAT, бібліотеку для роботи із USB, TCP/IP  стек, RTOS, тощо.
  • STM32CubeMX -- програми для комп'ютера, яка дозволяє графічно конфігурувати периферію, генеруючи код мовою С, який реалізує "намальоване". 
Після  кількох років дозрівання проект став дуже потужним. Особисті враження: як мало треба для щастя -- лише не виставляти ті сотні бітиків вручну, медитуючи над даташітами і аппнотами (appnotes). 

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

Інсталяція 


вівторок, 23 лютого 2016 р.

Далекомір HC-SR04 -- використовуючи GPIO/CoX

Структура CoX
Мушу зізнатися, написано цю серію постів було ще в 2012-му році. На фоні тодішньої ситуації, бібліотека периферії від CooCox - розробників CoIDE, виглядала перспективною. Зараз я в цьому вже дуже сумніваюся -- вона, на жаль, практично закинута. Однак, викидати тодішній приклад шкода, тому ось.

COX


CooCox, автори CoIDE, розробили також свою бібліотеку роботи із периферією, аналог SPL -- COX. Її перевага -- вона платформонезалежна (кросплатформова), працює і з контролерами ARM Cortex від інших виробників -- підтримуються пристрої від Nuvoton, NXP, ST, TI, Holtek, FreeScale, тоді як код із попередніх постів ([1], [2]), працюватиме лише на STM32 від STMicroelectronics.

Апаратна конфігурація та ж, що й в інших GPIO-прикладах:
  • PB1 -- Trig
  • PB2 -- Echo
  • PC8 -- синій світлодіод
  • PC9 -- зелений світлодіод